Skip to content
Snippets Groups Projects
Commit 7fbce9e3 authored by rswindells's avatar rswindells
Browse files

Add new FPU interface code.

parent 3d58c145
No related branches found
No related tags found
No related merge requests found
......@@ -15,7 +15,7 @@
* Frobbed for OpenBSD by Pierre R. Mai, 2001.
* Frobbed for NetBSD by Pierre R. Mai, 2002.
*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.11 2008/12/07 02:33:55 agoncharov Exp $
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.12 2009/08/30 19:17:55 rswindells Rel $
*
*/
......@@ -84,6 +84,61 @@ os_sigcontext_pc(ucontext_t *scp)
#endif
}
unsigned char *
os_sigcontext_fpu_reg(ucontext_t *scp, int index)
{
unsigned char *reg = NULL;
if (scp->uc_flags & _UC_FPU) {
if (scp->uc_flags & _UC_FXSAVE) {
reg = scp->uc_mcontext.__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm[index];
} else {
reg = scp->uc_mcontext.__fpregs.__fp_reg_set.__fpchip_state.__fp_state[index];
}
} else {
reg = NULL;
}
return reg;
}
unsigned int
os_sigcontext_fpu_modes(ucontext_t *scp)
{
unsigned int modes;
union savefpu *sv = (union savefpu *) &scp->uc_mcontext.__fpregs.__fp_reg_set;
struct env87 *env_87 = (struct env87 *) &sv->sv_87.sv_env;
struct envxmm *env_xmm = (struct envxmm *) &sv->sv_xmm.sv_env;
u_int16_t cw;
u_int16_t sw;
if (scp->uc_flags & _UC_FPU) {
if (scp->uc_flags & _UC_FXSAVE) {
cw = env_xmm->en_cw;
sw = env_xmm->en_sw;
} else {
cw = env_87->en_cw & 0xffff;
sw = env_87->en_sw & 0xffff;
}
} else {
cw = 0;
sw = 0x3f;
}
modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
#ifdef FEATURE_SSE2
if (fpu_mode == SSE2) {
u_int32_t mxcsr = env_xmm->en_mxcsr;
DPRINTF(0, (stderr, "SSE2 modes = %08x\n", (int)mxcsr));
modes |= mxcsr;
}
#endif
modes ^= (0x3f << 7);
return modes;
}
os_vm_address_t
os_validate(os_vm_address_t addr, os_vm_size_t len)
{
......@@ -236,11 +291,52 @@ sigbus_handler(HANDLER_ARGS)
interrupt_handle_now(signal, code, context);
}
/*
* Restore the exception flags cleared by the kernel. These bits must
* be set for Lisp to determine which exception caused the signal. At
* present, there is no way to distinguish underflow exceptions from
* denormalized operand exceptions. An underflow exception is assumed
* if the subcode is FPE_FLTUND.
*/
static void
sigfpe_handler(HANDLER_ARGS)
{
ucontext_t *ucontext = (ucontext_t *) context;
union savefpu *sv = (union savefpu *) &ucontext->uc_mcontext.__fpregs.__fp_reg_set;
unsigned char trap = 0;
switch (code->si_code) {
case FPE_FLTDIV: /* ZE */
trap = 0x04;
break;
case FPE_FLTOVF: /* OE */
trap = 0x08;
break;
case FPE_FLTUND: /* DE or UE */
trap = 0x10;
break;
case FPE_FLTRES: /* PE */
trap = 0x20;
break;
case FPE_FLTINV: /* IE */
trap = 0x01;
break;
}
if (ucontext->uc_flags & _UC_FXSAVE) {
sv->sv_xmm.sv_env.en_sw |= trap;
} else {
sv->sv_87.sv_env.en_sw |= trap;
}
interrupt_handle_now(signal, code, context);
}
void
os_install_interrupt_handlers(void)
{
interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler);
interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
}
void *
......@@ -262,3 +358,31 @@ os_dlsym(const char *sym_name, lispobj lib_list)
return dlsym(RTLD_DEFAULT, sym_name);
}
void
restore_fpu(ucontext_t *scp)
{
union savefpu *sv = (union savefpu *) &scp->uc_mcontext.__fpregs.__fp_reg_set;
struct env87 *env_87 = &sv->sv_87.sv_env;
struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
u_int16_t cw;
if (scp->uc_flags & _UC_FPU) {
if (scp->uc_flags & _UC_FXSAVE) {
cw = env_xmm->en_cw;
} else {
cw = env_87->en_cw & 0xffff;
}
} else {
return;
}
DPRINTF(0, (stderr, "restore_fpu: cw = %08x\n", (int)cw));
__asm__ __volatile__ ("fldcw %0"::"m"(*&cw));
if (arch_support_sse2()) {
u_int32_t mxcsr = env_xmm->en_mxcsr;
DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr));
__asm__ __volatile__ ("ldmxcsr %0"::"m"(*&mxcsr));
}
}
/*
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.h,v 1.8 2008/05/16 13:30:22 rswindells Exp $
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.h,v 1.9 2009/08/30 19:17:55 rswindells Rel $
This code was written as part of the CMU Common Lisp project at
Carnegie Mellon University, and has been placed in the public domain.
......@@ -36,6 +36,9 @@ typedef int os_vm_prot_t;
#define HANDLER_ARGS int signal, siginfo_t *code, ucontext_t *context
#define CODE(code) ((code) ? code->si_code : 0)
#define RESTORE_FPU(context) restore_fpu(context)
void restore_fpu(ucontext_t *);
#define PROTECTION_VIOLATION_SIGNAL SIGSEGV
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment