fpu-387.h (_FPU_MASK_ALL): New.
authorUros Bizjak <ubizjak@gmail.com>
Thu, 20 Jun 2013 17:08:51 +0000 (19:08 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 20 Jun 2013 17:08:51 +0000 (19:08 +0200)
* config/fpu-387.h (_FPU_MASK_ALL): New.
(_FPU_EX_ALL): Ditto.
(set_fpu): Use fstcw to store x87 FPU control word. Use fnclex to
clear stalled exception flags.  Correctly clear stalled SSE
exception flags.  Simplify code.
(get_fpu_except_flags): Simplify code.

From-SVN: r200255

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

index 40f98d205998cb4872f3f7b3150a45767c1688be..5ea24864adcb3a163eadeef7ba8ad5cf5692ed83 100644 (file)
@@ -1,9 +1,16 @@
+2013-06-20  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/fpu-387.h (_FPU_MASK_ALL): New.
+       (set_fpu): Use fstcw to store x87 FPU control word. Use fnclex to
+       clear stalled exception flags.  Correctly clear stalled SSE
+       exception flags.  Simplify code.
+
 2013-06-20  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/57633
        * io/list_read.c (next_char, eat_separator): Don't set EOL for \r.
 
-2012-06-19  Uros Bizjak  <ubizjak@gmail.com>
+2013-06-19  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/fpu-387.h: Use __asm__ and __volatile__ consistently.
        (get_fpu_except_flags): Initialize result.
index 6c42ab845248c7cc4e175b6359c777d588a16b27..09709b2ea245f23102b562919394e6b184598aa9 100644 (file)
@@ -95,24 +95,28 @@ has_sse (void)
 #define _FPU_MASK_OM  0x08
 #define _FPU_MASK_UM  0x10
 #define _FPU_MASK_PM  0x20
+#define _FPU_MASK_ALL 0x3f
+
+#define _FPU_EX_ALL   0x3f
 
 void set_fpu (void)
 {
+  int excepts = 0;
   unsigned short cw;
 
-  __asm__ __volatile__ ("fnstcw\t%0" : "=m" (cw));
+  __asm__ __volatile__ ("fstcw\t%0" : "=m" (cw));
 
-  cw |= (_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM
-        | _FPU_MASK_UM | _FPU_MASK_PM);
+  if (options.fpe & GFC_FPE_INVALID) excepts |= _FPU_MASK_IM;
+  if (options.fpe & GFC_FPE_DENORMAL) excepts |= _FPU_MASK_DM;
+  if (options.fpe & GFC_FPE_ZERO) excepts |= _FPU_MASK_ZM;
+  if (options.fpe & GFC_FPE_OVERFLOW) excepts |= _FPU_MASK_OM;
+  if (options.fpe & GFC_FPE_UNDERFLOW) excepts |= _FPU_MASK_UM;
+  if (options.fpe & GFC_FPE_INEXACT) excepts |= _FPU_MASK_PM;
 
-  if (options.fpe & GFC_FPE_INVALID) cw &= ~_FPU_MASK_IM;
-  if (options.fpe & GFC_FPE_DENORMAL) cw &= ~_FPU_MASK_DM;
-  if (options.fpe & GFC_FPE_ZERO) cw &= ~_FPU_MASK_ZM;
-  if (options.fpe & GFC_FPE_OVERFLOW) cw &= ~_FPU_MASK_OM;
-  if (options.fpe & GFC_FPE_UNDERFLOW) cw &= ~_FPU_MASK_UM;
-  if (options.fpe & GFC_FPE_INEXACT) cw &= ~_FPU_MASK_PM;
+  cw |= _FPU_MASK_ALL;
+  cw &= ~excepts;
 
-  __asm__ __volatile__ ("fldcw\t%0" : : "m" (cw));
+  __asm__ __volatile__ ("fnclex\n\tfldcw\t%0" : : "m" (cw));
 
   if (has_sse())
     {
@@ -120,45 +124,43 @@ void set_fpu (void)
 
       __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (cw_sse));
 
-      cw_sse &= 0xffff0000;
-      cw_sse |= (_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM
-                | _FPU_MASK_UM | _FPU_MASK_PM ) << 7;
+      /* The SSE exception masks are shifted by 7 bits.  */
+      cw_sse |= _FPU_MASK_ALL << 7;
+      cw_sse &= ~(excepts << 7);
 
-      if (options.fpe & GFC_FPE_INVALID) cw_sse &= ~(_FPU_MASK_IM << 7);
-      if (options.fpe & GFC_FPE_DENORMAL) cw_sse &= ~(_FPU_MASK_DM << 7);
-      if (options.fpe & GFC_FPE_ZERO) cw_sse &= ~(_FPU_MASK_ZM << 7);
-      if (options.fpe & GFC_FPE_OVERFLOW) cw_sse &= ~(_FPU_MASK_OM << 7);
-      if (options.fpe & GFC_FPE_UNDERFLOW) cw_sse &= ~(_FPU_MASK_UM << 7);
-      if (options.fpe & GFC_FPE_INEXACT) cw_sse &= ~(_FPU_MASK_PM << 7);
+      /* Clear stalled exception flags.  */
+      cw_sse &= ~_FPU_EX_ALL;
 
       __asm__ __volatile__ ("%vldmxcsr\t%0" : : "m" (cw_sse));
     }
 }
 
-
 int
 get_fpu_except_flags (void)
 {
-  int result = 0;
   unsigned short cw;
+  int excepts;
+  int result = 0;
 
   __asm__ __volatile__ ("fnstsw\t%0" : "=a" (cw));
+  excepts = cw;
 
   if (has_sse())
     {
       unsigned int cw_sse;
 
       __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (cw_sse));
-
-      cw |= cw_sse;
+      excepts |= cw_sse;
     }
 
-  if (cw & _FPU_MASK_IM) result |= GFC_FPE_INVALID;
-  if (cw & _FPU_MASK_DM) result |= GFC_FPE_DENORMAL;
-  if (cw & _FPU_MASK_ZM) result |= GFC_FPE_ZERO;
-  if (cw & _FPU_MASK_OM) result |= GFC_FPE_OVERFLOW;
-  if (cw & _FPU_MASK_UM) result |= GFC_FPE_UNDERFLOW;
-  if (cw & _FPU_MASK_PM) result |= GFC_FPE_INEXACT;
+  excepts &= _FPU_EX_ALL;
+
+  if (excepts & _FPU_MASK_IM) result |= GFC_FPE_INVALID;
+  if (excepts & _FPU_MASK_DM) result |= GFC_FPE_DENORMAL;
+  if (excepts & _FPU_MASK_ZM) result |= GFC_FPE_ZERO;
+  if (excepts & _FPU_MASK_OM) result |= GFC_FPE_OVERFLOW;
+  if (excepts & _FPU_MASK_UM) result |= GFC_FPE_UNDERFLOW;
+  if (excepts & _FPU_MASK_PM) result |= GFC_FPE_INEXACT;
 
   return result;
 }