/* * Copyright 1993,1994,1995 Emin Gun Sirer * MIPSI - Mips Instruction Set Simulator. */ #include #include "config.h" #include "main.h" #include "mem.h" #include "inst.h" extern void print(unsigned pc, unsigned steps) { unsigned int inst; unsigned int cop, offset, rs, rt, rd, sa, target; /* for decoding */ while(steps-- > 0) { inst = rnr_mem_word(pc); printf(":\t[0x%08x]\t", inst); rs = (inst >> 21) & 0x1f; rt = (inst >> 16) & 0x1f; offset = inst & 0xffff; switch(inst >> 26) { case SPECIAL: rd = (inst >> 11) & 0x1f; switch(inst & 0x3f) { case ADD: printf("add"); goto reg3; case ADDU: printf("addu"); goto reg3; case SUB: printf("sub"); goto reg3; case SUBU: printf("subu"); goto reg3; case AND: printf("and"); goto reg3; case OR: printf("or"); goto reg3; case XOR: printf("xor"); goto reg3; case NOR: printf("nor"); goto reg3; case SLT: printf("slt"); goto reg3; case SLTU: printf("sltu"); goto reg3; case SLLV: printf("sllv"); goto reg3; case SRLV: printf("srlv"); goto reg3; case SRAV: printf("srav"); goto reg3; reg3: printf(" $%d, $%d, $%d\n", rd, rs, rt); break; case SLL: printf("sll"); goto shift; case SRL: printf("srl"); goto shift; case SRA: printf("sra"); goto shift; shift: sa = (inst >> 6) & 0x1f; printf(" $%d [%x], $%d [%x], %d\n", rd, R[rd], rt, R[rt], sa); break; case SYSCALL: printf("syscall\n"); break; case BREAK: printf("break\n"); break; case JALR: printf("jalr $%d,$%d\n", rd, rs); break; case MFHI: printf("mfhi"); goto regrd; case MFLO: printf("mflo"); goto regrd; regrd: printf(" $%d\n", rd); break; case JR: printf("jr"); goto regrs; case MTHI: printf("mthi"); goto regrs; case MTLO: printf("mtlo"); goto regrs; regrs: printf(" $%d\n", rs); break; case MULT: printf("mult"); goto reg2; case MULTU: printf("multu"); goto reg2; case DIV: printf("div"); goto reg2; case DIVU: printf("divu"); goto reg2; reg2: printf(" $%d, $%d\n", rs, rt); break; } break; case REGIMM: switch((inst >> 16) & 0x1f) { case BLTZ: printf("bltz"); goto branch1; case BLTZAL: printf("bltzal"); goto branch1; case BGEZ: printf("bgez"); goto branch1; case BGEZAL: printf("bgezal"); goto branch1; branch1: target = pc + 4 + (SIGNEX(offset) << 2); printf(" $%d [0x%x], ",rs, R[rs]); break; default: error(Benign, "Unknown REGIMM instruction at 0x%x\n",pc); } break; case J: printf("j"); goto jump; case JAL: printf("jal"); goto jump; jump: target = ((pc + 4) & 0xf0000000) + ((inst & 0x03ffffff) << 2); printf(" "); break; case BNE: printf("bne"); goto branch2; case BLEZ: printf("blez"); goto branch2; case BGTZ: printf("bgtz"); goto branch2; case BEQ: printf("beq"); goto branch2; branch2: target = pc + 4 + (SIGNEX(offset) << 2); printf(" $%d [0x%x], $%d [0x%x], ", rs, R[rs], rt, R[rt]); break; case ADDI: printf("addi"); goto regimm; case ADDIU: printf("addiu"); goto regimm; case SLTI: printf("slti"); goto regimm; case SLTIU: printf("sltiu"); goto regimm; regimm: printf(" $%d, $%d, %d\n", rt, rs, SIGNEX(offset)); break; case ANDI: printf("andi"); goto regimmu; case ORI: printf("ori"); goto regimmu; case XORI: printf("xori"); goto regimmu; regimmu: printf(" $%d, $%d, 0x%0x\n", rt, rs, offset); break; case LUI: printf("lui $%d, 0x%0x\n", rt, offset); break; case LB: printf("lb"); goto mem; case LH: printf("lh"); goto mem; case LW: printf("lw"); goto mem; case LBU: printf("lbu"); goto mem; case LHU: printf("lhu"); goto mem; case SB: printf("sb"); goto mem; case SH: printf("sh"); goto mem; case SW: printf("sw"); goto mem; case LWL: printf("lwl"); goto mem; case LWR: printf("lwr"); goto mem; case SWL: printf("swl"); goto mem; case SWR: printf("swr"); goto mem; mem: printf(" $%d, %d($%d)\n",rt,SIGNEX(offset),rs); break; case COP0: case COP1: case COP2: case COP3: rd = (inst >> 11) & 0x1f; cop = (inst >> 26) - COP0; if(cop != 1) /* Not an FPU operation */ switch(rs) { case MF: printf("mfc%d ", cop); goto rtrd; case CF: printf("cfc%d ", cop); goto rtrd; case MT: printf("mtc%d ", cop); goto rtrd; case CT: printf("ctc%d ", cop); goto rtrd; rtrd: printf("$%d, $%d\n", rt, rd); continue; case BC: bcjump: if(rt == BCF) printf("bc%df ", cop); else printf("bc%dt ", cop); target = pc + 4 + (SIGNEX(offset) << 2); continue; case CO: printf("cop%d function?\n", cop); break; default: error(Benign,"Unknown coprocessor operation at 0x%0x\n",pc); } else { int fmt = ((inst >> 21) & 0x1f) - 16; /* S=0, D=1, W=4 */ int ft = (inst >> 16) & 0x1f; int fs = (inst >> 11) & 0x1f; int fd = (inst >> 6) & 0x1f; switch(rs) { case MF: printf("mfc%d ", cop); goto rtfs; case MT: printf("mtc%d ", cop); goto rtfs; rtfs: printf("$%d, $F%d\n", rt, fs); continue; case CT: printf("ctc%d ", cop); goto frtrd; case CF: printf("cfc%d ", cop); goto frtrd; frtrd: printf("$%d, $F%d\n", rt, rd); continue; case BC: goto bcjump; case FF_S: case FF_D: case FF_W: /* FPU function */ switch(inst & 0x3f) { case FABS: if(fmt == S) printf("abs.s "); else printf("abs.d "); goto fdfs; case FNEG: if(fmt == S) printf("neg.s "); else printf("neg.d "); goto fdfs; case FMOV: if(fmt == S) printf("mov.s "); else printf("mov.d "); goto fdfs; fdfs: printf("$F%d, $F%d\n", fd, fs); continue; case FADD: if(fmt == S) printf("add.s "); else printf("add.d "); goto fdfsft; case FSUB: if(fmt == S) printf("sub.s "); else printf("sub.d "); goto fdfsft; case FDIV: if(fmt == S) printf("div.s "); else printf("div.d "); goto fdfsft; case FMUL: if(fmt == S) printf("mul.s "); else printf("mul.d "); goto fdfsft; fdfsft: printf("$F%d, $F%d, $F%d\n", fd, fs, ft); continue; case C_F: printf("c.f."); goto fpcompare; case CUN: printf("c.un."); goto fpcompare; case CEQ: printf("c.eq."); goto fpcompare; case CUEQ: printf("c.ueq."); goto fpcompare; case COLT: printf("c.olt."); goto fpcompare; case CULT: printf("c.ult."); goto fpcompare; case COLE: printf("c.ole."); goto fpcompare; case CULE: printf("c.ule."); goto fpcompare; case CSF: printf("c.sf."); goto fpcompare; case CNGLE: printf("c.ngle."); goto fpcompare; case CSEQ: printf("c.seq."); goto fpcompare; case CNGL: printf("c.ngl."); goto fpcompare; case CLT: printf("c.lt."); goto fpcompare; case CNGE: printf("c.nge."); goto fpcompare; case CLE: printf("c.le."); goto fpcompare; case CNGT: printf("c.ngt."); goto fpcompare; fpcompare: if(fmt == D) printf("d "); else printf("s "); printf("$F%d, $F%d\n", fs, ft); continue; case FCVTD: printf("cvt.d."); if(fmt == S) printf("s "); else if(fmt == W) printf("w "); /* printf(" GGGG %d -- ",fmt); */ goto fdfs; case FCVTS: printf("cvt.s."); if(fmt == D) printf("d "); else if(fmt == W) printf("w "); goto fdfs; case FCVTW: printf("cvt.w."); if(fmt == D) printf("d "); else if(fmt == S) printf("s "); goto fdfs; default: error(Benign, "Unknown FPU function\n"); } } } case LWC0: printf("lwc0 "); goto mem; case LWC1: printf("lwc1 "); goto fmem; case LWC2: printf("lwc2 "); goto mem; case LWC3: printf("lwc3 "); goto mem; case SWC0: printf("swc0 "); goto mem; case SWC1: printf("swc1 "); goto fmem; case SWC2: printf("swc2 "); goto mem; case SWC3 :printf("swc3 "); goto mem; fmem: printf(" $F%d, %d($%d)\n",rt,SIGNEX(offset),rs); break; default: error(Benign, "Unknown opcode field of inst 0x%x at 0x%x\n", inst, pc); } pc += 4; } }