#include #include #include #include #define Extern extern #include "sparc.h" void add(ulong); void and(ulong); void or(ulong); void xor(ulong); void sub(ulong); void andn(ulong); void xnor(ulong); void subcc(ulong); void sll(ulong); void srl(ulong); void sra(ulong); void jmpl(ulong); void andcc(ulong); void xorcc(ulong); void andncc(ulong); void wry(ulong); void rdy(ulong); void mulscc(ulong); void fcmp(ulong); void farith(ulong); void addcc(ulong); void addx(ulong); void addxcc(ulong); void orcc(ulong); void orncc(ulong); void xnorcc(ulong); void orn(ulong); Inst op2[] = { { add, "add", Iarith }, { and, "and", Iarith }, { or, "or", Iarith }, { xor, "xor", Iarith }, { sub, "sub", Iarith }, { andn, "andn", Iarith }, { orn, "orn", Inop }, { xnor, "xnor", Iarith }, { addx, "addx", Iarith }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { addcc, "addcc", Iarith }, { andcc, "andcc", Iarith }, { orcc, "orcc", Iarith }, { xorcc, "xorcc", Iarith }, { subcc, "subcc", Iarith }, { andncc, "andncc",Iarith }, { orncc, "orncc", Iarith }, { xnorcc, "xnorcc",Iarith }, { addxcc, "addxcc",Iarith }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { mulscc, "mulscc", Iarith }, { sll, "sll", Iarith }, { srl, "srl", Iarith }, { sra, "sra", Iarith }, { rdy, "rdy", Ireg }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { wry, "wry", Ireg }, { undef, "" }, { undef, "" }, { undef, "" }, { farith, "farith", Ifloat }, { fcmp, "fcmp", Ifloat }, { undef, "" }, { undef, "" }, { jmpl, "jmpl", Ibranch }, { undef, "" }, { ta, "ta", Isyscall }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { 0 } }; void st(ulong); void stb(ulong); void sth(ulong); void ld(ulong); void ldub(ulong); void ldsb(ulong); void lduh(ulong); void stf(ulong); void ldf(ulong); void ldsh(ulong); void std(ulong); void ldd(ulong); void ldstub(ulong); void swap(ulong); void lddf(ulong); void stdf(ulong); Inst op3[] = { { ld, "ld", Iload }, { ldub, "ldub", Iload }, { lduh, "lduh", Iload }, { ldd, "ldd", Iload }, { st, "st", Istore }, { stb, "stb", Istore }, { sth, "sth", Istore }, { std, "std", Istore }, { undef, "" }, { ldsb, "ldsb", Iload }, { ldsh, "ldsh", Iload }, { undef, "" }, { undef, "" }, { ldstub, "ldstub", Iload }, { undef, "" }, { swap, "swap", Iload }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { ldf, "ldf", Ifloat }, { undef, "" }, { undef, "" }, { lddf, "lddf", Ifloat }, { stf, "stf", Ifloat }, { undef, "" }, { undef, "" }, { stdf, "stdf", Ifloat }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { undef, "" }, { 0 } }; void sethi(ulong); void bicc(ulong); void fbcc(ulong); void call(ulong); Inst op0[] = { { undef, "" }, { undef, "" }, { bicc, "bicc", Ibranch }, { undef, "" }, { sethi, "sethi",Iarith }, { undef, "" }, { fbcc, "fbcc", Ibranch }, { undef, "" }, /* This is a fake and connot be reached by op0 decode */ { call, "call", Ibranch }, { 0 } }; void call(ulong); void run(void) { do { reg.r[0] = 0; reg.ir = ifetch(reg.pc); switch(reg.ir>>30) { case 0: ci = &op0[(reg.ir>>22)&0x07]; ci->count++; (*ci->func)(reg.ir); break; case 1: ci = &op0[8]; ci->count++; call(reg.ir); break; case 2: ci = &op2[(reg.ir>>19)&0x3f]; ci->count++; (*ci->func)(reg.ir); break; case 3: ci = &op3[(reg.ir>>19)&0x3f]; ci->count++; (*ci->func)(reg.ir); break; } reg.pc += 4; if(bplist) brkchk(reg.pc, Instruction); }while(--count); } void ilock(int rd) { ulong ir; ir = getmem_4(reg.pc+4); switch(ir>>30) { case 0: case 1: break; case 2: if(((ir>>20)&0x1f) == 0x1a) /* floating point */ break; case 3: if(rd == ((ir>>14)&0x1f)) { loadlock++; break; } if(ir&IMMBIT) break; if(rd == (ir&0x1f)) loadlock++; break; } } void delay(ulong npc) { ulong opc; reg.r[0] = 0; if(reg.ir != NOP) ci->useddelay++; switch(reg.ir>>30) { case 0: ci = &op0[(reg.ir>>22)&0x07]; ci->count++; (*ci->func)(reg.ir); break; case 1: ci = &op0[8]; ci->count++; call(reg.ir); break; case 2: ci = &op2[(reg.ir>>19)&0x3f]; ci->count++; opc = reg.pc; reg.pc = npc-4; (*ci->func)(reg.ir); reg.pc = opc; break; case 3: ci = &op3[(reg.ir>>19)&0x3f]; ci->count++; opc = reg.pc; reg.pc = npc-4; (*ci->func)(reg.ir); reg.pc = opc; break; } } void undef(ulong ir) { /* Bprint(bioout, "op=%d op2=%d op3=%d\n", ir>>30, (ir>>21)&0x7, (ir>>19)&0x3f); */ Bprint(bioout, "illegal_instruction IR #%.8lux\n", ir); longjmp(errjmp, 0); } void sub(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("sub\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("sub\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] - v; } void sll(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("sll\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]&0x1F; if(trace) itrace("sll\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] << v; } void srl(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("srl\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("srl\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = (ulong)reg.r[rs1] >> v; } void sra(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("sra\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("sra\tr%d,r%d,r%d", rs1, rs2, rd); } if(reg.r[rs1]&SIGNBIT) reg.r[rd] = reg.r[rs1]>>v | ~((1<<(32-v))-1); else reg.r[rd] = reg.r[rs1]>>v; } void subcc(ulong ir) { long v; int b31rs1, b31op2, b31res, r, rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("subcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("subcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] - v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; b31rs1 = reg.r[rs1]>>31; b31op2 = v>>31; b31res = r>>31; if((b31rs1 & ~b31op2 & ~b31res)|(~b31rs1 & b31op2 & b31res)) reg.psr |= PSR_v; if((~b31rs1 & b31op2)|(b31res & (~b31rs1|b31op2))) reg.psr |= PSR_c; reg.r[rd] = r; } void add(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("add\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("add\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] + v; } void addcc(ulong ir) { long v, r; int rd, rs1, rs2, b31rs1, b31op2, b31r; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("addcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("addcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] + v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; b31rs1 = reg.r[rs1]>>31; b31op2 = v>>31; b31r = r>>31; if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r)) reg.psr |= PSR_v; if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2))) reg.psr |= PSR_c; reg.r[rd] = r; } void addx(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("addx\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("addx\tr%d,r%d,r%d", rs1, rs2, rd); } if(reg.psr&PSR_c) v++; reg.r[rd] = reg.r[rs1] + v; } void addxcc(ulong ir) { long r, v; int rd, rs1, rs2, b31rs1, b31op2, b31r; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("addxcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("addxcc\tr%d,r%d,r%d", rs1, rs2, rd); } if(reg.psr&PSR_c) v++; r = reg.r[rs1] + v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; b31rs1 = reg.r[rs1]>>31; b31op2 = v>>31; b31r = r>>31; if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r)) reg.psr |= PSR_v; if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2))) reg.psr |= PSR_c; reg.r[rd] = r; } void wry(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(rd != 0) undef(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("wry\tr%d,#0x%x,Y", rs1, v); } else { v = reg.r[rs2]; if(trace) itrace("wry\tr%d,r%d,Y", rs1, rs2); } reg.Y = reg.r[rs1] + v; } void rdy(ulong ir) { int rd, rs1, rs2; getrop23(ir); USED(rs2); if(rs1 != 0) undef(ir); if(trace) itrace("rdy\tY,r%d", rd); reg.r[rd] = reg.Y; } void and(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("and\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("and\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] & v; } void andcc(ulong ir) { long v, r; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("andcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("andcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] & v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void orcc(ulong ir) { long v, r; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("orcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("orcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] | v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void mulscc(ulong ir) { int b, n, v, rd, rs1, rs2; long o1, o2, r, b31o1, b31o2, b31r; getrop23(ir); if(ir&IMMBIT) { ximm(o2, ir); if(trace) itrace("mulscc\tr%d,#0x%x,r%d", rs1, o2, rd); } else { o2 = reg.r[rs2]; if(trace) itrace("mulscc\tr%d,r%d,r%d", rs1, rs2, rd); } o1 = reg.r[rs1]>>1; n = reg.psr&PSR_n ? 1 : 0; v = reg.psr&PSR_v ? 1 : 0; o1 |= (n ^ v)<<31; if((reg.Y&1) == 0) o2 = 0; r = o1 + o2; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; b31o1 = o1>>31; b31o2 = o2>>31; b31r = r>>31; if((b31o1 & b31o2 & ~b31r) | (~b31o1 & ~b31o2 & b31r)) reg.psr |= PSR_v; if((b31o1 & b31o2) | (~b31r & (b31o1 | b31o2))) reg.psr |= PSR_c; b = reg.r[rs1]&1; reg.Y = (reg.Y>>1)|(b<<31); reg.r[rd] = r; } void or(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("or\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("or\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] | v; } void xor(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("xor\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("xor\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] ^ v; } void xorcc(ulong ir) { long v, r; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("xorcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("xorcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] ^ v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void andn(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("andn\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("andn\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] & ~v; } void andncc(ulong ir) { long v, r; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("andncc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("andncc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] & ~v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void orn(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(rd == 0 && rs1 == 0) /* ken used orn r0,r0,r0 as nop */ nopcount++; if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("orn\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("orn\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] | ~v; } void orncc(ulong ir) { long r, v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("orncc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("orncc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] | ~v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void xnor(ulong ir) { long v; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("xnor\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("xnor\tr%d,r%d,r%d", rs1, rs2, rd); } reg.r[rd] = reg.r[rs1] ^ ~v; } void xnorcc(ulong ir) { long v, r; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(v, ir); if(trace) itrace("xnorcc\tr%d,#0x%x,r%d", rs1, v, rd); } else { v = reg.r[rs2]; if(trace) itrace("xnorcc\tr%d,r%d,r%d", rs1, rs2, rd); } r = reg.r[rs1] ^ ~v; reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); if(r == 0) reg.psr |= PSR_z; if(r < 0) reg.psr |= PSR_n; reg.r[rd] = r; } void st(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("st\tr%d,0x%lux(r%d) %lux=%lux", rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("st\tr%d,[r%d+r%d] %lux=%lux", rd, rs1, rs2, ea, reg.r[rd]); } putmem_w(ea, reg.r[rd]); } void std(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("std\tr%d,0x%lux(r%d) %lux=%lux", rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("std\tr%d,[r%d+r%d] %lux=%lux", rd, rs1, rs2, ea, reg.r[rd]); } putmem_w(ea, reg.r[rd]); putmem_w(ea+4, reg.r[rd+1]); } void stb(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("stb\tr%d,0x%lux(r%d) %lux=%lux", rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xff); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("stb\tr%d,[r%d+r%d] %lux=%lux", rd, rs1, rs2, ea, reg.r[rd]&0xff); } putmem_b(ea, reg.r[rd]); } void sth(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("sth\tr%d,0x%lux(r%d) %lux=%lux", rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xffff); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("sth\tr%d,[r%d+r%d] %lux=%lux", rd, rs1, rs2, ea, reg.r[rd]&0xffff); } putmem_h(ea, reg.r[rd]); } void ld(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ld\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ld\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = getmem_w(ea); ilock(rd); } void swap(ulong ir) { ulong t, ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("swap\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("swap\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } t = reg.r[rd]; reg.r[rd] = getmem_w(ea); putmem_w(ea, t); } void ldd(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ldd\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ldd\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = getmem_w(ea); reg.r[rd+1] = getmem_w(ea+4); } void ldub(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ldub\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ldub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = getmem_b(ea) & 0xff; ilock(rd); } void ldstub(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ldstub\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ldstub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = getmem_b(ea) & 0xff; putmem_b(ea, 0xff); } void ldsb(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ldsb\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ldsb\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = (schar)getmem_b(ea); ilock(rd); } void lduh(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("lduh\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("lduh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = getmem_h(ea) & 0xffff; ilock(rd); } void ldsh(ulong ir) { ulong ea; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); if(trace) itrace("ldsh\tr%d,0x%lux(r%d) ea=%lux", rd, ea, rs1, ea+reg.r[rs1]); ea += reg.r[rs1]; } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("ldsh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); } reg.r[rd] = (short)getmem_h(ea); ilock(rd); } void sethi(ulong ir) { int rd; ulong v; rd = (ir>>25)&0x1f; v = (ir&0x3FFFFF)<<10; if(rd == 0) nopcount++; if(trace) itrace("sethi\t0x%lux,r%d", v, rd); reg.r[rd] = v; } void call(ulong ir) { Symbol s; ulong npc; npc = (ir<<2) + reg.pc; if(trace) itrace("call\t%lux", npc); ci->taken++; reg.r[15] = reg.pc; reg.ir = ifetch(reg.pc+4); delay(npc); if(calltree) { findsym(npc, CTEXT, &s); Bprint(bioout, "%8lux %s(", reg.pc, s.name); printparams(&s, reg.r[1]); Bprint(bioout, "from "); printsource(reg.pc); Bputc(bioout, '\n'); } npc -= 4; reg.pc = npc; } void jmpl(ulong ir) { ulong ea, o; Symbol s; int rd, rs1, rs2; getrop23(ir); if(ir&IMMBIT) { ximm(ea, ir); o = ea; if(trace) itrace("jmpl\t0x%lux(r%d),r%d", ea, rs1, rd); ea += reg.r[rs1]; if(calltree && rd == 0 && o == 8) { findsym(ea-4, CTEXT, &s); Bprint(bioout, "%8lux return to %lux %s r7=%lux\n", reg.pc, ea-4, s.name, reg.r[7]); } } else { ea = reg.r[rs1] + reg.r[rs2]; if(trace) itrace("jmpl\t[r%d+r%d],r%d", rs1, rs2, rd); } ci->taken++; reg.r[rd] = reg.pc; reg.ir = ifetch(reg.pc+4); delay(ea); reg.pc = ea-4; } void bicc(ulong ir) { char *op; ulong npc, anul, ba; int takeit, z, v, n, c; SET(op, takeit); ba = 0; switch((ir>>25)&0x0F) { case 0: op = "bn"; takeit = 0; break; case 1: op = "be"; takeit = reg.psr&PSR_z; break; case 2: op = "ble"; z = reg.psr&PSR_z ? 1 : 0; v = reg.psr&PSR_v ? 1 : 0; n = reg.psr&PSR_n ? 1 : 0; takeit = z | (n ^ v); break; case 3: op = "bl"; v = reg.psr&PSR_v ? 1 : 0; n = reg.psr&PSR_n ? 1 : 0; takeit = n ^ v; break; case 4: op = "bleu"; z = reg.psr&PSR_z ? 1 : 0; c = reg.psr&PSR_c ? 1 : 0; takeit = c | z; break; case 5: op = "bcs"; takeit = reg.psr&PSR_c; break; case 6: op = "bneg"; takeit = reg.psr&PSR_n; break; case 7: op = "bvs"; takeit = reg.psr&PSR_v; break; case 8: op = "ba"; ba = 1; takeit = 1; break; case 9: op = "bne"; takeit = !(reg.psr&PSR_z); break; case 10: op = "bg"; z = reg.psr&PSR_z ? 1 : 0; v = reg.psr&PSR_v ? 1 : 0; n = reg.psr&PSR_n ? 1 : 0; takeit = !(z | (n ^ v)); break; case 11: op = "bge"; v = reg.psr&PSR_v ? 1 : 0; n = reg.psr&PSR_n ? 1 : 0; takeit = !(n ^ v); break; case 12: op = "bgu"; z = reg.psr&PSR_z ? 1 : 0; c = reg.psr&PSR_c ? 1 : 0; takeit = !(c | z); break; case 13: op = "bcc"; takeit = !(reg.psr&PSR_c); break; case 14: op = "bpos"; takeit = !(reg.psr&PSR_n); break; case 15: op = "bvc"; takeit = !(reg.psr&PSR_v); break; } npc = ir & 0x3FFFFF; if(npc & (1<<21)) npc |= ~((1<<22)-1); npc = (npc<<2) + reg.pc; anul = ir&ANUL; if(trace) { if(anul) itrace("%s,a\t%lux", op, npc); else itrace("%s\t%lux", op, npc); } if(takeit == 0) { reg.pc += 4; if(anul == 0) { reg.ir = ifetch(reg.pc); delay(reg.pc+4); } else anulled++; return; } ci->taken++; if(ba && anul) { anulled++; reg.pc = npc-4; return; } reg.ir = ifetch(reg.pc+4); delay(npc); reg.pc = npc-4; }