From c9e13e0b33ba96f4ed3925a825b7489e286b0536 Mon Sep 17 00:00:00 2001 From: liuk7071 Date: Sat, 23 Sep 2023 20:09:20 +0200 Subject: [PATCH] [CPU] Many fixes --- src/cpu/backends/interpreter/interpreter.cpp | 106 ++++++++++++------- src/cpu/cpu_core.hpp | 8 +- 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/src/cpu/backends/interpreter/interpreter.cpp b/src/cpu/backends/interpreter/interpreter.cpp index 86ba6d1..766dc3e 100644 --- a/src/cpu/backends/interpreter/interpreter.cpp +++ b/src/cpu/backends/interpreter/interpreter.cpp @@ -1,8 +1,8 @@ #include "interpreter.hpp" -#define DONT_CRASH_ON_BAD_READWRITE -#define DONT_CRASH_ON_BAD_JUMP +//#define DONT_CRASH_ON_BAD_READWRITE +//#define DONT_CRASH_ON_BAD_JUMP void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { // Handle interrupts @@ -61,6 +61,7 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { #ifndef DONT_CRASH_ON_BAD_JUMP Helpers::panic("Bad JR addr\n"); #else + core->exception(CpuCore::Exception::BadFetchAddr, true); break; #endif } @@ -70,14 +71,15 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { } case CpuOpcodes::SPECIALOpcode::JALR: { const u32 addr = gprs[instr.rs]; + gprs[instr.rd] = core->nextPc; if (addr & 3) { #ifndef DONT_CRASH_ON_BAD_JUMP Helpers::panic("Bad JALR addr\n"); #else + core->exception(CpuCore::Exception::BadFetchAddr, true); break; #endif } - gprs[CpuOpcodes::CpuReg::RA] = core->nextPc; core->nextPc = addr; core->branched = true; break; @@ -157,8 +159,14 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { break; } case CpuOpcodes::SPECIALOpcode::ADD: { + u32 a = gprs[instr.rs]; + u32 b = gprs[instr.rt]; + u32 res = a + b; + if (((a >> 31) == (b >> 31)) && ((a >> 31) != (res >> 31))) { + core->exception(CpuCore::Exception::Overflow, true); + break; + } gprs[instr.rd] = gprs[instr.rs] + gprs[instr.rt]; - // TODO: overflow exception break; } case CpuOpcodes::SPECIALOpcode::ADDU: { @@ -166,8 +174,14 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { break; } case CpuOpcodes::SPECIALOpcode::SUB: { - gprs[instr.rd] = gprs[instr.rs] - gprs[instr.rt]; - // TODO: overflow exception + u32 a = gprs[instr.rs]; + u32 b = gprs[instr.rt]; + u32 res = a - b; + if (((a ^ res) & (~b ^ res)) >> 31) { + core->exception(CpuCore::Exception::Overflow, true); + break; + } + gprs[instr.rd] = res; break; } case CpuOpcodes::SPECIALOpcode::SUBU: { @@ -204,40 +218,29 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { break; } case CpuOpcodes::Opcode::REGIMM: { - switch (instr.regimmOpc & 0x11) { - case CpuOpcodes::REGIMMOpcode::BLTZ: { - if ((s32)gprs[instr.rs] < 0) { - core->nextPc = core->pc + ((u32)(s16)instr.imm << 2); - core->branched = true; - } - break; - } - case CpuOpcodes::REGIMMOpcode::BGEZ: { - if ((s32)gprs[instr.rs] >= 0) { - core->nextPc = core->pc + ((u32)(s16)instr.imm << 2); - core->branched = true; - } - break; - } - case CpuOpcodes::REGIMMOpcode::BLTZAL: { - gprs[CpuOpcodes::CpuReg::RA] = core->nextPc; - if ((s32)gprs[instr.rs] < 0) { + bool ge = (instr.raw >> 16) & 1; + bool link = ((instr.raw >> 17) & 0xf) == 8; + + s32 rs = (s32)gprs[instr.rs]; + + if (link) gprs[CpuReg::RA] = core->nextPc; + + if (ge) { + if (rs >= 0) { core->nextPc = core->pc + ((u32)(s16)instr.imm << 2); core->branched = true; } break; } - case CpuOpcodes::REGIMMOpcode::BGEZAL: { - gprs[CpuOpcodes::CpuReg::RA] = core->nextPc; - if ((s32)gprs[instr.rs] >= 0) { + else { + if (rs < 0) { core->nextPc = core->pc + ((u32)(s16)instr.imm << 2); core->branched = true; } break; } - default: - Helpers::panic("[ FATAL ] Invalid REGIMM instruction 0x%02x (raw: 0x%08x)\n", instr.regimmOpc.Value(), instr.raw); - } + + Helpers::panic("[ FATAL ] Invalid REGIMM instruction 0x%02x (raw: 0x%08x)\n", instr.regimmOpc.Value(), instr.raw); break; } case CpuOpcodes::Opcode::J: { @@ -246,7 +249,7 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { break; } case CpuOpcodes::Opcode::JAL: { - gprs[CpuOpcodes::CpuReg::RA] = core->nextPc; + gprs[CpuReg::RA] = core->nextPc; core->nextPc = (core->pc & 0xf0000000) | (instr.jumpImm << 2); core->branched = true; break; @@ -280,8 +283,14 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { break; } case CpuOpcodes::Opcode::ADDI: { - gprs[instr.rt] = gprs[instr.rs] + (u32)(s16)instr.imm; - // TODO: overflow exception + u32 a = gprs[instr.rs]; + u32 b = (u32)(s16)instr.imm; + u32 res = a + b; + if (((a >> 31) == (b >> 31)) && ((a >> 31) != (res >> 31))) { + core->exception(CpuCore::Exception::Overflow, true); + break; + } + gprs[instr.rt] = res; break; } case CpuOpcodes::Opcode::ADDIU: { @@ -352,6 +361,9 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { if (addr & 1) { #ifndef DONT_CRASH_ON_BAD_READWRITE Helpers::panic("Bad lh addr 0x%08x\n", addr); +#else + core->exception(CpuCore::Exception::BadFetchAddr, true); + break; #endif } gprs[instr.rt] = (u32)(s16)mem->read(addr); @@ -361,8 +373,8 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { u32 address = gprs[instr.rs] + (u32)(s16)instr.imm; const int shift = ((address & 3) ^ 3) * 8; u32 dataTemp = mem->read(address & ~3); - u32 rtTemp = gprs[instr.rt] & ~(0xffffffff >> shift); - dataTemp >>= shift; + u32 rtTemp = gprs[instr.rt] & ~(0xffffffff << shift); + dataTemp <<= shift; gprs[instr.rt] = dataTemp | rtTemp; break; } @@ -371,6 +383,9 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { if (addr & 3) { #ifndef DONT_CRASH_ON_BAD_READWRITE Helpers::panic("Bad lw addr 0x%08x\n", addr); +#else + core->exception(CpuCore::Exception::BadFetchAddr, true); + break; #endif } gprs[instr.rt] = mem->read(addr); @@ -386,6 +401,9 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { if (addr & 1) { #ifndef DONT_CRASH_ON_BAD_READWRITE Helpers::panic("Bad lhu addr 0x%08x\n", addr); +#else + core->exception(CpuCore::Exception::BadFetchAddr, true); + break; #endif } gprs[instr.rt] = mem->read(addr); @@ -395,8 +413,8 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { u32 address = gprs[instr.rs] + (u32)(s16)instr.imm; const int shift = (address & 3) * 8; u32 dataTemp = mem->read(address & ~3); - u32 rtTemp = gprs[instr.rt] & ~(0xffffffff << shift); - dataTemp <<= shift; + u32 rtTemp = gprs[instr.rt] & ~(0xffffffff >> shift); + dataTemp >>= shift; gprs[instr.rt] = dataTemp | rtTemp; break; } @@ -412,6 +430,9 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { if (addr & 1) { #ifndef DONT_CRASH_ON_BAD_READWRITE Helpers::panic("Bad sh addr 0x%08x\n", addr); +#else + core->exception(CpuCore::Exception::BadStoreAddr, true); + break; #endif } mem->write(addr, gprs[instr.rt]); @@ -421,8 +442,8 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { u32 address = gprs[instr.rs] + (u32)(s16)instr.imm; const int shift = ((address & 3) ^ 3) * 8; u32 dataTemp = mem->read(address & ~3); - u32 rtTemp = gprs[instr.rt] << shift; - dataTemp &= ~(0xffffffff << shift); + u32 rtTemp = gprs[instr.rt] >> shift; + dataTemp &= ~(0xffffffff >> shift); mem->write(address & ~3, dataTemp | rtTemp); break; } @@ -432,6 +453,9 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { if (addr & 3) { #ifndef DONT_CRASH_ON_BAD_READWRITE Helpers::panic("Bad sw addr 0x%08x\n", addr); +#else + core->exception(CpuCore::Exception::BadStoreAddr, true); + break; #endif } mem->write(addr, gprs[instr.rt]); @@ -441,8 +465,8 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) { u32 address = gprs[instr.rs] + (u32)(s16)instr.imm; const int shift = (address & 3) * 8; u32 dataTemp = mem->read(address & ~3); - u32 rtTemp = gprs[instr.rt] >> shift; - dataTemp &= ~(0xffffffff >> shift); + u32 rtTemp = gprs[instr.rt] << shift; + dataTemp &= ~(0xffffffff << shift); mem->write(address & ~3, dataTemp | rtTemp); break; } diff --git a/src/cpu/cpu_core.hpp b/src/cpu/cpu_core.hpp index 5a1ca65..f31dc4a 100644 --- a/src/cpu/cpu_core.hpp +++ b/src/cpu/cpu_core.hpp @@ -77,7 +77,7 @@ struct COP0 { case (u32)COP0Reg::BDA: return 0; case (u32)COP0Reg::JumpDest: return 0; case (u32)COP0Reg::DCIC: return 0; - case (u32)COP0Reg::BadVAddr: return 0; + case (u32)COP0Reg::BadVAddr: return badVaddr; case (u32)COP0Reg::BDAM: return 0; case (u32)COP0Reg::BPCM: return 0; case (u32)COP0Reg::Status: return status.raw; @@ -168,8 +168,8 @@ class CpuCore { } }; -namespace CpuOpcodes { -enum CpuReg { +namespace CpuReg { +enum { R0 = 0, AT = 1, V0 = 2, V1 = 3, A0 = 4, A1 = 5, A2 = 6, A3 = 7, T0 = 8, T1 = 9, T2 = 10, T3 = 11, @@ -180,7 +180,9 @@ enum CpuReg { GP = 28, SP = 29, S8 = 30, RA = 31, LO = 32, HI = 33 }; +} +namespace CpuOpcodes { enum Opcode { SPECIAL = 0x00, REGIMM = 0x01,