diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2020-05-06 23:01:32 +0200 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2020-05-06 23:01:32 +0200 |
commit | d3a1459cd4f2d4997fb53e34ddef72e91a7855c1 (patch) | |
tree | 7a23bc1474d3f382a9b8e6044e53e5ee7b335347 | |
parent | bc95e478febd35e0d1fb13c1833d2383ad0e7d18 (diff) | |
download | gcc-d3a1459cd4f2d4997fb53e34ddef72e91a7855c1.zip gcc-d3a1459cd4f2d4997fb53e34ddef72e91a7855c1.tar.gz gcc-d3a1459cd4f2d4997fb53e34ddef72e91a7855c1.tar.bz2 |
i386: Use generic division to generate INEXACT exception
Introduce math_force_eval_div to use generic division to generate
INEXACT as well as INVALID and DIVZERO exceptions.
libgcc/ChangeLog:
* config/i386/sfp-exceptions.c (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(__sfp_handle_exceptions): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.
libatomic/ChangeLog:
* config/x86/fenv.c (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(__atomic_deraiseexcept): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.
libgfortran/ChangeLog:
* config/fpu-387.h (__math_force_eval): Remove.
(__math_force_eval_div): New define.
(local_feraiseexcept): Use __math_force_eval_div to use
generic division to generate INVALID, DIVZERO and INEXACT
exceptions.
(struct fenv): Define named struct instead of typedef.
-rw-r--r-- | libatomic/ChangeLog | 10 | ||||
-rw-r--r-- | libatomic/config/x86/fenv.c | 22 | ||||
-rw-r--r-- | libgcc/ChangeLog | 10 | ||||
-rw-r--r-- | libgcc/config/i386/sfp-exceptions.c | 22 | ||||
-rw-r--r-- | libgfortran/ChangeLog | 11 | ||||
-rw-r--r-- | libgfortran/config/fpu-387.h | 42 |
6 files changed, 67 insertions, 50 deletions
diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog index 48c115d..e8ab8ec 100644 --- a/libatomic/ChangeLog +++ b/libatomic/ChangeLog @@ -1,7 +1,15 @@ +2020-05-06 Uroš Bizjak <ubizjak@gmail.com> + + * config/x86/fenv.c (__math_force_eval): Remove. + (__math_force_eval_div): New define. + (__atomic_deraiseexcept): Use __math_force_eval_div to use + generic division to generate INVALID, DIVZERO and INEXACT + exceptions. + 2020-05-01 Uroš Bizjak <ubizjak@gmail.com> * config/x86/fenv.c (__math_force_eval): New define. - (__atomic_feraiseexcept): Use __math_force_eval to evaluete + (__atomic_feraiseexcept): Use __math_force_eval to evaluate generic division to generate INVALID and DIVZERO exceptions. 2020-04-19 Uroš Bizjak <ubizjak@gmail.com> diff --git a/libatomic/config/x86/fenv.c b/libatomic/config/x86/fenv.c index d972a99..88622c6 100644 --- a/libatomic/config/x86/fenv.c +++ b/libatomic/config/x86/fenv.c @@ -48,9 +48,11 @@ struct fenv }; #ifdef __SSE_MATH__ -# define __math_force_eval(x) asm volatile ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0) #else -# define __math_force_eval(x) asm volatile ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0) #endif /* Raise the supported floating-point exceptions from EXCEPTS. Other @@ -59,14 +61,15 @@ struct fenv void __atomic_feraiseexcept (int excepts) { + struct fenv temp; + if (excepts & FE_INVALID) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (excepts & FE_DENORM) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_DENORM; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -75,11 +78,10 @@ __atomic_feraiseexcept (int excepts) if (excepts & FE_DIVBYZERO) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (excepts & FE_OVERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_OVERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -87,7 +89,6 @@ __atomic_feraiseexcept (int excepts) } if (excepts & FE_UNDERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_UNDERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -96,11 +97,6 @@ __atomic_feraiseexcept (int excepts) if (excepts & FE_INEXACT) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 8e63e43..33e8929 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2020-05-06 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/sfp-exceptions.c (__math_force_eval): Remove. + (__math_force_eval_div): New define. + (__sfp_handle_exceptions): Use __math_force_eval_div to use + generic division to generate INVALID, DIVZERO and INEXACT + exceptions. + 2020-05-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/lse-init.c (init_have_lse_atomics): Use __getauxval @@ -54,7 +62,7 @@ 2020-05-01 Uroš Bizjak <ubizjak@gmail.com> * config/i386/sfp-exceptions.c (__math_force_eval): New define. - (__sfp_handle_exceptions): Use __math_force_eval to evaluete + (__sfp_handle_exceptions): Use __math_force_eval to evaluate generic division to generate INVALID and DIVZERO exceptions. 2020-04-27 Sebastian Huber <sebastian.huber@embedded-brains.de> diff --git a/libgcc/config/i386/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c index 4b3a7a0..72cb0f4 100644 --- a/libgcc/config/i386/sfp-exceptions.c +++ b/libgcc/config/i386/sfp-exceptions.c @@ -42,22 +42,25 @@ struct fenv }; #ifdef __SSE_MATH__ -# define __math_force_eval(x) asm volatile ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0) #else -# define __math_force_eval(x) asm volatile ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0) #endif void __sfp_handle_exceptions (int _fex) { + struct fenv temp; + if (_fex & FP_EX_INVALID) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (_fex & FP_EX_DENORM) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_DENORM; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -66,11 +69,10 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_DIVZERO) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (_fex & FP_EX_OVERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_OVERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -78,7 +80,6 @@ __sfp_handle_exceptions (int _fex) } if (_fex & FP_EX_UNDERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_UNDERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -87,12 +88,7 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_INEXACT) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } #endif diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index eecfb90..94c7e0f 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,7 +1,16 @@ +2020-05-06 Uroš Bizjak <ubizjak@gmail.com> + + * config/fpu-387.h (__math_force_eval): Remove. + (__math_force_eval_div): New define. + (local_feraiseexcept): Use __math_force_eval_div to use + generic division to generate INVALID, DIVZERO and INEXACT + exceptions. + (struct fenv): Define named struct instead of typedef. + 2020-05-01 Uroš Bizjak <ubizjak@gmail.com> * config/fpu-387.h (__math_force_eval): New define. - (local_feraiseexcept): Use __math_force_eval to evaluete + (local_feraiseexcept): Use __math_force_eval to evaluate generic division to generate INVALID and DIVZERO exceptions. 2020-04-22 Fritz Reese <foreese@gcc.gnu.org> diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h index 41b82bc..8b5e758 100644 --- a/libgfortran/config/fpu-387.h +++ b/libgfortran/config/fpu-387.h @@ -69,7 +69,7 @@ has_sse (void) /* This structure corresponds to the layout of the block written by FSTENV. */ -typedef struct +struct fenv { unsigned short int __control_word; unsigned short int __unused1; @@ -79,22 +79,28 @@ typedef struct unsigned short int __unused3; unsigned int __eip; unsigned short int __cs_selector; - unsigned short int __opcode; + unsigned int __opcode:11; + unsigned int __unused4:5; unsigned int __data_offset; unsigned short int __data_selector; unsigned short int __unused5; unsigned int __mxcsr; -} -my_fenv_t; +}; /* Check we can actually store the FPU state in the allocated size. */ -_Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, +_Static_assert (sizeof(struct fenv) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, "GFC_FPE_STATE_BUFFER_SIZE is too small"); #ifdef __SSE_MATH__ -# define __math_force_eval(x) __asm__ __volatile__ ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { \ + __asm__ ("" : "+x" (x)); __asm__ __volatile__ ("" : : "x" (x / y)); \ + } while (0) #else -# define __math_force_eval(x) __asm__ __volatile__ ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { \ + __asm__ ("" : "+t" (x)); __asm__ __volatile__ ("" : : "f" (x / y)); \ + } while (0) #endif /* Raise the supported floating-point exceptions from EXCEPTS. Other @@ -104,14 +110,15 @@ _Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, static void local_feraiseexcept (int excepts) { + struct fenv temp; + if (excepts & _FPU_MASK_IM) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (excepts & _FPU_MASK_DM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_DM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -120,11 +127,10 @@ local_feraiseexcept (int excepts) if (excepts & _FPU_MASK_ZM) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (excepts & _FPU_MASK_OM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_OM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -132,7 +138,6 @@ local_feraiseexcept (int excepts) } if (excepts & _FPU_MASK_UM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_UM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -141,12 +146,7 @@ local_feraiseexcept (int excepts) if (excepts & _FPU_MASK_PM) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - __asm__ __volatile__ ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - __asm__ __volatile__ ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } @@ -272,7 +272,7 @@ get_fpu_except_flags (void) void set_fpu_except_flags (int set, int clear) { - my_fenv_t temp; + struct fenv temp; int exc_set = 0, exc_clr = 0; /* Translate from GFC_PE_* values to _FPU_MASK_* values. */ @@ -426,7 +426,7 @@ support_fpu_rounding_mode (int mode __attribute__((unused))) void get_fpu_state (void *state) { - my_fenv_t *envp = state; + struct fenv *envp = state; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (*envp)); @@ -441,7 +441,7 @@ get_fpu_state (void *state) void set_fpu_state (void *state) { - my_fenv_t *envp = state; + struct fenv *envp = state; /* glibc sources (sysdeps/x86_64/fpu/fesetenv.c) do something more complex than this, but I think it suffices in our case. */ |