cvs commit: src/sys/i386/isa npx.c
David Xu
davidxu at freebsd.org
Sun May 28 05:06:55 PDT 2006
On Sunday 28 May 2006 19:15, Bruce Evans wrote:
> Starting with a clean FP state like the old code does is safest, but POSIX
> explicitly requires copying the environment, and bugs in the new code
> result in half of the most dangerous part of the environment (the SSE
> half of the exception flags) being copied anyway.
>
> Pending exceptions are not the only problem here. Pending exceptions
> are an i387 thing. Most exceptions are non-pending ones for IEEE inexact.
>
> Bruce
how about following patch ?
Index: npx.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/npx.c,v
retrieving revision 1.168
diff -u -u -r1.168 npx.c
--- npx.c 28 May 2006 04:40:45 -0000 1.168
+++ npx.c 28 May 2006 11:40:58 -0000
@@ -99,6 +99,7 @@
#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*(addr)))
#define fxsave(addr) __asm __volatile("fxsave %0" : "=m" (*(addr)))
#define ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
+#define stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr)))
#endif
#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
: : "n" (CR0_TS) : "ax")
@@ -950,7 +951,8 @@
{
union savefpu *state;
u_int32_t mxcsr;
- u_int32_t cw;
+ u_int16_t cw;
+ register_t s;
if (!(td->td_pcb->pcb_flags & PCB_NPXINITDONE)) {
newtd->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
@@ -958,21 +960,40 @@
}
state = &newtd->td_pcb->pcb_save;
- /* get control word */
- if (npxgetregs(td, state))
- return;
- if (cpu_fxsr) {
- mxcsr = state->sv_xmm.sv_env.en_mxcsr;
- cw = state->sv_xmm.sv_env.en_cw;
+ s = intr_disable();
+ if (curthread == PCPU_GET(fpcurthread)) {
+#ifdef CPU_ENABLE_SSE
+ if (cpu_fxsr) {
+ stmxcsr(&mxcsr);
+ fnstcw(&cw);
+ }
+ else
+#endif
+ {
+ mxcsr = 0;
+ fnstcw(&cw);
+ }
} else {
- cw = state->sv_87.sv_env.en_cw;
- mxcsr = 0;
+#ifdef CPU_ENABLE_SSE
+ if (cpu_fxsr) {
+ mxcsr = td->td_pcb->pcb_save.sv_xmm.sv_env.en_mxcsr;
+ cw = td->td_pcb->pcb_save.sv_87.sv_env.en_cw;
+ }
+ else
+#endif
+ {
+ mxcsr = 0;
+ cw = td->td_pcb->pcb_save.sv_87.sv_env.en_cw;
+ }
}
+ intr_restore(s);
bcopy(&npx_cleanstate, state, sizeof(*state));
+#ifdef CPU_ENABLE_SSE
if (cpu_fxsr) {
state->sv_xmm.sv_env.en_cw = cw;
- state->sv_xmm.sv_env.en_mxcsr = mxcsr;
+ state->sv_xmm.sv_env.en_mxcsr = mxcsr & ~0x3F;
} else
+#endif
state->sv_87.sv_env.en_cw = cw;
newtd->td_pcb->pcb_flags |= PCB_NPXINITDONE;
}
More information about the cvs-src
mailing list