You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.4 KiB
106 lines
3.4 KiB
9 months ago
|
commit de751ebc9efa97ce0115e42bd55fa1beeb614380
|
||
|
Author: Paul A. Clarke <pc@us.ibm.com>
|
||
|
Date: Fri Mar 15 19:04:24 2019 -0400
|
||
|
|
||
|
[powerpc] get_rounding_mode: utilize faster method to get rounding mode
|
||
|
|
||
|
Add support to use 'mffsl' instruction if compiled for POWER9 (or later).
|
||
|
|
||
|
Also, mask the result to avoid bleeding unrelated bits into the result of
|
||
|
_FPU_GET_RC().
|
||
|
|
||
|
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||
|
|
||
|
diff --git a/sysdeps/powerpc/fpu/get-rounding-mode.h b/sysdeps/powerpc/fpu/get-rounding-mode.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000..e2fdbbbcce72bd66
|
||
|
--- /dev/null
|
||
|
+++ b/sysdeps/powerpc/fpu/get-rounding-mode.h
|
||
|
@@ -0,0 +1,33 @@
|
||
|
+/* Determine floating-point rounding mode within libc. powerpc64 version.
|
||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||
|
+ This file is part of the GNU C Library.
|
||
|
+
|
||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||
|
+ modify it under the terms of the GNU Lesser General Public
|
||
|
+ License as published by the Free Software Foundation; either
|
||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||
|
+
|
||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public
|
||
|
+ License along with the GNU C Library; if not, see
|
||
|
+ <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+#ifndef _POWERPC64_GET_ROUNDING_MODE_H
|
||
|
+#define _POWERPC64_GET_ROUNDING_MODE_H 1
|
||
|
+
|
||
|
+#include <fenv.h>
|
||
|
+#include <fpu_control.h>
|
||
|
+
|
||
|
+/* Return the floating-point rounding mode. */
|
||
|
+
|
||
|
+static inline int
|
||
|
+get_rounding_mode (void)
|
||
|
+{
|
||
|
+ return _FPU_GET_RC ();
|
||
|
+}
|
||
|
+
|
||
|
+#endif /* get-rounding-mode.h */
|
||
|
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
|
||
|
index 9d0698b4fc3eb595..62c478d72ae660cb 100644
|
||
|
--- a/sysdeps/powerpc/fpu_control.h
|
||
|
+++ b/sysdeps/powerpc/fpu_control.h
|
||
|
@@ -71,6 +71,8 @@ extern fpu_control_t __fpu_control;
|
||
|
# define _FPU_RC_UP 0x02
|
||
|
# define _FPU_RC_ZERO 0x01
|
||
|
|
||
|
+# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO)
|
||
|
+
|
||
|
# define _FPU_MASK_NI 0x04 /* non-ieee mode */
|
||
|
|
||
|
/* masking of interrupts */
|
||
|
@@ -94,15 +96,36 @@ extern fpu_control_t __fpu_control;
|
||
|
typedef unsigned int fpu_control_t;
|
||
|
|
||
|
/* Macros for accessing the hardware control word. */
|
||
|
+# define __FPU_MFFS() \
|
||
|
+ ({register double __fr; \
|
||
|
+ __asm__ ("mffs %0" : "=f" (__fr)); \
|
||
|
+ __fr; \
|
||
|
+ })
|
||
|
+
|
||
|
# define _FPU_GETCW(cw) \
|
||
|
({union { double __d; unsigned long long __ll; } __u; \
|
||
|
- register double __fr; \
|
||
|
- __asm__ ("mffs %0" : "=f" (__fr)); \
|
||
|
- __u.__d = __fr; \
|
||
|
+ __u.__d = __FPU_MFFS(); \
|
||
|
(cw) = (fpu_control_t) __u.__ll; \
|
||
|
(fpu_control_t) __u.__ll; \
|
||
|
})
|
||
|
|
||
|
+#ifdef _ARCH_PWR9
|
||
|
+# define __FPU_MFFSL() \
|
||
|
+ ({register double __fr; \
|
||
|
+ __asm__ ("mffsl %0" : "=f" (__fr)); \
|
||
|
+ __fr; \
|
||
|
+ })
|
||
|
+#else
|
||
|
+# define __FPU_MFFSL() __FPU_MFFS()
|
||
|
+#endif
|
||
|
+
|
||
|
+# define _FPU_GET_RC() \
|
||
|
+ ({union { double __d; unsigned long long __ll; } __u; \
|
||
|
+ __u.__d = __FPU_MFFSL(); \
|
||
|
+ __u.__ll &= _FPU_MASK_RC; \
|
||
|
+ (fpu_control_t) __u.__ll; \
|
||
|
+ })
|
||
|
+
|
||
|
# define _FPU_SETCW(cw) \
|
||
|
{ union { double __d; unsigned long long __ll; } __u; \
|
||
|
register double __fr; \
|