📄 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() */#endifextern FILE *skyeye_logfd;/* 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); mstate->gpr[rd(instr)] = x; 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); mstate->gpr[rd(instr)] = x; 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 MOVZ: { if(!mstate->gpr[rt(instr)]) mstate->gpr[rd(instr)] = mstate->gpr[rs(instr)]; return nothing_special; } case MOVN: { if(mstate->gpr[rt(instr)]) mstate->gpr[rd(instr)] = mstate->gpr[rs(instr)]; 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); fprintf(stderr,"workaround for break instruction, pc=0x%x\n ", mstate->pc); 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 Int64 x = mstate->gpr[rs(instr)]; Int64 y = mstate->gpr[rt(instr)]; //multiply(x, y); long long z = x * y; mstate->hi = (z >> 32) & 0xFFFFFFFF; mstate->lo = z & 0xFFFFFFFF; return nothing_special; } case MULTU: { // Multiply Unsigned UInt64 x = mstate->gpr[rs(instr)]; UInt64 y = mstate->gpr[rt(instr)]; unsigned long long z = x * y; //multiply(x, y); mstate->hi = (z >> 32) & 0xFFFFFFFF; mstate->lo = z & 0xFFFFFFFF; 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -