unsigned long MemoryForCpu::read8_se(unsigned long addr) { unsigned char c; if(port->read8(addr, &c)) return signExtend8(c); if(ifont->read8(addr, &c)) return signExtend8(c); if(rommmp->read8(addr, &c)) return signExtend8(c); return signExtend8(readMemory8(addr)); }
bool Instruction::exec() { // // NOTE: Assumes pc has been pre-incremented // Important for branch instruction operation // uint64_t p; // product for mult, div bool keepGoing = true; pc += 4; switch(token) { case SLL: reg[rd] = reg[rt] << shamt; break; case SRL: reg[rd] = reg[rt] >> shamt; break; case SRA: reg[rd] = (int) reg[rt] >> shamt; break; case SLLV: reg[rd] = reg[rt] << reg[rs]; break; case SRLV: reg[rd] = reg[rt] >> reg[rs]; break; case SRAV: reg[rd] = (int) reg[rt] >> reg[rs]; break; case ADD: reg[rd] = reg[rs] + reg[rt]; break; case ADDU: reg[rd] = reg[rs] + reg[rt]; break; case SUB: reg[rd] = reg[rs] - reg[rt]; break; case SUBU: reg[rd] = reg[rs] - reg[rt]; break; case AND: reg[rd] = reg[rs] & reg[rt]; break; case OR: reg[rd] = reg[rs] | reg[rt]; break; case XOR: reg[rd] = reg[rs] ^ reg[rt]; break; case NOR: reg[rd] = ~(reg[rs] | reg[rt]); break; case MULT: p = (int) reg[rs] * (int) reg[rt]; hi = p >> 32L; lo = p & 0x00000000ffffffffL; break; case MULTU: p = (uint64_t) reg[rs] * (uint64_t) reg[rt]; hi = p >> 32L; lo = p & 0x00000000ffffffffL; break; case DIV: lo = (int) reg[rs] / (int) reg[rt]; hi = (int) reg[rs] % (int) reg[rt]; break; case DIVU: lo = reg[rs] / reg[rt]; hi = reg[rs] % reg[rt]; break; case SLT: reg[rd] = ((int) reg[rs] < (int) reg[rt]) ? 1 : 0; break; case SLTU: reg[rd] = (reg[rs] < reg[rt]) ? 1 : 0; break; case MFHI: reg[rd] = hi; break; case MFLO: reg[rd] = lo; break; case MTHI: hi = reg[rs]; break; case MTLO: lo = reg[rs]; break; case JR: pc = reg[rs]; break; case J: pc = (target << 2) | (pc & 0xf0000000); break; case JAL: reg[31] = pc; // pc has been pre-incremented pc = (target << 2) | (pc & 0xf0000000); break; case JALR: reg[31] = pc; pc = reg[rs]; break; case BEQ: // note pc was pre-incremented pc = (reg[rs] == reg[rt]) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case BNE: pc = (reg[rs] != reg[rt]) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case BGEZ: pc = ((int) reg[rs] >= 0) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case BGTZ: pc = ((int) reg[rs] > 0) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case BLEZ: pc = ((int) reg[rs] <= 0) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case BLTZ: pc = ((int) reg[rs] < 0) ? pc + (signExtend16(imm) << 2) - 4 : pc; break; case ADDI: reg[rt] = reg[rs] + signExtend16(imm); break; case ADDIU: reg[rt] = reg[rs] + signExtend16(imm);; break; case SLTI: reg[rt] = ((int) reg[rs] < (int) signExtend16(imm)) ? 1 : 0; break; case SLTIU: reg[rt] = (reg[rs] < signExtend16(imm)) ? 1 : 0; break; case ANDI: reg[rt] = reg[rs] & imm; break; case ORI: reg[rt] = reg[rs] | imm; break; case XORI: reg[rt] = reg[rs] ^ imm; break; case LUI: reg[rt] = (imm << 16); break; case LB: reg[rt] = signExtend8(M.read8(reg[rs] + signExtend16(imm))); break; case LH: reg[rt] = signExtend16(M.read16(reg[rs] + signExtend16(imm))); break; case LW: reg[rt] = M.read32(reg[rs] + signExtend16(imm)); break; case LBU: reg[rt] = M.read8(reg[rs] + signExtend16(imm)); break; case LHU: reg[rt] = M.read16(reg[rs] + signExtend16(imm)); break; case SB: M.write8(reg[rt], reg[rs] + signExtend16(imm)); break; case SH: M.write16(reg[rt], reg[rs] + signExtend16(imm)); break; case SW: M.write32(reg[rt], reg[rs] + signExtend16(imm)); break; case SYSCALL: switch (reg[2]) { case 1: printf("%d", reg[4]); break; case 4: printf("%s", M.getMemoryPtr(reg[4])); break; case 9: reg[2] = M.alloc(reg[4]); break; case 10: keepGoing = false; break; case 11: printf("%c", reg[4]); break; default: printf("Undefined syscall code: %d\n", reg[2]); // assert(false && "undefined syscall code"); break; } break; default: printf("undefined opcode: %u\n", opcode); assert(false); break; } ++instructionCount; ++itokenCounts[token]; ++xtypeCounts[xtype]; return keepGoing; }