105 lines
3.3 KiB
C
105 lines
3.3 KiB
C
/* Test vrnd_f64 works correctly. */
|
|
/* { dg-do run } */
|
|
/* { dg-options "--save-temps" } */
|
|
|
|
#include "arm_neon.h"
|
|
|
|
extern void abort (void);
|
|
|
|
/* Bit offset to round mode field in FPCR. */
|
|
#define RMODE_START 22
|
|
|
|
#define FPROUNDING_ZERO 3
|
|
|
|
/* Set RMODE field of FPCR control register
|
|
to rounding mode passed. */
|
|
void __inline __attribute__ ((__always_inline__))
|
|
set_rounding_mode (uint32_t mode)
|
|
{
|
|
uint32_t r;
|
|
|
|
/* Read current FPCR. */
|
|
asm volatile ("mrs %[r], fpcr" : [r] "=r" (r) : :);
|
|
|
|
/* Clear rmode. */
|
|
r &= ~(3 << RMODE_START);
|
|
/* Calculate desired FPCR. */
|
|
r |= mode << RMODE_START;
|
|
|
|
/* Write desired FPCR back. */
|
|
asm volatile ("msr fpcr, %[r]" : : [r] "r" (r) :);
|
|
}
|
|
|
|
float64_t __attribute__ ((noinline))
|
|
compare_f64 (float64x1_t passed, float64_t expected)
|
|
{
|
|
return (__builtin_fabs (vget_lane_f64 (passed, 0) - expected)
|
|
> __DBL_EPSILON__);
|
|
}
|
|
|
|
void __attribute__ ((noinline))
|
|
run_round_tests (float64x1_t *tests,
|
|
float64_t expectations[][6])
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
if (compare_f64 (vrnd_f64 (tests[i]), expectations[0][i]))
|
|
abort ();
|
|
if (compare_f64 (vrndx_f64 (tests[i]), expectations[1][i]))
|
|
abort ();
|
|
if (compare_f64 (vrndp_f64 (tests[i]), expectations[2][i]))
|
|
abort ();
|
|
if (compare_f64 (vrndn_f64 (tests[i]), expectations[3][i]))
|
|
abort ();
|
|
if (compare_f64 (vrndm_f64 (tests[i]), expectations[4][i]))
|
|
abort ();
|
|
if (compare_f64 (vrndi_f64 (tests[i]), expectations[5][i]))
|
|
abort ();
|
|
if (compare_f64 (vrnda_f64 (tests[i]), expectations[6][i]))
|
|
abort ();
|
|
}
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
float64x1_t tests[6] =
|
|
{
|
|
vcreate_f64 (0x3FE0000000000000), /* Hex for: 0.5. */
|
|
vcreate_f64 (0x3FD999999999999A), /* Hex for: 0.4. */
|
|
vcreate_f64 (0x3FE3333333333333), /* Hex for: 0.6. */
|
|
vcreate_f64 (0xBFE0000000000000), /* Hex for: -0.5. */
|
|
vcreate_f64 (0xBFD999999999999A), /* Hex for: -0.4. */
|
|
vcreate_f64 (0xBFE3333333333333), /* Hex for: -0.6. */
|
|
};
|
|
|
|
float64_t expectations[7][6] =
|
|
{
|
|
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrnd - round towards zero. */
|
|
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrndx - round using FPCR mode. */
|
|
{ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 }, /* vrndp - round to plus infinity. */
|
|
{ 0.0, 0.0, 1.0, 0.0, 0.0, -1.0 }, /* vrndn - round ties to even. */
|
|
{ 0.0, 0.0, 0.0, -1.0, -1.0, -1.0 }, /* vrndm - round to minus infinity. */
|
|
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* vrndi - round using FPCR mode. */
|
|
{ 1.0, 0.0, 1.0, -1.0, 0.0, -1.0 }, /* vrnda - round ties away from 0. */
|
|
};
|
|
|
|
/* Set floating point control register
|
|
to have predictable vrndx and vrndi behavior. */
|
|
set_rounding_mode (FPROUNDING_ZERO);
|
|
|
|
run_round_tests (tests, expectations);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* { dg-final { scan-assembler-times "frintz\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frintx\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frintp\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frintn\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frintm\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frinti\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|
|
/* { dg-final { scan-assembler-times "frinta\\td\[0-9\]+, d\[0-9\]+" 1 } } */
|