NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-arm/58782: fpsetround flips all the other fpcsr bits on aarch64
>Number: 58782
>Category: port-arm
>Synopsis: fpsetround flips all the other fpcsr bits on aarch64
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-arm-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Oct 28 21:30:00 +0000 2024
>Originator: Taylor R Campbell
>Release: current, 10, 9
>Organization:
The NetBSD Roundfliption
>Environment:
>Description:
The aarch64 implementation of fpsetround() from <ieeefp.h> has the effect of flipping all bits _other_ than the rounding mode in the fpcr, the floating-point control register.
48 const uint32_t old_fpcr = reg_fpcr_read();
49 const uint32_t new_fpcr = (~old_fpcr & ~FPCR_RMODE)
50 | __SHIFTIN(rnd, FPCR_RMODE);
51 reg_fpcr_write(new_fpcr);
https://nxr.netbsd.org/xref/src/lib/libc/arch/aarch64/gen/fpsetround.c?r=1.3#49
As a result, for example, setting the rounding mode has the side effect of toggling flush-to-zero (no gradual underflow) mode.
>How-To-Repeat:
$ cat noftz.c
#include <float.h>
#include <ieeefp.h>
#include <stdio.h>
int
main(void)
{
volatile double x = DBL_MIN;
volatile double y;
y = x/2;
printf("%a\n", y);
fpsetround(FP_RN);
y = x/2;
printf("%a\n", y);
fpsetround(FP_RN);
y = x/2;
printf("%a\n", y);
fflush(stdout);
return ferror(stdout);
}
$ make ftz
cc -O2 -o ftz ftz.c
$ ./ftz
0x1p-1023
0x0p+0
0x1p-1023
>Fix:
nix the extra ~
Home |
Main Index |
Thread Index |
Old Index