summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-03-12 22:14:50 +0000
committerpatrick <patrick@openbsd.org>2019-03-12 22:14:50 +0000
commit53b00876ee12a0c62c3f155b1de308a45679f18e (patch)
tree33c1119ed77dd2bbf72f464c2727380673320937
parentreference the /etc/examples files for httpd and acme-client. started from a thread (diff)
downloadwireguard-openbsd-53b00876ee12a0c62c3f155b1de308a45679f18e.tar.xz
wireguard-openbsd-53b00876ee12a0c62c3f155b1de308a45679f18e.zip
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@
-rw-r--r--lib/libm/arch/aarch64/fenv.c23
-rw-r--r--sys/arch/arm64/include/fenv.h5
2 files changed, 17 insertions, 11 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);
diff --git a/sys/arch/arm64/include/fenv.h b/sys/arch/arm64/include/fenv.h
index 674f2f8ed5e..dfb0176fe82 100644
--- a/sys/arch/arm64/include/fenv.h
+++ b/sys/arch/arm64/include/fenv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fenv.h,v 1.2 2017/01/11 00:18:22 patrick Exp $ */
+/* $OpenBSD: fenv.h,v 1.3 2019/03/12 22:14:50 patrick Exp $ */
/*
* Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org>
@@ -31,13 +31,14 @@
#define FE_OVERFLOW 0x04
#define FE_UNDERFLOW 0x08
#define FE_INEXACT 0x10
+#define FE_DENORMAL 0x80
/*
* The following symbol is simply the bitwise-inclusive OR of all floating-point
* exception constants defined above.
*/
#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \
- FE_UNDERFLOW | FE_INEXACT)
+ FE_UNDERFLOW | FE_INEXACT | FE_DENORMAL)
/*
* Each symbol representing the rounding direction, expands to an integer