]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
x86: Adapt "%v" usage on clang to emit VEX enconding
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 16 Oct 2025 19:23:18 +0000 (16:23 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 28 Oct 2025 16:36:29 +0000 (13:36 -0300)
clang does not support the %v to select the AVX encoding, nor the '%d' asm
contrain, and for AVX build it requires all 3 arguments.

This patch add a new internal header, math-inline-asm.h, that adds
functions to abstract the inline asm required differences between
gcc and clang.

35 files changed:
sysdeps/i386/fpu/fclrexcpt.c
sysdeps/i386/fpu/fedisblxcpt.c
sysdeps/i386/fpu/feenablxcpt.c
sysdeps/i386/fpu/fegetenv.c
sysdeps/i386/fpu/fegetmode.c
sysdeps/i386/fpu/feholdexcpt.c
sysdeps/i386/fpu/fesetenv.c
sysdeps/i386/fpu/fesetexcept.c
sysdeps/i386/fpu/fesetmode.c
sysdeps/i386/fpu/fesetround.c
sysdeps/i386/fpu/feupdateenv.c
sysdeps/i386/fpu/fgetexcptflg.c
sysdeps/i386/fpu/fsetexcptflg.c
sysdeps/i386/fpu/ftestexcept.c
sysdeps/i386/setfpucw.c
sysdeps/x86/fpu/fenv_private.h
sysdeps/x86/fpu/math-inline-asm.h [new file with mode: 0644]
sysdeps/x86/fpu/math_private.h
sysdeps/x86/fpu/sfp-machine.h
sysdeps/x86/fpu/test-fenv-sse-2.c
sysdeps/x86_64/fpu/fclrexcpt.c
sysdeps/x86_64/fpu/fedisblxcpt.c
sysdeps/x86_64/fpu/feenablxcpt.c
sysdeps/x86_64/fpu/fegetenv.c
sysdeps/x86_64/fpu/fegetmode.c
sysdeps/x86_64/fpu/feholdexcpt.c
sysdeps/x86_64/fpu/fesetenv.c
sysdeps/x86_64/fpu/fesetexcept.c
sysdeps/x86_64/fpu/fesetmode.c
sysdeps/x86_64/fpu/fesetround.c
sysdeps/x86_64/fpu/feupdateenv.c
sysdeps/x86_64/fpu/fgetexcptflg.c
sysdeps/x86_64/fpu/fraiseexcpt.c
sysdeps/x86_64/fpu/fsetexcptflg.c
sysdeps/x86_64/fpu/ftestexcept.c

index 39bcf3de590d761014a91dc8cbc20463a39244f9..5f586dae3734a485cbeae8037b60fbcd4fd76a35 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __feclearexcept (int excepts)
@@ -44,13 +45,13 @@ __feclearexcept (int excepts)
       unsigned int xnew_exc;
 
       /* Get the current MXCSR.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (xnew_exc));
+      xnew_exc = stmxcsr_inline_asm ();
 
       /* Clear the relevant bits.  */
       xnew_exc &= ~excepts;
 
       /* Put the new data in effect.  */
-      __asm__ ("%vldmxcsr %0" : : "m" (xnew_exc));
+      ldmxcsr_inline_asm (xnew_exc);
     }
 
   /* Success.  */
index a2dfa8e4c95dbb2b5e6590a7642007ba5878b0f7..6d65ebc052823a5bc3c03008c895ca23101257bf 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 fedisableexcept (int excepts)
@@ -41,11 +42,11 @@ fedisableexcept (int excepts)
       unsigned int xnew_exc;
 
       /* Get the current control word.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (xnew_exc));
+      xnew_exc = stmxcsr_inline_asm ();
 
       xnew_exc |= excepts << 7;
 
-      __asm__ ("%vldmxcsr %0" : : "m" (xnew_exc));
+      ldmxcsr_inline_asm (xnew_exc);
     }
 
   return old_exc;
index fa1d82a4b6b4299510e8e513c2e4600698da2263..c4a54583eea42f91bbb9ceb44ffea25c65478ae1 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 feenableexcept (int excepts)
@@ -41,11 +42,11 @@ feenableexcept (int excepts)
       unsigned int xnew_exc;
 
       /* Get the current control word.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (xnew_exc));
+      xnew_exc = stmxcsr_inline_asm ();
 
       xnew_exc &= ~(excepts << 7);
 
-      __asm__ ("%vldmxcsr %0" : : "m" (xnew_exc));
+      ldmxcsr_inline_asm (xnew_exc);
     }
 
   return old_exc;
index 5b3557715114c94b9bce2b6da7eee689c0b80765..12829e15495f850713fe528447f31c7dd24ece7f 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __fegetenv (fenv_t *envp)
@@ -30,7 +31,7 @@ __fegetenv (fenv_t *envp)
   __asm__ ("fldenv %0" : : "m" (*envp));
 
   if (CPU_FEATURE_USABLE (SSE))
-    __asm__ ("%vstmxcsr %0" : "=m" (envp->__eip));
+    envp->__eip = stmxcsr_inline_asm ();
 
   /* Success.  */
   return 0;
