summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2019-03-12 22:14:51 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2019-03-12 22:14:51 +0000
commit44274519e68b442ed87170b6df72fafc9fbfe25f (patch)
tree381f56ba140098e49d0082a3d1683dcdedd74953 /lib
parenta5c8ddd6848824eb90f47987e9585e6fa7a94853 (diff)
Setting and getting the rounding mode on our arm64 FPU has not worked
in libm since the rounding mode is in fpcr, not fpsr. Since both FPU registers are 32-bit we can store them in the 64-bit fenv_t to make handling the bits easier. While there add FE_DENORMAL, which also exists on x86. Also make sure that whenever we are being passed an exception mask, we only allow the bits that are supported by hardware. Found by regression tests Debugged with Moritz Buhl ok kettenis@
Diffstat (limited to 'lib')
-rw-r--r--lib/libm/arch/aarch64/fenv.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/lib/libm/arch/aarch64/fenv.c b/lib/libm/arch/aarch64/fenv.c
index 88dc3d8ed30..bdf942188b6 100644
--- a/lib/libm/arch/aarch64/fenv.c
+++ b/lib/libm/arch/aarch64/fenv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fenv.c,v 1.2 2018/03/16 10:22:52 kettenis Exp $ */
+/* $OpenBSD: fenv.c,v 1.3 2019/03/12 22:14:50 patrick Exp $ */
/*-
* Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
@@ -60,6 +60,7 @@ feclearexcept(int excepts)
{
fexcept_t r;
+ excepts &= FE_ALL_EXCEPT;
__mrs_fpsr(r);
r &= ~excepts;
__msr_fpsr(r);
@@ -77,6 +78,7 @@ fegetexceptflag(fexcept_t *flagp, int excepts)
{
fexcept_t r;
+ excepts &= FE_ALL_EXCEPT;
__mrs_fpsr(r);
*flagp = r & excepts;
return (0);
@@ -92,6 +94,7 @@ feraiseexcept(int excepts)
{
fexcept_t r;
+ excepts &= FE_ALL_EXCEPT;
__mrs_fpsr(r);
r |= excepts;
__msr_fpsr(r);
@@ -109,6 +112,7 @@ fesetexceptflag(const fexcept_t *flagp, int excepts)
{
fexcept_t r;
+ excepts &= FE_ALL_EXCEPT;
__mrs_fpsr(r);
r &= ~excepts;
r |= *flagp & excepts;
@@ -127,6 +131,7 @@ fetestexcept(int excepts)
{
fexcept_t r;
+ excepts &= FE_ALL_EXCEPT;
__mrs_fpsr(r);
return (r & excepts);
}
@@ -175,10 +180,10 @@ fegetenv(fenv_t *envp)
fenv_t r;
__mrs_fpcr(r);
- *envp = r & _ENABLE_MASK;
+ *envp = r;
__mrs_fpsr(r);
- *envp |= r & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT));
+ *envp |= (r << 32);
return (0);
}
@@ -196,13 +201,13 @@ feholdexcept(fenv_t *envp)
fenv_t r;
__mrs_fpcr(r);
- *envp = r & _ENABLE_MASK;
- r &= ~(_ENABLE_MASK);
+ *envp = r;
+ r &= ~_ENABLE_MASK;
__msr_fpcr(r);
__mrs_fpsr(r);
- *envp |= r & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT));
- r &= ~(_ENABLE_MASK);
+ *envp |= (r << 32);
+ r &= ~FE_ALL_EXCEPT;
__msr_fpsr(r);
return (0);
}
@@ -220,8 +225,8 @@ int
fesetenv(const fenv_t *envp)
{
- __msr_fpcr((*envp) & _ENABLE_MASK);
- __msr_fpsr((*envp) & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT)));
+ __msr_fpcr(*envp & 0xffffffff);
+ __msr_fpsr(*envp >> 32);
return (0);
}
DEF_STD(fesetenv);