Emulate C99 fenv.h on i386 through the i387 control word.
authorTaylor R Campbell <campbell@mumble.net>
Fri, 6 Aug 2010 01:17:07 +0000 (01:17 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Fri, 6 Aug 2010 01:17:07 +0000 (01:17 +0000)
src/microcode/cmpauxmd/i386.m4
src/microcode/cmpintmd/i386.h

index 6572857581e1d3e805028c0f67f95c7b01d59415..a69527e183f2c237898c7fa50b7ba731e4751a89 100644 (file)
@@ -1207,6 +1207,30 @@ asm_fixnum_rsh_overflow_negative:
        OP(mov,l)       TW(IMM_DETAGGED_FIXNUM_MINUS_ONE,REG(eax))
        ret
 \f
+define_c_label(i387_read_fp_control_word)
+IF387(`        OP(cmp,l)       TW(IMM(0),ABS(EVR(i387_presence)))
+       je              i387_read_fp_control_word_lose
+       enter           IMM(4),IMM(0)
+       fnstcw          IND(REG(esp))
+       OP(mov,w)       TW(IND(REG(esp)),REG(ax))
+       leave
+       ret
+')
+
+i387_read_fp_control_word_lose:
+       OP(xor,l)       TW(REG(eax),REG(eax))
+       ret
+
+define_c_label(i387_write_fp_control_word)
+IF387(`        OP(cmp,l)       TW(IMM(0),ABS(EVR(i387_presence)))
+       je              i387_write_fp_control_word_lose
+       fldcw           LOF(4,REG(esp))
+       ret
+')
+
+i387_write_fp_control_word_lose:
+       ret
+\f
 IFDASM(`end')
 
 # Mark the stack nonexecutable.  If we ever put code (e.g.,
index 5044e2970c22928c34a5d75f9b78bcd75621f57d..e39dbc8a75e2233faed116601c7a0b313708c415 100644 (file)
@@ -332,7 +332,40 @@ extern insn_t * read_compiled_closure_target (insn_t *, reloc_ref_t *);
 extern void start_operator_relocation (SCHEME_OBJECT *, reloc_ref_t *);
 extern insn_t * read_uuo_target (SCHEME_OBJECT *, reloc_ref_t *);
 extern void i386_reset_hook (void);
+extern int i387_read_fp_control_word (void);
+extern void i387_write_fp_control_word (int);
 
 extern int ia32_cpuid_needed;
 
+#ifndef HAVE_FENV_H
+
+#  define FE_TONEAREST 0
+#  define FE_DOWNWARD 1
+#  define FE_UPWARD 2
+#  define FE_TOWARDZERO 3
+
+#  define HAVE_FEGETROUND
+#  define HAVE_FESETROUND
+
+static inline int
+fegetround (void)
+{
+  return (3 & ((i387_read_fp_control_word ()) >> 10));
+}
+
+static inline int
+fesetround (int mode)
+{
+  switch (mode)
+    {
+    case 0: case 1: case 2: case 3: break;
+    default: return (1);
+    }
+  i387_write_fp_control_word
+    ((mode << 10) | (0xf3ff & (i387_read_fp_control_word ())));
+  return (0);
+}
+
+#endif /* HAVE_FENV_H */
+
 #endif /* !SCM_CMPINTMD_H_INCLUDED */