index 8b109072f50469cf628ad7fb0e582933cf80bf1e..1ee1c11a54633b5ab57cd12f57e56c620b3092da 100644 (file)
 #include <fpu_control.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 fegetmode (femode_t *modep)
 {
   _FPU_GETCW (modep->__control_word);
   if (CPU_FEATURE_USABLE (SSE))
-    __asm__ ("%vstmxcsr %0" : "=m" (modep->__mxcsr));
+    modep->__mxcsr = stmxcsr_inline_asm ();
   return 0;
 }
index f6f6b70dd4f3076547496ba652be0a06c83aa77c..2f1fa503b99cf08bf73ba54bfb62e7c7cd5533c6 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __feholdexcept (fenv_t *envp)
@@ -33,12 +34,12 @@ __feholdexcept (fenv_t *envp)
       unsigned int xwork;
 
       /* Get the current control word.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (envp->__eip));
+      envp->__eip = stmxcsr_inline_asm ();
 
       /* Set all exceptions to non-stop and clear them.  */
       xwork = (envp->__eip | 0x1f80) & ~0x3f;
 
-      __asm__ ("%vldmxcsr %0" : : "m" (xwork));
+      ldmxcsr_inline_asm (xwork);
     }
 
   return 0;
index e6b276a0fcd0450267ff35fa281b4bf21c74b831..0305eb5146ee4c8a9ebc2fd36adacdd66548a5ef 100644 (file)
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 
 /* All exceptions, including the x86-specific "denormal operand"
@@ -79,8 +80,7 @@ __fesetenv (const fenv_t *envp)
 
   if (CPU_FEATURE_USABLE (SSE))
     {
-      unsigned int mxcsr;
-      __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+      unsigned int mxcsr = stmxcsr_inline_asm ();
 
       if (envp == FE_DFL_ENV)
        {
@@ -111,7 +111,7 @@ __fesetenv (const fenv_t *envp)
       else
        mxcsr = envp->__eip;
 
-      __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+      ldmxcsr_inline_asm (mxcsr);
     }
 
   /* Success.  */
index 876bde233fb85d22814959888c1ecaf21d462884..20ab75becd5fbb485e1f340ff0e3368b72a6e5bd 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <fenv.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 fesetexcept (int excepts)
@@ -32,14 +33,13 @@ fesetexcept (int excepts)
   if (CPU_FEATURE_USABLE (SSE))
     {
       /* Get the control word of the SSE unit.  */
-      unsigned int mxcsr;
-      __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+      unsigned int mxcsr = stmxcsr_inline_asm ();
 
       /* Set relevant flags.  */
       mxcsr |= excepts;
 
       /* Put the new data in effect.  */
-      __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+      ldmxcsr_inline_asm (mxcsr);
     }
   else
     {
index ee61ca1cec66a4e4a5e6a2597ca5a0f6569e0e95..0616cabc4572124503fe8022351893b9ef5fd45a 100644 (file)
@@ -20,6 +20,7 @@
 #include <fpu_control.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 /* All exceptions, including the x86-specific "denormal operand"
    exception.  */
@@ -36,8 +37,7 @@ fesetmode (const femode_t *modep)
   _FPU_SETCW (cw);
   if (CPU_FEATURE_USABLE (SSE))
     {
-      unsigned int mxcsr;
-      __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+      unsigned int mxcsr = stmxcsr_inline_asm ();
       /* Preserve SSE exception flags but restore other state in
         MXCSR.  */
       mxcsr &= FE_ALL_EXCEPT_X86;
@@ -47,7 +47,7 @@ fesetmode (const femode_t *modep)
        mxcsr |= FE_ALL_EXCEPT_X86 << 7;
       else
        mxcsr |= modep->__mxcsr & ~FE_ALL_EXCEPT_X86;
-      __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+      ldmxcsr_inline_asm (mxcsr);
     }
   return 0;
 }
