From ac9ff89bf189a4021da1795c0a3b3910377b9901 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Fri, 5 Jul 2024 16:56:14 +0200 Subject: [PATCH] Massive register overhaul --- src/backend/core/Interpreter.cpp | 4 - src/backend/core/Mem.cpp | 20 - src/backend/core/interpreter/decode.cpp | 59 +- src/backend/core/interpreter/instructions.cpp | 513 +++++++----------- src/backend/core/mmio/PIF.cpp | 400 +++++++------- src/backend/core/registers/Registers.cpp | 76 +++ src/backend/core/registers/Registers.hpp | 8 +- .../core/registers/cop/cop0instructions.cpp | 8 +- .../core/registers/cop/cop1instructions.cpp | 20 +- 9 files changed, 521 insertions(+), 587 deletions(-) diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 728269fc..675ee6b4 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -48,10 +48,6 @@ int Interpreter::Step() { return 1; } - if((u64)regs.pc == 0xFFFFFFFF8002070C) { - printf("\n"); - } - regs.oldPC = regs.pc; regs.pc = regs.nextPC; regs.nextPC += 4; diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 687cdc2e..dfb65dc3 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -337,11 +337,6 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto pointer = writePages[page]; SI& si = mmio.si; - if(paddr == 0x0023e650) { - //DumpRDRAM(); - //fmt::print("PC is 0x{:016X}: Writing 0x{:02X} -> 0x{:08X}\n", (u64)regs.oldPC, (u8)val, paddr); - } - if(pointer) { ((u8*)pointer)[BYTE_ADDRESS(offset)] = val; } else { @@ -387,11 +382,6 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto pointer = writePages[page]; SI& si = mmio.si; - if(paddr == 0x0023e650) { - //DumpRDRAM(); - //fmt::print("PC is 0x{:016X}: Writing 0x{:04X} -> 0x{:08X}\n", (u64) regs.oldPC, (u16) val, paddr); - } - if(pointer) { Util::WriteAccess((u8*)pointer, HALF_ADDRESS(offset), val); } else { @@ -437,11 +427,6 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto pointer = writePages[page]; SI& si = mmio.si; - if(paddr == 0x0023e650) { - //DumpRDRAM(); - //fmt::print("PC is 0x{:016X}: Writing 0x{:08X} -> 0x{:08X}\n", (u64) regs.oldPC, val, paddr); - } - if(pointer) { Util::WriteAccess((u8*)pointer, offset, val); } else { @@ -481,11 +466,6 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) { const auto pointer = writePages[page]; SI& si = mmio.si; - if(paddr == 0x0023e650) { - //DumpRDRAM(); - //fmt::print("PC is 0x{:016X}: Writing 0x{:016X} -> 0x{:08X}\n", (u64) regs.oldPC, val, paddr); - } - if(pointer) { Util::WriteAccess((u8*)pointer, offset, val); } else { diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index d27cdbc7..878c18ba 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -51,12 +51,12 @@ void Interpreter::special(u32 instr) { case DADDU: daddu(instr); break; case DSUB: dsub(instr); break; case DSUBU: dsubu(instr); break; - case TGE: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; - case TGEU: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; - case TLT: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; - case TLTU: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; - case TEQ: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case TNE: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; + case TGE: trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); break; + case TGEU: trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); break; + case TLT: trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); break; + case TLTU: trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); break; + case TEQ: trap(regs.Read(RS(instr)) == regs.Read(RT(instr))); break; + case TNE: trap(regs.Read(RS(instr)) != regs.Read(RT(instr))); break; case DSLL: dsll(instr); break; case DSRL: dsrl(instr); break; case DSRA: dsra(instr); break; @@ -72,20 +72,20 @@ void Interpreter::regimm(u32 instr) { u8 mask = ((instr >> 16) & 0x1F); // 000r_rccc switch (mask) { // TODO: named constants for clearer code - case BLTZ: b(instr, regs.gpr[RS(instr)] < 0); break; - case BGEZ: b(instr, regs.gpr[RS(instr)] >= 0); break; - case BLTZL: bl(instr, regs.gpr[RS(instr)] < 0); break; - case BGEZL: bl(instr, regs.gpr[RS(instr)] >= 0); break; - case TGEI: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break; - case TGEIU: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; - case TLTI: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break; - case TLTIU: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; - case TEQI: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break; - case TNEI: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break; - case BLTZAL: blink(instr, regs.gpr[RS(instr)] < 0); break; - case BGEZAL: blink(instr, regs.gpr[RS(instr)] >= 0); break; - case BLTZALL: bllink(instr, regs.gpr[RS(instr)] < 0); break; - case BGEZALL: bllink(instr, regs.gpr[RS(instr)] >= 0); break; + case BLTZ: b(instr, regs.Read(RS(instr)) < 0); break; + case BGEZ: b(instr, regs.Read(RS(instr)) >= 0); break; + case BLTZL: bl(instr, regs.Read(RS(instr)) < 0); break; + case BGEZL: bl(instr, regs.Read(RS(instr)) >= 0); break; + case TGEI: trap(regs.Read(RS(instr)) >= s64(s16(instr))); break; + case TGEIU: trap(regs.Read(RS(instr)) >= u64(s64(s16(instr)))); break; + case TLTI: trap(regs.Read(RS(instr)) < s64(s16(instr))); break; + case TLTIU: trap(regs.Read(RS(instr)) < u64(s64(s16(instr)))); break; + case TEQI: trap(regs.Read(RS(instr)) == s64(s16(instr))); break; + case TNEI: trap(regs.Read(RS(instr)) != s64(s16(instr))); break; + case BLTZAL: blink(instr, regs.Read(RS(instr)) < 0); break; + case BGEZAL: blink(instr, regs.Read(RS(instr)) >= 0); break; + case BLTZALL: bllink(instr, regs.Read(RS(instr)) < 0); break; + case BGEZALL: bllink(instr, regs.Read(RS(instr)) >= 0); break; default: Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); } @@ -116,13 +116,10 @@ void Interpreter::Exec(u32 instr) { case REGIMM: regimm(instr); break; case J: j(instr); break; case JAL: jal(instr); break; - case BEQ: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case BNE: { - //fmt::print("RS: {:016X}, RT: {:016X}", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]); - b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); - } break; - case BLEZ: b(instr, regs.gpr[RS(instr)] <= 0); break; - case BGTZ: b(instr, regs.gpr[RS(instr)] > 0); break; + case BEQ: b(instr, regs.Read(RS(instr)) == regs.Read(RT(instr))); break; + case BNE: b(instr, regs.Read(RS(instr)) != regs.Read(RT(instr))); break; + case BLEZ: b(instr, regs.Read(RS(instr)) <= 0); break; + case BGTZ: b(instr, regs.Read(RS(instr)) > 0); break; case ADDI: addi(instr); break; case ADDIU: addiu(instr); break; case SLTI: slti(instr); break; @@ -134,10 +131,10 @@ void Interpreter::Exec(u32 instr) { case COP0: regs.cop0.decode(*this, instr); break; case COP1: regs.cop1.decode(*this, instr); break; case COP2: cop2Decode(instr); break; - case BEQL: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case BNEL: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case BLEZL: bl(instr, regs.gpr[RS(instr)] <= 0); break; - case BGTZL: bl(instr, regs.gpr[RS(instr)] > 0); break; + case BEQL: bl(instr, regs.Read(RS(instr)) == regs.Read(RT(instr))); break; + case BNEL: bl(instr, regs.Read(RS(instr)) != regs.Read(RT(instr))); break; + case BLEZL: bl(instr, regs.Read(RS(instr)) <= 0); break; + case BGTZL: bl(instr, regs.Read(RS(instr)) > 0); break; case DADDI: daddi(instr); break; case DADDIU: daddiu(instr); break; case LDL: ldl(instr); break; diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 3f197c37..b31a2272 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -5,94 +5,78 @@ namespace n64 { void Interpreter::add(u32 instr) { - u32 rs = (s32)regs.gpr[RS(instr)]; - u32 rt = (s32)regs.gpr[RT(instr)]; + u32 rs = regs.Read(RS(instr)); + u32 rt = regs.Read(RT(instr)); u32 result = rs + rt; if(check_signed_overflow(rs, rt, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = s32(result); - } + regs.Write(RD(instr), s32(result)); } } void Interpreter::addu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s32 rs = (s32)regs.gpr[RS(instr)]; - s32 rt = (s32)regs.gpr[RT(instr)]; - s32 result = rs + rt; - regs.gpr[RD(instr)] = result; - } + s32 rs = (s32)regs.Read(RS(instr)); + s32 rt = (s32)regs.Read(RT(instr)); + s32 result = rs + rt; + regs.Write(RD(instr), result); } void Interpreter::addi(u32 instr) { - u32 rs = regs.gpr[RS(instr)]; + u32 rs = regs.Read(RS(instr)); u32 imm = s32(s16(instr)); u32 result = rs + imm; if(check_signed_overflow(rs, imm, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = s32(result); - } + regs.Write(RT(instr), s32(result)); } } void Interpreter::addiu(u32 instr) { - s32 rs = (s32)regs.gpr[RS(instr)]; + s32 rs = regs.Read(RS(instr)); s16 imm = (s16)(instr); s32 result = rs + imm; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + regs.Write(RT(instr), result); } void Interpreter::dadd(u32 instr) { - u64 rs = regs.gpr[RS(instr)]; - u64 rt = regs.gpr[RT(instr)]; + u64 rs = regs.Read(RS(instr)); + u64 rt = regs.Read(RT(instr)); u64 result = rt + rs; if(check_signed_overflow(rs, rt, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = result; - } + regs.Write(RD(instr), result); } } void Interpreter::daddu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rs = regs.gpr[RS(instr)]; - s64 rt = regs.gpr[RT(instr)]; - regs.gpr[RD(instr)] = rs + rt; - } + s64 rs = regs.Read(RS(instr)); + s64 rt = regs.Read(RT(instr)); + regs.Write(RD(instr), rs + rt); } void Interpreter::daddi(u32 instr) { u64 imm = s64(s16(instr)); - u64 rs = regs.gpr[RS(instr)]; + u64 rs = regs.Read(RS(instr)); u64 result = imm + rs; if(check_signed_overflow(rs, imm, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + regs.Write(RT(instr), result); } } void Interpreter::daddiu(u32 instr) { s16 imm = (s16)(instr); - s64 rs = regs.gpr[RS(instr)]; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = rs + imm; - } + s64 rs = regs.Read(RS(instr)); + regs.Write(RT(instr), rs + imm); } void Interpreter::div(u32 instr) { - s64 dividend = (s32)regs.gpr[RS(instr)]; - s64 divisor = (s32)regs.gpr[RT(instr)]; + s64 dividend = regs.Read(RS(instr)); + s64 divisor = regs.Read(RT(instr)); if(divisor == 0) { regs.hi = dividend; @@ -110,8 +94,8 @@ void Interpreter::div(u32 instr) { } void Interpreter::divu(u32 instr) { - u32 dividend = regs.gpr[RS(instr)]; - u32 divisor = regs.gpr[RT(instr)]; + u32 dividend = regs.Read(RS(instr)); + u32 divisor = regs.Read(RT(instr)); if(divisor == 0) { regs.lo = -1; regs.hi = (s32)dividend; @@ -124,8 +108,8 @@ void Interpreter::divu(u32 instr) { } void Interpreter::ddiv(u32 instr) { - s64 dividend = regs.gpr[RS(instr)]; - s64 divisor = regs.gpr[RT(instr)]; + s64 dividend = regs.Read(RS(instr)); + s64 divisor = regs.Read(RT(instr)); if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { regs.lo = dividend; regs.hi = 0; @@ -145,8 +129,8 @@ void Interpreter::ddiv(u32 instr) { } void Interpreter::ddivu(u32 instr) { - u64 dividend = regs.gpr[RS(instr)]; - u64 divisor = regs.gpr[RT(instr)]; + u64 dividend = regs.Read(RS(instr)); + u64 divisor = regs.Read(RT(instr)); if(divisor == 0) { regs.lo = -1; regs.hi = (s64)dividend; @@ -182,7 +166,7 @@ void Interpreter::b(u32 instr, bool cond) { } void Interpreter::blink(u32 instr, bool cond) { - regs.gpr[31] = regs.nextPC; + regs.Write(31, regs.nextPC); s16 imm = instr; s64 offset = u64((s64)imm) << 2; s64 address = regs.pc + offset; @@ -197,7 +181,7 @@ void Interpreter::bl(u32 instr, bool cond) { } void Interpreter::bllink(u32 instr, bool cond) { - regs.gpr[31] = regs.nextPC; + regs.Write(31, regs.nextPC); s16 imm = instr; s64 offset = u64((s64)imm) << 2; s64 address = regs.pc + offset; @@ -207,26 +191,22 @@ void Interpreter::bllink(u32 instr, bool cond) { void Interpreter::lui(u32 instr) { u64 val = s64((s16)instr); val <<= 16; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = val; - } + regs.Write(RT(instr), val); } void Interpreter::lb(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr = 0; if(!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s8) mem.Read(regs, paddr); - } + regs.Write(RT(instr), (s8) mem.Read(regs, paddr)); } } void Interpreter::lh(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; if (check_address_error(0b1, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); @@ -238,15 +218,13 @@ void Interpreter::lh(u32 instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s16) mem.Read(regs, paddr); - } + regs.Write(RT(instr), (s16) mem.Read(regs, paddr)); } } void Interpreter::lw(u32 instr) { s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; + u64 address = regs.Read(RS(instr)) + offset; if (check_address_error(0b11, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); @@ -258,14 +236,12 @@ void Interpreter::lw(u32 instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { - if(RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s32) mem.Read(regs, physical); - } + regs.Write(RT(instr), (s32) mem.Read(regs, physical)); } } void Interpreter::ll(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 physical; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, physical)) { regs.cop0.HandleTLBException(address); @@ -276,10 +252,8 @@ void Interpreter::ll(u32 instr) { regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); return; } - - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + + regs.Write(RT(instr), result); regs.cop0.llbit = true; regs.cop0.LLAddr = physical >> 4; @@ -287,7 +261,7 @@ void Interpreter::ll(u32 instr) { } void Interpreter::lwl(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr = 0; if(!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -296,15 +270,13 @@ void Interpreter::lwl(u32 instr) { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF << shift; u32 data = mem.Read(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + s32 result = s32((regs.Read(RT(instr)) & ~mask) | (data << shift)); + regs.Write(RT(instr), result); } } void Interpreter::lwr(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr = 0; if(!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -313,15 +285,13 @@ void Interpreter::lwr(u32 instr) { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF >> shift; u32 data = mem.Read(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + s32 result = s32((regs.Read(RT(instr)) & ~mask) | (data >> shift)); + regs.Write(RT(instr), result); } } void Interpreter::ld(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; if (check_address_error(0b111, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); @@ -334,9 +304,7 @@ void Interpreter::ld(u32 instr) { regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { s64 value = mem.Read(regs, paddr); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = value; - } + regs.Write(RT(instr), value); } } @@ -346,7 +314,7 @@ void Interpreter::lld(u32 instr) { return; } - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -355,9 +323,7 @@ void Interpreter::lld(u32 instr) { if (check_address_error(0b111, address)) { regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = mem.Read(regs, paddr); - } + regs.Write(RT(instr), mem.Read(regs, paddr)); regs.cop0.llbit = true; regs.cop0.LLAddr = paddr >> 4; } @@ -365,7 +331,7 @@ void Interpreter::lld(u32 instr) { } void Interpreter::ldl(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr = 0; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -374,15 +340,13 @@ void Interpreter::ldl(u32 instr) { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 data = mem.Read(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + s64 result = (s64) ((regs.Read(RT(instr)) & ~mask) | (data << shift)); + regs.Write(RT(instr), result); } } void Interpreter::ldr(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -391,29 +355,25 @@ void Interpreter::ldr(u32 instr) { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 data = mem.Read(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + s64 result = (s64) ((regs.Read(RT(instr)) & ~mask) | (data >> shift)); + regs.Write(RT(instr), result); } } void Interpreter::lbu(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { u8 value = mem.Read(regs, paddr); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = value; - } + regs.Write(RT(instr), value); } } void Interpreter::lhu(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; if (check_address_error(0b1, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); @@ -425,14 +385,12 @@ void Interpreter::lhu(u32 instr) { regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { u16 value = mem.Read(regs, paddr); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = value; - } + regs.Write(RT(instr), value); } } void Interpreter::lwu(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; if (check_address_error(0b11, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC); @@ -445,31 +403,29 @@ void Interpreter::lwu(u32 instr) { regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); } else { u32 value = mem.Read(regs, paddr); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = value; - } + regs.Write(RT(instr), value); } } void Interpreter::sb(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.Read(RT(instr))); } } void Interpreter::sc(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; if(regs.cop0.llbit) { regs.cop0.llbit = false; if (check_address_error(0b11, address)) { - regs.gpr[RT(instr)] = 0; + regs.Write(RT(instr), 0); regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC); return; @@ -477,19 +433,15 @@ void Interpreter::sc(u32 instr) { u32 paddr = 0; if(!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { - regs.gpr[RT(instr)] = 0; + regs.Write(RT(instr), 0); regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = 1; - } + mem.Write(regs, paddr, regs.Read(RT(instr))); + regs.Write(RT(instr), 1); } } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = 0; - } + regs.Write(RT(instr), 0); } } @@ -499,13 +451,13 @@ void Interpreter::scd(u32 instr) { return; } - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; if(regs.cop0.llbit) { regs.cop0.llbit = false; if (check_address_error(0b111, address)) { - regs.gpr[RT(instr)] = 0; + regs.Write(RT(instr), 0); regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC); return; @@ -513,37 +465,33 @@ void Interpreter::scd(u32 instr) { u32 paddr = 0; if(!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { - regs.gpr[RT(instr)] = 0; + regs.Write(RT(instr), 0); regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = 1; - } + mem.Write(regs, paddr, regs.Read(RT(instr))); + regs.Write(RT(instr), 1); } } else { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = 0; - } + regs.Write(RT(instr), 0); } } void Interpreter::sh(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; u32 physical; if(!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.Read(RT(instr))); } } void Interpreter::sw(u32 instr) { s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; + u64 address = regs.Read(RS(instr)) + offset; if (check_address_error(0b11, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC); @@ -555,12 +503,12 @@ void Interpreter::sw(u32 instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.Read(RT(instr))); } } void Interpreter::sd(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; + s64 address = regs.Read(RS(instr)) + (s16)instr; if (check_address_error(0b111, address)) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC); @@ -572,12 +520,12 @@ void Interpreter::sd(u32 instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.Read(RT(instr))); } } void Interpreter::sdl(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -586,13 +534,13 @@ void Interpreter::sdl(u32 instr) { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 data = mem.Read(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; + u64 rt = regs.Read(RT(instr)); mem.Write(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); } } void Interpreter::sdr(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -601,13 +549,13 @@ void Interpreter::sdr(u32 instr) { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 data = mem.Read(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; + u64 rt = regs.Read(RT(instr)); mem.Write(regs, paddr & ~7, (data & ~mask) | (rt << shift)); } } void Interpreter::swl(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -616,13 +564,13 @@ void Interpreter::swl(u32 instr) { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF >> shift; u32 data = mem.Read(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; + u32 rt = regs.Read(RT(instr)); mem.Write(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); } } void Interpreter::swr(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; + u64 address = regs.Read(RS(instr)) + (s16)instr; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::STORE, address, paddr)) { regs.cop0.HandleTLBException(address); @@ -631,29 +579,23 @@ void Interpreter::swr(u32 instr) { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF << shift; u32 data = mem.Read(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; + u32 rt = regs.Read(RT(instr)); mem.Write(regs, paddr & ~3, (data & ~mask) | (rt << shift)); } } void Interpreter::ori(u32 instr) { s64 imm = (u16)instr; - s64 result = imm | regs.gpr[RS(instr)]; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = result; - } + s64 result = imm | regs.Read(RS(instr)); + regs.Write(RT(instr), result); } void Interpreter::or_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; - } + regs.Write(RD(instr), regs.Read(RS(instr)) | regs.Read(RT(instr))); } void Interpreter::nor(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); - } + regs.Write(RD(instr), ~(regs.Read(RS(instr)) | regs.Read(RT(instr)))); } void Interpreter::j(u32 instr) { @@ -664,302 +606,243 @@ void Interpreter::j(u32 instr) { } void Interpreter::jal(u32 instr) { - regs.gpr[31] = regs.nextPC; + regs.Write(31, regs.nextPC); j(instr); } void Interpreter::jalr(u32 instr) { - u64 addr = regs.gpr[RS(instr)]; + u64 addr = regs.Read(RS(instr)); + s64 currentNextPC = regs.nextPC; branch(true, addr); - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.pc + 4; - } + regs.Write(RD(instr), currentNextPC); } void Interpreter::jr(u32 instr) { - u64 address = regs.gpr[RS(instr)]; + u64 address = regs.Read(RS(instr)); branch(true, address); } void Interpreter::slti(u32 instr) { s16 imm = instr; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < imm; - } + regs.Write(RT(instr), regs.Read(RS(instr)) < imm); } void Interpreter::sltiu(u32 instr) { s16 imm = instr; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (u64) regs.gpr[RS(instr)] < imm; - } + regs.Write(RT(instr), regs.Read(RS(instr)) < imm); } void Interpreter::slt(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; - } + regs.Write(RD(instr), regs.Read(RS(instr)) < regs.Read(RT(instr))); } void Interpreter::sltu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = (u64) regs.gpr[RS(instr)] < (u64) regs.gpr[RT(instr)]; - } + regs.Write(RD(instr), regs.Read(RS(instr)) < regs.Read(RT(instr))); } void Interpreter::xori(u32 instr) { s64 imm = (u16)instr; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; - } + regs.Write(RT(instr), regs.Read(RS(instr)) ^ imm); } void Interpreter::xor_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; - } + regs.Write(RD(instr), regs.Read(RT(instr)) ^ regs.Read(RS(instr))); } void Interpreter::andi(u32 instr) { s64 imm = (u16)instr; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; - } + regs.Write(RT(instr), regs.Read(RS(instr)) & imm); } void Interpreter::and_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; - } + regs.Write(RD(instr), regs.Read(RS(instr)) & regs.Read(RT(instr))); } void Interpreter::sll(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - s32 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = (s64) result; - } + u8 sa = ((instr >> 6) & 0x1f); + s32 result = regs.Read(RT(instr)) << sa; + regs.Write(RD(instr), (s64) result); } void Interpreter::sllv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = (regs.gpr[RS(instr)]) & 0x1F; - u32 rt = regs.gpr[RT(instr)]; - s32 result = rt << sa; - regs.gpr[RD(instr)] = (s64) result; - } + u8 sa = (regs.Read(RS(instr))) & 0x1F; + u32 rt = regs.Read(RT(instr)); + s32 result = rt << sa; + regs.Write(RD(instr), (s64) result); } void Interpreter::dsll32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - s64 result = regs.gpr[RT(instr)] << (sa + 32); - regs.gpr[RD(instr)] = result; - } + u8 sa = ((instr >> 6) & 0x1f); + s64 result = regs.Read(RT(instr)) << (sa + 32); + regs.Write(RD(instr), result); } void Interpreter::dsll(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - s64 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = result; - } + u8 sa = ((instr >> 6) & 0x1f); + s64 result = regs.Read(RT(instr)) << sa; + regs.Write(RD(instr), result); } void Interpreter::dsllv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 sa = regs.gpr[RS(instr)] & 63; - s64 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = result; - } + s64 sa = regs.Read(RS(instr)) & 63; + s64 result = regs.Read(RT(instr)) << sa; + regs.Write(RD(instr), result); } void Interpreter::srl(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u32 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u32 result = rt >> sa; - regs.gpr[RD(instr)] = (s32) result; - } + u32 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + u32 result = rt >> sa; + regs.Write(RD(instr), (s32) result); } void Interpreter::srlv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = (regs.gpr[RS(instr)] & 0x1F); - u32 rt = regs.gpr[RT(instr)]; - s32 result = rt >> sa; - regs.gpr[RD(instr)] = (s64) result; - } + u8 sa = (regs.Read(RS(instr)) & 0x1F); + u32 rt = regs.Read(RT(instr)); + s32 result = rt >> sa; + regs.Write(RD(instr), (s64) result); } void Interpreter::dsrl(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u64 result = rt >> sa; - regs.gpr[RD(instr)] = s64(result); - } + u64 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + u64 result = rt >> sa; + regs.Write(RD(instr), s64(result)); } void Interpreter::dsrlv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 amount = (regs.gpr[RS(instr)] & 63); - u64 rt = regs.gpr[RT(instr)]; - u64 result = rt >> amount; - regs.gpr[RD(instr)] = s64(result); - } + u8 amount = (regs.Read(RS(instr)) & 63); + u64 rt = regs.Read(RT(instr)); + u64 result = rt >> amount; + regs.Write(RD(instr), s64(result)); } void Interpreter::dsrl32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u64 result = rt >> (sa + 32); - regs.gpr[RD(instr)] = s64(result); - } + u64 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + u64 result = rt >> (sa + 32); + regs.Write(RD(instr), s64(result)); } void Interpreter::sra(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s32 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } + s64 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + s32 result = rt >> sa; + regs.Write(RD(instr), result); } void Interpreter::srav(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rs = regs.gpr[RS(instr)]; - s64 rt = regs.gpr[RT(instr)]; - u8 sa = rs & 0x1f; - s32 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } + s64 rs = regs.Read(RS(instr)); + s64 rt = regs.Read(RT(instr)); + u8 sa = rs & 0x1f; + s32 result = rt >> sa; + regs.Write(RD(instr), result); } void Interpreter::dsra(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s64 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } + s64 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + s64 result = rt >> sa; + regs.Write(RD(instr), result); } void Interpreter::dsrav(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; - s64 sa = rs & 63; - s64 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } + s64 rt = regs.Read(RT(instr)); + s64 rs = regs.Read(RS(instr)); + s64 sa = rs & 63; + s64 result = rt >> sa; + regs.Write(RD(instr), result); } void Interpreter::dsra32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s64 result = rt >> (sa + 32); - regs.gpr[RD(instr)] = result; - } + s64 rt = regs.Read(RT(instr)); + u8 sa = ((instr >> 6) & 0x1f); + s64 result = rt >> (sa + 32); + regs.Write(RD(instr), result); } void Interpreter::dsub(u32 instr) { - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; + s64 rt = regs.Read(RT(instr)); + s64 rs = regs.Read(RS(instr)); s64 result = rs - rt; if(check_signed_underflow(rs, rt, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = result; - } + regs.Write(RD(instr), result); } } void Interpreter::dsubu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u64 rt = regs.gpr[RT(instr)]; - u64 rs = regs.gpr[RS(instr)]; - u64 result = rs - rt; - regs.gpr[RD(instr)] = s64(result); - } + u64 rt = regs.Read(RT(instr)); + u64 rs = regs.Read(RS(instr)); + u64 result = rs - rt; + regs.Write(RD(instr), s64(result)); } void Interpreter::sub(u32 instr) { - s32 rt = regs.gpr[RT(instr)]; - s32 rs = regs.gpr[RS(instr)]; + s32 rt = regs.Read(RT(instr)); + s32 rs = regs.Read(RS(instr)); s32 result = rs - rt; if(check_signed_underflow(rs, rt, result)) { regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); } else { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = result; - } + regs.Write(RD(instr), result); } } void Interpreter::subu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u32 rt = regs.gpr[RT(instr)]; - u32 rs = regs.gpr[RS(instr)]; - u32 result = rs - rt; - regs.gpr[RD(instr)] = (s64) ((s32) result); - } + u32 rt = regs.Read(RT(instr)); + u32 rs = regs.Read(RS(instr)); + u32 result = rs - rt; + regs.Write(RD(instr), (s64) ((s32) result)); } void Interpreter::dmultu(u32 instr) { - u64 rt = regs.gpr[RT(instr)]; - u64 rs = regs.gpr[RS(instr)]; + u64 rt = regs.Read(RT(instr)); + u64 rs = regs.Read(RS(instr)); u128 result = (u128)rt * (u128)rs; regs.lo = (s64)(result & 0xFFFFFFFFFFFFFFFF); regs.hi = (s64)(result >> 64); } void Interpreter::dmult(u32 instr) { - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; + s64 rt = regs.Read(RT(instr)); + s64 rs = regs.Read(RS(instr)); s128 result = (s128)rt * (s128)rs; regs.lo = result & 0xFFFFFFFFFFFFFFFF; regs.hi = result >> 64; } void Interpreter::multu(u32 instr) { - u32 rt = regs.gpr[RT(instr)]; - u32 rs = regs.gpr[RS(instr)]; + u32 rt = regs.Read(RT(instr)); + u32 rs = regs.Read(RS(instr)); u64 result = (u64)rt * (u64)rs; regs.lo = (s64)((s32)result); regs.hi = (s64)((s32)(result >> 32)); } void Interpreter::mult(u32 instr) { - s32 rt = regs.gpr[RT(instr)]; - s32 rs = regs.gpr[RS(instr)]; + s32 rt = regs.Read(RT(instr)); + s32 rs = regs.Read(RS(instr)); s64 result = (s64)rt * (s64)rs; regs.lo = (s64)((s32)result); regs.hi = (s64)((s32)(result >> 32)); } void Interpreter::mflo(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.lo; - } + regs.Write(RD(instr), regs.lo); } void Interpreter::mfhi(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.hi; - } + regs.Write(RD(instr), regs.hi); } void Interpreter::mtlo(u32 instr) { - regs.lo = regs.gpr[RS(instr)]; + regs.lo = regs.Read(RS(instr)); } void Interpreter::mthi(u32 instr) { - regs.hi = regs.gpr[RS(instr)]; + regs.hi = regs.Read(RS(instr)); } void Interpreter::trap(bool cond) { @@ -969,24 +852,20 @@ void Interpreter::trap(bool cond) { } void Interpreter::mtc2(u32 instr) { - cop2Latch = regs.gpr[RT(instr)]; + cop2Latch = regs.Read(RT(instr)); } void Interpreter::mfc2(u32 instr) { s32 value = cop2Latch; - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = value; - } + regs.Write(RT(instr), value); } void Interpreter::dmtc2(u32 instr) { - cop2Latch = regs.gpr[RT(instr)]; + cop2Latch = regs.Read(RT(instr)); } void Interpreter::dmfc2(u32 instr) { - if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = cop2Latch; - } + regs.Write(RT(instr), cop2Latch); } void Interpreter::ctc2(u32) { diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index 4f8c96d4..9b0d96e8 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -342,202 +342,202 @@ void PIF::HLE(bool pal, CICType cicType) { Util::warn("Unknown CIC type!"); break; case CIC_NUS_6101: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000000; - regs.gpr[2] = 0xFFFFFFFFDF6445CCll; - regs.gpr[3] = 0xFFFFFFFFDF6445CCll; - regs.gpr[4] = 0x00000000000045CC; - regs.gpr[5] = 0x0000000073EE317A; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0xFFFFFFFFC7601FACll; - regs.gpr[13] = 0xFFFFFFFFC7601FACll; - regs.gpr[14] = 0xFFFFFFFFB48E2ED6ll; - regs.gpr[15] = 0xFFFFFFFFBA1A7D4Bll; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000001; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000001; - regs.gpr[24] = 0x0000000000000002; - regs.gpr[25] = 0xFFFFFFFF905F4718ll; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001550ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFDF6445CC); + regs.Write(3, 0xFFFFFFFFDF6445CC); + regs.Write(4, 0x00000000000045CC); + regs.Write(5, 0x0000000073EE317A); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFC7601FAC); + regs.Write(13, 0xFFFFFFFFC7601FAC); + regs.Write(14, 0xFFFFFFFFB48E2ED6); + regs.Write(15, 0xFFFFFFFFBA1A7D4B); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000001); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0xFFFFFFFF905F4718); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); regs.lo = 0xFFFFFFFFBA1A7D4Bll; regs.hi = 0xFFFFFFFF997EC317ll; break; case CIC_NUS_7102: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000001; - regs.gpr[2] = 0x000000001E324416; - regs.gpr[3] = 0x000000001E324416; - regs.gpr[4] = 0x0000000000004416; - regs.gpr[5] = 0x000000000EC5D9AF; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0x00000000495D3D7B; - regs.gpr[13] = 0xFFFFFFFF8B3DFA1Ell; - regs.gpr[14] = 0x000000004798E4D4; - regs.gpr[15] = 0xFFFFFFFFF1D30682ll; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000000; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[22] = 0x000000000000003F; - regs.gpr[23] = 0x0000000000000007; - regs.gpr[24] = 0x0000000000000000; - regs.gpr[25] = 0x0000000013D05CAB; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001554ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x000000001E324416); + regs.Write(3, 0x000000001E324416); + regs.Write(4, 0x0000000000004416); + regs.Write(5, 0x000000000EC5D9AF); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0x00000000495D3D7B); + regs.Write(13, 0xFFFFFFFF8B3DFA1E); + regs.Write(14, 0x000000004798E4D4); + regs.Write(15, 0xFFFFFFFFF1D30682); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000000); + regs.Write(21, 0x0000000000000000); + regs.Write(22, 0x000000000000003F); + regs.Write(23, 0x0000000000000007); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0x0000000013D05CAB); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001554); regs.lo = 0xFFFFFFFFF1D30682ll; regs.hi = 0x0000000010054A98; break; case CIC_NUS_6102_7101: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000001; - regs.gpr[2] = 0x000000000EBDA536; - regs.gpr[3] = 0x000000000EBDA536; - regs.gpr[4] = 0x000000000000A536; - regs.gpr[5] = 0xFFFFFFFFC0F1D859ll; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0xFFFFFFFFED10D0B3ll; - regs.gpr[13] = 0x000000001402A4CC; - regs.gpr[14] = 0x000000002DE108EA; - regs.gpr[15] = 0x000000003103E121; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000001; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000000; - regs.gpr[24] = 0x0000000000000000; - regs.gpr[25] = 0xFFFFFFFF9DEBB54Fll; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001550ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x000000000EBDA536); + regs.Write(3, 0x000000000EBDA536); + regs.Write(4, 0x000000000000A536); + regs.Write(5, 0xFFFFFFFFC0F1D859); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFED10D0B3); + regs.Write(13, 0x000000001402A4CC); + regs.Write(14, 0x000000002DE108EA); + regs.Write(15, 0x000000003103E121); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0xFFFFFFFF9DEBB54F); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); regs.hi = 0x000000003FC18657; regs.lo = 0x000000003103E121; if (pal) { - regs.gpr[20] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000006; - regs.gpr[31] = 0xFFFFFFFFA4001554ll; + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); } break; case CIC_NUS_6103_7103: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000001; - regs.gpr[2] = 0x0000000049A5EE96; - regs.gpr[3] = 0x0000000049A5EE96; - regs.gpr[4] = 0x000000000000EE96; - regs.gpr[5] = 0xFFFFFFFFD4646273ll; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0xFFFFFFFFCE9DFBF7ll; - regs.gpr[13] = 0xFFFFFFFFCE9DFBF7ll; - regs.gpr[14] = 0x000000001AF99984; - regs.gpr[15] = 0x0000000018B63D28; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000001; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000000; - regs.gpr[24] = 0x0000000000000000; - regs.gpr[25] = 0xFFFFFFFF825B21C9ll; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001550ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x0000000049A5EE96); + regs.Write(3, 0x0000000049A5EE96); + regs.Write(4, 0x000000000000EE96); + regs.Write(5, 0xFFFFFFFFD4646273); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFCE9DFBF7); + regs.Write(13, 0xFFFFFFFFCE9DFBF7); + regs.Write(14, 0x000000001AF99984); + regs.Write(15, 0x0000000018B63D28); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0xFFFFFFFF825B21C9); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); regs.lo = 0x0000000018B63D28; regs.hi = 0x00000000625C2BBE; if (pal) { - regs.gpr[20] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000006; - regs.gpr[31] = 0xFFFFFFFFA4001554ll; + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); } break; case CIC_NUS_6105_7105: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000000; - regs.gpr[2] = 0xFFFFFFFFF58B0FBFll; - regs.gpr[3] = 0xFFFFFFFFF58B0FBFll; - regs.gpr[4] = 0x0000000000000FBF; - regs.gpr[5] = 0xFFFFFFFFDECAAAD1ll; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0xFFFFFFFF9651F81Ell; - regs.gpr[13] = 0x000000002D42AAC5; - regs.gpr[14] = 0x00000000489B52CF; - regs.gpr[15] = 0x0000000056584D60; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000001; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000000; - regs.gpr[24] = 0x0000000000000002; - regs.gpr[25] = 0xFFFFFFFFCDCE565Fll; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001550ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFF58B0FBF); + regs.Write(3, 0xFFFFFFFFF58B0FBF); + regs.Write(4, 0x0000000000000FBF); + regs.Write(5, 0xFFFFFFFFDECAAAD1); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFF9651F81E); + regs.Write(13, 0x000000002D42AAC5); + regs.Write(14, 0x00000000489B52CF); + regs.Write(15, 0x0000000056584D60); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0xFFFFFFFFCDCE565F); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); regs.lo = 0x0000000056584D60; regs.hi = 0x000000004BE35D1F; if (pal) { - regs.gpr[20] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000006; - regs.gpr[31] = 0xFFFFFFFFA4001554ll; + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); } mem.Write(regs, IMEM_REGION_START + 0x00, 0x3C0DBFC0); @@ -550,49 +550,49 @@ void PIF::HLE(bool pal, CICType cicType) { mem.Write(regs, IMEM_REGION_START + 0x1C, 0x3C0BB000); break; case CIC_NUS_6106_7106: - regs.gpr[0] = 0x0000000000000000; - regs.gpr[1] = 0x0000000000000000; - regs.gpr[2] = 0xFFFFFFFFA95930A4ll; - regs.gpr[3] = 0xFFFFFFFFA95930A4ll; - regs.gpr[4] = 0x00000000000030A4; - regs.gpr[5] = 0xFFFFFFFFB04DC903ll; - regs.gpr[6] = 0xFFFFFFFFA4001F0Cll; - regs.gpr[7] = 0xFFFFFFFFA4001F08ll; - regs.gpr[8] = 0x00000000000000C0; - regs.gpr[9] = 0x0000000000000000; - regs.gpr[10] = 0x0000000000000040; - regs.gpr[11] = 0xFFFFFFFFA4000040ll; - regs.gpr[12] = 0xFFFFFFFFBCB59510ll; - regs.gpr[13] = 0xFFFFFFFFBCB59510ll; - regs.gpr[14] = 0x000000000CF85C13; - regs.gpr[15] = 0x000000007A3C07F4; - regs.gpr[16] = 0x0000000000000000; - regs.gpr[17] = 0x0000000000000000; - regs.gpr[18] = 0x0000000000000000; - regs.gpr[19] = 0x0000000000000000; - regs.gpr[20] = 0x0000000000000001; - regs.gpr[21] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000000; - regs.gpr[24] = 0x0000000000000002; - regs.gpr[25] = 0x00000000465E3F72; - regs.gpr[26] = 0x0000000000000000; - regs.gpr[27] = 0x0000000000000000; - regs.gpr[28] = 0x0000000000000000; - regs.gpr[29] = 0xFFFFFFFFA4001FF0ll; - regs.gpr[30] = 0x0000000000000000; - regs.gpr[31] = 0xFFFFFFFFA4001550ll; + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFA95930A4); + regs.Write(3, 0xFFFFFFFFA95930A4); + regs.Write(4, 0x00000000000030A4); + regs.Write(5, 0xFFFFFFFFB04DC903); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFBCB59510); + regs.Write(13, 0xFFFFFFFFBCB59510); + regs.Write(14, 0x000000000CF85C13); + regs.Write(15, 0x000000007A3C07F4); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0x00000000465E3F72); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); regs.lo = 0x000000007A3C07F4; regs.hi = 0x0000000023953898; if (pal) { - regs.gpr[20] = 0x0000000000000000; - regs.gpr[23] = 0x0000000000000006; - regs.gpr[31] = 0xFFFFFFFFA4001554ll; + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); } break; } - regs.gpr[22] = (cicSeeds[cicType] >> 8) & 0xFF; + regs.Write(22, (cicSeeds[cicType] >> 8) & 0xFF); regs.cop0.Reset(); mem.Write(regs, 0x04300004, 0x01010101); std::copy(mem.rom.cart.begin(), mem.rom.cart.begin() + 0x1000, mem.mmio.rsp.dmem.begin()); diff --git a/src/backend/core/registers/Registers.cpp b/src/backend/core/registers/Registers.cpp index c2f8cdfb..ea168393 100644 --- a/src/backend/core/registers/Registers.cpp +++ b/src/backend/core/registers/Registers.cpp @@ -30,4 +30,80 @@ void Registers::SetPC32(s32 val) { pc = s64(val); nextPC = pc + 4; } + +template <> u64 Registers::Read(size_t idx) { + return idx == 0 ? 0 : gpr[idx]; +} + +template <> s64 Registers::Read(size_t idx) { + return s64(Read(idx)); +} + +template <> u32 Registers::Read(size_t idx) { + return idx == 0 ? 0 : gpr[idx]; +} + +template <> s32 Registers::Read(size_t idx) { + return s32(Read(idx)); +} + +template <> u16 Registers::Read(size_t idx) { + return idx == 0 ? 0 : gpr[idx]; +} + +template <> s16 Registers::Read(size_t idx) { + return s16(Read(idx)); +} + +template <> u8 Registers::Read(size_t idx) { + return idx == 0 ? 0 : gpr[idx]; +} + +template <> s8 Registers::Read(size_t idx) { + return s8(Read(idx)); +} + +template <> void Registers::Write(size_t idx, bool v) { + if(idx == 0) return; + gpr[idx] = v; +} + +template <> void Registers::Write(size_t idx, u64 v) { + if(idx == 0) return; + gpr[idx] = v; +} + +template <> void Registers::Write(size_t idx, s64 v) { + Write(idx, v); +} + +template <> void Registers::Write(size_t idx, u32 v) { + if(idx == 0) return; + gpr[idx] = (u32)v; +} + +template <> void Registers::Write(size_t idx, s32 v) { + if(idx == 0) return; + gpr[idx] = v; +} + +template <> void Registers::Write(size_t idx, u16 v) { + if(idx == 0) return; + gpr[idx] = (u16)v; +} + +template <> void Registers::Write(size_t idx, s16 v) { + if(idx == 0) return; + gpr[idx] = v; +} + +template <> void Registers::Write(size_t idx, u8 v) { + if(idx == 0) return; + gpr[idx] = (u8)v; +} + +template <> void Registers::Write(size_t idx, s8 v) { + if(idx == 0) return; + gpr[idx] = v; +} } diff --git a/src/backend/core/registers/Registers.hpp b/src/backend/core/registers/Registers.hpp index c182e818..71eb87af 100644 --- a/src/backend/core/registers/Registers.hpp +++ b/src/backend/core/registers/Registers.hpp @@ -7,7 +7,6 @@ struct Registers { void Reset(); void SetPC64(s64); void SetPC32(s32); - s64 gpr[32]{}; Cop0 cop0; Cop1 cop1; s64 oldPC{}, pc{}, nextPC{}; @@ -25,5 +24,12 @@ struct Registers { extraCycles = 0; return ret; } + + template + T Read(size_t); + template + void Write(size_t, T); +private: + s64 gpr[32]{}; }; } diff --git a/src/backend/core/registers/cop/cop0instructions.cpp b/src/backend/core/registers/cop/cop0instructions.cpp index 2bc1da5d..ee0fb578 100644 --- a/src/backend/core/registers/cop/cop0instructions.cpp +++ b/src/backend/core/registers/cop/cop0instructions.cpp @@ -4,19 +4,19 @@ namespace n64 { void Cop0::mtc0(u32 instr) { - SetReg32(RD(instr), regs.gpr[RT(instr)]); + SetReg32(RD(instr), regs.Read(RT(instr))); } void Cop0::dmtc0(u32 instr) { - SetReg64(RD(instr), regs.gpr[RT(instr)]); + SetReg64(RD(instr), regs.Read(RT(instr))); } void Cop0::mfc0(u32 instr) { - regs.gpr[RT(instr)] = s32(GetReg32(RD(instr))); + regs.Write(RT(instr), s32(GetReg32(RD(instr)))); } void Cop0::dmfc0(u32 instr) const { - regs.gpr[RT(instr)] = s64(GetReg64(RD(instr))); + regs.Write(RT(instr), s64(GetReg64(RD(instr)))); } void Cop0::eret() { diff --git a/src/backend/core/registers/cop/cop1instructions.cpp b/src/backend/core/registers/cop/cop1instructions.cpp index 2e3da8e8..bbe584d3 100644 --- a/src/backend/core/registers/cop/cop1instructions.cpp +++ b/src/backend/core/registers/cop/cop1instructions.cpp @@ -471,13 +471,13 @@ void Cop1::cfc1(u32 instr) { break; default: Util::panic("Undefined CFC1 with rd != 0 or 31"); } - regs.gpr[RT(instr)] = val; + regs.Write(RT(instr), val); } void Cop1::ctc1(u32 instr) { if(!CheckFPUUsable()) return; u8 fs = RD(instr); - u32 val = regs.gpr[RT(instr)]; + u32 val = regs.Read(RT(instr)); switch(fs) { case 0: break; case 31: { @@ -1087,7 +1087,7 @@ template void Cop1::sdc1(Interpreter&, Mem&, u32); template void Cop1::sdc1(JIT&, Mem&, u32); void Cop1::lwc1Interp(Mem& mem, u32 instr) { - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; + u64 addr = (s64)(s16)instr + regs.Read(BASE(instr)); u32 physical; if(!regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) { @@ -1100,7 +1100,7 @@ void Cop1::lwc1Interp(Mem& mem, u32 instr) { } void Cop1::swc1Interp(Mem& mem, u32 instr) { - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; + u64 addr = (s64)(s16)instr + regs.Read(BASE(instr)); u32 physical; if(!regs.cop0.MapVAddr(Cop0::STORE, addr, physical)) { @@ -1118,7 +1118,7 @@ void Cop1::unimplemented() { } void Cop1::ldc1Interp(Mem& mem, u32 instr) { - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; + u64 addr = (s64)(s16)instr + regs.Read(BASE(instr)); u32 physical; if(!regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) { @@ -1131,7 +1131,7 @@ void Cop1::ldc1Interp(Mem& mem, u32 instr) { } void Cop1::sdc1Interp(Mem& mem, u32 instr) { - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; + u64 addr = (s64)(s16)instr + regs.Read(BASE(instr)); u32 physical; if(!regs.cop0.MapVAddr(Cop0::STORE, addr, physical)) { @@ -1144,21 +1144,21 @@ void Cop1::sdc1Interp(Mem& mem, u32 instr) { void Cop1::mfc1(u32 instr) { if(!CheckFPUUsable()) return; - regs.gpr[RT(instr)] = FGR_T(regs.cop0.status, FS(instr)); + regs.Write(RT(instr), FGR_T(regs.cop0.status, FS(instr))); } void Cop1::dmfc1(u32 instr) { if(!CheckFPUUsable()) return; - regs.gpr[RT(instr)] = FGR_S(regs.cop0.status, FS(instr)); + regs.Write(RT(instr), FGR_S(regs.cop0.status, FS(instr))); } void Cop1::mtc1(u32 instr) { if(!CheckFPUUsable()) return; - FGR_T(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)]; + FGR_T(regs.cop0.status, FS(instr)) = regs.Read(RT(instr)); } void Cop1::dmtc1(u32 instr) { if(!CheckFPUUsable()) return; - FGR_S(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)]; + FGR_S(regs.cop0.status, FS(instr)) = regs.Read(RT(instr)); } }