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