int fpu_post_test (int flags) { int fpu = fpu_status (); int ret = 0; WATCHDOG_RESET (); if (!fpu) fpu_enable (); if (ret == 0) ret = fpu_post_test_math1 (); if (ret == 0) ret = fpu_post_test_math2 (); if (ret == 0) ret = fpu_post_test_math3 (); if (ret == 0) ret = fpu_post_test_math4 (); if (ret == 0) ret = fpu_post_test_math5 (); if (ret == 0) ret = fpu_post_test_math6 (); if (ret == 0) ret = fpu_post_test_math7 (); if (!fpu) fpu_disable (); WATCHDOG_RESET (); return ret; }
void fpe_signal_handler(int signal, siginfo_t* siginfo, void* uap) { factor_vm* vm = current_vm(); vm->signal_number = signal; vm->signal_fpu_status = fpu_status(uap_fpu_status(uap)); uap_clear_fpu_status(uap); vm->dispatch_signal( uap, (siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF) ? factor::synchronous_signal_handler_impl : factor::fp_signal_handler_impl); }
LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c, void* dispatch) { switch (e->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: signal_fault_addr = e->ExceptionInformation[1]; signal_fault_pc = c->EIP; verify_memory_protection_error(signal_fault_addr); dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, (cell)factor::memory_signal_handler_impl); break; case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: case STATUS_FLOAT_INEXACT_RESULT: case STATUS_FLOAT_INVALID_OPERATION: case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: case STATUS_FLOAT_UNDERFLOW: case STATUS_FLOAT_MULTIPLE_FAULTS: case STATUS_FLOAT_MULTIPLE_TRAPS: #ifdef FACTOR_64 signal_fpu_status = fpu_status(MXCSR(c)); #else signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c)); // This seems to have no effect X87SW(c) = 0; #endif MXCSR(c) &= 0xffffffc0; dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, (cell)factor::fp_signal_handler_impl); break; default: signal_number = e->ExceptionCode; dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, (cell)factor::synchronous_signal_handler_impl); break; } return ExceptionContinueExecution; }
LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch) { c->ESP = (cell)fix_callstack_top((stack_frame *)c->ESP); ctx->callstack_top = (stack_frame *)c->ESP; switch (e->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: signal_fault_addr = e->ExceptionInformation[1]; c->EIP = (cell)factor::memory_signal_handler_impl; break; case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: case STATUS_FLOAT_INEXACT_RESULT: case STATUS_FLOAT_INVALID_OPERATION: case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: case STATUS_FLOAT_UNDERFLOW: case STATUS_FLOAT_MULTIPLE_FAULTS: case STATUS_FLOAT_MULTIPLE_TRAPS: #ifdef FACTOR_64 signal_fpu_status = fpu_status(MXCSR(c)); #else signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c)); /* This seems to have no effect */ X87SW(c) = 0; #endif MXCSR(c) &= 0xffffffc0; c->EIP = (cell)factor::fp_signal_handler_impl; break; default: signal_number = e->ExceptionCode; c->EIP = (cell)factor::misc_signal_handler_impl; break; } return 0; }
/* Modify a suspended thread's thread_state so that when the thread resumes executing, the call frame of the current C primitive (if any) is rewound, and the appropriate Factor error is thrown from the top-most Factor frame. */ void factor_vm::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_FLOAT_STATE_TYPE* float_state) { cell handler = 0; if (exception == EXC_BAD_ACCESS) { signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state); signal_fault_pc = (cell)MACH_PROGRAM_COUNTER(thread_state); verify_memory_protection_error(signal_fault_addr); handler = (cell)factor::memory_signal_handler_impl; } 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); handler = (cell)factor::fp_signal_handler_impl; } else { switch (exception) { case EXC_ARITHMETIC: signal_number = SIGFPE; break; case EXC_BAD_INSTRUCTION: signal_number = SIGILL; break; default: signal_number = SIGABRT; break; } handler = (cell)factor::synchronous_signal_handler_impl; } FACTOR_ASSERT(handler != 0); dispatch_signal_handler((cell*)&MACH_STACK_POINTER(thread_state), (cell*)&MACH_PROGRAM_COUNTER(thread_state), (cell)handler); }