From b6c7f6e5950e609a2ede7990d2be0a1d1b55304f Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 3 Nov 2017 16:46:32 -0700 Subject: [PATCH] Fix arm/arm64 to match current reality. ARM stopped supporting enabling of FP exceptions years ago. Bug: http://b/68832485 Test: ran tests Change-Id: I8450baa78e04d994c352180975b0a1ecd5a9f662 --- .../include/android/legacy_fenv_inlines_arm.h | 27 ++--- libc/include/bits/fenv_arm.h | 32 ++++-- libc/include/bits/fenv_arm64.h | 102 ------------------ libc/include/fenv.h | 4 +- libm/arm/fenv.c | 25 ++--- libm/arm64/fenv.c | 43 ++------ tests/fenv_test.cpp | 20 ++-- 7 files changed, 57 insertions(+), 196 deletions(-) delete mode 100644 libc/include/bits/fenv_arm64.h diff --git a/libc/include/android/legacy_fenv_inlines_arm.h b/libc/include/android/legacy_fenv_inlines_arm.h index 58c49c2cf..de024cf3c 100644 --- a/libc/include/android/legacy_fenv_inlines_arm.h +++ b/libc/include/android/legacy_fenv_inlines_arm.h @@ -35,9 +35,6 @@ __BEGIN_DECLS -#define FPSCR_ENABLE_SHIFT 8 -#define FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << FPSCR_ENABLE_SHIFT) - #define FPSCR_RMODE_SHIFT 22 static __inline int fegetenv(fenv_t* __envp) { @@ -108,7 +105,7 @@ static __inline int feholdexcept(fenv_t* __envp) { fenv_t __env; fegetenv(&__env); *__envp = __env; - __env &= ~(FE_ALL_EXCEPT | FPSCR_ENABLE_MASK); + __env &= ~FE_ALL_EXCEPT; fesetenv(&__env); return 0; } @@ -121,30 +118,18 @@ static __inline int feupdateenv(const fenv_t* __envp) { return 0; } -static __inline int feenableexcept(int __mask) { - fenv_t __old_fpscr, __new_fpscr; - fegetenv(&__old_fpscr); - __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT; - fesetenv(&__new_fpscr); - return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT); +static __inline int feenableexcept(int __mask __unused) { + return -1; } -static __inline int fedisableexcept(int __mask) { - fenv_t __old_fpscr, __new_fpscr; - fegetenv(&__old_fpscr); - __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT); - fesetenv(&__new_fpscr); - return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT); +static __inline int fedisableexcept(int __mask __unused) { + return 0; } static __inline int fegetexcept(void) { - fenv_t __fpscr; - fegetenv(&__fpscr); - return ((__fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT); + return 0; } -#undef FPSCR_ENABLE_SHIFT -#undef FPSCR_ENABLE_MASK #undef FPSCR_RMODE_SHIFT __END_DECLS diff --git a/libc/include/bits/fenv_arm.h b/libc/include/bits/fenv_arm.h index 542ddbe11..042fec30b 100644 --- a/libc/include/bits/fenv_arm.h +++ b/libc/include/bits/fenv_arm.h @@ -26,13 +26,6 @@ * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $ */ -/* - * Rewritten for Android. - * - * The ARM FPSCR is described here: - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344b/Chdfafia.html - */ - #ifndef _BITS_FENV_ARM_H_ #define _BITS_FENV_ARM_H_ @@ -40,7 +33,28 @@ __BEGIN_DECLS +/* + * The ARM Cortex-A75 registers are described here: + * + * AArch64: + * FPCR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442502503726.html + * FPSR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442502526288.html + * AArch32: + * FPSCR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442504290459.html + */ + +#if defined(__LP64__) +typedef struct { + /* FPCR, Floating-point Control Register. */ + __uint32_t __control; + /* FPSR, Floating-point Status Register. */ + __uint32_t __status; +} fenv_t; + +#else typedef __uint32_t fenv_t; +#endif + typedef __uint32_t fexcept_t; /* Exception flags. */ @@ -49,8 +63,8 @@ typedef __uint32_t fexcept_t; #define FE_OVERFLOW 0x04 #define FE_UNDERFLOW 0x08 #define FE_INEXACT 0x10 -#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#define FE_DENORMAL 0x80 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) /* Rounding modes. */ #define FE_TONEAREST 0x0 diff --git a/libc/include/bits/fenv_arm64.h b/libc/include/bits/fenv_arm64.h deleted file mode 100644 index 67f0fb492..000000000 --- a/libc/include/bits/fenv_arm64.h +++ /dev/null @@ -1,102 +0,0 @@ -/*- - * Copyright (c) 2004-2005 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $ - */ - -/* - * In ARMv8, AArch64 state, floating-point operation is controlled by: - * - * * FPCR - 32Bit Floating-Point Control Register: - * * [31:27] - Reserved, Res0; - * * [26] - AHP, Alternative half-precision control bit; - * * [25] - DN, Default NaN mode control bit; - * * [24] - FZ, Flush-to-zero mode control bit; - * * [23:22] - RMode, Rounding Mode control field: - * * 00 - Round to Nearest (RN) mode; - * * 01 - Round towards Plus Infinity (RP) mode; - * * 10 - Round towards Minus Infinity (RM) mode; - * * 11 - Round towards Zero (RZ) mode. - * * [21:20] - Stride, ignored during AArch64 execution; - * * [19] - Reserved, Res0; - * * [18:16] - Len, ignored during AArch64 execution; - * * [15] - IDE, Input Denormal exception trap; - * * [14:13] - Reserved, Res0; - * * [12] - IXE, Inexact exception trap; - * * [11] - UFE, Underflow exception trap; - * * [10] - OFE, Overflow exception trap; - * * [9] - DZE, Division by Zero exception; - * * [8] - IOE, Invalid Operation exception; - * * [7:0] - Reserved, Res0. - * - * * FPSR - 32Bit Floating-Point Status Register: - * * [31] - N, Negative condition flag for AArch32 (AArch64 sets PSTATE.N); - * * [30] - Z, Zero condition flag for AArch32 (AArch64 sets PSTATE.Z); - * * [29] - C, Carry conditon flag for AArch32 (AArch64 sets PSTATE.C); - * * [28] - V, Overflow conditon flag for AArch32 (AArch64 sets PSTATE.V); - * * [27] - QC, Cumulative saturation bit, Advanced SIMD only; - * * [26:8] - Reserved, Res0; - * * [7] - IDC, Input Denormal cumulative exception; - * * [6:5] - Reserved, Res0; - * * [4] - IXC, Inexact cumulative exception; - * * [3] - UFC, Underflow cumulative exception; - * * [2] - OFC, Overflow cumulative exception; - * * [1] - DZC, Division by Zero cumulative exception; - * * [0] - IOC, Invalid Operation cumulative exception. - */ - -#ifndef _BITS_FENV_ARM64_H_ -#define _BITS_FENV_ARM64_H_ - -#include - -__BEGIN_DECLS - -typedef struct { - __uint32_t __control; /* FPCR, Floating-point Control Register */ - __uint32_t __status; /* FPSR, Floating-point Status Register */ -} fenv_t; - -typedef __uint32_t fexcept_t; - -/* Exception flags. */ -#define FE_INVALID 0x01 -#define FE_DIVBYZERO 0x02 -#define FE_OVERFLOW 0x04 -#define FE_UNDERFLOW 0x08 -#define FE_INEXACT 0x10 -#define FE_DENORMAL 0x80 -#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) - -/* Rounding modes. */ -#define FE_TONEAREST 0x0 -#define FE_UPWARD 0x1 -#define FE_DOWNWARD 0x2 -#define FE_TOWARDZERO 0x3 - -__END_DECLS - -#endif diff --git a/libc/include/fenv.h b/libc/include/fenv.h index 4276e87b8..2b607f578 100644 --- a/libc/include/fenv.h +++ b/libc/include/fenv.h @@ -32,9 +32,7 @@ #include -#if defined(__aarch64__) -#include -#elif defined(__arm__) +#if defined(__aarch64__) || defined(__arm__) #include #elif defined(__i386__) #include diff --git a/libm/arm/fenv.c b/libm/arm/fenv.c index 212473071..c988e4fa5 100644 --- a/libm/arm/fenv.c +++ b/libm/arm/fenv.c @@ -28,9 +28,6 @@ #include -#define FPSCR_ENABLE_SHIFT 8 -#define FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << FPSCR_ENABLE_SHIFT) - #define FPSCR_RMODE_SHIFT 22 const fenv_t __fe_dfl_env = 0; @@ -103,7 +100,7 @@ int feholdexcept(fenv_t* __envp) { fenv_t __env; fegetenv(&__env); *__envp = __env; - __env &= ~(FE_ALL_EXCEPT | FPSCR_ENABLE_MASK); + __env &= ~FE_ALL_EXCEPT; fesetenv(&__env); return 0; } @@ -116,24 +113,14 @@ int feupdateenv(const fenv_t* __envp) { return 0; } -int feenableexcept(int __mask) { - fenv_t __old_fpscr, __new_fpscr; - fegetenv(&__old_fpscr); - __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT; - fesetenv(&__new_fpscr); - return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT); +int feenableexcept(int __mask __unused) { + return -1; } -int fedisableexcept(int __mask) { - fenv_t __old_fpscr, __new_fpscr; - fegetenv(&__old_fpscr); - __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT); - fesetenv(&__new_fpscr); - return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT); +int fedisableexcept(int __mask __unused) { + return 0; } int fegetexcept(void) { - fenv_t __fpscr; - fegetenv(&__fpscr); - return ((__fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT); + return 0; } diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c index 19a239334..a99288b66 100644 --- a/libm/arm64/fenv.c +++ b/libm/arm64/fenv.c @@ -29,9 +29,6 @@ #include #include -#define FPCR_EXCEPT_SHIFT 8 -#define FPCR_EXCEPT_MASK (FE_ALL_EXCEPT << FPCR_EXCEPT_SHIFT) - #define FPCR_RMODE_SHIFT 22 const fenv_t __fe_dfl_env = { 0 /* control */, 0 /* status */}; @@ -137,22 +134,13 @@ int fesetround(int round) { } int feholdexcept(fenv_t* envp) { - fenv_t env; fpu_status_t fpsr; - fpu_control_t fpcr, new_fpcr; - __get_fpsr(fpsr); + fpu_control_t fpcr; __get_fpcr(fpcr); - env.__status = fpsr; - env.__control = fpcr; + fenv_t env = { .__status = fpsr, .__control = fpcr }; *envp = env; - // Set exceptions to untrapped. - new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FPCR_EXCEPT_SHIFT); - if (new_fpcr != fpcr) { - __set_fpcr(new_fpcr); - } - // Clear all exceptions. fpsr &= ~FE_ALL_EXCEPT; __set_fpsr(fpsr); @@ -176,31 +164,14 @@ int feupdateenv(const fenv_t* envp) { return 0; } -int feenableexcept(int mask) { - fpu_control_t old_fpcr, new_fpcr; - - __get_fpcr(old_fpcr); - new_fpcr = old_fpcr | ((mask & FE_ALL_EXCEPT) << FPCR_EXCEPT_SHIFT); - if (new_fpcr != old_fpcr) { - __set_fpcr(new_fpcr); - } - return ((old_fpcr >> FPCR_EXCEPT_SHIFT) & FE_ALL_EXCEPT); +int feenableexcept(int mask __unused) { + return -1; } -int fedisableexcept(int mask) { - fpu_control_t old_fpcr, new_fpcr; - - __get_fpcr(old_fpcr); - new_fpcr = old_fpcr & ~((mask & FE_ALL_EXCEPT) << FPCR_EXCEPT_SHIFT); - if (new_fpcr != old_fpcr) { - __set_fpcr(new_fpcr); - } - return ((old_fpcr >> FPCR_EXCEPT_SHIFT) & FE_ALL_EXCEPT); +int fedisableexcept(int mask __unused) { + return 0; } int fegetexcept(void) { - fpu_control_t fpcr; - - __get_fpcr(fpcr); - return ((fpcr & FPCR_EXCEPT_MASK) >> FPCR_EXCEPT_SHIFT); + return 0; } diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp index c914692bd..9fc7d96fc 100644 --- a/tests/fenv_test.cpp +++ b/tests/fenv_test.cpp @@ -182,12 +182,20 @@ TEST(fenv, fedisableexcept_fegetexcept) { TEST(fenv, feenableexcept_fegetexcept) { #if defined(__aarch64__) || defined(__arm__) - // Unsupported. - // arm: - // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100403_0200_00_en/lau1442504290459.html - // aarch64: - // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488h/way1382990760439.html - GTEST_LOG_(INFO) << "arm and arm64 don't support feenableexcept"; + // ARM doesn't support this. They used to if you go back far enough, but it was removed in + // the Cortex-A8 between r3p1 and r3p2. + ASSERT_EQ(-1, feenableexcept(FE_INVALID)); + ASSERT_EQ(0, fegetexcept()); + ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO)); + ASSERT_EQ(0, fegetexcept()); + ASSERT_EQ(-1, feenableexcept(FE_OVERFLOW)); + ASSERT_EQ(0, fegetexcept()); + ASSERT_EQ(-1, feenableexcept(FE_UNDERFLOW)); + ASSERT_EQ(0, fegetexcept()); + ASSERT_EQ(-1, feenableexcept(FE_INEXACT)); + ASSERT_EQ(0, fegetexcept()); + ASSERT_EQ(-1, feenableexcept(FE_DENORMAL)); + ASSERT_EQ(0, fegetexcept()); #else // We can't recover from SIGFPE, so sacrifice a child... pid_t pid = fork();