1 /* Test vrnd_f64 works correctly. */
2 /* { dg-do run } */
3 /* { dg-options "--save-temps" } */
4
5 #include "arm_neon.h"
6
7 extern void abort (void);
8
9 /* Bit offset to round mode field in FPCR. */
10 #define RMODE_START 22
11
12 #define FPROUNDING_ZERO 3
13
14 /* Set RMODE field of FPCR control register
15 to rounding mode passed. */
16 void __inline __attribute__ ((__always_inline__))
set_rounding_mode(uint32_t mode)17 set_rounding_mode (uint32_t mode)
18 {
19 uint32_t r;
20
21 /* Read current FPCR. */
22 asm volatile ("mrs %[r], fpcr" : [r] "=r" (r) : :);
23
24 /* Clear rmode. */
25 r &= ~(3 << RMODE_START);
26 /* Calculate desired FPCR. */
27 r |= mode << RMODE_START;
28
29 /* Write desired FPCR back. */
30 asm volatile ("msr fpcr, %[r]" : : [r] "r" (r) :);
31 }
32
33 float64_t __attribute__ ((noinline))
compare_f64(float64x1_t passed,float64_t expected)34 compare_f64 (float64x1_t passed, float64_t expected)
35 {
36 return (__builtin_fabs (vget_lane_f64 (passed, 0) - expected)
37 > __DBL_EPSILON__);
38 }
39
40 void __attribute__ ((noinline))
run_round_tests(float64x1_t * tests,float64_t expectations[][6])41 run_round_tests (float64x1_t *tests,
42 float64_t expectations[][6])
43 {
44 int i;
45
46 for (i = 0; i < 6; i++)
47 {
48 if (compare_f64 (vrnd_f64 (tests[i]), expectations[0][i]))
49 abort ();
50 if (compare_f64 (vrndx_f64 (tests[i]), expectations[1][i]))
51 abort ();
52 if (compare_f64 (vrndp_f64 (tests[i]), expectations[2][i]))
53 abort ();
54 if (compare_f64 (vrndn_f64 (tests[i]), expectations[3][i]))
55 abort ();
56 if (compare_f64 (vrndm_f64 (tests[i]), expectations[4][i]))
57 abort ();
58 if (compare_f64 (vrndi_f64 (tests[i]), expectations[5][i]))
59 abort ();
60 if (compare_f64 (vrnda_f64 (tests[i]), expectations[6][i]))
61 abort ();
62 }
63 }
64
65 int
main(int argc,char ** argv)66 main (int argc, char **argv)
67 {
68 float64x1_t tests[6] =
69 {
70 vcreate_f64 (0x3FE0000000000000), /* Hex for: 0.5. */
71 vcreate_f64 (0x3FD999999999999A), /* Hex for: 0.4. */
72 vcreate_f64 (0x3FE3333333333333), /* Hex for: 0.6. */
73 vcreate_f64 (0xBFE0000000000000), /* Hex for: -0.5. */
74 vcreate_f64 (0xBFD999999999999A), /* Hex for: -0.4. */
75 vcreate_f64 (0xBFE3333333333333), /* Hex for: -0.6. */
76 };
77
78 float64_t expectations[7][6] =
79 {
80 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrnd - round towards zero. */
81 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrndx - round using FPCR mode. */
82 { 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 }, /* vrndp - round to plus infinity. */
83 { 0.0, 0.0, 1.0, 0.0, 0.0, -1.0 }, /* vrndn - round ties to even. */
84 { 0.0, 0.0, 0.0, -1.0, -1.0, -1.0 }, /* vrndm - round to minus infinity. */
85 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrndi - round using FPCR mode. */
86 { 1.0, 0.0, 1.0, -1.0, 0.0, -1.0 }, /* vrnda - round ties away from 0. */
87 };
88
89 /* Set floating point control register
90 to have predictable vrndx and vrndi behavior. */
91 set_rounding_mode (FPROUNDING_ZERO);
92
93 run_round_tests (tests, expectations);
94
95 return 0;
96 }
97
98 /* { dg-final { scan-assembler-times "frintz\\td\[0-9\]+, d\[0-9\]+" 1 } } */
99 /* { dg-final { scan-assembler-times "frintx\\td\[0-9\]+, d\[0-9\]+" 1 } } */
100 /* { dg-final { scan-assembler-times "frintp\\td\[0-9\]+, d\[0-9\]+" 1 } } */
101 /* { dg-final { scan-assembler-times "frintn\\td\[0-9\]+, d\[0-9\]+" 1 } } */
102 /* { dg-final { scan-assembler-times "frintm\\td\[0-9\]+, d\[0-9\]+" 1 } } */
103 /* { dg-final { scan-assembler-times "frinti\\td\[0-9\]+, d\[0-9\]+" 1 } } */
104 /* { dg-final { scan-assembler-times "frinta\\td\[0-9\]+, d\[0-9\]+" 1 } } */
105