vfp emulation is not necessary for these machines. this is done for consistency. Reference: /n/atom/patch/applied2013/vfpemu Date: Sat Jun 15 04:22:23 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/teg2/fpiarm.c Sat Jun 15 04:22:00 2013 +++ /sys/src/9/teg2/fpiarm.c Sat Jun 15 04:22:00 2013 @@ -15,18 +15,13 @@ #include "arm.h" #include "../port/fpi.h" -#define ARM7500 /* emulate old pre-VFP opcodes */ - /* undef this if correct kernel r13 isn't in Ureg; * check calculation in fpiarm below */ + #define REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)])) -#ifdef ARM7500 #define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7]) -#else -#define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&(Nfpregs - 1)]) -#endif typedef struct FP2 FP2; typedef struct FP1 FP1; @@ -63,7 +58,7 @@ OFR(r12), OFR(r13), OFR(r14), OFR(pc), }; -static Internal fpconst[8] = { /* indexed by op&7 (ARM 7500 FPA) */ +static Internal fpconst[8] = { /* indexed by op&7 */ /* s, e, l, h */ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */ @@ -163,10 +158,6 @@ } } -/* - * ARM 7500 FPA opcodes - */ - static FP1 optab1[16] = { /* Fd := OP Fm */ [0] {"MOVF", fmov}, [1] {"NEGF", fmovn}, @@ -458,15 +449,102 @@ } } +void +casemu(ulong pc, ulong op, Ureg *ur) +{ + ulong *rp, ro, rn, *rd; + + USED(pc); + + rp = (ulong*)ur; + ro = rp[op>>16 & 0x7]; + rn = rp[op>>0 & 0x7]; + rd = rp + (op>>12 & 0x7); + rp = (ulong*)*rd; + validaddr((ulong)rp, 4, 1); + splhi(); + if(*rd = (*rp == ro)) + *rp = rn; + spllo(); +} + +int ldrexvalid; + +void +ldrex(ulong pc, ulong op, Ureg *ur) +{ + ulong *rp, *rd, *addr; + + USED(pc); + + rp = (ulong*)ur; + rd = rp + (op>>16 & 0x7); + addr = (ulong*)*rd; + validaddr((ulong)addr, 4, 0); + ldrexvalid = 1; + rp[op>>12 & 0x7] = *addr; + if(fpemudebug) + print("ldrex, r%ld = [r%ld]@0x%8.8p = 0x%8.8lux", + op>>12 & 0x7, op>>16 & 0x7, addr, rp[op>>12 & 0x7]); +} + +void +clrex(ulong, ulong, Ureg *) +{ + ldrexvalid = 0; + if(fpemudebug) + print("clrex"); +} + +void +strex(ulong pc, ulong op, Ureg *ur) +{ + ulong *rp, rn, *rd, *addr; + + USED(pc); + + rp = (ulong*)ur; + rd = rp + (op>>16 & 0x7); + rn = rp[op>>0 & 0x7]; + addr = (ulong*)*rd; + validaddr((ulong)addr, 4, 1); + splhi(); + if(ldrexvalid){ + if(fpemudebug) + print("strex valid, [r%ld]@0x%8.8p = r%ld = 0x%8.8lux", + op>>16 & 0x7, addr, op>>0 & 0x7, rn); + *addr = rn; + ldrexvalid = 0; + rp[op>>12 & 0x7] = 0; + }else{ + if(fpemudebug) + print("strex invalid, r%ld = 1", op>>16 & 0x7); + rp[op>>12 & 0x7] = 1; + } + spllo(); +} + +struct { + ulong opc; + ulong mask; + void (*f)(ulong, ulong, Ureg*); +} specialopc[] = { + { 0x01900f9f, 0x0ff00fff, ldrex }, + { 0x01800f90, 0x0ff00ff0, strex }, + { 0xf57ff01f, 0xffffffff, clrex }, + { 0x0ed00100, 0x0ef08100, casemu }, + { 0x00000000, 0x00000000, nil } +}; + /* * returns the number of FP instructions emulated */ int fpiarm(Ureg *ur) { - ulong op, o, cp; + ulong op, o; FPsave *ufp; - int n; + int i, n; if(up == nil) panic("fpiarm not in a process"); @@ -475,15 +553,11 @@ * because all the emulated fp state is in the proc structure, * it need not be saved/restored */ - switch(up->fpstate){ - case FPactive: - case FPinactive: - error("illegal instruction: emulated fpu opcode in VFP mode"); - case FPinit: - assert(sizeof(Internal) <= sizeof(ufp->regs[0])); - up->fpstate = FPemu; + if(up->fpstate != FPactive){ +// assert(sizeof(Internal) == sizeof(ufp->regs[0])); + up->fpstate = FPactive; ufp->control = 0; - ufp->status = (0x01<<28)|(1<<12); /* sw emulation, alt. C flag */ + ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */ for(n = 0; n < 8; n++) FR(ufp, n) = fpconst[0]; } @@ -493,14 +567,20 @@ if(fpemudebug) print("%#lux: %#8.8lux ", ur->pc, op); o = (op>>24) & 0xF; - cp = (op>>8) & 0xF; - if(!ISFPAOP(cp, o)) + if(condok(ur->psr, op>>28)){ + for(i = 0; specialopc[i].f; i++) + if((op & specialopc[i].mask) == specialopc[i].opc) + break; + if(specialopc[i].f) + specialopc[i].f(ur->pc, op, ur); + else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC) + break; + else + fpemu(ur->pc, op, ur, ufp); + }else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC) break; - if(condok(ur->psr, op>>28)) - fpemu(ur->pc, op, ur, ufp); - ur->pc += 4; /* pretend cpu executed the instr */ + ur->pc += 4; } - if(fpemudebug) - print("\n"); + if(fpemudebug) print("\n"); return n; } --- /sys/src/9/omap/fpiarm.c Sat Jun 15 04:22:00 2013 +++ /sys/src/9/omap/fpiarm.c Sat Jun 15 04:22:00 2013 @@ -549,7 +549,8 @@ if(up == nil) panic("fpiarm not in a process"); ufp = &up->fpsave; - /* because all the state is in the proc structure, + /* + * because all the emulated fp state is in the proc structure, * it need not be saved/restored */ if(up->fpstate != FPactive){