]> gitweb.factorcode.org Git - factor.git/commitdiff
save the FP status out of the signal context and use it as part of the fp trap factor...
authorJoe Groff <arcata@gmail.com>
Mon, 14 Sep 2009 04:37:28 +0000 (23:37 -0500)
committerJoe Groff <arcata@gmail.com>
Mon, 14 Sep 2009 04:39:12 +0000 (23:39 -0500)
20 files changed:
basis/math/floats/env/ppc/ppc.factor
vm/cpu-ppc.hpp
vm/cpu-x86.hpp
vm/errors.cpp
vm/errors.hpp
vm/layouts.hpp
vm/mach_signal.cpp
vm/os-freebsd-x86.32.hpp
vm/os-freebsd-x86.64.hpp
vm/os-linux-x86.32.hpp
vm/os-linux-x86.64.hpp
vm/os-macosx-ppc.hpp
vm/os-macosx-x86.32.hpp
vm/os-macosx-x86.64.hpp
vm/os-netbsd-x86.32.hpp
vm/os-netbsd-x86.64.hpp
vm/os-openbsd-x86.32.hpp
vm/os-openbsd-x86.64.hpp
vm/os-unix.cpp
vm/os-windows-nt.cpp

index 4ce3f0512e23c5d2493bfff827f7488615c32b3b..dd8fd88b13c2bc61c20cdfcd0c0f74a2d51239c8 100644 (file)
@@ -34,7 +34,7 @@ M: ppc-vmx-env (set-fp-env-register)
 M: ppc (fp-env-registers)
     <ppc-fpu-env> <ppc-vmx-env> 2array ;
 
-CONSTANT: ppc-exception-flag-bits HEX: 3e00,0000
+CONSTANT: ppc-exception-flag-bits HEX: fff8,0000
 CONSTANT: ppc-exception-flag>bit
     H{
         { +fp-invalid-operation+ HEX: 2000,0000 }
index 6ae2cce27d488566593b79c52d79d4d619c22792..db02a72959d7557b232a5f92add54363c03f0c5c 100644 (file)
@@ -62,6 +62,24 @@ inline static bool tail_call_site_p(cell return_address)
        return (insn & 0x1) == 0;
 }
 
+inline static unsigned int fpu_status(unsigned int status)
+{
+        unsigned int r = 0;
+
+        if (status & 0x20000000)
+            r |= FP_TRAP_INVALID_OPERATION;
+        if (status & 0x10000000)
+            r |= FP_TRAP_OVERFLOW;
+        if (status & 0x08000000)
+            r |= FP_TRAP_UNDERFLOW;
+        if (status & 0x04000000)
+            r |= FP_TRAP_ZERO_DIVIDE;
+        if (status & 0x02000000)
+            r |= FP_TRAP_INEXACT;
+
+        return r;
+}
+
 /* Defined in assembly */
 VM_ASM_API void c_to_factor(cell quot);
 VM_ASM_API void throw_impl(cell quot, stack_frame *rewind);
index e5852f9ad9fc50f3ca32d6bdf344acb4d78cf1d8..7054f907357e1ccc28c1cb369d2df2bc1e95d1b8 100644 (file)
@@ -50,6 +50,24 @@ inline static bool tail_call_site_p(cell return_address)
        return call_site_opcode(return_address) == jmp_opcode;
 }
 
+inline static unsigned int fpu_status(unsigned int status)
+{
+        unsigned int r = 0;
+
+        if (status & 0x01)
+            r |= FP_TRAP_INVALID_OPERATION;
+        if (status & 0x04)
+            r |= FP_TRAP_ZERO_DIVIDE;
+        if (status & 0x08)
+            r |= FP_TRAP_OVERFLOW;
+        if (status & 0x10)
+            r |= FP_TRAP_UNDERFLOW;
+        if (status & 0x20)
+            r |= FP_TRAP_INEXACT;
+
+        return r;
+}
+
 /* Defined in assembly */
 VM_ASM_API void c_to_factor(cell quot);
 VM_ASM_API void throw_impl(cell quot, stack_frame *rewind_to);
index c9d2a94e56476e26f124e79ecc7012b9ad1c880e..ebe6201f729a967789a9d16dfa49a5f2908513f9 100644 (file)
@@ -7,6 +7,7 @@ namespace factor
 user-space */
 cell signal_number;
 cell signal_fault_addr;