index e87d794319e00d7c843914169c706bc23dcc2556..e3e16e87b1da2d6cafff3a4fda55cda621f19ca6 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __fesetround (int round)
@@ -37,12 +38,10 @@ __fesetround (int round)
   /* If the CPU supports SSE we set the MXCSR as well.  */
   if (CPU_FEATURE_USABLE (SSE))
     {
-      unsigned int xcw;
-
-      __asm__ ("%vstmxcsr %0" : "=m" (xcw));
+      unsigned int xcw = stmxcsr_inline_asm ();
       xcw &= ~0x6000;
       xcw |= round << 3;
-      __asm__ ("%vldmxcsr %0" : : "m" (xcw));
+      ldmxcsr_inline_asm (xcw);
     }
 
   return 0;
index 9e1ad97118cb1a5ee26d36e454ac8c5286ed8da7..d56276f2ceea3140e7e012ea55398ba7c8f117a4 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __feupdateenv (const fenv_t *envp)
@@ -31,7 +32,7 @@ __feupdateenv (const fenv_t *envp)
 
   /* If the CPU supports SSE we test the MXCSR as well.  */
   if (CPU_FEATURE_USABLE (SSE))
-    __asm__ ("%vstmxcsr %0" : "=m" (xtemp));
+    xtemp = stmxcsr_inline_asm ();
 
   temp = (temp | xtemp) & FE_ALL_EXCEPT;
 
index 36dd297cdcb37eef7f7368c486faa730a1843bd6..bcba833381259780e93229ec2d75bd96b4ccfaf4 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 
 int
@@ -34,10 +35,8 @@ __fegetexceptflag (fexcept_t *flagp, int excepts)
   /* If the CPU supports SSE, we clear the MXCSR as well.  */
   if (CPU_FEATURE_USABLE (SSE))
     {
-      unsigned int sse_exc;
-
       /* Get the current MXCSR.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (sse_exc));
+      unsigned int sse_exc = stmxcsr_inline_asm ();
 
       *flagp |= sse_exc & excepts & FE_ALL_EXCEPT;
     }
index b78d1dcd3cd9cce5e1a41a16bedbd564dc335ef1..9616fec52e416c230fba562ded7db1a7003b08b7 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <fenv.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __fesetexceptflag (const fexcept_t *flagp, int excepts)
@@ -50,13 +51,13 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
       __asm__ ("fldenv %0" : : "m" (temp));
 
       /* And now similarly for SSE.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+      mxcsr = stmxcsr_inline_asm ();
 
       /* Clear or set relevant flags.  */
       mxcsr ^= (mxcsr ^ *flagp) & excepts;
 
       /* Put the new data in effect.  */
-      __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+      ldmxcsr_inline_asm (mxcsr);
     }
   else
     {
index 51abfd39172ad1758ee9d375970ccc80ed001303..0869582d0a1e0ab1cb55569ab29484042ba64384 100644 (file)
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 int
 __fetestexcept (int excepts)
@@ -31,7 +32,7 @@ __fetestexcept (int excepts)
 
   /* If the CPU supports SSE we test the MXCSR as well.  */
   if (CPU_FEATURE_USABLE (SSE))
-    __asm__ ("%vstmxcsr %0" : "=m" (xtemp));
+    xtemp = stmxcsr_inline_asm ();
 
   return (temp | xtemp) & excepts & FE_ALL_EXCEPT;
 }
index 8438c7ed75448c86e8d44fc9bfca48cd19acbe9b..b48892b41410cd1b86d0faa6e35090d4bd5fda90 100644 (file)
@@ -21,6 +21,7 @@
 #include <fenv.h>
 #include <unistd.h>
 #include <ldsodefs.h>
+#include <math-inline-asm.h>
 
 void
 __setfpucw (fpu_control_t set)
@@ -40,14 +41,12 @@ __setfpucw (fpu_control_t set)
   /* If the CPU supports SSE, we set the MXCSR as well.  */
   if (CPU_FEATURE_USABLE (SSE))
     {
-      unsigned int xnew_exc;
-
       /* Get the current MXCSR.  */
-      __asm__ ("%vstmxcsr %0" : "=m" (xnew_exc));
+      unsigned int xnew_exc = stmxcsr_inline_asm ();
 
       xnew_exc &= ~((0xc00 << 3) | (FE_ALL_EXCEPT << 7));
       xnew_exc |= ((set & 0xc00) << 3) | ((set & FE_ALL_EXCEPT) << 7);
 
-      __asm__ ("%vldmxcsr %0" : : "m" (xnew_exc));
+      ldmxcsr_inline_asm (xnew_exc);
     }
 }
index c9b573cacd52343176c16e91d534ae06f8b87301..2bd20ee99243915445d9b29eed3fdd8888d6841f 100644 (file)
@@ -4,6 +4,7 @@
 #include <bits/floatn.h>
 #include <fenv.h>
 #include <fpu_control.h>
+#include <math-inline-asm.h>
 
 /* This file is used by both the 32- and 64-bit ports.  The 64-bit port
    has a field in the fenv_t for the mxcsr; the 32-bit port does not.
 static __always_inline void
 libc_feholdexcept_sse (fenv_t *e)
 {
-  unsigned int mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();;
   e->__mxcsr = mxcsr;
   mxcsr = (mxcsr | 0x1f80) & ~0x3f;
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 static __always_inline void
@@ -42,10 +42,9 @@ libc_feholdexcept_387 (fenv_t *e)
 static __always_inline void
 libc_fesetround_sse (int r)
 {
-  unsigned int mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();;
   mxcsr = (mxcsr & ~0x6000) | (r << 3);
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 static __always_inline void
@@ -60,11 +59,10 @@ libc_fesetround_387 (int r)
 static __always_inline void
 libc_feholdexcept_setround_sse (fenv_t *e, int r)
 {
-  unsigned int mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();;
   e->__mxcsr = mxcsr;
   mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3);
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 /* Set both rounding mode and precision.  A convenience function for use
@@ -95,8 +93,7 @@ libc_feholdexcept_setround_387_53bit (fenv_t *e, int r)
 static __always_inline int
 libc_fetestexcept_sse (int e)
 {
-  unsigned int mxcsr;
-  asm volatile ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();
   return mxcsr & e & FE_ALL_EXCEPT;
 }
 
@@ -111,7 +108,7 @@ libc_fetestexcept_387 (int ex)
 static __always_inline void
 libc_fesetenv_sse (fenv_t *e)
 {
-  asm volatile ("%vldmxcsr %0" : : "m" (e->__mxcsr));
+  ldmxcsr_inline_asm (e->__mxcsr);
 }
 
 static __always_inline void
@@ -129,13 +126,13 @@ static __always_inline int
 libc_feupdateenv_test_sse (fenv_t *e, int ex)
 {
   unsigned int mxcsr, old_mxcsr, cur_ex;
-  asm volatile ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
   cur_ex = mxcsr & FE_ALL_EXCEPT;
 
   /* Merge current exceptions with the old environment.  */
   old_mxcsr = e->__mxcsr;
   mxcsr = old_mxcsr | cur_ex;
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   /* Raise SIGFPE for any new exceptions since the hold.  Expect that
      the normal environment has all exceptions masked.  */
@@ -180,11 +177,10 @@ libc_feupdateenv_387 (fenv_t *e)
 static __always_inline void
 libc_feholdsetround_sse (fenv_t *e, int r)
 {
-  unsigned int mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();;
   e->__mxcsr = mxcsr;
   mxcsr = (mxcsr & ~0x6000) | (r << 3);
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 static __always_inline void
@@ -214,10 +210,9 @@ libc_feholdsetround_387_53bit (fenv_t *e, int r)
 static __always_inline void
 libc_feresetround_sse (fenv_t *e)
 {
-  unsigned int mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();;
   mxcsr = (mxcsr & ~0x6000) | (e->__mxcsr & 0x6000);
-  asm volatile ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 static __always_inline void
@@ -307,13 +302,13 @@ static __always_inline void
 libc_feholdexcept_setround_sse_ctx (struct rm_ctx *ctx, int r)
 {
   unsigned int mxcsr, new_mxcsr;
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
   new_mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3);
 
   ctx->env.__mxcsr = mxcsr;
   if (__glibc_unlikely (mxcsr != new_mxcsr))
     {
-      asm volatile ("%vldmxcsr %0" : : "m" (new_mxcsr));
+      ldmxcsr_inline_asm (new_mxcsr);
       ctx->updated_status = true;
     }
   else
@@ -404,13 +399,13 @@ libc_feholdsetround_sse_ctx (struct rm_ctx *ctx, int r)
 {
   unsigned int mxcsr, new_mxcsr;
 
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
   new_mxcsr = (mxcsr & ~0x6000) | (r << 3);
 
   ctx->env.__mxcsr = mxcsr;
   if (__glibc_unlikely (new_mxcsr != mxcsr))
     {
-      asm volatile ("%vldmxcsr %0" : : "m" (new_mxcsr));
+      ldmxcsr_inline_asm (new_mxcsr);
       ctx->updated_status = true;
     }
   else
diff --git a/sysdeps/x86/fpu/math-inline-asm.h b/sysdeps/x86/fpu/math-inline-asm.h
new file mode 100644 (file)
index 0000000..1b002d0
--- /dev/null
@@ -0,0 +1,79 @@
+/* Math inline asm compat layer
+   Copyright (C) 2025 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_INLINE_ASM
+#define _MATH_INLINE_ASM
+
+#include <sys/cdefs.h>
+
+/* clang does not support the %v to select the AVX encoding, nor the '%d' asm
+   contrain, and for AVX build it requires all 3 arguments.  */
+#ifdef __clang__
+#if defined __AVX__ || defined SSE2AVX
+#  define VPREFIX    "v"
+#  define VROUND_ARG ", %0"
+# else
+#  define VPREFIX    ""
+#  define VROUND_ARG ""
+# endif
+# define VARGPREFIX  "%"
+#else
+# define VPREFIX     "%v"
+# define VARGPREFIX  "%d"
+# define VROUND_ARG  ""
+#endif
+
+__extern_always_inline double
+trunc_inline_asm (double x)
+{
+  asm (VPREFIX "roundsd $11, " VARGPREFIX "1, %0" VROUND_ARG : "=v" (x)
+       : "v" (x));
+  return x;
+}
+
+__extern_always_inline float
+truncf_inline_asm (float x)
+{
+  asm (VPREFIX "roundss $11, " VARGPREFIX "1, %0" VROUND_ARG : "=v" (x)
+       : "v" (x));
+  return x;
+}
+
+static __always_inline unsigned int
+stmxcsr_inline_asm (void)
+{
+  unsigned int mxcsr;
+  asm volatile (VPREFIX "stmxcsr %0" : "=m" (mxcsr));
+  return mxcsr;
+}
+
+static __always_inline void
+ldmxcsr_inline_asm (unsigned int mxcsr)
+{
+  asm volatile (VPREFIX "ldmxcsr %0" : : "m" (mxcsr));
+}
+
+static __always_inline float
+divss_inline_asm (float x, float y)
+{
+  asm volatile (VPREFIX "divss %1, " VARGPREFIX "0" VROUND_ARG
+               : "+x" (x) : "x" (y));
+  return x;
+}
+
+#endif
index bba085a5788b020765d8684a2aaf353351a8fa5b..47de90bcec901e23876b7644dd268ba8ddaa3c34 100644 (file)
 #define X86_MATH_PRIVATE_H 1
 
 #include <math.h>
+#include <math-inline-asm.h>
 #include_next <math_private.h>
 
+
 __extern_always_inline long double
 __NTH (__ieee754_atan2l (long double y, long double x))
 {
@@ -36,8 +38,7 @@ __trunc (double x)
 #if HAVE_X86_INLINE_TRUNC || !defined __SSE4_1__
   return trunc (x);
 #else
-  asm ("%vroundsd $11, %d1, %0" : "=v" (x) : "v" (x));
-  return x;
+  return trunc_inline_asm (x);
 #endif
 }
 
@@ -47,8 +48,7 @@ __truncf (float x)
 #if HAVE_X86_INLINE_TRUNC || !defined __SSE4_1__
   return truncf (x);
 #else
-  asm ("%vroundss $11, %d1, %0" : "=v" (x) : "v" (x));
-  return x;
+  return truncf_inline_asm (x);
 #endif
 }
 
index 9ef85c4e6c270d92a7def89c131d9948a7cacfb9..3ec3185f8c1129c43ade45d9efce62de80112304 100644 (file)
@@ -1,6 +1,8 @@
 /* Configure soft-fp for building sqrtf128.  Based on sfp-machine.h in
    libgcc, with soft-float and other irrelevant parts removed.  */
 
+#include <math-inline-asm.h>
+
 #if HAVE_X86_LIBGCC_CMP_RETURN_ATTR
 /* The type of the result of a floating point comparison.  This must
    match `__libgcc_cmp_return__' in GCC for the target.  */
@@ -55,7 +57,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
 
 # define FP_INIT_ROUNDMODE                                     \
   do {                                                         \
-    __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (_fcw));      \
+    _fcw = stmxcsr_inline_asm ();                              \
   } while (0)
 #else
 # define _FP_W_TYPE_SIZE       32
index d12009bb8115430cddb49296b3e744a1931f1450..cf93a5919dd45bc248156fee0310e2356150302f 100644 (file)
 #include <stdio.h>
 #include <cpu-features.h>
 #include <support/check.h>
-
-static uint32_t
-get_sse_mxcsr (void)
-{
-  uint32_t temp;
-  __asm__ __volatile__ ("%vstmxcsr %0" : "=m" (temp));
-  return temp;
-}
-
-static void
-set_sse_mxcsr (uint32_t val)
-{
-  __asm__ __volatile__ ("%vldmxcsr %0" : : "m" (val));
-}
+#include <math-inline-asm.h>
 
 static void
 set_sse_mxcsr_bits (uint32_t mask, uint32_t bits)
 {
-  uint32_t mxcsr = get_sse_mxcsr ();
+  uint32_t mxcsr = stmxcsr_inline_asm ();
   mxcsr = (mxcsr & ~mask) | bits;
-  set_sse_mxcsr (mxcsr);
+  ldmxcsr_inline_asm (mxcsr);
 }
 
 static int
 test_sse_mxcsr_bits (const char *test, uint32_t mask, uint32_t bits)
 {
-  uint32_t mxcsr = get_sse_mxcsr ();
+  uint32_t mxcsr = stmxcsr_inline_asm ();
   printf ("Testing %s: mxcsr = %x\n", test, mxcsr);
   if ((mxcsr & mask) == bits)
     {
index d5f70458c0dfacf5a54288d7c8a8c3423dc580f2..1c70a9da980e164a9ff993d1e0db8d79de5575e4 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __feclearexcept (int excepts)
@@ -38,13 +39,13 @@ __feclearexcept (int excepts)
   __asm__ ("fldenv %0" : : "m" (temp));
 
   /* And the same procedure for SSE.  */
-  __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
 
   /* Clear the relevant bits.  */
   mxcsr &= ~excepts;
 
   /* And put them into effect.  */
-  __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   /* Success.  */
   return 0;
index dab9ad19c23ddd7e40682e95d8d46c34f6372fdb..38bbdb4f45c437c9a9ee373aaa59a7c9c4aa6e54 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 fedisableexcept (int excepts)
@@ -35,11 +36,11 @@ fedisableexcept (int excepts)
   __asm__ ("fldcw %0" : : "m" (new_exc));
 
   /* And now the same for the SSE MXCSR register.  */
-  __asm__ ("%vstmxcsr %0" : "=m" (new));
+  new = stmxcsr_inline_asm ();
 
   /* The SSE exception masks are shifted by 7 bits.  */
   new |= excepts << 7;
-  __asm__ ("%vldmxcsr %0" : : "m" (new));
+  ldmxcsr_inline_asm (new);
 
   return old_exc;
 }
index 828b2b247a81002cc96a515019cd0d6b90810fa9..848e2d0eaed6c88718ef5d0a12e71199abb8b4aa 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 feenableexcept (int excepts)
@@ -35,11 +36,11 @@ feenableexcept (int excepts)
   __asm__ ("fldcw %0" : : "m" (new_exc));
 
   /* And now the same for the SSE MXCSR register.  */
-  __asm__ ("%vstmxcsr %0" : "=m" (new));
+  new = stmxcsr_inline_asm ();
 
   /* The SSE exception masks are shifted by 7 bits.  */
   new &= ~(excepts << 7);
-  __asm__ ("%vldmxcsr %0" : : "m" (new));
+  ldmxcsr_inline_asm (new);
 
   return old_exc;
 }
index fa21ec4f86200ee41d500d4d36f6138f25801686..2b996d6d5781a8ec6722f69855435ea0e93d5879 100644 (file)
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __fegetenv (fenv_t *envp)
 {
-  __asm__ ("fnstenv %0\n"
-          /* fnstenv changes the exception mask, so load back the
-             stored environment.  */
-          "fldenv %0\n"
-          "%vstmxcsr %1" : "=m" (*envp), "=m" (envp->__mxcsr));
+  asm volatile ("fnstenv %0\n"
+               /* fnstenv changes the exception mask, so load back the
+                  stored environment.  */
+               "fldenv %0"
+               : "=m" (*envp));
+  envp->__mxcsr = stmxcsr_inline_asm ();
 
   /* Success.  */
   return 0;
index 39d124a6d82233160764a33f260ab5eb8156ea82..6c1c1f1f00a2c2683dd70e93402613f7bd501236 100644 (file)
 
 #include <fenv.h>
 #include <fpu_control.h>
+#include <math-inline-asm.h>
 
 int
 fegetmode (femode_t *modep)
 {
   _FPU_GETCW (modep->__control_word);
-  __asm__ ("%vstmxcsr %0" : "=m" (modep->__mxcsr));
+  modep->__mxcsr = stmxcsr_inline_asm ();
   return 0;
 }
index 30e3120596505173ffe061272a79af6bc29fcf4d..959f9c4a6c42b929f001335d6f5e13c16a889726 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __feholdexcept (fenv_t *envp)
@@ -25,14 +26,13 @@ __feholdexcept (fenv_t *envp)
 
   /* Store the environment.  Recall that fnstenv has a side effect of
      masking all exceptions.  Then clear all exceptions.  */
-  __asm__ ("fnstenv %0\n\t"
-          "%vstmxcsr %1\n\t"
-          "fnclex"
-          : "=m" (*envp), "=m" (envp->__mxcsr));
+  asm volatile ("fnstenv %0" : "=m" (*envp));
+  envp->__mxcsr = stmxcsr_inline_asm ();
+  asm volatile ("fnclex" : "=m" (*envp));
 
   /* Set the SSE MXCSR register.  */
   mxcsr = (envp->__mxcsr | 0x1f80) & ~0x3f;
-  __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   return 0;
 }
index a7b87efcde592944d2908343c1e9eaaa4cf831f6..d719186f21ff26402235bd43f7838b2d2cf3a976 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 #include <fpu_control.h>
 #include <assert.h>
 
@@ -35,8 +36,8 @@ __fesetenv (const fenv_t *envp)
      values which we do not want to come from the saved environment.
      Therefore, we get the current environment and replace the values
      we want to use from the environment specified by the parameter.  */
-  __asm__ ("fnstenv %0\n"
-          "%vstmxcsr %1" : "=m" (temp), "=m" (temp.__mxcsr));
+  asm volatile ("fnstenv %0" : "=m" (temp));
+  temp.__mxcsr = stmxcsr_inline_asm ();
 
   if (envp == FE_DFL_ENV)
     {
@@ -103,8 +104,8 @@ __fesetenv (const fenv_t *envp)
       temp.__mxcsr = envp->__mxcsr;
     }
 
-  __asm__ ("fldenv %0\n"
-          "%vldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));
+  asm volatile ("fldenv %0" : "=m" (temp));
+  ldmxcsr_inline_asm (temp.__mxcsr);
 
   /* Success.  */
   return 0;
index 91d5270f8e7ffca9207718ace6c16d7580ce5722..943d1136f04e6261f571c433519d3858527387f5 100644 (file)
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 fesetexcept (int excepts)
 {
-  unsigned int mxcsr;
-
-  __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr =stmxcsr_inline_asm ();
   mxcsr |= excepts & FE_ALL_EXCEPT;
-  __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   return 0;
 }
index 2b35d7e719d20baaa404621cc618ca3b08e762c3..5f393200ea25c06fddcf4dbb1effa58a41cb7277 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 #include <fpu_control.h>
 
 /* All exceptions, including the x86-specific "denormal operand"
@@ -27,8 +28,7 @@ int
 fesetmode (const femode_t *modep)
 {
   fpu_control_t cw;
-  unsigned int mxcsr;
-  __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+  unsigned int mxcsr = stmxcsr_inline_asm ();
   /* Preserve SSE exception flags but restore other state in
      MXCSR.  */
   mxcsr &= FE_ALL_EXCEPT_X86;
@@ -45,6 +45,6 @@ fesetmode (const femode_t *modep)
       mxcsr |= modep->__mxcsr & ~FE_ALL_EXCEPT_X86;
     }
   _FPU_SETCW (cw);
-  __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
   return 0;
 }
index 8a5f6c425c6a000965f9212322400e07064a1de7..6b8480c3f3deadbdd102ea1edcfa5440bd685f78 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __fesetround (int round)
@@ -36,10 +37,10 @@ __fesetround (int round)
 
   /* And now the MSCSR register for SSE, the precision is at different bit
      positions in the different units, we need to shift it 3 bits.  */
-  asm ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
   mxcsr &= ~ 0x6000;
   mxcsr |= round << 3;
-  asm ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   return 0;
 }
index 0e26b92af517f2db24eb07cf302efe7476b3cddf..514854352969eb15e2c1dbd99dcfe65082ecfd3c 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __feupdateenv (const fenv_t *envp)
@@ -25,7 +26,8 @@ __feupdateenv (const fenv_t *envp)
   unsigned int xtemp;
 
   /* Save current exceptions.  */
-  __asm__ ("fnstsw %0\n\t%vstmxcsr %1" : "=m" (temp), "=m" (xtemp));
+  asm volatile ("fnstsw %0" : "=m" (temp));
+  xtemp = stmxcsr_inline_asm ();
   temp = (temp | xtemp) & FE_ALL_EXCEPT;
 
   /* Install new environment.  */
index a7b500b6008c34520927d0eb4d72c84b08ea2e63..ec7324b829b13fc781431993f8fe581ee78b8d59 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 fegetexceptflag (fexcept_t *flagp, int excepts)
@@ -25,8 +26,8 @@ fegetexceptflag (fexcept_t *flagp, int excepts)
   unsigned int mxscr;
 
   /* Get the current exceptions for the x87 FPU and SSE unit.  */
