Implement BORKED_FENV for i386.
authorMatt Birkholz <matt@birkholz.chandler.az.us>
Thu, 2 Jun 2011 05:24:36 +0000 (22:24 -0700)
committerMatt Birkholz <matt@birkholz.chandler.az.us>
Thu, 2 Jun 2011 05:24:36 +0000 (22:24 -0700)
src/microcode/achost.ac
src/microcode/cmpauxmd/x86-64.m4
src/microcode/cmpintmd/i386.c
src/microcode/cmpintmd/i386.h
src/microcode/cmpintmd/x86-fenv.h
src/microcode/configure.ac
src/microcode/floenv.h

index e4fc6b51726430e2917aee39f00229f252d72b0d..1bdc2a1f30571574a21a3dcb7b0993b7dcb2e779 100644 (file)
@@ -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"
index 2ae38405c15195d1ffa17ea92eab58ecedb3fb9d..864f416e13e3b0c42dc2bd5b403996c3cabecc9b 100644 (file)
@@ -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)
index 0d66de11b758a503901e17defc8b3c37a483df8b..152e93e639a8807fd31638be6662e8d8341daf55 100644 (file)
@@ -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
index f07d5c2408f9b81a3351249355c5edc4c895b519..db76f50abe41f6e7a5daaa55bdfba79e87af5f30 100644 (file)
@@ -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
index dc5ddcd2e667460bc8158615e8da4f5e767ce6a8..a65f40ee79457b1f2898046aa356b63d57f474fc 100644 (file)
@@ -26,6 +26,23 @@ USA.
 
 /* C99 <fenv.h> 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
 
index 642cf04a08db2628e56b5d1124d014c41bd5d025..0a9b688450498bd9a644098ace5a5d6b2ea53eb7 100644 (file)
@@ -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])
index 6ab58ac79c998039ce084d8293481df67fb2a58b..0ff82ae40cf6b2d88664ca4783dc006576cd67dd 100644 (file)
@@ -32,7 +32,7 @@ USA.
 
 #include "cmpintmd.h"
 
-#if (defined (HAVE_FENV_H))
+#if (defined (HAVE_FENV_H) && !defined (BORKED_FENV))
 #  include <fenv.h>
 #  ifdef HAVE_FENV_T
 #    define scheme_fenv_t fenv_t