+unsigned int signal_fpu_status;
 stack_frame *signal_callstack_top;
 
 void out_of_memory()
@@ -130,9 +131,9 @@ void divide_by_zero_error()
        general_error(ERROR_DIVIDE_BY_ZERO,F,F,NULL);
 }
 
-void fp_trap_error(stack_frame *signal_callstack_top)
+void fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top)
 {
-       general_error(ERROR_FP_TRAP,F,F,signal_callstack_top);
+       general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),F,signal_callstack_top);
 }
 
 PRIMITIVE(call_clear)
@@ -158,7 +159,7 @@ void misc_signal_handler_impl()
 
 void fp_signal_handler_impl()
 {
-       fp_trap_error(signal_callstack_top);
+       fp_trap_error(signal_fpu_status,signal_callstack_top);
 }
 
 }
index e4be61cdbf075af53336ba5c15a2476c8980059a..7f3c4dcd4ace382aa5e36ec8505e487bae0a36ea 100644 (file)
@@ -20,7 +20,7 @@ enum vm_error_type
        ERROR_RS_UNDERFLOW,
        ERROR_RS_OVERFLOW,
        ERROR_MEMORY,
-    ERROR_FP_TRAP,
+       ERROR_FP_TRAP,
 };
 
 void out_of_memory();
@@ -36,7 +36,7 @@ void memory_protection_error(cell addr, stack_frame *native_stack);
 void signal_error(int signal, stack_frame *native_stack);
 void type_error(cell type, cell tagged);
 void not_implemented_error();
-void fp_trap_error();
+void fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top);
 
 PRIMITIVE(call_clear);
 PRIMITIVE(unimplemented);
@@ -45,6 +45,7 @@ PRIMITIVE(unimplemented);
 user-space */
 extern cell signal_number;
 extern cell signal_fault_addr;
+extern unsigned int signal_fpu_status;
 extern stack_frame *signal_callstack_top;
 
 void memory_signal_handler_impl();
index 7736143c50cf924c9cb921ee84e226843e99e332..a14c234aaab6cd1ce158da349a124658d93bad5f 100644 (file)
@@ -67,6 +67,16 @@ inline static cell align8(cell a)
 /* Not a real type, but code_block's type field can be set to this */
 #define PIC_TYPE 69
 
