void execute_one_inst(processor_t* p, int prompt, int print_regs) { inst_t inst; /* fetch an instruction */ inst.bits = load_mem(p->pc, SIZE_WORD); /* interactive-mode prompt */ if(prompt) { if (prompt == 1) { printf("simulator paused, enter to continue..."); while(getchar() != '\n') ; } printf("%08x: ",p->pc); disassemble(inst); } uint32_t temp; switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */ { case 0x0: // opcode == 0x0 (SPECIAL) switch (inst.rtype.funct) { case 0x0: // funct == 0x0 (sll) p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt; p->pc += 4; break; case 0x2: // funct == 0x0 (srl) p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt; p->pc += 4; break; case 0x3: // funct == 0x0 (sra) p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rt] >> inst.rtype.shamt; p->pc += 4; break; case 0x8: // funct == 0x8 (jr) p->pc = p->R[inst.rtype.rs]; break; case 0x9: // funct == 0x9 (jalr) temp = p->pc + 4; p->pc = p->R[inst.rtype.rs]; p->R[inst.rtype.rd] = temp; break; case 0x10: // funct == 0x10 (mfhi) p->R[inst.rtype.rd] = p->RHI; p->pc += 4; break; case 0x12: // funct == 0x12 (mflo) p->R[inst.rtype.rd] = p->RLO; p->pc += 4; break; case 0x18: // funct == 0x18 (mult) perform_mult(p->R[inst.rtype.rs], p->R[inst.rtype.rt], &(p->RHI), &(p->RLO)); p->pc += 4; break; case 0x21: // funct == 0x21 (addu) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt]; p->pc += 4; break; case 0x23: // funct == 0x23 (subu) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rd]; p->pc += 4; break; case 0x24: // funct == 0x24 (and) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt]; p->pc += 4; break; case 0x26: // funct == 0x26 (xor) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt]; p->pc += 4; break; case 0x27: // funct == 0x27 (nor) p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] | p->R[inst.rtype.rt]); p->pc += 4; break; case 0x2a: // funct == 0x2a (slt) p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rs] < (signed)p->R[inst.rtype.rt]; p->pc += 4; break; case 0x2b: // funct == 0x2a (sltu) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt]; p->pc += 4; break; case 0xc: // funct == 0xc (SYSCALL) handle_syscall(p); p->pc += 4; break; case 0x25: // funct == 0x25 (OR) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt]; p->pc += 4; break; default: // undefined funct fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits); exit(-1); break; } break; case 0x3: // opcode == 0x3 (jal) p->R[31] = p->pc += 4; p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2); break; case 0x4: // opcode == 0x4 (beq) if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) { p->pc += 4 + signext(inst.itype.imm)*4; } else { p->pc += 4; } break; case 0x5: // opcode == 0x4 (bne) if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) { p->pc += 4 + signext(inst.itype.imm)*4; } else { p->pc += 4; } break; case 0x9: // opcode == 0x9 (addiu) p->R[inst.rtype.rt] = p->R[inst.itype.rs] + signext(inst.itype.imm); p->pc += 4; break; case 0xa: // opcode == 0xa (slti) p->R[inst.itype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm); p->pc += 4; break; case 0xb: // opcode == 0xb (sltiu) p->R[inst.rtype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm); p->pc += 4; break; case 0xc: // opcode == 0xc (andi) p->R[inst.rtype.rt] = p->R[inst.itype.rs] & zeroext(inst.itype.imm); p->pc += 4; break; case 0xe: // opcode == 0xe (xori) p->R[inst.rtype.rt] = p->R[inst.itype.rs] ^ zeroext(inst.itype.imm); p->pc += 4; break; case 0xf: // opcode == 0xf (lui) p->R[inst.rtype.rt] = inst.itype.imm << 16; p->pc += 4; break; case 0x20: // opcode == 0x20 (lb) p->R[inst.rtype.rt] = signext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE)); p->pc += 4; break; case 0x23: // opcode == 0x23 (lw) p->R[inst.rtype.rt] = load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD); p->pc += 4; break; case 0x24: // opcode == 0x24 (lbu) p->R[inst.itype.rt] = zeroext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD)); p->pc += 4; break; case 0x28: // opcode == 0x28 (sb) store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]); p->pc += 4; break; case 0x2b: // opcode == 0x20 (sw) store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]); p->pc += 4; break; case 0xd: // opcode == 0xd (ORI) p->R[inst.itype.rt] = (p->R[inst.itype.rs] | inst.itype.imm); p->pc += 4; break; case 0x2: // opcode == 0x2 (J) p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2); break; default: // undefined opcode fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits); exit(-1); break; } // enforce $0 being hard-wired to 0 p->R[0] = 0; if(print_regs) { print_registers(p); } }
void execute_one_inst(processor_t* p, int prompt, int print_regs) { inst_t inst; /* fetch an instruction */ inst.bits = load_mem(p->pc, SIZE_WORD); /* interactive-mode prompt */ if(prompt) { if (prompt == 1) { printf("simulator paused, enter to continue..."); while(getchar() != '\n') ; } printf("%08x: ",p->pc); disassemble(inst); } switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */ { case 0x0: // opcode == 0x0 (SPECIAL) switch (inst.rtype.funct) { case 0x0: //opcode = 0x0 (SLL) p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt; p->pc += 4; break; case 0x2: //opcode = 0x2 (SRL) p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt; p->pc += 4; break; case 0x3: //opcode = 0x3 (SRA) p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rt]) >> inst.rtype.shamt; p->pc += 4; break; case 0x8: //opcode = 0x8 (JR) p->pc = p->R[inst.rtype.rs]; break; case 0x9: //opcode = 0x9 (JALR) { int tmp = p->pc + 4; p->pc = p->R[inst.rtype.rs]; p->R[inst.rtype.rd] = tmp; } break; case 0xc: // funct == 0xc (SYSCALL) handle_syscall(p); p->pc += 4; break; case 0x21: //opcode = 0x21 (ADDU) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt]; p->pc += 4; break; case 0x23: //opcode = 0x23 (SUBU) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rt]; p->pc += 4; break; case 0x24: //opcode = 0x24 (AND) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt]; p->pc += 4; break; case 0x25: // funct == 0x25 (OR) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt]; p->pc += 4; break; case 0x26: // funct == 0x26 (XOR) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt]; p->pc += 4; break; case 0x27: // funct == 0x27 (NOR) p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt]); p->pc += 4; break; case 0x2a: // funct == 0x2a (SLT) p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rs]) < (signed int)(p->R[inst.rtype.rt]); p->pc += 4; break; case 0x2b: // funct == 0x2b (SLTU) p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt]; p->pc += 4; break; default: // undefined funct fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits); exit(-1); break; } break; case 0x2: // opcode == 0x2 (J) p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2); break; case 0x3: // opcode == 0x3 (JAL) p->R[31] = p->pc + 4; p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2); break; case 0x4: // opcode == 0x4 (BEQ) if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) { p->pc += (4 + (((int16_t)inst.itype.imm) << 2)); } else { p->pc += 4; } break; case 0x5: // opcode == 0x5 (BNE) if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) { p->pc += (4 + (((int16_t)inst.itype.imm) << 2)); } else { p->pc += 4; } break; case 0x9: // opcode == 0x9 (ADDIU) p->R[inst.itype.rt] = p->R[inst.itype.rs] + (int16_t)(inst.itype.imm); p->pc += 4; break; case 0xa: // opcode == 0xa (SLTI) p->R[inst.itype.rt] = (signed int)p->R[inst.itype.rs] < (int16_t)(inst.itype.imm); p->pc += 4; break; case 0xb: // opcode == 0xb (SLTIU) p->R[inst.itype.rt] = p->R[inst.itype.rs] < (int16_t)(inst.itype.imm); p->pc += 4; break; case 0xc: // opcode == 0xc (ANDI) p->R[inst.itype.rt] = p->R[inst.itype.rs] & inst.itype.imm; p->pc += 4; break; case 0xd: // opcode == 0xd (ORI) p->R[inst.itype.rt] = p->R[inst.itype.rs] | inst.itype.imm; p->pc += 4; break; case 0xe: // opcode == 0xe (XORI) p->R[inst.itype.rt] = p->R[inst.itype.rs] ^ inst.itype.imm; p->pc += 4; break; case 0xf: // opcode == 0xf (LUI) p->R[inst.itype.rt] = inst.itype.imm << 16; p->pc += 4; break; case 0x20: // opcode == 0x20 (LB) p->R[inst.itype.rt] = (int8_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE)); p->pc += 4; break; case 0x21: // opcode == 0x21 (LH) p->R[inst.itype.rt] = (int16_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD)); p->pc += 4; break; case 0x23: // opcode == 0x23 (LW) p->R[inst.itype.rt] = (int32_t)load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD); p->pc += 4; break; case 0x24: // opcode == 0x24 (LBU) p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE); p->pc += 4; break; case 0x25: // opcode == 0x25 (LHU) p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD); p->pc += 4; break; case 0x28: // opcode == 0x28 (SB) store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]); p->pc += 4; break; case 0x29: // opcode == 0x29 (SH) store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD, p->R[inst.itype.rt]); p->pc += 4; break; case 0x2b: // opcode == 0x2b (SW) store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]); p->pc += 4; break; default: // undefined opcode fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits); exit(-1); break; } // enforce $0 being hard-wired to 0 p->R[0] = 0; if(print_regs) print_registers(p); }