From a10f6e24e9d333d430226b887ae561654a1ac7d6 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Wed, 1 Jun 2011 22:24:36 -0700 Subject: [PATCH] Implement BORKED_FENV for i386. --- src/microcode/achost.ac | 11 +++++++++++ src/microcode/cmpauxmd/x86-64.m4 | 12 ++++++------ src/microcode/cmpintmd/i386.c | 2 +- src/microcode/cmpintmd/i386.h | 2 +- src/microcode/cmpintmd/x86-fenv.h | 17 +++++++++++++++++ src/microcode/configure.ac | 9 +++++++-- src/microcode/floenv.h | 2 +- 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/microcode/achost.ac b/src/microcode/achost.ac index e4fc6b517..1bdc2a1f3 100644 --- a/src/microcode/achost.ac +++ b/src/microcode/achost.ac @@ -115,6 +115,17 @@ linux-gnu) M4_FLAGS="${M4_FLAGS} -P __linux__,1" DO_GCC_TESTS=yes GNU_LD=yes + # In Ubuntu 11.04 on i386 eglibc-2.13's fesetenv(FE_DFL_ENV) does + # not mask all FPEs. Its feclear/disableexcept() functions are + # not effective either. A callout to pango_layout_get_pixel_ + # extents can use these and still SIGFPE Underflow. However the + # emulation in cmpintmd/x86-fenv.c IS effective. Defining + # BORKED_FENV causes libc's fenv.h to be ignored and x86-fenv.c to + # be included. Not all linux-gnu/i386 hosts need this, but the + # emulation should work on all of them. + if test "x${mit_scheme_native_code}" = "xi386"; then + BORKED_FENV=yes + fi ;; freebsd*) M4_FLAGS="${M4_FLAGS} -P SUPPRESS_LEADING_UNDERSCORE,1" diff --git a/src/microcode/cmpauxmd/x86-64.m4 b/src/microcode/cmpauxmd/x86-64.m4 index 2ae38405c..864f416e1 100644 --- a/src/microcode/cmpauxmd/x86-64.m4 +++ b/src/microcode/cmpauxmd/x86-64.m4 @@ -990,22 +990,22 @@ define_c_label(x87_trap_exceptions) define_c_label(x87_read_control_word) enter IMM(4),IMM(0) - fnstcw IND(REG(esp)) - OP(mov,w) TW(IND(REG(esp)),REG(ax)) + fnstcw IND(REG(rsp)) + OP(mov,w) TW(IND(REG(rsp)),REG(ax)) leave ret define_c_label(x87_write_control_word) enter IMM(4),IMM(0) OP(mov,w) TW(REG(di),IND(REG(rsp))) - fldcw IND(REG(esp)) + fldcw IND(REG(rsp)) leave ret define_c_label(x87_read_status_word) enter IMM(4),IMM(0) - fnstsw IND(REG(esp)) - OP(mov,w) TW(IND(REG(esp)),REG(ax)) + fnstsw IND(REG(rsp)) + OP(mov,w) TW(IND(REG(rsp)),REG(ax)) leave ret @@ -1013,7 +1013,7 @@ define_c_label(x87_read_environment) fnstenv IND(REG(rdi)) # fnstenv masks all exceptions (go figure), so we must load # the control word back in order to undo that. - fldcw IND(REG(eax)) + fldcw IND(REG(rdi)) ret define_c_label(x87_write_environment) diff --git a/src/microcode/cmpintmd/i386.c b/src/microcode/cmpintmd/i386.c index 0d66de11b..152e93e63 100644 --- a/src/microcode/cmpintmd/i386.c +++ b/src/microcode/cmpintmd/i386.c @@ -391,7 +391,7 @@ i386_reset_hook (void) #endif /* _MACH_UNIX */ } -#ifndef HAVE_FENV_H +#if !defined(HAVE_FENV_H) || defined(BORKED_FENV) extern int i387_presence; extern int sse_presence; # define x87_p i387_presence diff --git a/src/microcode/cmpintmd/i386.h b/src/microcode/cmpintmd/i386.h index f07d5c240..db76f50ab 100644 --- a/src/microcode/cmpintmd/i386.h +++ b/src/microcode/cmpintmd/i386.h @@ -335,7 +335,7 @@ extern void i386_reset_hook (void); extern int ia32_cpuid_needed; -#ifndef HAVE_FENV_H +#if !defined(HAVE_FENV_H) || defined(BORKED_FENV) # define CMPINTMD_EMULATES_FENV # include "cmpintmd/x86-fenv.h" #endif diff --git a/src/microcode/cmpintmd/x86-fenv.h b/src/microcode/cmpintmd/x86-fenv.h index dc5ddcd2e..a65f40ee7 100644 --- a/src/microcode/cmpintmd/x86-fenv.h +++ b/src/microcode/cmpintmd/x86-fenv.h @@ -26,6 +26,23 @@ USA. /* C99 emulation for x86 (shared between i386 and amd64) */ +#ifdef BORKED_FENV +# undef HAVE_FEGETROUND +# undef HAVE_FESETROUND +# undef HAVE_FECLEAREXCEPT +# undef HAVE_FEGETEXCEPTFLAG +# undef HAVE_FERAISEEXCEPT +# undef HAVE_FESETEXCEPTFLAG +# undef HAVE_FETESTEXCEPT +# undef HAVE_FEDISABLEEXCEPT +# undef HAVE_FEENABLEEXCEPT +# undef HAVE_FEGETEXCEPT +# undef HAVE_FEGETENV +# undef HAVE_FESETENV +# undef HAVE_FEHOLDEXCEPT +# undef HAVE_FEUPDATEENV +#endif + #define HAVE_FENV_T #define HAVE_FEXCEPT_T diff --git a/src/microcode/configure.ac b/src/microcode/configure.ac index 642cf04a0..0a9b68845 100644 --- a/src/microcode/configure.ac +++ b/src/microcode/configure.ac @@ -369,8 +369,13 @@ define([SCM_INC_FENV], ]) if test "x$ac_cv_header_fenv_h" = "xyes"; then - AC_CHECK_TYPES([fenv_t], [], [], [SCM_INC_FENV]) - AC_CHECK_TYPES([fexcept_t], [], [], [SCM_INC_FENV]) + if test "x$BORKED_FENV" = "xyes"; then + AC_DEFINE([BORKED_FENV], [1], + [Define to 1 if your fenv implementation is broken.]) + else + AC_CHECK_TYPES([fenv_t], [], [], [SCM_INC_FENV]) + AC_CHECK_TYPES([fexcept_t], [], [], [SCM_INC_FENV]) + fi fi AC_CHECK_SIZEOF([time_t]) diff --git a/src/microcode/floenv.h b/src/microcode/floenv.h index 6ab58ac79..0ff82ae40 100644 --- a/src/microcode/floenv.h +++ b/src/microcode/floenv.h @@ -32,7 +32,7 @@ USA. #include "cmpintmd.h" -#if (defined (HAVE_FENV_H)) +#if (defined (HAVE_FENV_H) && !defined (BORKED_FENV)) # include # ifdef HAVE_FENV_T # define scheme_fenv_t fenv_t -- 2.25.1