+/* Constants used when floating-point trap exceptions are thrown */
+enum
+{
+        FP_TRAP_INVALID_OPERATION = 1 << 0,
+        FP_TRAP_OVERFLOW          = 1 << 1,
+        FP_TRAP_UNDERFLOW         = 1 << 2,
+        FP_TRAP_ZERO_DIVIDE       = 1 << 3,
+        FP_TRAP_INEXACT           = 1 << 4,
+};
+
 inline static bool immediate_p(cell obj)
 {
        return (obj == F || TAG(obj) == FIXNUM_TYPE);
index facf512b77b42b7d7ddadbb5a7737f6de1a427f0..d8eea06f0b81b62bb67c6153201a055952e0c19d 100644 (file)
@@ -32,7 +32,8 @@ static void call_fault_handler(
     exception_type_t exception,
     exception_data_type_t code,
        MACH_EXC_STATE_TYPE *exc_state,
-       MACH_THREAD_STATE_TYPE *thread_state)
+       MACH_THREAD_STATE_TYPE *thread_state,
+        MACH_FLOAT_STATE_TYPE *float_state)
 {
        /* There is a race condition here, but in practice an exception
        delivered during stack frame setup/teardown or while transitioning
@@ -56,6 +57,8 @@ static void call_fault_handler(
        }
        else if(exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV)
        {
+                signal_fpu_status = fpu_status(mach_fpu_status(float_state));
+                mach_clear_fpu_status(float_state);
                MACH_PROGRAM_COUNTER(thread_state) = (cell)fp_signal_handler_impl;
        }
        else
@@ -78,14 +81,15 @@ catch_exception_raise (mach_port_t exception_port,
 {
        MACH_EXC_STATE_TYPE exc_state;
        MACH_THREAD_STATE_TYPE thread_state;
-       mach_msg_type_number_t state_count;
+       MACH_FLOAT_STATE_TYPE float_state;
+       mach_msg_type_number_t exc_state_count, thread_state_count, float_state_count;
 
        /* Get fault information and the faulting thread's register contents..
        
        See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html.  */
-       state_count = MACH_EXC_STATE_COUNT;
+       exc_state_count = MACH_EXC_STATE_COUNT;
        if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR,
-                             (natural_t *)&exc_state, &state_count)
+                             (natural_t *)&exc_state, &exc_state_count)
                != KERN_SUCCESS)
        {
                /* The thread is supposed to be suspended while the exception
@@ -93,9 +97,19 @@ catch_exception_raise (mach_port_t exception_port,
                return KERN_FAILURE;
        }
 
-       state_count = MACH_THREAD_STATE_COUNT;
+       thread_state_count = MACH_THREAD_STATE_COUNT;
        if (thread_get_state (thread, MACH_THREAD_STATE_FLAVOR,
-                             (natural_t *)&thread_state, &state_count)
+                             (natural_t *)&thread_state, &thread_state_count)
+               != KERN_SUCCESS)
+       {
+               /* The thread is supposed to be suspended while the exception
+               handler is called. This shouldn't fail. */
+               return KERN_FAILURE;
+       }
+
+        float_state_count = MACH_FLOAT_STATE_COUNT;
+       if (thread_get_state (thread, MACH_FLOAT_STATE_FLAVOR,
+                             (natural_t *)&float_state, &float_state_count)
                != KERN_SUCCESS)
        {
                /* The thread is supposed to be suspended while the exception
@@ -105,13 +119,20 @@ catch_exception_raise (mach_port_t exception_port,
 
        /* Modify registers so to have the thread resume executing the
        fault handler */
-       call_fault_handler(exception,code[0],&exc_state,&thread_state);
+       call_fault_handler(exception,code[0],&exc_state,&thread_state,&float_state);
 
        /* Set the faulting thread's register contents..
        
        See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html.  */
+       if (thread_set_state (thread, MACH_FLOAT_STATE_FLAVOR,
+                             (natural_t *)&float_state, float_state_count)
+               != KERN_SUCCESS)
+       {
+               return KERN_FAILURE;
+       }
+
        if (thread_set_state (thread, MACH_THREAD_STATE_FLAVOR,
-                             (natural_t *)&thread_state, state_count)
+                             (natural_t *)&thread_state, thread_state_count)
                != KERN_SUCCESS)
        {
                return KERN_FAILURE;
index c276ce6174da9f6217974f1051841b7e4de25889..e386532b0c7ea23af57e09c1275d37c321d11417 100644 (file)
@@ -1,4 +1,5 @@
 #include <ucontext.h>
+#include <machine/npx.h>
 
 namespace factor
 {
@@ -9,6 +10,32 @@ inline static void *ucontext_stack_pointer(void *uap)
         return (void *)ucontext->uc_mcontext.mc_esp;
 }
 
+inline static unsigned int uap_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_387) {
+            struct save87 *x87 = (struct save87 *)(&ucontext->uc_mcontext.mc_fpstate);
+            return x87->en_sw;
+        } else if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_XMM) {
+            struct savexmm *xmm = (struct savexmm *)(&ucontext->uc_mcontext.mc_fpstate);
+            return xmm->en_sw | xmm->en_mxcsr;
+        } else
+            return 0;
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_387) {
+            struct save87 *x87 = (struct save87 *)(&ucontext->uc_mcontext.mc_fpstate);
+            x87->en_sw = 0;
+        } else if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_XMM) {
+            struct savexmm *xmm = (struct savexmm *)(&ucontext->uc_mcontext.mc_fpstate);
+            xmm->en_sw = 0;
+            xmm->en_mxcsr &= 0xffffffc0;
+        }
+}
+
 #define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)(ucontext))->uc_mcontext.mc_eip)
 
 }
index 6ee491f3aeadd67f60fe11de249da0296809ff14..78c08447bd337b5d97bf7ecd7af7056e2933f55e 100644 (file)
@@ -1,4 +1,5 @@
 #include <ucontext.h>
+#include <machine/fpu.h>
 
 namespace factor
 {
@@ -9,6 +10,26 @@ inline static void *ucontext_stack_pointer(void *uap)
         return (void *)ucontext->uc_mcontext.mc_rsp;
 }
 
+inline static unsigned int uap_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_XMM) {
+            struct savexmm *xmm = (struct savexmm *)(&ucontext->uc_mcontext.mc_fpstate);
+            return xmm->en_sw | xmm->en_mxcsr;
+        } else
+            return 0;
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        if (uap->uc_mcontext.mc_fpformat == _MC_FPFMT_XMM) {
+            struct savexmm *xmm = (struct savexmm *)(&ucontext->uc_mcontext.mc_fpstate);
+            xmm->en_sw = 0;
+            xmm->en_mxcsr &= 0xffffffc0;
+        }
+}
+
 #define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)(ucontext))->uc_mcontext.mc_rip)
 
 }
index 4ba7c77e4b34fa9f01e641cda2bd3314fe8b8464..e4fd8402a848152dca1c46ea47a434cc383ba6db 100644 (file)
@@ -9,6 +9,20 @@ inline static void *ucontext_stack_pointer(void *uap)
         return (void *)ucontext->uc_mcontext.gregs[7];
 }
 
+inline static unsigned int uap_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        return ucontext->uc_mcontext.fpregs->swd
+             | ucontext->uc_mcontext.fpregs->mxcsr;
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        ucontext->uc_mcontext.fpregs->swd = 0;
+        ucontext->uc_mcontext.fpregs->mxcsr &= 0xffffffc0;
+}
+
 #define UAP_PROGRAM_COUNTER(ucontext) \
        (((ucontext_t *)(ucontext))->uc_mcontext.gregs[14])
 
index 477e21708c4db3220476b438b7e8f0ca23b131ed..42adb3c6b8cffffac90a481b3bb4a9421714d858 100644 (file)
@@ -9,6 +9,20 @@ inline static void *ucontext_stack_pointer(void *uap)
         return (void *)ucontext->uc_mcontext.gregs[15];
 }
 
+inline static unsigned int uap_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        return ucontext->uc_mcontext.fpregs->swd
+             | ucontext->uc_mcontext.fpregs->mxcsr;
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        ucontext->uc_mcontext.fpregs->swd = 0;
+        ucontext->uc_mcontext.fpregs->mxcsr &= 0xffffffc0;
+}
+
 #define UAP_PROGRAM_COUNTER(ucontext) \
        (((ucontext_t *)(ucontext))->uc_mcontext.gregs[16])
 
index 62e71bfa69e2ff24894d693bfdbd628eaea6306f..31a1e228820fc814aaf0cacbe65250c665d3d775 100644 (file)
@@ -18,28 +18,63 @@ Modified for Factor by Slava Pestov */
 #define MACH_EXC_STATE_TYPE ppc_exception_state_t
 #define MACH_EXC_STATE_FLAVOR PPC_EXCEPTION_STATE
 #define MACH_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
+
 #define MACH_EXC_INTEGER_DIV EXC_PPC_ZERO_DIVIDE
+
 #define MACH_THREAD_STATE_TYPE ppc_thread_state_t
 #define MACH_THREAD_STATE_FLAVOR PPC_THREAD_STATE
 #define MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
 
+#define MACH_FLOAT_STATE_TYPE ppc_float_state_t
+#define MACH_FLOAT_STATE_FLAVOR PPC_FLOAT_STATE
+#define MACH_FLOAT_STATE_COUNT PPC_FLOAT_STATE_COUNT
+
 #if __DARWIN_UNIX03
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__dar
        #define MACH_STACK_POINTER(thr_state) (thr_state)->__r1
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__srr0
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->__ss))
+
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__fs)
+
+        #define FPSCR(float_state) (float_state)->__fpscr
 #else
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->dar
        #define MACH_STACK_POINTER(thr_state) (thr_state)->r1
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->srr0
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss))
+
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->fs)
+
+        #define FPSCR(float_state) (float_state)->fpscr
 #endif
 
+#define UAP_PROGRAM_COUNTER(ucontext) \
+        MACH_PROGRAM_COUNTER(UAP_SS(ucontext))
+
+inline static unsigned int mach_fpu_status(ppc_float_state_t *float_state)
+{
+    return FPSCR(float_state);
+}
+
+inline static unsigned int uap_fpu_status(void *uap)
+{
+    return mach_fpu_status(UAP_FS(uap));
+}
+
 inline static cell fix_stack_pointer(cell sp)
 {
-       return sp;
+    return sp;
+}
+
+inline static void mach_clear_fpu_status(ppc_float_state_t *float_state)
+{
+    FPSCR(float_state) &= 0x0007ffff;
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+    mach_clear_fpu_status(UAP_FS(uap));
 }
 
 }
