1/* Test vrnd_f64 works correctly.  */
2/* { dg-do run } */
3/* { dg-options "--save-temps" } */
4
5#include "arm_neon.h"
6
7extern 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.  */
16void __inline __attribute__ ((__always_inline__))
17set_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
33float64_t __attribute__ ((noinline))
34compare_f64 (float64x1_t passed, float64_t expected)
35{
36  return (__builtin_fabs (vget_lane_f64 (passed, 0) - expected)
37	  > __DBL_EPSILON__);
38}
39
40void __attribute__ ((noinline))
41run_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
65int
66main (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 behaviour.  */
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/* { dg-final { cleanup-saved-temps } } */
106