diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index 360f2314..ea40d5b4 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -25,7 +25,7 @@ CartInfo Core::LoadROM(const std::string& rom_) { romLoaded = true; CartInfo cartInfo = mem.LoadROM(rom); - DoPIFHLE(mem, CpuGetRegs(), cartInfo); + DoPIFHLE(mem, regs, cartInfo); return cartInfo; } @@ -33,7 +33,6 @@ CartInfo Core::LoadROM(const std::string& rom_) { void Core::Run(Window& window, float volumeL, float volumeR) { MMIO& mmio = mem.mmio; Controller& controller = mmio.si.controller; - Registers& regs = CpuGetRegs(); for(int field = 0; field < mmio.vi.numFields; field++) { int frameCycles = 0; @@ -46,7 +45,7 @@ void Core::Run(Window& window, float volumeL, float volumeR) { } for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { - CpuStep(mem); + CpuStep(); if(!mmio.rsp.spStatus.halt) { regs.steps++; if(regs.steps > 2) { @@ -74,7 +73,7 @@ void Core::Run(Window& window, float volumeL, float volumeR) { UpdateScreenParallelRdp(*this, window, GetVI()); int missedCycles = N64_CYCLES_PER_FRAME - frameCycles; - mmio.ai.Step(mem, CpuGetRegs(), missedCycles, volumeL, volumeR); + mmio.ai.Step(mem, regs, missedCycles, volumeL, volumeR); } else if(pause && romLoaded) { UpdateScreenParallelRdp(*this, window, GetVI()); } else if(pause && !romLoaded) { diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index a8f9d6ae..8ccd311e 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -24,22 +24,15 @@ struct Core { void CpuReset() { switch(cpuType) { - case CpuType::Dynarec: cpuDynarec.Reset(); break; - case CpuType::Interpreter: cpuInterp.Reset(); break; + case CpuType::Dynarec: break; + case CpuType::Interpreter: break; } } - void CpuStep(Mem& mem) { + void CpuStep() { switch(cpuType) { - case CpuType::Dynarec: cpuDynarec.Step(mem); break; - case CpuType::Interpreter: cpuInterp.Step(mem); break; - } - } - - Registers& CpuGetRegs() { - switch(cpuType) { - case CpuType::Dynarec: return cpuDynarec.regs; - case CpuType::Interpreter: return cpuInterp.regs; + case CpuType::Dynarec: cpuDynarec.Step(mem, regs); break; + case CpuType::Interpreter: cpuInterp.Step(regs, mem); break; } } @@ -56,5 +49,6 @@ struct Core { CpuType cpuType = CpuType::Dynarec; Interpreter cpuInterp; Dynarec cpuDynarec; + Registers regs; }; } diff --git a/src/backend/core/Dynarec.cpp b/src/backend/core/Dynarec.cpp index 8e91ebb4..0d9bba57 100644 --- a/src/backend/core/Dynarec.cpp +++ b/src/backend/core/Dynarec.cpp @@ -5,7 +5,7 @@ void Dynarec::Reset() { } -void Dynarec::Step(Mem &mem) { +void Dynarec::Step(Mem &mem, Registers& regs) { } } \ No newline at end of file diff --git a/src/backend/core/Dynarec.hpp b/src/backend/core/Dynarec.hpp index 8ff9a2d5..adcd4155 100644 --- a/src/backend/core/Dynarec.hpp +++ b/src/backend/core/Dynarec.hpp @@ -5,7 +5,7 @@ namespace n64 { struct Dynarec { - void Step(Mem& mem); + void Step(Mem& mem, Registers& regs); void Reset(); Registers regs; private: diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index cc7cc2cd..6fc28cf4 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -2,10 +2,6 @@ #include namespace n64 { -void Interpreter::Reset() { - regs.Reset(); -} - inline bool ShouldServiceInterrupt(Registers& regs) { bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; bool interrupts_enabled = regs.cop0.status.ie == 1; @@ -25,7 +21,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) { } } -void Interpreter::Step(Mem& mem) { +void Interpreter::Step(Registers& regs, Mem& mem) { regs.gpr[0] = 0; CheckCompareInterrupt(mem.mmio.mi, regs); @@ -44,6 +40,6 @@ void Interpreter::Step(Mem& mem) { regs.pc = regs.nextPC; regs.nextPC += 4; - Exec(mem, instruction); + Exec(regs, mem, instruction); } } \ No newline at end of file diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index 34305818..b773fd87 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -5,113 +5,108 @@ namespace n64 { struct Interpreter { - Interpreter() { - Reset(); - } - + Interpreter() = default; ~Interpreter() = default; - void Reset(); - void Step(Mem&); - Registers regs; + void Step(Registers& regs, Mem&); private: u64 cop2Latch{}; friend struct Cop1; - void cop2Decode(u32); - void special(Mem&, u32); - void regimm(u32); - void Exec(Mem&, u32); - void add(u32); - void addu(u32); - void addi(u32); - void addiu(u32); - void andi(u32); - void and_(u32); - void branch(bool, s64); - void branch_likely(bool, s64); - void b(u32, bool); - void blink(u32, bool); - void bl(u32, bool); - void bllink(u32, bool); - void dadd(u32); - void daddu(u32); - void daddi(u32); - void daddiu(u32); - void ddiv(u32); - void ddivu(u32); - void div(u32); - void divu(u32); - void dmult(u32); - void dmultu(u32); - void dsll(u32); - void dsllv(u32); - void dsll32(u32); - void dsra(u32); - void dsrav(u32); - void dsra32(u32); - void dsrl(u32); - void dsrlv(u32); - void dsrl32(u32); - void dsub(u32); - void dsubu(u32); - void j(u32); - void jr(u32); - void jal(u32); - void jalr(u32); - void lui(u32); - void lbu(Mem&, u32); - void lb(Mem&, u32); - void ld(Mem&, u32); - void ldl(Mem&, u32); - void ldr(Mem&, u32); - void lh(Mem&, u32); - void lhu(Mem&, u32); - void ll(Mem&, u32); - void lld(Mem&, u32); - void lw(Mem&, u32); - void lwl(Mem&, u32); - void lwu(Mem&, u32); - void lwr(Mem&, u32); - void mfhi(u32); - void mflo(u32); - void mult(u32); - void multu(u32); - void mthi(u32); - void mtlo(u32); - void nor(u32); - void sb(Mem&, u32); - void sc(Mem&, u32); - void scd(Mem&, u32); - void sd(Mem&, u32); - void sdl(Mem&, u32); - void sdr(Mem&, u32); - void sh(Mem&, u32); - void sw(Mem&, u32); - void swl(Mem&, u32); - void swr(Mem&, u32); - void slti(u32); - void sltiu(u32); - void slt(u32); - void sltu(u32); - void sll(u32); - void sllv(u32); - void sub(u32); - void subu(u32); - void sra(u32); - void srav(u32); - void srl(u32); - void srlv(u32); - void trap(bool); - void or_(u32); - void ori(u32); - void xor_(u32); - void xori(u32); + void cop2Decode(Registers&, u32); + void special(Registers&, Mem&, u32); + void regimm(Registers&, u32); + void Exec(Registers&, Mem&, u32); + void add(Registers&, u32); + void addu(Registers&, u32); + void addi(Registers&, u32); + void addiu(Registers&, u32); + void andi(Registers&, u32); + void and_(Registers&, u32); + void branch(Registers&, bool, s64); + void branch_likely(Registers&, bool, s64); + void b(Registers&, u32, bool); + void blink(Registers&, u32, bool); + void bl(Registers&, u32, bool); + void bllink(Registers&, u32, bool); + void dadd(Registers&, u32); + void daddu(Registers&, u32); + void daddi(Registers&, u32); + void daddiu(Registers&, u32); + void ddiv(Registers&, u32); + void ddivu(Registers&, u32); + void div(Registers&, u32); + void divu(Registers&, u32); + void dmult(Registers&, u32); + void dmultu(Registers&, u32); + void dsll(Registers&, u32); + void dsllv(Registers&, u32); + void dsll32(Registers&, u32); + void dsra(Registers&, u32); + void dsrav(Registers&, u32); + void dsra32(Registers&, u32); + void dsrl(Registers&, u32); + void dsrlv(Registers&, u32); + void dsrl32(Registers&, u32); + void dsub(Registers&, u32); + void dsubu(Registers&, u32); + void j(Registers&, u32); + void jr(Registers&, u32); + void jal(Registers&, u32); + void jalr(Registers&, u32); + void lui(Registers&, u32); + void lbu(Registers&, Mem&, u32); + void lb(Registers&, Mem&, u32); + void ld(Registers&, Mem&, u32); + void ldl(Registers&, Mem&, u32); + void ldr(Registers&, Mem&, u32); + void lh(Registers&, Mem&, u32); + void lhu(Registers&, Mem&, u32); + void ll(Registers&, Mem&, u32); + void lld(Registers&, Mem&, u32); + void lw(Registers&, Mem&, u32); + void lwl(Registers&, Mem&, u32); + void lwu(Registers&, Mem&, u32); + void lwr(Registers&, Mem&, u32); + void mfhi(Registers&, u32); + void mflo(Registers&, u32); + void mult(Registers&, u32); + void multu(Registers&, u32); + void mthi(Registers&, u32); + void mtlo(Registers&, u32); + void nor(Registers&, u32); + void sb(Registers&, Mem&, u32); + void sc(Registers&, Mem&, u32); + void scd(Registers&, Mem&, u32); + void sd(Registers&, Mem&, u32); + void sdl(Registers&, Mem&, u32); + void sdr(Registers&, Mem&, u32); + void sh(Registers&, Mem&, u32); + void sw(Registers&, Mem&, u32); + void swl(Registers&, Mem&, u32); + void swr(Registers&, Mem&, u32); + void slti(Registers&, u32); + void sltiu(Registers&, u32); + void slt(Registers&, u32); + void sltu(Registers&, u32); + void sll(Registers&, u32); + void sllv(Registers&, u32); + void sub(Registers&, u32); + void subu(Registers&, u32); + void sra(Registers&, u32); + void srav(Registers&, u32); + void srl(Registers&, u32); + void srlv(Registers&, u32); + void trap(Registers&, bool); + void or_(Registers&, u32); + void ori(Registers&, u32); + void xor_(Registers&, u32); + void xori(Registers&, u32); - void mtc2(u32); - void mfc2(u32); - void dmtc2(u32); - void dmfc2(u32); - void ctc2(u32); - void cfc2(u32); + void mtc2(Registers&, u32); + void mfc2(Registers&, u32); + void dmtc2(Registers&, u32); + void dmfc2(Registers&, u32); + void ctc2(Registers&, u32); + void cfc2(Registers&, u32); }; } diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index f62a56f6..f1f68b3a 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -2,172 +2,172 @@ #include namespace n64 { -void Interpreter::special(Mem& mem, u32 instr) { +void Interpreter::special(Registers& regs, Mem& mem, u32 instr) { u8 mask = (instr & 0x3F); // 00rr_rccc switch (mask) { // TODO: named constants for clearer code case 0: if (instr != 0) { - sll(instr); + sll(regs, instr); } break; - case 0x02: srl(instr); break; - case 0x03: sra(instr); break; - case 0x04: sllv(instr); break; - case 0x06: srlv(instr); break; - case 0x07: srav(instr); break; - case 0x08: jr(instr); break; - case 0x09: jalr(instr); break; + case 0x02: srl(regs, instr); break; + case 0x03: sra(regs, instr); break; + case 0x04: sllv(regs, instr); break; + case 0x06: srlv(regs, instr); break; + case 0x07: srav(regs, instr); break; + case 0x08: jr(regs, instr); break; + case 0x09: jalr(regs, instr); break; case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break; case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break; case 0x0F: break; // SYNC - case 0x10: mfhi(instr); break; - case 0x11: mthi(instr); break; - case 0x12: mflo(instr); break; - case 0x13: mtlo(instr); break; - case 0x14: dsllv(instr); break; - case 0x16: dsrlv(instr); break; - case 0x17: dsrav(instr); break; - case 0x18: mult(instr); break; - case 0x19: multu(instr); break; - case 0x1A: div(instr); break; - case 0x1B: divu(instr); break; - case 0x1C: dmult(instr); break; - case 0x1D: dmultu(instr); break; - case 0x1E: ddiv(instr); break; - case 0x1F: ddivu(instr); break; - case 0x20: add(instr); break; - case 0x21: addu(instr); break; - case 0x22: sub(instr); break; - case 0x23: subu(instr); break; - case 0x24: and_(instr); break; - case 0x25: or_(instr); break; - case 0x26: xor_(instr); break; - case 0x27: nor(instr); break; - case 0x2A: slt(instr); break; - case 0x2B: sltu(instr); break; - case 0x2C: dadd(instr); break; - case 0x2D: daddu(instr); break; - case 0x2E: dsub(instr); break; - case 0x2F: dsubu(instr); break; - case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; - case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; - case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; - case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; - case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case 0x38: dsll(instr); break; - case 0x3A: dsrl(instr); break; - case 0x3B: dsra(instr); break; - case 0x3C: dsll32(instr); break; - case 0x3E: dsrl32(instr); break; - case 0x3F: dsra32(instr); break; + case 0x10: mfhi(regs, instr); break; + case 0x11: mthi(regs, instr); break; + case 0x12: mflo(regs, instr); break; + case 0x13: mtlo(regs, instr); break; + case 0x14: dsllv(regs, instr); break; + case 0x16: dsrlv(regs, instr); break; + case 0x17: dsrav(regs, instr); break; + case 0x18: mult(regs, instr); break; + case 0x19: multu(regs, instr); break; + case 0x1A: div(regs, instr); break; + case 0x1B: divu(regs, instr); break; + case 0x1C: dmult(regs, instr); break; + case 0x1D: dmultu(regs, instr); break; + case 0x1E: ddiv(regs, instr); break; + case 0x1F: ddivu(regs, instr); break; + case 0x20: add(regs, instr); break; + case 0x21: addu(regs, instr); break; + case 0x22: sub(regs, instr); break; + case 0x23: subu(regs, instr); break; + case 0x24: and_(regs, instr); break; + case 0x25: or_(regs, instr); break; + case 0x26: xor_(regs, instr); break; + case 0x27: nor(regs, instr); break; + case 0x2A: slt(regs, instr); break; + case 0x2B: sltu(regs, instr); break; + case 0x2C: dadd(regs, instr); break; + case 0x2D: daddu(regs, instr); break; + case 0x2E: dsub(regs, instr); break; + case 0x2F: dsubu(regs, instr); break; + case 0x30: trap(regs, regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; + case 0x31: trap(regs, (u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; + case 0x32: trap(regs, regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; + case 0x33: trap(regs, (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; + case 0x34: trap(regs, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x36: trap(regs, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; + case 0x38: dsll(regs, instr); break; + case 0x3A: dsrl(regs, instr); break; + case 0x3B: dsra(regs, instr); break; + case 0x3C: dsll32(regs, instr); break; + case 0x3E: dsrl32(regs, instr); break; + case 0x3F: dsra32(regs, instr); break; default: util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); } } -void Interpreter::regimm(u32 instr) { +void Interpreter::regimm(Registers& regs, u32 instr) { u8 mask = ((instr >> 16) & 0x1F); // 000r_rccc switch (mask) { // TODO: named constants for clearer code - case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break; - case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break; - case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break; - case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break; - case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break; - case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; - case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break; - case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; - case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break; - case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break; - case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break; - case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break; - case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break; - case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break; + case 0x00: b(regs, instr, regs.gpr[RS(instr)] < 0); break; + case 0x01: b(regs, instr, regs.gpr[RS(instr)] >= 0); break; + case 0x02: bl(regs, instr, regs.gpr[RS(instr)] < 0); break; + case 0x03: bl(regs, instr, regs.gpr[RS(instr)] >= 0); break; + case 0x08: trap(regs, regs.gpr[RS(instr)] >= s64(s16(instr))); break; + case 0x09: trap(regs, u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; + case 0x0A: trap(regs, regs.gpr[RS(instr)] < s64(s16(instr))); break; + case 0x0B: trap(regs, u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; + case 0x0C: trap(regs, regs.gpr[RS(instr)] == s64(s16(instr))); break; + case 0x0E: trap(regs, regs.gpr[RS(instr)] != s64(s16(instr))); break; + case 0x10: blink(regs, instr, regs.gpr[RS(instr)] < 0); break; + case 0x11: blink(regs, instr, regs.gpr[RS(instr)] >= 0); break; + case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break; + case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break; default: util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); } } -void Interpreter::cop2Decode(u32 instr) { +void Interpreter::cop2Decode(Registers& regs, u32 instr) { if(!regs.cop0.status.cu2) { FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC); return; } switch(RS(instr)) { - case 0x00: mfc2(instr); break; - case 0x01: dmfc2(instr); break; - case 0x02: cfc2(instr); break; - case 0x04: mtc2(instr); break; - case 0x05: dmtc2(instr); break; - case 0x06: ctc2(instr); break; + case 0x00: mfc2(regs, instr); break; + case 0x01: dmfc2(regs, instr); break; + case 0x02: cfc2(regs, instr); break; + case 0x04: mtc2(regs, instr); break; + case 0x05: dmtc2(regs, instr); break; + case 0x06: ctc2(regs, instr); break; default: FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC); } } -void Interpreter::Exec(Mem& mem, u32 instr) { +void Interpreter::Exec(Registers& regs, Mem& mem, u32 instr) { u8 mask = (instr >> 26) & 0x3f; // 00rr_rccc switch(mask) { // TODO: named constants for clearer code - case 0x00: special(mem, instr); break; - case 0x01: regimm(instr); break; - case 0x02: j(instr); break; - case 0x03: jal(instr); break; - case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x00: special(regs, mem, instr); break; + case 0x01: regimm(regs, instr); break; + case 0x02: j(regs, instr); break; + case 0x03: jal(regs, instr); break; + case 0x04: b(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; case 0x05: { //fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]); - b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); + b(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); } break; - case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break; - case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break; - case 0x08: addi(instr); break; - case 0x09: addiu(instr); break; - case 0x0A: slti(instr); break; - case 0x0B: sltiu(instr); break; - case 0x0C: andi(instr); break; - case 0x0D: ori(instr); break; - case 0x0E: xori(instr); break; - case 0x0F: lui(instr); break; + case 0x06: b(regs, instr, regs.gpr[RS(instr)] <= 0); break; + case 0x07: b(regs, instr, regs.gpr[RS(instr)] > 0); break; + case 0x08: addi(regs, instr); break; + case 0x09: addiu(regs, instr); break; + case 0x0A: slti(regs, instr); break; + case 0x0B: sltiu(regs, instr); break; + case 0x0C: andi(regs, instr); break; + case 0x0D: ori(regs, instr); break; + case 0x0E: xori(regs, instr); break; + case 0x0F: lui(regs, instr); break; case 0x10: regs.cop0.decode(regs, mem, instr); break; - case 0x11: regs.cop1.decode(*this, instr); break; - case 0x12: cop2Decode(instr); break; - case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break; - case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break; - case 0x18: daddi(instr); break; - case 0x19: daddiu(instr); break; - case 0x1A: ldl(mem, instr); break; - case 0x1B: ldr(mem, instr); break; + case 0x11: regs.cop1.decode(regs, *this, instr); break; + case 0x12: cop2Decode(regs, instr); break; + case 0x14: bl(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x15: bl(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; + case 0x16: bl(regs, instr, regs.gpr[RS(instr)] <= 0); break; + case 0x17: bl(regs, instr, regs.gpr[RS(instr)] > 0); break; + case 0x18: daddi(regs, instr); break; + case 0x19: daddiu(regs, instr); break; + case 0x1A: ldl(regs, mem, instr); break; + case 0x1B: ldr(regs, mem, instr); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break; - case 0x20: lb(mem, instr); break; - case 0x21: lh(mem, instr); break; - case 0x22: lwl(mem, instr); break; - case 0x23: lw(mem, instr); break; - case 0x24: lbu(mem, instr); break; - case 0x25: lhu(mem, instr); break; - case 0x26: lwr(mem, instr); break; - case 0x27: lwu(mem, instr); break; - case 0x28: sb(mem, instr); break; - case 0x29: sh(mem, instr); break; - case 0x2A: swl(mem, instr); break; - case 0x2B: sw(mem, instr); break; - case 0x2C: sdl(mem, instr); break; - case 0x2D: sdr(mem, instr); break; - case 0x2E: swr(mem, instr); break; + case 0x20: lb(regs, mem, instr); break; + case 0x21: lh(regs, mem, instr); break; + case 0x22: lwl(regs, mem, instr); break; + case 0x23: lw(regs, mem, instr); break; + case 0x24: lbu(regs, mem, instr); break; + case 0x25: lhu(regs, mem, instr); break; + case 0x26: lwr(regs, mem, instr); break; + case 0x27: lwu(regs, mem, instr); break; + case 0x28: sb(regs, mem, instr); break; + case 0x29: sh(regs, mem, instr); break; + case 0x2A: swl(regs, mem, instr); break; + case 0x2B: sw(regs, mem, instr); break; + case 0x2C: sdl(regs, mem, instr); break; + case 0x2D: sdr(regs, mem, instr); break; + case 0x2E: swr(regs, mem, instr); break; case 0x2F: break; // CACHE - case 0x30: ll(mem, instr); break; + case 0x30: ll(regs, mem, instr); break; case 0x31: regs.cop1.lwc1(regs, mem, instr); break; - case 0x34: lld(mem, instr); break; + case 0x34: lld(regs, mem, instr); break; case 0x35: regs.cop1.ldc1(regs, mem, instr); break; - case 0x37: ld(mem, instr); break; - case 0x38: sc(mem, instr); break; + case 0x37: ld(regs, mem, instr); break; + case 0x38: sc(regs, mem, instr); break; case 0x39: regs.cop1.swc1(regs, mem, instr); break; - case 0x3C: scd(mem, instr); break; + case 0x3C: scd(regs, mem, instr); break; case 0x3D: regs.cop1.sdc1(regs, mem, instr); break; - case 0x3F: sd(mem, instr); break; + case 0x3F: sd(regs, mem, instr); break; default: util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); } diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 6641ed6e..5ee3a00e 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -6,7 +6,7 @@ #define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) namespace n64 { -void Interpreter::add(u32 instr) { +void Interpreter::add(Registers& regs, u32 instr) { u32 rs = (s32)regs.gpr[RS(instr)]; u32 rt = (s32)regs.gpr[RT(instr)]; u32 result = rs + rt; @@ -17,14 +17,14 @@ void Interpreter::add(u32 instr) { } } -void Interpreter::addu(u32 instr) { +void Interpreter::addu(Registers& regs, u32 instr) { s32 rs = (s32)regs.gpr[RS(instr)]; s32 rt = (s32)regs.gpr[RT(instr)]; s32 result = rs + rt; regs.gpr[RD(instr)] = result; } -void Interpreter::addi(u32 instr) { +void Interpreter::addi(Registers& regs, u32 instr) { u32 rs = regs.gpr[RS(instr)]; u32 imm = s32(s16(instr)); u32 result = rs + imm; @@ -35,14 +35,14 @@ void Interpreter::addi(u32 instr) { } } -void Interpreter::addiu(u32 instr) { +void Interpreter::addiu(Registers& regs, u32 instr) { s32 rs = (s32)regs.gpr[RS(instr)]; s16 imm = (s16)(instr); s32 result = rs + imm; regs.gpr[RT(instr)] = result; } -void Interpreter::dadd(u32 instr) { +void Interpreter::dadd(Registers& regs, u32 instr) { u64 rs = regs.gpr[RS(instr)]; u64 rt = regs.gpr[RT(instr)]; u64 result = rt + rs; @@ -53,13 +53,13 @@ void Interpreter::dadd(u32 instr) { } } -void Interpreter::daddu(u32 instr) { +void Interpreter::daddu(Registers& regs, u32 instr) { s64 rs = regs.gpr[RS(instr)]; s64 rt = regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = rs + rt; } -void Interpreter::daddi(u32 instr) { +void Interpreter::daddi(Registers& regs, u32 instr) { u64 imm = s64(s16(instr)); u64 rs = regs.gpr[RS(instr)]; u64 result = imm + rs; @@ -70,13 +70,13 @@ void Interpreter::daddi(u32 instr) { } } -void Interpreter::daddiu(u32 instr) { +void Interpreter::daddiu(Registers& regs, u32 instr) { s16 imm = (s16)(instr); s64 rs = regs.gpr[RS(instr)]; regs.gpr[RT(instr)] = rs + imm; } -void Interpreter::div(u32 instr) { +void Interpreter::div(Registers& regs, u32 instr) { s64 dividend = (s32)regs.gpr[RS(instr)]; s64 divisor = (s32)regs.gpr[RT(instr)]; @@ -95,7 +95,7 @@ void Interpreter::div(u32 instr) { } } -void Interpreter::divu(u32 instr) { +void Interpreter::divu(Registers& regs, u32 instr) { u32 dividend = regs.gpr[RS(instr)]; u32 divisor = regs.gpr[RT(instr)]; if(divisor == 0) { @@ -109,7 +109,7 @@ void Interpreter::divu(u32 instr) { } } -void Interpreter::ddiv(u32 instr) { +void Interpreter::ddiv(Registers& regs, u32 instr) { s64 dividend = regs.gpr[RS(instr)]; s64 divisor = regs.gpr[RT(instr)]; if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { @@ -130,7 +130,7 @@ void Interpreter::ddiv(u32 instr) { } } -void Interpreter::ddivu(u32 instr) { +void Interpreter::ddivu(Registers& regs, u32 instr) { u64 dividend = regs.gpr[RS(instr)]; u64 divisor = regs.gpr[RT(instr)]; if(divisor == 0) { @@ -144,14 +144,14 @@ void Interpreter::ddivu(u32 instr) { } } -void Interpreter::branch(bool cond, s64 address) { +void Interpreter::branch(Registers& regs, bool cond, s64 address) { regs.delaySlot = true; if (cond) { regs.nextPC = address; } } -void Interpreter::branch_likely(bool cond, s64 address) { +void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) { regs.delaySlot = true; if (cond) { regs.nextPC = address; @@ -160,44 +160,44 @@ void Interpreter::branch_likely(bool cond, s64 address) { } } -void Interpreter::b(u32 instr, bool cond) { +void Interpreter::b(Registers& regs, u32 instr, bool cond) { s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch(cond, address); + branch(regs, cond, address); } -void Interpreter::blink(u32 instr, bool cond) { +void Interpreter::blink(Registers& regs, u32 instr, bool cond) { regs.gpr[31] = regs.nextPC; s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch(cond, address); + branch(regs, cond, address); } -void Interpreter::bl(u32 instr, bool cond) { +void Interpreter::bl(Registers& regs, u32 instr, bool cond) { s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch_likely(cond, address); + branch_likely(regs, cond, address); } -void Interpreter::bllink(u32 instr, bool cond) { +void Interpreter::bllink(Registers& regs, u32 instr, bool cond) { regs.gpr[31] = regs.nextPC; s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch_likely(cond, address); + branch_likely(regs, cond, address); } -void Interpreter::lui(u32 instr) { +void Interpreter::lui(Registers& regs, u32 instr) { s64 val = (s16)instr; val <<= 16; regs.gpr[RT(instr)] = val; } -void Interpreter::lb(Mem& mem, u32 instr) { +void Interpreter::lb(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC); } -void Interpreter::lh(Mem& mem, u32 instr) { +void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -208,7 +208,7 @@ void Interpreter::lh(Mem& mem, u32 instr) { regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC); } -void Interpreter::lw(Mem& mem, u32 instr) { +void Interpreter::lw(Registers& regs, Mem& mem, u32 instr) { s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; if (check_address_error(address, 0b11)) { @@ -226,7 +226,7 @@ void Interpreter::lw(Mem& mem, u32 instr) { } } -void Interpreter::ll(Mem& mem, u32 instr) { +void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; u32 physical; if (!MapVAddr(regs, LOAD, address, physical)) { @@ -240,7 +240,7 @@ void Interpreter::ll(Mem& mem, u32 instr) { regs.cop0.LLAddr = physical >> 4; } -void Interpreter::lwl(Mem& mem, u32 instr) { +void Interpreter::lwl(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if(!MapVAddr(regs, LOAD, address, paddr)) { @@ -255,7 +255,7 @@ void Interpreter::lwl(Mem& mem, u32 instr) { } } -void Interpreter::lwr(Mem& mem, u32 instr) { +void Interpreter::lwr(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if(!MapVAddr(regs, LOAD, address, paddr)) { @@ -270,7 +270,7 @@ void Interpreter::lwr(Mem& mem, u32 instr) { } } -void Interpreter::ld(Mem& mem, u32 instr) { +void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b111)) { HandleTLBException(regs, address); @@ -282,7 +282,7 @@ void Interpreter::ld(Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::lld(Mem& mem, u32 instr) { +void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -296,7 +296,7 @@ void Interpreter::lld(Mem& mem, u32 instr) { regs.cop0.LLAddr = paddr >> 4; } -void Interpreter::ldl(Mem& mem, u32 instr) { +void Interpreter::ldl(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -311,7 +311,7 @@ void Interpreter::ldl(Mem& mem, u32 instr) { } } -void Interpreter::ldr(Mem& mem, u32 instr) { +void Interpreter::ldr(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -326,13 +326,13 @@ void Interpreter::ldr(Mem& mem, u32 instr) { } } -void Interpreter::lbu(Mem& mem, u32 instr) { +void Interpreter::lbu(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u8 value = mem.Read8(regs, address, regs.oldPC); regs.gpr[RT(instr)] = value; } -void Interpreter::lhu(Mem& mem, u32 instr) { +void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -344,7 +344,7 @@ void Interpreter::lhu(Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::lwu(Mem& mem, u32 instr) { +void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -356,12 +356,12 @@ void Interpreter::lwu(Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::sb(Mem& mem, u32 instr) { +void Interpreter::sb(Registers& regs, Mem& mem, u32 instr) { u32 address = regs.gpr[RS(instr)] + (s16)instr; mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC); } -void Interpreter::sc(Mem& mem, u32 instr) { +void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -376,7 +376,7 @@ void Interpreter::sc(Mem& mem, u32 instr) { regs.cop0.llbit = false; } -void Interpreter::scd(Mem& mem, u32 instr) { +void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b111)) { HandleTLBException(regs, address); @@ -392,7 +392,7 @@ void Interpreter::scd(Mem& mem, u32 instr) { regs.cop0.llbit = false; } -void Interpreter::sh(Mem& mem, u32 instr) { +void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -409,7 +409,7 @@ void Interpreter::sh(Mem& mem, u32 instr) { } } -void Interpreter::sw(Mem& mem, u32 instr) { +void Interpreter::sw(Registers& regs, Mem& mem, u32 instr) { s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; if (check_address_error(address, 0b11)) { @@ -427,7 +427,7 @@ void Interpreter::sw(Mem& mem, u32 instr) { } } -void Interpreter::sd(Mem& mem, u32 instr) { +void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -445,7 +445,7 @@ void Interpreter::sd(Mem& mem, u32 instr) { } -void Interpreter::sdl(Mem& mem, u32 instr) { +void Interpreter::sdl(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -460,7 +460,7 @@ void Interpreter::sdl(Mem& mem, u32 instr) { } } -void Interpreter::sdr(Mem& mem, u32 instr) { +void Interpreter::sdr(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -475,7 +475,7 @@ void Interpreter::sdr(Mem& mem, u32 instr) { } } -void Interpreter::swl(Mem& mem, u32 instr) { +void Interpreter::swl(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -490,7 +490,7 @@ void Interpreter::swl(Mem& mem, u32 instr) { } } -void Interpreter::swr(Mem& mem, u32 instr) { +void Interpreter::swr(Registers& regs, Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -505,21 +505,21 @@ void Interpreter::swr(Mem& mem, u32 instr) { } } -void Interpreter::ori(u32 instr) { +void Interpreter::ori(Registers& regs, u32 instr) { s64 imm = (u16)instr; s64 result = imm | regs.gpr[RS(instr)]; regs.gpr[RT(instr)] = result; } -void Interpreter::or_(u32 instr) { +void Interpreter::or_(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; } -void Interpreter::nor(u32 instr) { +void Interpreter::nor(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); } -void Interpreter::j(u32 instr) { +void Interpreter::j(Registers& regs, u32 instr) { s32 target = (instr & 0x3ffffff) << 2; s64 address = (regs.oldPC & ~0xfffffff) | target; if (check_address_error(address, 0b11)) { @@ -527,127 +527,127 @@ void Interpreter::j(u32 instr) { FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC); } - branch(true, address); + branch(regs, true, address); } -void Interpreter::jal(u32 instr) { +void Interpreter::jal(Registers& regs, u32 instr) { regs.gpr[31] = regs.nextPC; - j(instr); + j(regs, instr); } -void Interpreter::jalr(u32 instr) { - branch(true, regs.gpr[RS(instr)]); +void Interpreter::jalr(Registers& regs, u32 instr) { + branch(regs, true, regs.gpr[RS(instr)]); regs.gpr[RD(instr)] = regs.pc + 4; } -void Interpreter::slti(u32 instr) { +void Interpreter::slti(Registers& regs, u32 instr) { regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr); } -void Interpreter::sltiu(u32 instr) { +void Interpreter::sltiu(Registers& regs, u32 instr) { regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr); } -void Interpreter::slt(u32 instr) { +void Interpreter::slt(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; } -void Interpreter::sltu(u32 instr) { +void Interpreter::sltu(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]; } -void Interpreter::xori(u32 instr) { +void Interpreter::xori(Registers& regs, u32 instr) { s64 imm = (u16)instr; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; } -void Interpreter::xor_(u32 instr) { +void Interpreter::xor_(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; } -void Interpreter::andi(u32 instr) { +void Interpreter::andi(Registers& regs, u32 instr) { s64 imm = (u16)instr; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; } -void Interpreter::and_(u32 instr) { +void Interpreter::and_(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; } -void Interpreter::sll(u32 instr) { +void Interpreter::sll(Registers& regs, u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s32 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::sllv(u32 instr) { +void Interpreter::sllv(Registers& regs, u32 instr) { u8 sa = (regs.gpr[RS(instr)]) & 0x1F; u32 rt = regs.gpr[RT(instr)]; s32 result = rt << sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::dsll32(u32 instr) { +void Interpreter::dsll32(Registers& regs, u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s64 result = regs.gpr[RT(instr)] << (sa + 32); regs.gpr[RD(instr)] = result; } -void Interpreter::dsll(u32 instr) { +void Interpreter::dsll(Registers& regs, u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s64 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = result; } -void Interpreter::dsllv(u32 instr) { +void Interpreter::dsllv(Registers& regs, u32 instr) { s64 sa = regs.gpr[RS(instr)] & 63; s64 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = result; } -void Interpreter::srl(u32 instr) { +void Interpreter::srl(Registers& regs, u32 instr) { u32 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u32 result = rt >> sa; regs.gpr[RD(instr)] = (s32)result; } -void Interpreter::srlv(u32 instr) { +void Interpreter::srlv(Registers& regs, u32 instr) { u8 sa = (regs.gpr[RS(instr)] & 0x1F); u32 rt = regs.gpr[RT(instr)]; s32 result = rt >> sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::dsrl(u32 instr) { +void Interpreter::dsrl(Registers& regs, u32 instr) { u64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> sa; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::dsrlv(u32 instr) { +void Interpreter::dsrlv(Registers& regs, u32 instr) { u8 amount = (regs.gpr[RS(instr)] & 63); u64 rt = regs.gpr[RT(instr)]; u64 result = rt >> amount; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::dsrl32(u32 instr) { +void Interpreter::dsrl32(Registers& regs, u32 instr) { u64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> (sa + 32); regs.gpr[RD(instr)] = s64(result); } -void Interpreter::sra(u32 instr) { +void Interpreter::sra(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s32 result = rt >> sa; regs.gpr[RD(instr)] = result; } -void Interpreter::srav(u32 instr) { +void Interpreter::srav(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; u8 sa = rs & 0x1f; @@ -655,14 +655,14 @@ void Interpreter::srav(u32 instr) { regs.gpr[RD(instr)] = result; } -void Interpreter::dsra(u32 instr) { +void Interpreter::dsra(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> sa; regs.gpr[RD(instr)] = result; } -void Interpreter::dsrav(u32 instr) { +void Interpreter::dsrav(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s64 sa = rs & 63; @@ -670,24 +670,24 @@ void Interpreter::dsrav(u32 instr) { regs.gpr[RD(instr)] = result; } -void Interpreter::dsra32(u32 instr) { +void Interpreter::dsra32(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> (sa + 32); regs.gpr[RD(instr)] = result; } -void Interpreter::jr(u32 instr) { +void Interpreter::jr(Registers& regs, u32 instr) { s64 address = regs.gpr[RS(instr)]; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC); } - branch(true, address); + branch(regs, true, address); } -void Interpreter::dsub(u32 instr) { +void Interpreter::dsub(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s64 result = rs - rt; @@ -698,14 +698,14 @@ void Interpreter::dsub(u32 instr) { } } -void Interpreter::dsubu(u32 instr) { +void Interpreter::dsubu(Registers& regs, u32 instr) { u64 rt = regs.gpr[RT(instr)]; u64 rs = regs.gpr[RS(instr)]; u64 result = rs - rt; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::sub(u32 instr) { +void Interpreter::sub(Registers& regs, u32 instr) { s32 rt = regs.gpr[RT(instr)]; s32 rs = regs.gpr[RS(instr)]; s32 result = rs - rt; @@ -716,14 +716,14 @@ void Interpreter::sub(u32 instr) { } } -void Interpreter::subu(u32 instr) { +void Interpreter::subu(Registers& regs, u32 instr) { u32 rt = regs.gpr[RT(instr)]; u32 rs = regs.gpr[RS(instr)]; u32 result = rs - rt; regs.gpr[RD(instr)] = (s64)((s32)result); } -void Interpreter::dmultu(u32 instr) { +void Interpreter::dmultu(Registers& regs, u32 instr) { u64 rt = regs.gpr[RT(instr)]; u64 rs = regs.gpr[RS(instr)]; u128 result = (u128)rt * (u128)rs; @@ -731,7 +731,7 @@ void Interpreter::dmultu(u32 instr) { regs.hi = (s64)(result >> 64); } -void Interpreter::dmult(u32 instr) { +void Interpreter::dmult(Registers& regs, u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s128 result = (s128)rt * (s128)rs; @@ -739,7 +739,7 @@ void Interpreter::dmult(u32 instr) { regs.hi = result >> 64; } -void Interpreter::multu(u32 instr) { +void Interpreter::multu(Registers& regs, u32 instr) { u32 rt = regs.gpr[RT(instr)]; u32 rs = regs.gpr[RS(instr)]; u64 result = (u64)rt * (u64)rs; @@ -747,7 +747,7 @@ void Interpreter::multu(u32 instr) { regs.hi = (s64)((s32)(result >> 32)); } -void Interpreter::mult(u32 instr) { +void Interpreter::mult(Registers& regs, u32 instr) { s32 rt = regs.gpr[RT(instr)]; s32 rs = regs.gpr[RS(instr)]; s64 result = (s64)rt * (s64)rs; @@ -755,50 +755,50 @@ void Interpreter::mult(u32 instr) { regs.hi = (s64)((s32)(result >> 32)); } -void Interpreter::mflo(u32 instr) { +void Interpreter::mflo(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.lo; } -void Interpreter::mfhi(u32 instr) { +void Interpreter::mfhi(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = regs.hi; } -void Interpreter::mtlo(u32 instr) { +void Interpreter::mtlo(Registers& regs, u32 instr) { regs.lo = regs.gpr[RS(instr)]; } -void Interpreter::mthi(u32 instr) { +void Interpreter::mthi(Registers& regs, u32 instr) { regs.hi = regs.gpr[RS(instr)]; } -void Interpreter::trap(bool cond) { +void Interpreter::trap(Registers& regs, bool cond) { if(cond) { FireException(regs, ExceptionCode::Trap, 0, regs.oldPC); } } -void Interpreter::mtc2(u32 instr) { +void Interpreter::mtc2(Registers& regs, u32 instr) { cop2Latch = regs.gpr[RT(instr)]; } -void Interpreter::mfc2(u32 instr) { +void Interpreter::mfc2(Registers& regs, u32 instr) { s32 value = cop2Latch; regs.gpr[RT(instr)] = value; } -void Interpreter::dmtc2(u32 instr) { +void Interpreter::dmtc2(Registers& regs, u32 instr) { cop2Latch = regs.gpr[RT(instr)]; } -void Interpreter::dmfc2(u32 instr) { +void Interpreter::dmfc2(Registers& regs, u32 instr) { regs.gpr[RT(instr)] = cop2Latch; } -void Interpreter::ctc2(u32) { +void Interpreter::ctc2(Registers& regs, u32) { } -void Interpreter::cfc2(u32) { +void Interpreter::cfc2(Registers& regs, u32) { } diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index 84bc2205..f8af3dc6 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -14,8 +14,7 @@ void Cop1::Reset() { memset(fgr, 0, 32 * sizeof(FGR)); } -void Cop1::decode(Interpreter& cpu, u32 instr) { - Registers& regs = cpu.regs; +void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) { if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC); return; @@ -36,10 +35,10 @@ void Cop1::decode(Interpreter& cpu, u32 instr) { case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC); break; case 0x08: switch(mask_branch) { - case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break; - case 1: cpu.b(instr, regs.cop1.fcr31.compare); break; - case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break; - case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break; + case 0: cpu.b(regs, instr, !regs.cop1.fcr31.compare); break; + case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break; + case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break; + case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break; default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch); } break; diff --git a/src/backend/core/registers/Cop1.hpp b/src/backend/core/registers/Cop1.hpp index 48b8ac04..4ef1f4ac 100644 --- a/src/backend/core/registers/Cop1.hpp +++ b/src/backend/core/registers/Cop1.hpp @@ -64,7 +64,7 @@ struct Cop1 { FCR31 fcr31{}; FGR fgr[32]{}; void Reset(); - void decode(Interpreter&, u32); + void decode(Registers&, Interpreter&, u32); friend struct Interpreter; private: template