index 2275555846f012c9533aa2b8b40ffc0be9ab7f7e..01ad28df4f8e67ea0a7c12a8299d3e228c17e8cc 100644 (file)
@@ -16,28 +16,68 @@ Modified for Factor by Slava Pestov */
 #define MACH_EXC_STATE_TYPE i386_exception_state_t
 #define MACH_EXC_STATE_FLAVOR i386_EXCEPTION_STATE
 #define MACH_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT
+
 #define MACH_EXC_INTEGER_DIV EXC_I386_DIV
+
 #define MACH_THREAD_STATE_TYPE i386_thread_state_t
 #define MACH_THREAD_STATE_FLAVOR i386_THREAD_STATE
 #define MACH_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
 
+#define MACH_FLOAT_STATE_TYPE i386_float_state_t
+#define MACH_FLOAT_STATE_FLAVOR i386_FLOAT_STATE
+#define MACH_FLOAT_STATE_COUNT i386_FLOAT_STATE_COUNT
+
 #if __DARWIN_UNIX03
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__faultvaddr
        #define MACH_STACK_POINTER(thr_state) (thr_state)->__esp
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__eip
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->__ss))
+
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__fs)
+
+        #define MXCSR(float_state) (float_state)->__fpu_mxcsr
+        #define X87SW(float_state) (float_state)->__fpu_fsw
 #else
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->faultvaddr
        #define MACH_STACK_POINTER(thr_state) (thr_state)->esp
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->eip
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss))    
+
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->fs)
+
+        #define MXCSR(float_state) (float_state)->fpu_mxcsr
+        #define X87SW(float_state) (float_state)->fpu_fsw
 #endif
 
+#define UAP_PROGRAM_COUNTER(ucontext) \
+        MACH_PROGRAM_COUNTER(UAP_SS(ucontext))
+
+inline static unsigned int mach_fpu_status(i386_float_state_t *float_state)
+{
+    unsigned short x87sw;
+    memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
+    return MXCSR(float_state) | x87sw;
+}
+
+inline static unsigned int uap_fpu_status(void *uap)
+{
+    return mach_fpu_status(UAP_FS(uap));
+}
+
 inline static cell fix_stack_pointer(cell sp)
 {
        return ((sp + 4) & ~15) - 4;
 }
 
+inline static void mach_clear_fpu_status(i386_float_state_t *float_state)
+{
+        MXCSR(float_state) &= 0xffffffc0;
+        memset(&X87SW(float_state), 0, sizeof(X87SW(float_state)));
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+    mach_clear_fpu_status(UAP_FS(uap));
+}
+
 }
index b97eb55f2603d7ffc85bb567cbca3803227f7056..f56ada23fd80687db5fe8e444ac70074d1206833 100644 (file)
@@ -16,28 +16,66 @@ Modified for Factor by Slava Pestov and Daniel Ehrenberg */
 #define MACH_EXC_STATE_TYPE x86_exception_state64_t
 #define MACH_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64
 #define MACH_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
+
 #define MACH_EXC_INTEGER_DIV EXC_I386_DIV
+
 #define MACH_THREAD_STATE_TYPE x86_thread_state64_t
 #define MACH_THREAD_STATE_FLAVOR x86_THREAD_STATE64
 #define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT
 
+#define MACH_FLOAT_STATE_TYPE x86_float_state64_t
+#define MACH_FLOAT_STATE_FLAVOR x86_FLOAT_STATE64
+#define MACH_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT
+
 #if __DARWIN_UNIX03
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__faultvaddr
        #define MACH_STACK_POINTER(thr_state) (thr_state)->__rsp
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__rip
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->__ss))
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->__fs)
+
+        #define MXCSR(float_state) (float_state)->__fpu_mxcsr
+        #define X87SW(float_state) (float_state)->__fpu_fsw
 #else
        #define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->faultvaddr
        #define MACH_STACK_POINTER(thr_state) (thr_state)->rsp
        #define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->rip
-       #define UAP_PROGRAM_COUNTER(ucontext) \
-               MACH_PROGRAM_COUNTER(&(((ucontext_t *)(ucontext))->uc_mcontext->ss))    
+        #define UAP_SS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->ss)
+        #define UAP_FS(ucontext) &(((ucontext_t *)(ucontext))->uc_mcontext->fs)
+
+        #define MXCSR(float_state) (float_state)->fpu_mxcsr
+        #define X87SW(float_state) (float_state)->fpu_fsw
 #endif
 
