int interp_control() { uint32_t opcode = GET_OPCODE(if_id.inst); uint32_t address; switch (opcode) { case OPCODE_R : id_ex.reg_write = true; id_ex.reg_dst = GET_RD(if_id.inst); id_ex.rt = GET_RT(if_id.inst); id_ex.rs_value = regs[GET_RS(if_id.inst)]; id_ex.rt_value = regs[id_ex.rt]; id_ex.funct = GET_FUNCT(if_id.inst); id_ex.shamt = GET_SHAMT(if_id.inst); if (id_ex.funct == FUNCT_JR) { id_ex.jump = true; id_ex.jump_target = id_ex.rs_value; } break; case OPCODE_BEQ : id_ex.branch = true; id_ex.beq = true; id_ex.rt = GET_RT(if_id.inst); id_ex.rs_value = regs[GET_RS(if_id.inst)]; id_ex.rt_value = regs[id_ex.rt]; id_ex.sign_ext_imm = SIGN_EXTEND(GET_IMM(if_id.inst)); // INSTRUKTOR 0: no reason to updates fields that you dont use id_ex.funct = FUNCT_SUB; break; case OPCODE_BNE : id_ex.branch = true; id_ex.beq = false; id_ex.rt = GET_RT(if_id.inst); id_ex.rs_value = regs[GET_RS(if_id.inst)]; id_ex.rt_value = regs[id_ex.rt]; id_ex.sign_ext_imm = SIGN_EXTEND(GET_IMM(if_id.inst)); id_ex.funct = FUNCT_SUB; break; case OPCODE_LW : id_ex.mem_read = true; id_ex.reg_write = true; id_ex.alu_src = true; id_ex.mem_to_reg = true; id_ex.reg_dst = GET_RT(if_id.inst); id_ex.rt = GET_RT(if_id.inst); id_ex.rs_value = regs[GET_RS(if_id.inst)]; id_ex.rt_value = regs[id_ex.rt]; id_ex.sign_ext_imm = SIGN_EXTEND(GET_IMM(if_id.inst)); id_ex.funct = FUNCT_ADD; break; case OPCODE_SW : id_ex.mem_write = true; id_ex.alu_src = true; id_ex.rt = GET_RT(if_id.inst); id_ex.rs_value = regs[GET_RS(if_id.inst)]; id_ex.rt_value = regs[id_ex.rt]; id_ex.sign_ext_imm = SIGN_EXTEND(GET_IMM(if_id.inst)); id_ex.funct = FUNCT_ADD; break; case OPCODE_J : id_ex.jump = true; address = GET_ADDRESS(if_id.inst); id_ex.jump_target = (if_id.next_pc & MS_4B) | (address << 2); break; case OPCODE_JAL : id_ex.reg_write = true; id_ex.jump = true; address = GET_ADDRESS(if_id.inst); id_ex.jump_target = (if_id.next_pc & MS_4B) | (address << 2); id_ex.rs_value = 0; id_ex.rt_value = if_id.next_pc; id_ex.reg_dst = 31; id_ex.funct = FUNCT_ADD; break; // INSTRUKTOR -2: Make cases for all I-type and J-type instructions default: printf("ERROR: Unknown opcode in interp_control()\n"); return ERROR_UNKNOWN_OPCODE; } return 0; }
const void Cpu::executeImmOp(const uInt op){ #if DEBUGLEVEL > 2 printf("I-op, op:%x, r%d, r%d, imm:%x\n", GET_OPCODE(op), OP_SRC_REG(op), OP_ADD_REG(op), GET_IMM(op)); #endif uInt* const add = &mips->r[OP_ADD_REG(op)]; const uInt* const src = &mips->r[OP_SRC_REG(op)]; const uInt pmem = *src + GET_IMMSGN(op); switch (GET_OPCODE(op)){ case OPCODE_BEQ: mips->pc += (*src == *add) ? GET_IMMSGN(op)*4 : 0; break; case OPCODE_BNE: mips->pc += (*src != *add) ? GET_IMMSGN(op)*4 : 0; break; case OPCODE_ADDI: //TODO throw overflow exception case OPCODE_ADDIU: *add = *src + GET_IMMSGN(op); break; case OPCODE_MFC: fatalError("Unimplemented I-op\n"); case OPCODE_FP: fatalError("In executeImmOp, but found FP-op!\n"); case OPCODE_SLTI: *add = (sInt(*src) < GET_IMMSGN(op)) ? 1 : 0; break; case OPCODE_SLTIU: *add = (*src < GET_IMMSGN(op)) ? 1 : 0; break; case OPCODE_ANDI: *add = *src & GET_IMM(op); break; case OPCODE_ORI: *add = *src | GET_IMM(op); break; case OPCODE_LUI: *add = GET_IMM(op); break; case OPCODE_LW: *add = mem->get<uInt>(pmem); break; case OPCODE_LD: fatalError("Unimplemented I-op\n"); case OPCODE_LBU: *add = mem->get<uChar>(pmem); break; case OPCODE_LHU: *add = mem->get<uShort>(pmem); break; case OPCODE_SB: mem->set(pmem, uChar(*add)); break; case OPCODE_SH: mem->set(pmem, uShort(*add)); break; case OPCODE_LL: fatalError("Unimplemented I-op\n"); case OPCODE_SW: mem->set(pmem, *add); break; default: fatalError("Unknown I-op instruction\n"); } };