fpu-387.h (get_fpu_rounding_mode): Read rounding mode from SSE mxcsr register on...
authorUros Bizjak <uros@gcc.gnu.org>
Tue, 23 Jul 2013 09:45:30 +0000 (11:45 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Tue, 23 Jul 2013 09:45:30 +0000 (11:45 +0200)
* config/fpu-387.h (get_fpu_rounding_mode): Read rounding mode
from SSE mxcsr register on x86_64.

From-SVN: r201161

libgfortran/ChangeLog
libgfortran/config/fpu-387.h

index 0a035ebb23856f6ca726729820ae2971c437b465..940d41444a5b1ff656bf958b78ebf924d49ae4f9 100644 (file)
@@ -1,4 +1,9 @@
-2013-07-21   Ondřej Bílka  <neleai@seznam.cz>
+2013-07-23  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/fpu-387.h (get_fpu_rounding_mode): Read rounding mode
+       from SSE mxcsr register on x86_64.
+
+2013-07-21  Ondřej Bílka  <neleai@seznam.cz>
 
        * io/transfer.c: Fix comment typos.
 
index 62f1e935b5351dec2d6f359d440c7f607d38929f..b35c315445cf12d0c5104596d64e507e7d9b9c8b 100644 (file)
@@ -102,11 +102,11 @@ has_sse (void)
 /* i387 rounding modes.  */
 
 #define _FPU_RC_NEAREST 0x0
-#define _FPU_RC_DOWN    0x400
-#define _FPU_RC_UP      0x800
-#define _FPU_RC_ZERO    0xc00
+#define _FPU_RC_DOWN    0x1
+#define _FPU_RC_UP      0x2
+#define _FPU_RC_ZERO    0x3
 
-#define _FPU_RC_MASK    0xc00
+#define _FPU_RC_MASK    0x3
 
 
 void
@@ -202,8 +202,9 @@ set_fpu_rounding_mode (int round)
 
   __asm__ __volatile__ ("fnstcw\t%0" : "=m" (cw));
 
-  cw &= ~_FPU_RC_MASK;
-  cw |= round_mode;
+  /* The x87 round control bits are shifted by 10 bits.  */
+  cw &= ~(_FPU_RC_MASK << 10);
+  cw |= round_mode << 10;
 
   __asm__ __volatile__ ("fldcw\t%0" : : "m" (cw));
 
@@ -213,9 +214,9 @@ set_fpu_rounding_mode (int round)
 
       __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (cw_sse));
 
-      /* The SSE round control bits are shifted by 3 bits.  */
-      cw_sse &= ~(_FPU_RC_MASK << 3);
-      cw_sse |= round_mode << 3;
+      /* The SSE round control bits are shifted by 13 bits.  */
+      cw_sse &= ~(_FPU_RC_MASK << 13);
+      cw_sse |= round_mode << 13;
 
       __asm__ __volatile__ ("%vldmxcsr\t%0" : : "m" (cw_sse));
     }
@@ -224,13 +225,27 @@ set_fpu_rounding_mode (int round)
 int
 get_fpu_rounding_mode (void)
 {
+  int round_mode;
+
+#ifdef __x86_64__
+  unsigned int cw;
+
+  __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (cw));
+
+  /* The SSE round control bits are shifted by 13 bits.  */
+  round_mode = cw >> 13;
+#else
   unsigned short cw;
 
   __asm__ __volatile__ ("fnstcw\t%0" : "=m" (cw));
 
-  cw &= _FPU_RC_MASK;
+  /* The x87 round control bits are shifted by 10 bits.  */
+  round_mode = cw >> 10;
+#endif
+
+  round_mode &= _FPU_RC_MASK;
 
-  switch (cw)
+  switch (round_mode)
     {
     case _FPU_RC_NEAREST:
       return GFC_FPE_TONEAREST;