+#define UAP_PROGRAM_COUNTER(ucontext) \
+        MACH_PROGRAM_COUNTER(UAP_SS(ucontext))
+
+inline static unsigned int mach_fpu_status(x86_float_state64_t *float_state)
+{
+    unsigned short x87sw;
+    memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
+    return MXCSR(float_state) | x87sw;
+}
+
+inline static unsigned int uap_fpu_status(void *uap)
+{
+    return mach_fpu_status(UAP_FS(uap));
+}
+
 inline static cell fix_stack_pointer(cell sp)
 {
-       return ((sp + 8) & ~15) - 8;
+    return ((sp + 8) & ~15) - 8;
+}
+
+inline static void mach_clear_fpu_status(x86_float_state64_t *float_state)
+{
+    MXCSR(float_state) &= 0xffffffc0;
+    memset(&X87SW(float_state), 0, sizeof(X87SW(float_state)));
+}
+
+inline static void uap_clear_fpu_status(void *uap)
+{
+    mach_clear_fpu_status(UAP_FS(uap));
 }
 
 }
index ebba4f356d0881567ffba4237c8dbc56671bc06f..f2f47ecf6ccd14160b060eb705a3588226111401 100644 (file)
@@ -5,4 +5,7 @@ namespace factor
 
 #define ucontext_stack_pointer(uap) ((void *)_UC_MACHINE_SP((ucontext_t *)uap))
 
+static inline unsigned int uap_fpu_status(void *uap) { return 0; }
+static inline void uap_clear_fpu_status(void *uap) {  }
+
 }
index 1a062cc6efc196217daa02dd0876c967d28f5e3d..a9d52a6c2bfb071689cd42d18f8d2a7a4a2645a1 100644 (file)
@@ -6,4 +6,7 @@ namespace factor
 #define ucontext_stack_pointer(uap) \
        ((void *)(((ucontext_t *)(uap))->uc_mcontext.__gregs[_REG_URSP]))
 
+static inline unsigned int uap_fpu_status(void *uap) { return 0; }
+static inline void uap_clear_fpu_status(void *uap) {  }
+
 }
index 6065d96a5f0298821e9001d1b162b36bc16aa23f..0abd01921904d8bee7d0b333c0d98222995810d2 100644 (file)
@@ -12,4 +12,7 @@ inline static void *openbsd_stack_pointer(void *uap)
 #define ucontext_stack_pointer openbsd_stack_pointer
 #define UAP_PROGRAM_COUNTER(uap) (((struct sigcontext*)(uap))->sc_eip)
 
+static inline unsigned int uap_fpu_status(void *uap) { return 0; }
+static inline void uap_clear_fpu_status(void *uap) {  }
+
 }
index 7338b04e6fb66890621b866b2316758be18fb414..9dce48ee910cd13ff07dd4cce4c92b8f7ec03914 100644 (file)
@@ -12,4 +12,7 @@ inline static void *openbsd_stack_pointer(void *uap)
 #define ucontext_stack_pointer openbsd_stack_pointer
 #define UAP_PROGRAM_COUNTER(uap) (((struct sigcontext*)(uap))->sc_rip)
 
+static inline unsigned int uap_fpu_status(void *uap) { return 0; }
+static inline void uap_clear_fpu_status(void *uap) {  }
+
 }
index 735c614b7a2fd08fe6281284b57b25658c527f04..189fca0cf789591362bcca8b10e0878586b5a794 100644 (file)
@@ -136,6 +136,8 @@ void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
        signal_number = signal;
        signal_callstack_top = uap_stack_pointer(uap);
+        signal_fpu_status = fpu_status(uap_fpu_status(uap));
+        uap_clear_fpu_status(uap);
        UAP_PROGRAM_COUNTER(uap) =
             (siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
                 ? (cell)misc_signal_handler_impl
index e2d959aacef60650ebb56d13d051d61e2b9a2a96..c2b4e2af9e668acb98f8d26c6aab3a29298b1794 100644 (file)
@@ -34,6 +34,9 @@ FACTOR_STDCALL LONG exception_handler(PEXCEPTION_POINTERS pe)
     case EXCEPTION_FLT_OVERFLOW:
     case EXCEPTION_FLT_STACK_CHECK:
     case EXCEPTION_FLT_UNDERFLOW:
+        /* XXX MxCsr is not available in CONTEXT structure on x86.32 */
+        signal_fpu_status = c->FloatSave.StatusWord;
+        c->FloatSave.StatusWord = 0;
         c->EIP = (cell)fp_signal_handler_impl;
         break;