diff options
| -rw-r--r-- | sys/lib/acid/386 | 24 | ||||
| -rw-r--r-- | sys/src/9/pc/dat.h | 8 | ||||
| -rw-r--r-- | sys/src/9/pc/fns.h | 2 | ||||
| -rw-r--r-- | sys/src/9/pc/l.s | 4 | ||||
| -rw-r--r-- | sys/src/9/pc/main.c | 177 | ||||
| -rw-r--r-- | sys/src/9/port/sysproc.c | 2 | ||||
| -rw-r--r-- | sys/src/libmach/8.c | 59 |
7 files changed, 177 insertions, 99 deletions
diff --git a/sys/lib/acid/386 b/sys/lib/acid/386 index 2aa319daa..5ae46fd83 100644 --- a/sys/lib/acid/386 +++ b/sys/lib/acid/386 @@ -69,22 +69,14 @@ defn fpr() print("F5\t", *F5, "\n"); print("F6\t", *F6, "\n"); print("F7\t", *F7, "\n"); - print("control\t", *fmt(E0, 'x'), "\n"); - print("status\t", *fmt(E1, 'x'), "\n"); - print("tag\t", *fmt(E2, 'x'), "\n"); - print("ip offset\t", *fmt(E3, 'X'), "\n"); - print("cs selector\t", *fmt(E4, 'x'), "\n"); - print("opcode\t", *fmt(E4>>8, 'x'), "\n"); - print("data operand offset\t", *fmt(E5, 'x'), "\n"); - print("operand selector\t", *fmt(E6, 'x'), "\n"); -} - -defn mmregs() -{ - print("MM0\t", *MM0, " MM1\t", *MM1, "\n"); - print("MM2\t", *MM2, " MM3\t", *MM3, "\n"); - print("MM4\t", *MM4, " MM5\t", *MM5, "\n"); - print("MM6\t", *MM6, " MM7\t", *MM7, "\n"); + print("control\t", *FCW, "\n"); + print("status\t", *FSW, "\n"); + print("tag\t", *FTW, "\n"); + print("ip\t", *FIP, "\n"); + print("cs selector\t", *FCS, "\n"); + print("opcode\t", *FOP, "\n"); + print("data operand\t", *FDP, "\n"); + print("operand selector\t", *FDS, "\n"); } defn pstop(pid) diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index e8d422414..862dc344a 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -76,10 +76,10 @@ struct FPstate ushort r3; ulong pc; ushort selector; - ushort r4; + ushort opcode; ulong operand; ushort oselector; - ushort r5; + ushort r4; uchar regs[80]; /* floating point registers */ }; @@ -91,10 +91,10 @@ struct FPssestate /* SSE fp state */ ushort fop; /* opcode */ ulong fpuip; /* pc */ ushort cs; /* pc segment */ - ushort r1; /* reserved */ + ushort rsrvd1; /* reserved */ ulong fpudp; /* data pointer */ ushort ds; /* data pointer segment */ - ushort r2; + ushort rsrvd2; ulong mxcsr; /* MXCSR register state */ ulong mxcsr_mask; /* MXCSR mask register */ uchar xregs[480]; /* extended registers */ diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index a066c44ea..176b36aae 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -41,7 +41,9 @@ void fpssesave(FPsave*); void fpssesave0(FPsave*); ulong fpstatus(void); void fpx87restore(FPsave*); +void fpx87restore0(FPsave*); void fpx87save(FPsave*); +void fpx87save0(FPsave*); ulong getcr0(void); ulong getcr2(void); ulong getcr3(void); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 4087b3f1a..e86b22449 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -657,13 +657,13 @@ TEXT fpinit(SB), $0 /* enable and init */ WAIT RET -TEXT fpx87save(SB), $0 /* save state and disable */ +TEXT fpx87save0(SB), $0 /* save state and disable */ MOVL p+0(FP), AX FSAVE 0(AX) /* no WAIT */ FPOFF(l2) RET -TEXT fpx87restore(SB), $0 /* enable and restore state */ +TEXT fpx87restore0(SB), $0 /* enable and restore state */ FPON MOVL p+0(FP), AX FRSTOR 0(AX) 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); diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index 0676dffd0..9c5c8899e 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -84,7 +84,6 @@ sysrfork(ulong *arg) p = newproc(); - p->fpsave = up->fpsave; p->scallnr = up->scallnr; p->s = up->s; p->nerrlab = 0; @@ -180,7 +179,6 @@ sysrfork(ulong *arg) if((flag&RFNOTEG) == 0) p->noteid = up->noteid; - p->fpstate = up->fpstate; pid = p->pid; memset(p->time, 0, sizeof(p->time)); p->time[TReal] = MACHP(0)->ticks; diff --git a/sys/src/libmach/8.c b/sys/src/libmach/8.c index 5ec20a581..5e23cca71 100644 --- a/sys/src/libmach/8.c +++ b/sys/src/libmach/8.c @@ -14,9 +14,11 @@ #define AX REGOFF(ax) #define REGSIZE sizeof(struct Ureg) +#define FP_CTLS(x) (REGSIZE+2*(x)) #define FP_CTL(x) (REGSIZE+4*(x)) -#define FP_REG(x) (FP_CTL(7)+10*(x)) -#define FPREGSIZE (7*4+8*10) +#define FP_REG(x) (FP_CTL(8)+16*(x)) +#define XM_REG(x) (FP_CTL(8)+8*16+16*(x)) +#define FPREGSIZE 512 Reglist i386reglist[] = { {"DI", REGOFF(di), RINT, 'X'}, @@ -38,21 +40,44 @@ Reglist i386reglist[] = { {"SP", SP, RINT, 'X'}, {"SS", REGOFF(ss), RINT, 'X'}, - {"E0", FP_CTL(0), RFLT, 'X'}, - {"E1", FP_CTL(1), RFLT, 'X'}, - {"E2", FP_CTL(2), RFLT, 'X'}, - {"E3", FP_CTL(3), RFLT, 'X'}, - {"E4", FP_CTL(4), RFLT, 'X'}, - {"E5", FP_CTL(5), RFLT, 'X'}, - {"E6", FP_CTL(6), RFLT, 'X'}, - {"F0", FP_REG(0), RFLT, '3'}, - {"F1", FP_REG(1), RFLT, '3'}, - {"F2", FP_REG(2), RFLT, '3'}, - {"F3", FP_REG(3), RFLT, '3'}, - {"F4", FP_REG(4), RFLT, '3'}, - {"F5", FP_REG(5), RFLT, '3'}, - {"F6", FP_REG(6), RFLT, '3'}, - {"F7", FP_REG(7), RFLT, '3'}, + {"FCW", FP_CTLS(0), RFLT, 'x'}, + {"FSW", FP_CTLS(1), RFLT, 'x'}, + {"FTW", FP_CTLS(2), RFLT, 'b'}, + {"FOP", FP_CTLS(3), RFLT, 'x'}, + {"FIP", FP_CTL(2), RFLT, 'X'}, + {"FCS", FP_CTLS(6), RFLT, 'x'}, + {"FDP", FP_CTL(4), RFLT, 'X'}, + {"FDS", FP_CTLS(10), RFLT, 'x'}, + {"MXCSR", FP_CTL(6), RFLT, 'X'}, + {"MXCSRMASK", FP_CTL(7), RFLT, 'X'}, + + {"M0", FP_REG(0), RFLT, 'F'}, /* assumes double */ + {"M1", FP_REG(1), RFLT, 'F'}, + {"M2", FP_REG(2), RFLT, 'F'}, + {"M3", FP_REG(3), RFLT, 'F'}, + {"M4", FP_REG(4), RFLT, 'F'}, + {"M5", FP_REG(5), RFLT, 'F'}, + {"M6", FP_REG(6), RFLT, 'F'}, + {"M7", FP_REG(7), RFLT, 'F'}, + + {"X0", XM_REG(0), RFLT, 'F'}, /* assumes double */ + {"X1", XM_REG(1), RFLT, 'F'}, + {"X2", XM_REG(2), RFLT, 'F'}, + {"X3", XM_REG(3), RFLT, 'F'}, + {"X4", XM_REG(4), RFLT, 'F'}, + {"X5", XM_REG(5), RFLT, 'F'}, + {"X6", XM_REG(6), RFLT, 'F'}, + {"X7", XM_REG(7), RFLT, 'F'}, + + {"F0", FP_REG(7), RFLT, '3'}, + {"F1", FP_REG(6), RFLT, '3'}, + {"F2", FP_REG(5), RFLT, '3'}, + {"F3", FP_REG(4), RFLT, '3'}, + {"F4", FP_REG(3), RFLT, '3'}, + {"F5", FP_REG(2), RFLT, '3'}, + {"F6", FP_REG(1), RFLT, '3'}, + {"F7", FP_REG(0), RFLT, '3'}, + { 0 } }; |
