diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2013-06-20 19:08:51 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2013-06-20 19:08:51 +0200 |
commit | 86c2f4b76123e283b387cf82a3fb0c2a293e982d (patch) | |
tree | 3d8b9d4d6942766e89168518129d63e78ce8f16e /libgfortran | |
parent | 1ef3b58e572bc76797b69159117ba8ab6da13391 (diff) | |
download | gcc-86c2f4b76123e283b387cf82a3fb0c2a293e982d.tar.gz |
fpu-387.h (_FPU_MASK_ALL): New.
* 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
Diffstat (limited to 'libgfortran')
-rw-r--r-- | libgfortran/ChangeLog | 9 | ||||
-rw-r--r-- | libgfortran/config/fpu-387.h | 60 |
2 files changed, 39 insertions, 30 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 40f98d20599..5ea24864adc 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -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. diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h index 6c42ab84524..09709b2ea24 100644 --- a/libgfortran/config/fpu-387.h +++ b/libgfortran/config/fpu-387.h @@ -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; } |