The fpcr register used in aarch64 is the same as the fpscr register in 32 bit arm, but when the register is accessed via the msr/mrs instructions, a 64 bit register has to be used - thus use a 64 bit local variable instead of accessing a fenv_t directly. --- mingw-w64-crt/crt/CRT_fp10.c | 3 +++ mingw-w64-crt/misc/feclearexcept.c | 12 +++++++++--- mingw-w64-crt/misc/fegetenv.c | 10 +++++++--- mingw-w64-crt/misc/fegetexceptflag.c | 10 +++++++--- mingw-w64-crt/misc/fegetround.c | 6 +++++- mingw-w64-crt/misc/feholdexcept.c | 8 +++++++- mingw-w64-crt/misc/feraiseexcept.c | 8 +++++++- mingw-w64-crt/misc/fesetenv.c | 14 +++++++++++--- mingw-w64-crt/misc/fesetexceptflag.c | 13 ++++++++++--- mingw-w64-crt/misc/fesetround.c | 14 +++++++++++--- mingw-w64-crt/misc/fetestexcept.c | 10 +++++++--- mingw-w64-headers/crt/fenv.h | 16 +++++++++++++++- 12 files changed, 99 insertions(+), 25 deletions(-)
diff --git a/mingw-w64-crt/crt/CRT_fp10.c b/mingw-w64-crt/crt/CRT_fp10.c index 41cb573..f39b517 100644 --- a/mingw-w64-crt/crt/CRT_fp10.c +++ b/mingw-w64-crt/crt/CRT_fp10.c @@ -11,6 +11,9 @@ void _fpreset (void) #if defined(_ARM_) || defined(__arm__) __asm__ __volatile__ ( "vmsr fpscr, %0\n\t" : : "r"(0 /* INITIAL_FPSCR */)); +#elif defined(_ARM64_) || defined(__aarch64__) + __asm__ __volatile__ ( + "msr fpcr, %0\n\t" : : "r"(0LL /* INITIAL_FPSCR */)); #else #ifdef __GNUC__ __asm__ ("fninit"); diff --git a/mingw-w64-crt/misc/feclearexcept.c b/mingw-w64-crt/misc/feclearexcept.c index b5a3b70..673528b 100644 --- a/mingw-w64-crt/misc/feclearexcept.c +++ b/mingw-w64-crt/misc/feclearexcept.c @@ -5,7 +5,7 @@ */ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) int __mingw_has_sse (void); int __mingw_has_sse(void) @@ -32,7 +32,7 @@ int __mingw_has_sse(void) return 1; return 0; } -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.2.1 The feclearexcept function clears the supported exceptions @@ -45,6 +45,12 @@ int feclearexcept (int excepts) __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); _env.__cw &= ~(excepts & FE_ALL_EXCEPT); __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~(excepts & FE_ALL_EXCEPT); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); #else int _mxcsr; if (excepts == FE_ALL_EXCEPT) @@ -63,6 +69,6 @@ int feclearexcept (int excepts) _mxcsr &= ~(((excepts & FE_ALL_EXCEPT))); __asm__ volatile ("ldmxcsr %0" : : "m" (_mxcsr)); } -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return (0); } diff --git a/mingw-w64-crt/misc/fegetenv.c b/mingw-w64-crt/misc/fegetenv.c index 96f57e4..3196081 100644 --- a/mingw-w64-crt/misc/fegetenv.c +++ b/mingw-w64-crt/misc/fegetenv.c @@ -5,9 +5,9 @@ */ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.4.1 The fegetenv function stores the current floating-point environment @@ -17,6 +17,10 @@ int fegetenv (fenv_t * envp) { #if defined(_ARM_) || defined(__arm__) __asm__ volatile ("fmrx %0, FPSCR" : "=r" (*envp)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + envp->__cw = fpcr; #else __asm__ __volatile__ ("fnstenv %0;": "=m" (*envp)); /* fnstenv sets control word to non-stop for all exceptions, so we @@ -29,7 +33,7 @@ int fegetenv (fenv_t * envp) envp->__unused0 = (((unsigned int) _mxcsr) >> 16); envp->__unused1 = (((unsigned int) _mxcsr) & 0xffff); } -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fegetexceptflag.c b/mingw-w64-crt/misc/fegetexceptflag.c index e8dae96..eaa940a 100644 --- a/mingw-w64-crt/misc/fegetexceptflag.c +++ b/mingw-w64-crt/misc/fegetexceptflag.c @@ -5,9 +5,9 @@ */ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) extern int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.2.2 The fegetexceptflag function stores an implementation-defined @@ -20,6 +20,10 @@ int fegetexceptflag (fexcept_t * flagp, int excepts) fenv_t _env; __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); *flagp = _env.__cw & excepts & FE_ALL_EXCEPT; +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + *flagp = fpcr & excepts & FE_ALL_EXCEPT; #else int _mxcsr; unsigned short _status; @@ -30,6 +34,6 @@ int fegetexceptflag (fexcept_t * flagp, int excepts) __asm__ volatile ("stmxcsr %0" : "=m" (_mxcsr)); *flagp = (_mxcsr | _status) & excepts & FE_ALL_EXCEPT; -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fegetround.c b/mingw-w64-crt/misc/fegetround.c index b4b757b..d2fdb77 100644 --- a/mingw-w64-crt/misc/fegetround.c +++ b/mingw-w64-crt/misc/fegetround.c @@ -16,9 +16,13 @@ fegetround (void) fenv_t _env; __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); return (_env.__cw & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + return (fpcr & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); #else int _control; __asm__ volatile ("fnstcw %0" : "=m" (*&_control)); return (_control & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ } diff --git a/mingw-w64-crt/misc/feholdexcept.c b/mingw-w64-crt/misc/feholdexcept.c index a2b7834..8736faa 100644 --- a/mingw-w64-crt/misc/feholdexcept.c +++ b/mingw-w64-crt/misc/feholdexcept.c @@ -19,11 +19,17 @@ int feholdexcept (fenv_t * envp) envp->__cw = _env.__cw; _env.__cw &= ~(FE_ALL_EXCEPT); __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + envp->__cw = fpcr; + fpcr &= ~(FE_ALL_EXCEPT); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); #else __asm__ __volatile__ ("fnstenv %0;" : "=m" (* envp)); /* save current into envp */ /* fnstenv sets control word to non-stop for all exceptions, so all we need to do is clear the exception flags. */ __asm__ __volatile__ ("fnclex"); -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/feraiseexcept.c b/mingw-w64-crt/misc/feraiseexcept.c index 5175026..8ec36f7 100644 --- a/mingw-w64-crt/misc/feraiseexcept.c +++ b/mingw-w64-crt/misc/feraiseexcept.c @@ -20,11 +20,17 @@ int feraiseexcept (int excepts) __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); _env.__cw |= excepts & FE_ALL_EXCEPT; __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr |= excepts & FE_ALL_EXCEPT; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); #else __asm__ volatile ("fnstenv %0;" : "=m" (_env)); _env.__status_word |= excepts & FE_ALL_EXCEPT; __asm__ volatile ("fldenv %0;" "fwait;" : : "m" (_env)); -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fesetenv.c b/mingw-w64-crt/misc/fesetenv.c index d16dd65..f998017 100644 --- a/mingw-w64-crt/misc/fesetenv.c +++ b/mingw-w64-crt/misc/fesetenv.c @@ -7,9 +7,9 @@ #include <fenv.h> #include <float.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) extern int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.4.3 The fesetenv function establishes the floating-point environment @@ -32,6 +32,14 @@ int fesetenv (const fenv_t * envp) _fpreset(); else __asm__ volatile ("fmxr FPSCR, %0" : : "r" (*envp)); +#elif defined(_ARM64_) || defined(__aarch64__) + if (envp == FE_DFL_ENV) { + /* Use the choice made at app startup */ + _fpreset(); + } else { + unsigned __int64 fpcr = envp->__cw; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); + } #else if (envp == FE_PC64_ENV) /* @@ -70,6 +78,6 @@ int fesetenv (const fenv_t * envp) __asm__ volatile ("ldmxcsr %0" : : "m" (*&_mxcsr)); } -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fesetexceptflag.c b/mingw-w64-crt/misc/fesetexceptflag.c index cb9ba3f..7e3361c 100644 --- a/mingw-w64-crt/misc/fesetexceptflag.c +++ b/mingw-w64-crt/misc/fesetexceptflag.c @@ -5,9 +5,9 @@ */ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) extern int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.2.4 The fesetexceptflag function sets the complete status for those @@ -29,6 +29,13 @@ int fesetexceptflag (const fexcept_t * flagp, int excepts) _env.__cw &= ~excepts; _env.__cw |= (*flagp & excepts); __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~excepts; + fpcr |= (*flagp & excepts); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); #else __asm__ volatile ("fnstenv %0;" : "=m" (_env)); _env.__status_word &= ~excepts; @@ -44,6 +51,6 @@ int fesetexceptflag (const fexcept_t * flagp, int excepts) __asm__ volatile ("ldmxcsr %0" : : "m" (sse_cw)); } -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fesetround.c b/mingw-w64-crt/misc/fesetround.c index 74dc355..624a999 100644 --- a/mingw-w64-crt/misc/fesetround.c +++ b/mingw-w64-crt/misc/fesetround.c @@ -5,9 +5,9 @@ */ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.3.2 The fesetround function establishes the rounding direction @@ -25,6 +25,14 @@ int fesetround (int mode) _env.__cw &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); _env.__cw |= mode; __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) != 0) + return -1; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); + fpcr |= mode; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); #else unsigned short _cw; if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) @@ -44,6 +52,6 @@ int fesetround (int mode) mxcsr |= mode << 3; __asm__ volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); } -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ return 0; } diff --git a/mingw-w64-crt/misc/fetestexcept.c b/mingw-w64-crt/misc/fetestexcept.c index f27d535..da073e6 100644 --- a/mingw-w64-crt/misc/fetestexcept.c +++ b/mingw-w64-crt/misc/fetestexcept.c @@ -6,9 +6,9 @@ #include <fenv.h> -#if !(defined(_ARM_) || defined(__arm__)) +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) extern int __mingw_has_sse (void); -#endif /* !(defined(_ARM_) || defined(__arm__)) */ +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ /* 7.6.2.5 The fetestexcept function determines which of a specified subset of @@ -24,6 +24,10 @@ int fetestexcept (int excepts) fenv_t _env; __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); return _env.__cw & excepts & FE_ALL_EXCEPT; +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + return fpcr & excepts & FE_ALL_EXCEPT; #else unsigned short _sw; __asm__ __volatile__ ("fnstsw %%ax" : "=a" (_sw)); @@ -35,5 +39,5 @@ int fetestexcept (int excepts) _sw |= sse_sw; } return _sw & excepts & FE_ALL_EXCEPT; -#endif /* defined(_ARM_) || defined(__arm__) */ +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ } diff --git a/mingw-w64-headers/crt/fenv.h b/mingw-w64-headers/crt/fenv.h index 3339337..b0c0f56 100644 --- a/mingw-w64-headers/crt/fenv.h +++ b/mingw-w64-headers/crt/fenv.h @@ -8,7 +8,7 @@ #include <crtdefs.h> -#if defined(_ARM_) || defined(__arm__) +#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) /* FPU status word exception flags */ #define FE_INVALID 0x01 @@ -74,6 +74,20 @@ typedef struct /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1l) +#elif defined(_ARM64_) || defined(__aarch64__) + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. */ +typedef struct +{ + unsigned int __cw; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1l) + #else /* -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public