diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-05-26 22:41:40 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-05-26 22:41:40 +0200 |
commit | 257c7e958ef125ec12cc218519ce56f767eb112d (patch) | |
tree | 815353b334a8f22f1a6f771fd58c0f27a140bfc9 /sys/src/9/pc/main.c | |
parent | 7aea1204b9843842827302a3eb58752333daf918 (diff) |
keep fpregs always in sse (FXSAVE) format, adapt libmach and acid files for new format
we now always use the new FXSAVE format in FPsave structure and fpregs
file, converting back and forth in fpx87save() and fpx87restore().
document that fprestore() is a destructive operation now.
change fp register definition in libmach and adapt fpr() acid funciton.
avoid unneccesary copy of fpstate and fpsave in sysfork(). functions
including syscalls do not preserve the fp registers and copying fpstate
from the current process would mean we had to fpsave(&up->fpsave); first.
simply not doing it, new process starts in FPinit state.
Diffstat (limited to 'sys/src/9/pc/main.c')
-rw-r--r-- | sys/src/9/pc/main.c | 177 |
1 files changed, 119 insertions, 58 deletions
diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 35cfccf01..538bec15b 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -469,6 +469,121 @@ confinit(void) } } +/* + * we keep FPsave structure in sse format emulating FXSAVE / FXRSTOR + * instructions for legacy x87 fpu. + * + * Note that fpx87restore() and fpxsserestore() do modify the FPsave + * data structure for conversion / realignment shuffeling. this means + * that p->fpsave is only valid when p->fpstate == FPinactive. + */ +void +fpx87save(FPsave *fps) +{ + fpx87save0(fps); + + /* NOP fps->fcw = fps->control; */ + fps->fsw = fps->status; + fps->ftw = fps->tag; + fps->fop = fps->opcode; + fps->fpuip = fps->pc; + fps->cs = fps->selector; + fps->fpudp = fps->operand; + fps->ds = fps->oselector; + +#define MOVA(d,s) \ + *((ushort*)(d+8)) = *((ushort*)(s+8)), \ + *((ulong*)(d+4)) = *((ulong*)(s+4)), \ + *((ulong*)(d)) = *((ulong*)(s)) + + MOVA(fps->xregs+0x70, fps->regs+70); + MOVA(fps->xregs+0x60, fps->regs+60); + MOVA(fps->xregs+0x50, fps->regs+50); + MOVA(fps->xregs+0x40, fps->regs+40); + MOVA(fps->xregs+0x30, fps->regs+30); + MOVA(fps->xregs+0x20, fps->regs+20); + MOVA(fps->xregs+0x10, fps->regs+10); + MOVA(fps->xregs+0x00, fps->regs+00); + +#undef MOVA + +#define CLR6(d) \ + *((ulong*)(d)) = 0, \ + *((ushort*)(d+4)) = 0 + + CLR6(fps->xregs+0x70+10); + CLR6(fps->xregs+0x60+10); + CLR6(fps->xregs+0x50+10); + CLR6(fps->xregs+0x40+10); + CLR6(fps->xregs+0x30+10); + CLR6(fps->xregs+0x20+10); + CLR6(fps->xregs+0x10+10); + CLR6(fps->xregs+0x00+10); + +#undef CLR6 + + fps->rsrvd1 = fps->rsrvd2 = fps->mxcsr = fps->mxcsr_mask = 0; +} + +void +fpx87restore(FPsave *fps) +{ +#define MOVA(d,s) \ + *((ulong*)(d)) = *((ulong*)(s)), \ + *((ulong*)(d+4)) = *((ulong*)(s+4)), \ + *((ushort*)(d+8)) = *((ushort*)(s+8)) + + MOVA(fps->regs+00, fps->xregs+0x00); + MOVA(fps->regs+10, fps->xregs+0x10); + MOVA(fps->regs+20, fps->xregs+0x20); + MOVA(fps->regs+30, fps->xregs+0x30); + MOVA(fps->regs+40, fps->xregs+0x40); + MOVA(fps->regs+50, fps->xregs+0x50); + MOVA(fps->regs+60, fps->xregs+0x60); + MOVA(fps->regs+70, fps->xregs+0x70); + +#undef MOVA + + fps->oselector = fps->ds; + fps->operand = fps->fpudp; + fps->opcode = (fps->fop & 0x7ff); + fps->selector = fps->cs; + fps->pc = fps->fpuip; + fps->tag = fps->ftw; + fps->status = fps->fsw; + /* NOP fps->control = fps->fcw; */ + + fps->r1 = fps->r2 = fps->r3 = fps->r4 = 0; + + fpx87restore0(fps); +} + +/* + * sse fp save and restore buffers have to be 16-byte (FPalign) aligned, + * so we shuffle the data up and down as needed or make copies. + */ +void +fpssesave(FPsave *fps) +{ + FPsave *afps; + + afps = (FPsave *)ROUND(((uintptr)fps), FPalign); + fpssesave0(afps); + if(fps != afps) /* not aligned? shuffle down from aligned buffer */ + memmove(fps, afps, sizeof(FPssestate) - FPalign); +} + +void +fpsserestore(FPsave *fps) +{ + FPsave *afps; + + afps = (FPsave *)ROUND(((uintptr)fps), FPalign); + if(fps != afps) /* shuffle up to make aligned */ + memmove(afps, fps, sizeof(FPssestate) - FPalign); + fpsserestore0(afps); +} + static char* mathmsg[] = { nil, /* handled below */ @@ -511,61 +626,6 @@ mathnote(ulong status, ulong pc) } /* - * sse fp save and restore buffers have to be 16-byte (FPalign) aligned, - * so we shuffle the data up and down as needed or make copies. - */ -void -fpssesave(FPsave *fps) -{ - FPsave *afps; - - afps = (FPsave *)ROUND(((uintptr)fps), FPalign); - fpssesave0(afps); - if(fps != afps) /* not aligned? shuffle down from aligned buffer */ - memmove(fps, afps, sizeof(FPssestate) - FPalign); -} - -void -fpsserestore(FPsave *fps) -{ - FPsave *afps; - - afps = (FPsave *)ROUND(((uintptr)fps), FPalign); - if(fps != afps) /* shuffle up to make aligned */ - memmove(afps, fps, sizeof(FPssestate) - FPalign); - fpsserestore0(afps); - if(fps != afps) /* shuffle regs back down when unaligned */ - memmove(fps, afps, sizeof(FPssestate) - FPalign); -} - -/* - * extract control, status and fppc from process - * floating point state independent of format. - */ -static void -mathstate(ulong *stsp, ulong *pcp, ulong *ctlp) -{ - ulong sts, fpc, ctl; - FPsave *f = &up->fpsave; - - if(fpsave == fpx87save){ - sts = f->status; - fpc = f->pc; - ctl = f->control; - } else { - sts = f->fsw; - fpc = f->fpuip; - ctl = f->fcw; - } - if(stsp) - *stsp = sts; - if(pcp) - *pcp = fpc; - if(ctlp) - *ctlp = ctl; -} - -/* * math coprocessor error */ static void @@ -591,7 +651,7 @@ matherror(Ureg*, void*) static void mathemu(Ureg *ureg, void*) { - ulong status, control, pc; + ulong status, control; if(up->fpstate & FPillegal){ /* someone did floating point in a note handler */ @@ -611,9 +671,10 @@ mathemu(Ureg *ureg, void*) * More attention should probably be paid here to the * exception masks and error summary. */ - mathstate(&status, &pc, &control); + status = up->fpsave.fsw; + control = up->fpsave.fcw; if((status & ~control) & 0x07F){ - mathnote(status, pc); + mathnote(status, up->fpsave.fpuip); break; } fprestore(&up->fpsave); |