#include #include #include #include #define Extern extern #include "mips.h" void Iaddi(ulong); void Isw(ulong); void Ilui(ulong); void Iori(ulong); void Ixori(ulong); void Ilw(ulong); void Ijal(ulong); void Ispecial(ulong); void Ibeq(ulong); void Ibeql(ulong); void Iaddiu(ulong); void Ilb(ulong); void Iandi(ulong); void Ij(ulong); void Ibne(ulong); void Ibnel(ulong); void Isb(ulong); void Islti(ulong); void Ibcond(ulong); void Ibgtz(ulong); void Ibgtzl(ulong); void Ilbu(ulong); void Ilhu(ulong); void Ish(ulong); void Ilh(ulong); void Iblez(ulong); void Iblezl(ulong); void Isltiu(ulong); void Iswc1(ulong); void Ilwc1(ulong); void Icop1(ulong); void Ilwl(ulong); void Ilwr(ulong); void Ill(ulong); void Isc(ulong); Inst itab[] = { { Ispecial, 0 }, { Ibcond, "bcond", Ibranch }, { Ij, "j", Ibranch }, { Ijal, "jal", Ibranch }, { Ibeq, "beq", Ibranch }, { Ibne, "bne", Ibranch }, { Iblez, "blez", Ibranch }, { Ibgtz, "bgtz", Ibranch }, { Iaddi, "addi", Iarith }, /* 8 */ { Iaddiu, "addiu", Iarith }, { Islti, "slti", Iarith }, { Isltiu, "sltiu", Iarith }, { Iandi, "andi", Iarith }, { Iori, "ori", Iarith }, { Ixori, "xori", Iarith }, { Ilui, "lui", Iload }, /* 15 */ { undef, "" }, { Icop1, "cop1", Ifloat }, { undef, "" }, { undef, "" }, { Ibeql, "beql" }, { Ibnel, "bnel" }, { Iblezl, "blezl" }, { Ibgtzl, "bgtzl" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { Ilb, "lb", Iload }, { Ilh, "lh", Iload }, { Ilwl, "lwl", Iload }, { Ilw, "lw", Iload }, { Ilbu, "lbu", Iload }, { Ilhu, "lhu", Iload }, { Ilwr, "lwr", Iload }, { undef, "" }, { Isb, "sb", Istore }, { Ish, "sh", Istore }, { undef, "" }, { Isw, "sw", Istore }, /* 43 */ { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { Ill, "ll", Iload}, { Ilwc1, "lwc1", Ifloat }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { Isc, "sc", Istore }, { Iswc1, "swc1", Ifloat }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { 0 } }; void dortrace(void) { int i; for(i = 0; i < 32; i++) if(rtrace & (1<>26) == 0) Bprint(bioout, "special=%d,%d table=%d\n", (reg.ir>>3)&0x7, reg.ir&0x7, reg.ir&0x3f); else Bprint(bioout, "code=%d,%d table=%d\n", reg.ir>>29, (reg.ir>>26)&0x7, reg.ir>>26); */ Bprint(bioout, "Undefined Instruction Trap IR %.8lux\n", inst); longjmp(errjmp, 0); } void Iaddi(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = (short)(inst&0xffff); if(trace) itrace("addi\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs] + imm; } void Iandi(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = inst&0xffff; if(trace) itrace("andi\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs] & imm; } void Isw(ulong inst) { int rt, rb; int off; ulong v; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); v = reg.r[rt]; if(trace) itrace("sw\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, reg.r[rb]+off, v); putmem_w(reg.r[rb]+off, v); } void Isb(ulong inst) { int rt, rb; int off; uchar value; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); value = reg.r[rt]; if(trace) itrace("sb\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, reg.r[rb]+off, value); putmem_b(reg.r[rb]+off, value); } void Ish(ulong inst) { int rt, rb; int off; ushort value; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); value = reg.r[rt]; if(trace) itrace("sh\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, reg.r[rb]+off, value&0xffff); putmem_h(reg.r[rb]+off, value); } void Ilui(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); USED(rs); imm = inst<<16; if(trace) itrace("lui\tr%d,#0x%x", rt, imm); reg.r[rt] = imm; } void Iori(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = inst&0xffff; if(trace) itrace("ori\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs] | imm; } void Ixori(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = inst&0xffff; if(trace) itrace("xori\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs] ^ imm; } void Ilw(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 4)) v = getmem_w(va); itrace("lw\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = getmem_w(va); } void Ilwl(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 4)) v = getmem_w(va & ~3) << ((va & 3) << 3); itrace("lwl\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } v = getmem_w(va & ~3); switch(va & 3) { case 0: reg.r[rt] = v; break; case 1: reg.r[rt] = (v<<8) | (reg.r[rt] & 0xff); break; case 2: reg.r[rt] = (v<<16) | (reg.r[rt] & 0xffff); break; case 3: reg.r[rt] = (v<<24) | (reg.r[rt] & 0xffffff); break; } } void Ilwr(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 4)) v = getmem_w(va & ~3) << ((va & 3) << 3); itrace("lwr\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } v = getmem_w(va & ~3); switch(va & 3) { case 0: break; case 1: reg.r[rt] = (v>>24) | (reg.r[rt] & 0xffffff00); break; case 2: reg.r[rt] = (v>>16) | (reg.r[rt] & 0xffff0000); break; case 3: reg.r[rt] = (v>>8) | (reg.r[rt] & 0xff000000); break; } } void Ilh(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 2)) v = (short)getmem_h(va); itrace("lw\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = (short)getmem_h(va); } void Ilhu(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 2)) v = getmem_h(va) & 0xffff; itrace("lhu\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = getmem_h(va) & 0xffff; } void Ilb(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 1)) v = (schar)getmem_b(va); itrace("lb\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = (schar)getmem_b(va); } void Ilbu(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 1)) v = getmem_b(va) & 0xff; itrace("lbu\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = getmem_b(va) & 0xff; } void Ijal(ulong inst) { ulong npc; Symbol s; npc = (reg.pc&0xF0000000)|((inst&0x3FFFFFF)<<2); if(trace) itrace("jal\t0x%lux", npc); reg.r[31] = reg.pc+8; /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); if(calltree) { findsym(npc, CTEXT, &s); Bprint(bioout, "%8lux %s(", reg.pc, s.name); printparams(&s, reg.r[29]); Bprint(bioout, "from "); printsource(reg.pc); Bputc(bioout, '\n'); } reg.pc = npc-4; } void Ij(ulong inst) { ulong npc; npc = (reg.pc&0xF0000000)|((inst&0x3FFFFFF)<<2); if(trace) itrace("j\t0x%lux", npc); /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } void Ibeq(ulong inst) { int rt, rs; int off; ulong npc; Getrsrt(rs, rt, inst); off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("beq\tr%d,r%d,0x%lux", rs, rt, npc); if(reg.r[rs] == reg.r[rt]) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } } void Ibeql(ulong inst) { int rt, rs; int off; ulong npc; Getrsrt(rs, rt, inst); off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("beq\tr%d,r%d,0x%lux", rs, rt, npc); if(reg.r[rs] == reg.r[rt]) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } else reg.pc += 4; } void Ibgtz(ulong inst) { int rs; int off; ulong npc, r; rs = (inst>>21)&0x1f; off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("bgtz\tr%d,0x%lux", rs, npc); r = reg.r[rs]; if(!(r&SIGNBIT) && r != 0) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Iexec(reg.ir); reg.pc = npc-4; } } void Ibgtzl(ulong inst) { int rs; int off; ulong npc, r; rs = (inst>>21)&0x1f; off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("bgtz\tr%d,0x%lux", rs, npc); r = reg.r[rs]; if(!(r&SIGNBIT) && r != 0) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Iexec(reg.ir); reg.pc = npc-4; } else reg.pc += 4; } void Iblez(ulong inst) { int rs; int off; ulong npc, r; rs = (inst>>21)&0x1f; off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("blez\tr%d,0x%lux", rs, npc); r = reg.r[rs]; if((r&SIGNBIT) || r == 0) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } } void Iblezl(ulong inst) { int rs; int off; ulong npc, r; rs = (inst>>21)&0x1f; off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("blez\tr%d,0x%lux", rs, npc); r = reg.r[rs]; if((r&SIGNBIT) || r == 0) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } else reg.pc += 4; } void Ibne(ulong inst) { int rt, rs; int off; ulong npc; Getrsrt(rs, rt, inst); off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("bne\tr%d,r%d,0x%lux", rs, rt, npc); if(reg.r[rs] != reg.r[rt]) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } } void Ibnel(ulong inst) { int rt, rs; int off; ulong npc; Getrsrt(rs, rt, inst); off = (short)(inst&0xffff); npc = reg.pc + (off<<2) + 4; if(trace) itrace("bne\tr%d,r%d,0x%lux", rs, rt, npc); if(reg.r[rs] != reg.r[rt]) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } else reg.pc += 4; } void Iaddiu(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = (short)(inst&0xffff); if(trace) itrace("addiu\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs]+imm; } void Islti(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = (short)(inst&0xffff); if(trace) itrace("slti\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = reg.r[rs] < imm ? 1 : 0; } void Isltiu(ulong inst) { int rs, rt; int imm; Getrsrt(rs, rt, inst); imm = (short)(inst&0xffff); if(trace) itrace("sltiu\tr%d,r%d,#0x%x", rt, rs, imm); reg.r[rt] = (ulong)reg.r[rs] < (ulong)imm ? 1 : 0; } /* ll and sc are implemented as lw and sw, since we simulate a uniprocessor */ void Ill(ulong inst) { int rt, rb; int off; ulong v, va; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); va = reg.r[rb]+off; if(trace) { v = 0; if(!badvaddr(va, 4)) v = getmem_w(va); itrace("ll\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); } reg.r[rt] = getmem_w(va); } void Isc(ulong inst) { int rt, rb; int off; ulong v; Getrbrt(rb, rt, inst); off = (short)(inst&0xffff); v = reg.r[rt]; if(trace) itrace("sc\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, reg.r[rb]+off, v); putmem_w(reg.r[rb]+off, v); } enum { Bltz = 0, Bgez = 1, Bltzal = 0x10, Bgezal = 0x11, Bltzl = 2, Bgezl = 3, Bltzall = 0x12, Bgezall = 0x13, }; static char *sbcond[] = { [Bltz] "ltz", [Bgez] "gez", [Bltzal] "ltzal", [Bgezal] "gezal", [Bltzl] "ltzl", [Bgezl] "gezl", [Bltzall] "ltzall", [Bgezall] "gezall", }; void Ibcond(ulong inst) { int rs, bran; int off, doit, likely; ulong npc; rs = (inst>>21)&0x1f; bran = (inst>>16)&0x1f; off = (short)(inst&0xffff); doit = 0; likely = 0; npc = reg.pc + (off<<2) + 4; switch(bran) { default: Bprint(bioout, "bcond=%d\n", bran); undef(inst); case Bltzl: likely = 1; case Bltz: if(reg.r[rs]&SIGNBIT) doit = 1; break; case Bgezl: likely = 1; case Bgez: if(!(reg.r[rs]&SIGNBIT)) doit = 1; break; case Bltzall: likely = 1; case Bltzal: reg.r[31] = reg.pc+8; if(reg.r[rs]&SIGNBIT) doit = 1; break; case Bgezall: likely = 1; case Bgezal: reg.r[31] = reg.pc+8; if(!(reg.r[rs]&SIGNBIT)) doit = 1; break; } if(trace) itrace("b%s\tr%d,0x%lux", sbcond[bran], rs, npc); if(doit) { /* Do the delay slot */ reg.ir = ifetch(reg.pc+4); Statbra(); Iexec(reg.ir); reg.pc = npc-4; } else if(likely) reg.pc += 4; }