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.
This commit is contained in:
parent
bc95e478fe
commit
d3a1459cd4
6 changed files with 67 additions and 50 deletions
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue