The fpcr register used in arm64 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

Reply via email to