?? decoder.c
字號:
#include "instr.h"#include "emul.h"#include <stdio.h>/* Anthony Lee: 2006-09-18 */#ifdef __MINGW32__#define sync() _flushall()#else#include <unistd.h> /* for sync() */#endif/* This monster of a switch statement decodes all CPU instructions. I've * decided against an explicit jump table, as such implementation both * increases the code size and introduced additional overhead to the inner * decoder loop. *//* WARNING: The below code currently does not simulate any slips. * This should be fixed soon (it's fairly easy to simulate, too.) */const char* regname[32] = { "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"};int decode(MIPS_State* mstate, Instr instr){ switch (opcode(instr)) { case SPECIAL: { /* Special instructions, decoded using the (function) field */ switch (function(instr)) { case SLL: { // Shift Left Logical if (rd(instr)) { UInt32 x = mstate->gpr[rt(instr)]; int s = shamt(instr); x <<= s; mstate->gpr[rd(instr)] = x; } return nothing_special; } case SRL: { // Shift Right Logical UInt32 x = mstate->gpr[rt(instr)]; int s = shamt(instr); x >>= s; mstate->gpr[rd(instr)] = x; return nothing_special; } case SRA: { // Shift Right Arithmetic UInt32 x = mstate->gpr[rt(instr)]; int s = shamt(instr); x >>= s; mstate->gpr[rd(instr)] = sign_extend_UInt32(x, 32 - s); return nothing_special; } case SLLV: { UInt32 x = mstate->gpr[rt(instr)]; int s = bits(mstate->gpr[rs(instr)], 4, 0); x <<= s; mstate->gpr[rd(instr)] = sign_extend_UInt32(x, 32 - s); return nothing_special; } case SRLV: { // Shift Right Logical Variable UInt32 x = mstate->gpr[rt(instr)]; int s = bits(mstate->gpr[rs(instr)], 4, 0); x >>= s; mstate->gpr[rd(instr)] = sign_extend_UInt32(x, 32 - s); return nothing_special; } case SRAV: { // Shift Right Arithmetic Variable UInt32 x = mstate->gpr[rt(instr)]; int s = bits(mstate->gpr[rs(instr)], 4, 0); x >>= s; mstate->gpr[rd(instr)] = sign_extend_UInt32(x, 32 - s); return nothing_special; } case JR: { // Jump Register mstate->branch_target = mstate->gpr[rs(instr)]; if (mstate->pipeline == branch_delay) printf("Can't handle branch in branch delay slot\n"); return bits(mstate->branch_target, 1, 0) ? instr_addr_error : branch_delay; } case JALR: { // Jump And Link Register mstate->branch_target = mstate->gpr[rs(instr)]; if(rd(instr) != 31) mstate->gpr[rd(instr)] = mstate->pc + 8; else mstate->gpr[31] = mstate->pc + 8; if (mstate->pipeline == branch_delay) printf("Can't handle branch in branch delay slot\n"); return bits(mstate->branch_target, 1, 0) ? instr_addr_error : branch_delay; } case SYSCALL: { // System Call process_syscall(mstate); return nothing_special; } case BREAK: { process_breakpoint(mstate); return nothing_special; } case SYNC: { // Synchronize //Fix me Shi yang 2006-08-08 process_reserved_instruction(mstate); return nothing_special; } case MFHI: { // Move From HI mstate->gpr[rd(instr)] = mstate->hi; return nothing_special; } case MTHI: { // Move To HI mstate->hi = mstate->gpr[rs(instr)]; return nothing_special; } case MFLO: { // Move From LO mstate->gpr[rd(instr)] = mstate->lo; return nothing_special; } case MTLO: { // Move To LO mstate->lo = mstate->gpr[rs(instr)]; return nothing_special; } case DSLLV: { // Doubleword Shift Left Logical Variable process_reserved_instruction(mstate); return nothing_special; } case DSRLV: { // Doubleword Shift Right Logical Variable process_reserved_instruction(mstate); return nothing_special; } case DSRAV: { // Doubleword Shift Right Arithmetic Variable process_reserved_instruction(mstate); return nothing_special; } case MULT: { // Multiply Int32 x = mstate->gpr[rs(instr)]; Int32 y = mstate->gpr[rt(instr)]; multiply(x, y); return nothing_special; } case MULTU: { // Multiply Unsigned UInt32 x = mstate->gpr[rs(instr)]; UInt32 y = mstate->gpr[rt(instr)]; multiply(x, y); return nothing_special; } case DIV: { // Divide Int32 y = (Int32) mstate->gpr[rt(instr)]; Int32 x = (Int32) mstate->gpr[rs(instr)]; divide_Int32(x, y); return nothing_special; } case DIVU: { UInt32 y = (UInt32) mstate->gpr[rt(instr)]; UInt32 x = (UInt32) mstate->gpr[rs(instr)]; divide_UInt32(x, y); return nothing_special; } case DMULT: { // Doubleword Multiply process_reserved_instruction(mstate); return nothing_special; } case DMULTU: { // Doubleword Multiply Unsigned process_reserved_instruction(mstate); return nothing_special; } case DDIV: { // Doubleword Divide process_reserved_instruction(mstate); return nothing_special; } case DDIVU: { // Doubleword Divide Unsigned process_reserved_instruction(mstate); return nothing_special; } case ADD: { // Add UInt32 x = mstate->gpr[rs(instr)]; UInt32 y = mstate->gpr[rt(instr)]; UInt32 z = x + y; // Overflow occurs is sign(x) == sign(y) != sign(z). if (bit(x ^ y, 31) == 0 && bit(x ^ z, 31) != 0) process_integer_overflow(mstate); mstate->gpr[rd(instr)] = z; return nothing_special; } case ADDU: { // Add Unsigned UInt32 x = mstate->gpr[rs(instr)]; UInt32 y = mstate->gpr[rt(instr)]; UInt32 z = x + y; mstate->gpr[rd(instr)] = z; return nothing_special; } case SUB: { // Subtract Int32 x = mstate->gpr[rs(instr)]; Int32 y = mstate->gpr[rt(instr)]; Int32 z = (UInt32)x - (UInt32)y; if ((y < 0 && z < x) || (y > 0 && z > x)) process_integer_overflow(); mstate->gpr[rd(instr)] = z; return nothing_special; } case SUBU: { // Subtract Unsigned UInt32 x = mstate->gpr[rs(instr)]; UInt32 y = mstate->gpr[rt(instr)]; mstate->gpr[rd(instr)] = x - y; return nothing_special; } case AND: { // And mstate->gpr[rd(instr)] = mstate->gpr[rs(instr)] & mstate->gpr[rt(instr)]; return nothing_special; } case OR: { // Or mstate->gpr[rd(instr)] = mstate->gpr[rs(instr)] | mstate->gpr[rt(instr)]; return nothing_special; } case XOR: { // Exclusive Or mstate->gpr[rd(instr)] = mstate->gpr[rs(instr)] ^ mstate->gpr[rt(instr)]; return nothing_special; } case NOR: { // Nor mstate->gpr[rd(instr)] = ~((mstate->gpr[rs(instr)] | mstate->gpr[rt(instr)])); return nothing_special; } case SLT: { // Set On Less Than Int32 x = mstate->gpr[rs(instr)]; Int32 y = mstate->gpr[rt(instr)]; mstate->gpr[rd(instr)] = (x < y); return nothing_special; } case SLTU: { mstate->gpr[rd(instr)] = (mstate->gpr[rs(instr)] < mstate->gpr[rt(instr)]); return nothing_special; } case DADD: { // Doubleword Add process_reserved_instruction(mstate); return nothing_special; } case DADDU: { // Doubleword Add Unsigned process_reserved_instruction(mstate); return nothing_special; } case DSUB: { // Doubleword Subtract process_reserved_instruction(mstate); return nothing_special; } case DSUBU: { // Doubleword Subtract Unsigned process_reserved_instruction(mstate); return nothing_special; } case TGE: { // Trap If Greater Than Or Equal process_reserved_instruction(mstate); return nothing_special; } case TGEU: { // Trap If Greater Than Or Equal Unsigned process_reserved_instruction(mstate); return nothing_special; } case TLT: { // Trap If Less Than process_reserved_instruction(mstate); return nothing_special; } case TLTU: { // Trap If Less Than Unsigned process_reserved_instruction(mstate); return nothing_special; } case TEQ: { // Trap If Equal process_reserved_instruction(mstate); return nothing_special; } case TNE: { // Trap If Not Equal process_reserved_instruction(mstate); return nothing_special; } case DSLL: { // Doubleword Shift Left Logical process_reserved_instruction(mstate); return nothing_special; } case DSRL: { // Doubleword Shift Right Logical process_reserved_instruction(mstate); return nothing_special; } case DSRA: { // Doubleword Shift Right Arithmetic process_reserved_instruction(mstate); return nothing_special; } case DSLL32: { // Doubleword Shift Left Logical + 32 process_reserved_instruction(mstate); return nothing_special; } case DSRL32: { // Doubleword Shift Right Logical + 32 process_reserved_instruction(mstate); return nothing_special; } case DSRA32: { // Doubleword Shift Right Arithmetic + 32 process_reserved_instruction(mstate); return nothing_special; } default: // Reserved instruction process_reserved_instruction(mstate); return nothing_special; } } case REGIMM: { switch (rt(instr)) { case BLTZ: { // Branch On Less Than Zero Int32 x = mstate->gpr[rs(instr)]; if (x < 0) { VA off = sign_extend_UInt32(offset(instr), 16); mstate->branch_target = mstate->pc + 4 + (off << 2); } else { mstate->branch_target = mstate->pc + 8; } if (mstate->pipeline == branch_delay) { printf("Can't handle branch in branch delay slot\n"); } return branch_delay; } case BGEZ: { // Branch On greater Than Zero Int32 x = mstate->gpr[rs(instr)]; if (x >= 0) { VA off = sign_extend_UInt32(offset(instr), 16); mstate->branch_target = mstate->pc + 4 + (off << 2); } else { mstate->branch_target = mstate->pc + 8; } if (mstate->pipeline == branch_delay) { printf("Can't handle branch in branch delay slot\n"); } return branch_delay; } case BLTZL: { // Branch On Less Than Zero Likely return nothing_special; } case BGEZL: { // Branch On Greater Than Or Equal To Zero Likely return nothing_special; } case TGEI: { // Trap If Greater Than Or Equal Immediate return nothing_special; } case TGEIU: { // Trap If Greater Than Or Equal Immediate Unsigned return nothing_special; } case TLTI: { // Trap If Less Than Immediate return nothing_special; } case TLTIU: { // Trap If Less Than Immediate Unsigned return nothing_special; } case TEQI: { // Trap If Equal Immediate return nothing_special; } case TNEI: { // Trap If Not Equal Immediate return nothing_special; } case BLTZAL: { // Branch On Less Than Zero And Link Int32 x = mstate->gpr[rs(instr)]; mstate->gpr[31] = mstate->pc + 8; if (x < 0) { VA off = sign_extend_UInt32(offset(instr), 16); mstate->branch_target = mstate->pc + 4 + (off << 2); } else { mstate->branch_target = mstate->pc + 8; } if (mstate->pipeline == branch_delay) { printf("Can't handle branch in branch delay slot\n"); } return branch_delay; } case BGEZAL: { // Branch On Greater Than Or Equal To Zero And Link Int32 x = mstate->gpr[rs(instr)]; mstate->gpr[31] = mstate->pc + 8; if (x >= 0) { VA off = sign_extend_UInt32(offset(instr), 16); mstate->branch_target = mstate->pc + 4 + (off << 2); } else { mstate->branch_target = mstate->pc + 8; } if (mstate->pipeline == branch_delay) { printf("Can't handle branch in branch delay slot\n"); } return branch_delay; } case BLTZALL: { // Branch On Less Than Zero And Link Likely return nothing_special; } case BGEZALL: { // Branch On Greater Than Or Equal To Zero And Link Likely
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -