## diffname power/fptrap.c 1992/0802 ## diff -e /dev/null /n/bootesdump/1992/0802/sys/src/9/power/fptrap.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "io.h" #include "../port/error.h" typedef struct FPinstr FPinstr; struct FPinstr { ulong op; ulong load; ulong store; ulong branch; ulong fmt; ulong fs; ulong fd; ulong ft; ulong cft; }; enum /* op */ { ABS = 5, ADD = 0, CVTD = 65, CVTS = 64, CVTW = 68, DIV = 3, MOV = 6, MUL = 2, NEG = 7, SUB = 1, }; static int fpunimp(Ureg*, ulong, ulong); static ulong branch(Ureg*, ulong); int fptrap(Ureg *ur, ulong fcr31) { ulong iw, x, npc; int i, ret; savefpregs(&u->fpsave); if(ur->cause & (1<<31)) iw = *(ulong*)(ur->pc+4); else iw = *(ulong*)ur->pc; ret = 0; x = fcr31>>12; fcr31 &= ~(0x3F<<12); for(i=0; i<6; i++,x>>=1) if(x & 1) switch(i){ case 0: /* inexact */ pprint("inexact\n"); return 0; case 1: /* underflow */ pprint("underflow\n"); return 0; case 2: /* overflow */ pprint("overflow\n"); return 0; case 3: /* division by zero */ return 0; case 4: /* invalid operation */ pprint("invalid op\n"); return 0; case 5: /* unimplemented operation */ ret = fpunimp(ur, fcr31, iw); } if(ret){ if(ur->cause & (1<<31)){ npc = branch(ur, fcr31); if(npc) ur->pc = npc; else return 0; }else ur->pc += 4; restfpregs(&u->fpsave, fcr31); } return ret; } static int fpdas(ulong iw, FPinstr *fp) { memset(fp, ~0, sizeof(*fp)); if((iw>>25) == 0x23){ fp->op = iw & ((1<<5)-1); fp->fmt = (iw>>21) & ((1<<4)-1); fp->ft = (iw>>16) & ((1<<5)-1); fp->fs = (iw>>11) & ((1<<5)-1); fp->fd = (iw>>6) & ((1<<5)-1); fp->cft = (iw>>21) & ((1<<5)-1); return 1; } return 0; } static void unpack(FPsave *f, int fmt, int reg, int *sign, int *exp) { *sign = 1; if(f->fpreg[reg] & 0x80000000) *sign = -1; switch(fmt){ case 0: *exp = ((f->fpreg[reg]>>23)&0xFF) - ((1<<7)-2); break; case 1: if(reg & 1){ pprint("unaligned double fp register\n"); reg &= ~1; } pprint("%lux %lux\n", f->fpreg[reg], f->fpreg[reg+1]); *exp = ((f->fpreg[reg]>>20)&0x7FF) - ((1<<10)-2); break; } } static void zeroreg(FPsave *f, int fmt, int reg, int sign) { int size; size = 0; switch(fmt){ case 0: size = 4; break; case 1: if(reg & 1) reg &= ~1; size = 8; break; } memset(&f->fpreg[reg], 0, size); if(sign < 0) f->fpreg[reg] |= 0x80000000; } static int fpunimp(Ureg *ur, ulong fcr31, ulong iw) { FPinstr instr; int ss, st, sd; int es, et, ed; int maxe, maxm; pprint("fpunimp %lux %lux\n", iw, iw>>25); if(!fpdas(iw, &instr)) return 0; pprint("%d\n", instr.op); if(instr.op == ~0) return 0; unpack(&u->fpsave, instr.fmt, instr.fs, &ss, &es); unpack(&u->fpsave, instr.fmt, instr.ft, &st, &et); ed = 0; maxe = 0; maxm = 0; switch(instr.fmt){ case 0: maxe = 1<<7; maxm = 24; break; case 1: maxe = 1<<10; maxm = 53; break; } switch(instr.op){ case SUB: st = -st; case ADD: if(es<-(maxe-maxm) && et<-(maxe-maxm)) ed = -maxe; if(es > et) sd = es; else sd = et; break; case DIV: et = -et; case MUL: sd = 1; if(ss != st) sd = -1; ed = es + et; break; default: pprint("unknown unimplemented fp op\n"); return 0; } if(ed <= -(maxe-4)){ /* guess: underflow */ pprint("guess underflow\n"); zeroreg(&u->fpsave, instr.fmt, instr.fd, sd); return 1; } return 0; } static ulong* reg(Ureg *ur, int regno) { /* regs go from R31 down in ureg, R29 is missing */ if(regno == 31) return &ur->r31; if(regno == 30) return &ur->r30; if(regno == 29) return &ur->sp; return (&ur->r28) + (28-regno); } static ulong branch(Ureg *ur, ulong fcr31) { ulong iw, npc, rs, rt, rd, offset; iw = *(ulong*)ur->pc; rs = (iw>>21) & 0x1F; if(rs) rs = *reg(ur, rs); rt = (iw>>16) & 0x1F; if(rt) rt = *reg(ur, rt); offset = iw & ((1<<16)-1); if(offset & (1<<15)) /* sign extend */ offset |= ~((1<<16)-1); offset <<= 2; /* * Integer unit jumps first */ switch(iw>>26){ case 0: /* SPECIAL: JR or JALR */ switch(iw&0x3F){ case 0x09: /* JALR */ rd = (iw>>11) & 0x1F; if(rd) *reg(ur, rd) = ur->pc+8; /* fall through */ case 0x08: /* JR */ return rs; default: return 0; } case 1: /* BCOND */ switch((iw>>16) & 0x1F){ case 0x10: /* BLTZAL */ ur->r31 = ur->pc + 8; /* fall through */ case 0x00: /* BLTZ */ if((long)rs < 0) return ur->pc+4 + offset; return ur->pc + 8; case 0x11: /* BGEZAL */ ur->r31 = ur->pc + 8; /* fall through */ case 0x01: /* BGEZ */ if((long)rs >= 0) return ur->pc+4 + offset; return ur->pc + 8; default: return 0; } case 3: /* JAL */ ur->r31 = ur->pc+8; /* fall through */ case 2: /* JMP */ npc = iw & ((1<<26)-1); npc <<= 2; return npc | (ur->pc&0xF0000000); case 4: /* BEQ */ if(rs == rt) return ur->pc+4 + offset; return ur->pc + 8; case 5: /* BNE */ if(rs != rt) return ur->pc+4 + offset; return ur->pc + 8; case 6: /* BLEZ */ if((long)rs <= 0) return ur->pc+4 + offset; return ur->pc + 8; case 7: /* BGTZ */ if((long)rs > 0) return ur->pc+4 + offset; return ur->pc + 8; } /* * Floating point unit jumps */ if((iw>>26) == 0x11) /* COP1 */ switch((iw>>16) & 0x3C1){ case 0x101: /* BCT */ case 0x181: /* BCT */ if(fcr31 & (1<<23)) return ur->pc+4 + offset; return ur->pc + 8; case 0x100: /* BCF */ case 0x180: /* BCF */ if(!(fcr31 & (1<<23))) return ur->pc+4 + offset; return ur->pc + 8; } pprint("fptrap: can't do jump %lux\n", iw); return 0; } . ## diffname power/fptrap.c 1992/0803 ## diff -e /n/bootesdump/1992/0802/sys/src/9/power/fptrap.c /n/bootesdump/1992/0803/sys/src/9/power/fptrap.c 314d 312c /* shouldn't get here */ . 201,202c zeroreg(&u->fpsave, fmt, fd, sd); . 197c /* shouldn't get here */ . 195a case CVTS: if(fmt != 1) return 0; fmt = 0; /* convert FROM double TO single */ maxe = 1<<7; ed = es; sd = ss; break; . 176c switch(op){ case ABS: u->fpsave.fpreg[fd] &= ~0x80000000; return 1; case NEG: u->fpsave.fpreg[fd] ^= 0x80000000; return 1; . 166c switch(fmt){ . 158,162c op = iw & ((1<<6)-1); fmt = (iw>>21) & ((1<<4)-1); ft = (iw>>16) & ((1<<5)-1); fs = (iw>>11) & ((1<<5)-1); fd = (iw>>6) & ((1<<5)-1); unpack(&u->fpsave, fmt, fs, &ss, &es); unpack(&u->fpsave, fmt, ft, &st, &et); . 155,156c if((iw>>25) != 0x23) . 153a ulong op, fmt, ft, fs, fd; . 150d 148c fpunimp(ulong iw) . 119,120d 116,117c if(reg & 1) /* shouldn't happen */ . 89,104d 86c return 1; . 52,75c if(fpunimp(iw)){ . 47a if((fcr31&(1<<17)) == 0) return 0; . 44,45c ulong iw, npc; . 38c static int fpunimp(ulong); . 28,30c CVTD = 33, CVTS = 32, CVTW = 36, . 10,23d ## diffname power/fptrap.c 1992/0806 ## diff -e /n/bootesdump/1992/0803/sys/src/9/power/fptrap.c /n/bootesdump/1992/0806/sys/src/9/power/fptrap.c 48c u->fpsave.fpstatus = fcr31 & ~(1<<17); . 32a u->p->fpstate = FPinactive; /* will get turned on again in trap() */ . ## diffname power/fptrap.c 1992/0822 ## diff -e /n/bootesdump/1992/0806/sys/src/9/power/fptrap.c /n/bootesdump/1992/0822/sys/src/9/power/fptrap.c 161,162c default: /* probably a compare */ . 51c return 0; . 49a return 1; . ## diffname power/fptrap.c 1992/1128 ## diff -e /n/bootesdump/1992/0822/sys/src/9/power/fptrap.c /n/bootesdump/1992/1128/sys/src/9/power/fptrap.c 32,33d ## diffname power/fptrap.c 1992/1129 ## diff -e /n/bootesdump/1992/1128/sys/src/9/power/fptrap.c /n/bootesdump/1992/1129/sys/src/9/power/fptrap.c 164a /* Set underflow exception and sticky */ u->fpsave.fpstatus |= (1<<3)|(1<<13); . 58a . 50c else ur->pc += 4; u->fpsave.fpstatus = u->fpsave.fpstatus & ~(1<<17); . 38,48c if(fpunimp(iw) == 0) return; if(ur->cause & (1<<31)){ npc = branch(ur, u->fpsave.fpstatus); if(npc == 0) return; ur->pc = npc; . 32,33c if((u->fpsave.fpstatus&(1<<17)) == 0) return; . 27,28c void fptrap(Ureg *ur) . ## diffname power/fptrap.c 1993/0107 ## diff -e /n/bootesdump/1992/1129/sys/src/9/power/fptrap.c /n/bootesdump/1993/0107/sys/src/9/power/fptrap.c 34a print("fpt: %d %s %lux\n", u->p->pid, u->p->text, u->fpsave.fpstatus); . ## diffname power/fptrap.c 1993/0319 ## diff -e /n/bootesdump/1993/0107/sys/src/9/power/fptrap.c /n/bootesdump/1993/0319/sys/src/9/power/fptrap.c 168c if(ed <= -(maxe-5)){ /* guess: underflow */ . ## diffname power/fptrap.c 1993/0403 ## diff -e /n/bootesdump/1993/0319/sys/src/9/power/fptrap.c /n/bootesdump/1993/0403/sys/src/9/power/fptrap.c 195d 193c ulong npc, rs, rt, rd, offset; . 191c branch(Ureg *ur, ulong iw, ulong fcr31) . 54c u->fpsave.fpstatus &= ~(1<<17); . 46c npc = branch(ur, iw_4, u->fpsave.fpstatus); . 39,40c } . 37c if(tlbp(ur->pc) == 0) panic("not in tlb %lux\n", ur->pc); iw = *(ulong*)ur->pc; iw_4 = iw; if(ur->cause & (1<<31)){ if(tlbp(ur->pc+4) == 0) panic("not in tlb %lux\n", ur->pc+4); . 35c print("fpt: %d %s %lux %lux\n", u->p->pid, u->p->text, u->fpsave.fpstatus, ur->pc); . 30c ulong iw, iw_4, npc; . 25c static ulong branch(Ureg*, ulong, ulong); . ## diffname power/fptrap.c 1993/0416 ## diff -e /n/bootesdump/1993/0403/sys/src/9/power/fptrap.c /n/bootesdump/1993/0416/sys/src/9/power/fptrap.c 34a if((counter&0xff) == 0) . 30a static int counter; . ## diffname power/fptrap.c 1993/0417 ## diff -e /n/bootesdump/1993/0416/sys/src/9/power/fptrap.c /n/bootesdump/1993/0417/sys/src/9/power/fptrap.c 37d ## diffname power/fptrap.c 1993/0501 ## diff -e /n/bootesdump/1993/0417/sys/src/9/power/fptrap.c /n/fornaxdump/1993/0501/sys/src/brazil/power/fptrap.c 200a iw = *(ulong*)ur->pc; . 199c ulong iw, npc, rs, rt, rd, offset; . 197c branch(Ureg *ur, ulong fcr31) . 177c up->fpsave.fpstatus |= (1<<3)|(1<<13); . 174,175c if(ed <= -(maxe-4)){ /* guess: underflow */ zeroreg(&up->fpsave, fmt, fd, sd); . 139c up->fpsave.fpreg[fd] ^= 0x80000000; . 135c up->fpsave.fpreg[fd] &= ~0x80000000; . 118,119c unpack(&up->fpsave, fmt, fs, &ss, &es); unpack(&up->fpsave, fmt, ft, &st, &et); . 60c up->fpsave.fpstatus = up->fpsave.fpstatus & ~(1<<17); . 52c npc = branch(ur, up->fpsave.fpstatus); . 46c else iw = *(ulong*)ur->pc; . 38,44c if(ur->cause & (1<<31)) . 36c print("fpt: %d %s %lux\n", up->pid, up->text, up->fpsave.fpstatus); . 33c if((up->fpsave.fpstatus&(1<<17)) == 0) . 30,31c ulong iw, npc; . 25c static ulong branch(Ureg*, ulong); . ## diffname power/fptrap.c 1997/0327 # deleted ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/power/fptrap.c /n/emeliedump/1997/0327/sys/src/brazil/power/fptrap.c 1,283d