From: Taylor R Campbell Date: Fri, 6 Aug 2010 01:17:07 +0000 (+0000) Subject: Emulate C99 fenv.h on i386 through the i387 control word. X-Git-Tag: 20101212-Gtk~119 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=c1d4fe13baffe0c5a1059a995c8f39faf9649164;p=mit-scheme.git Emulate C99 fenv.h on i386 through the i387 control word. --- diff --git a/src/microcode/cmpauxmd/i386.m4 b/src/microcode/cmpauxmd/i386.m4 index 657285758..a69527e18 100644 --- a/src/microcode/cmpauxmd/i386.m4 +++ b/src/microcode/cmpauxmd/i386.m4 @@ -1207,6 +1207,30 @@ asm_fixnum_rsh_overflow_negative: OP(mov,l) TW(IMM_DETAGGED_FIXNUM_MINUS_ONE,REG(eax)) ret +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 + IFDASM(`end') # Mark the stack nonexecutable. If we ever put code (e.g., diff --git a/src/microcode/cmpintmd/i386.h b/src/microcode/cmpintmd/i386.h index 5044e2970..e39dbc8a7 100644 --- a/src/microcode/cmpintmd/i386.h +++ b/src/microcode/cmpintmd/i386.h @@ -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 */