-  __asm__ ("fnstsw %0\n"
-          "%vstmxcsr %1" : "=m" (temp), "=m" (mxscr));
+  __asm__ ("fnstsw %0" : "=m" (temp));
+  mxscr = stmxcsr_inline_asm ();
 
   *flagp = (temp | mxscr) & FE_ALL_EXCEPT & excepts;
 
index dae0c3bc3110cb55e0b3a804151c5ee77dc7550c..f0a1d8282b5b40fd0e16b29b488b4e1d0aa731b2 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 #include <math.h>
 
 int
@@ -29,23 +30,12 @@ __feraiseexcept (int excepts)
 
   /* First: invalid exception.  */
   if ((FE_INVALID & excepts) != 0)
-    {
-      /* One example of an invalid operation is 0.0 / 0.0.  */
-      float f = 0.0;
-
-      __asm__ __volatile__ ("%vdivss %0, %d0 " : "+x" (f));
-      (void) &f;
-    }
+    /* One example of an invalid operation is 0.0 / 0.0.  */
+    divss_inline_asm (0.0f, 0.0f);
 
   /* Next: division by zero.  */
   if ((FE_DIVBYZERO & excepts) != 0)
-    {
-      float f = 1.0;
-      float g = 0.0;
-
-      __asm__ __volatile__ ("%vdivss %1, %d0" : "+x" (f) : "x" (g));
-      (void) &f;
-    }
+    divss_inline_asm (1.0f, 0.0f);
 
   /* Next: overflow.  */
   if ((FE_OVERFLOW & excepts) != 0)
index 34ea24c0613fadefc226eceffbdfd6c049f8392b..aa744878149e4544975a4b4cec3b506adcd59c88 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 #include <math.h>
 
 int
@@ -44,13 +45,13 @@ fesetexceptflag (const fexcept_t *flagp, int excepts)
   __asm__ ("fldenv %0" : : "m" (temp));
 
   /* And now similarly for SSE.  */
-  __asm__ ("%vstmxcsr %0" : "=m" (mxcsr));
+  mxcsr = stmxcsr_inline_asm ();
 
   /* Clear or set relevant flags.  */
   mxcsr ^= (mxcsr ^ *flagp) & excepts;
 
   /* Put the new data in effect.  */
-  __asm__ ("%vldmxcsr %0" : : "m" (mxcsr));
+  ldmxcsr_inline_asm (mxcsr);
 
   /* Success.  */
   return 0;
index 7e0a097696c3dcb02085eea175f106559c5f0b7f..bf35fd819d39b5d1b415a39fd3aa74b1bd2e01c9 100644 (file)
@@ -17,6 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
+#include <math-inline-asm.h>
 
 int
 __fetestexcept (int excepts)
@@ -25,8 +26,8 @@ __fetestexcept (int excepts)
   unsigned int mxscr;
 
   /* Get current exceptions.  */
-  __asm__ ("fnstsw %0\n"
-          "%vstmxcsr %1" : "=m" (temp), "=m" (mxscr));
+  asm volatile ("fnstsw %0" : "=m" (temp));
+  mxscr = stmxcsr_inline_asm ();
 
   return (temp | mxscr) & excepts & FE_ALL_EXCEPT;
 }