diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 88a60058..a7ccace2 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -40,7 +40,7 @@ int Interpreter::Step() { return 1; } - u32 instruction = mem.Read32(regs, paddr); + u32 instruction = mem.Read(regs, paddr); if(ShouldServiceInterrupt()) { FireException(regs, ExceptionCode::Interrupt, 0, regs.pc); diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index 3c6adbd9..e58683a3 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -57,7 +57,7 @@ Fn JIT::Recompile() { goto _epilogue; } - u32 instr = mem.Read32(regs, paddr); + u32 instr = mem.Read(regs, paddr); stable = isStable(instr); Emit(instr); diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index 399fc067..a5976648 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -98,7 +98,7 @@ private: }; u8 Read8(u64 addr) { - return mem.Read8(regs, addr); + return mem.Read(regs, addr); } std::vector Serialize() override { return {}; } diff --git a/src/backend/core/JIT/instructions.cpp b/src/backend/core/JIT/instructions.cpp index 16beac43..d3301fc6 100644 --- a/src/backend/core/JIT/instructions.cpp +++ b/src/backend/core/JIT/instructions.cpp @@ -296,7 +296,7 @@ void JIT::lh(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr); + regs.gpr[RT(instr)] = (s16)mem.Read(regs, paddr); } } @@ -314,7 +314,7 @@ void JIT::lw(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); + regs.gpr[RT(instr)] = (s32)mem.Read(regs, physical); } } @@ -329,7 +329,7 @@ void JIT::ll(u32 instr) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); return; } else { - regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); + regs.gpr[RT(instr)] = (s32)mem.Read(regs, physical); } } @@ -346,7 +346,7 @@ void JIT::lwl(u32 instr) { } else { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift)); regs.gpr[RT(instr)] = result; } @@ -361,7 +361,7 @@ void JIT::lwr(u32 instr) { } else { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); regs.gpr[RT(instr)] = result; } @@ -380,7 +380,7 @@ void JIT::ld(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - s64 value = mem.Read64(regs, paddr); + s64 value = mem.Read(regs, paddr); regs.gpr[RT(instr)] = value; } } @@ -400,7 +400,7 @@ void JIT::lld(u32 instr) { if ((address & 0b111) > 0) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); } else { - regs.gpr[RT(instr)] = mem.Read64(regs, paddr); + regs.gpr[RT(instr)] = mem.Read(regs, paddr); regs.cop0.llbit = true; regs.cop0.LLAddr = paddr >> 4; } @@ -416,7 +416,7 @@ void JIT::ldl(u32 instr) { } else { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift)); regs.gpr[RT(instr)] = result; } @@ -431,7 +431,7 @@ void JIT::ldr(u32 instr) { } else { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); regs.gpr[RT(instr)] = result; } @@ -444,7 +444,7 @@ void JIT::lbu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u8 value = mem.Read8(regs, paddr); + u8 value = mem.Read(regs, paddr); regs.gpr[RT(instr)] = value; } } @@ -461,7 +461,7 @@ void JIT::lhu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u16 value = mem.Read16(regs, paddr); + u16 value = mem.Read(regs, paddr); regs.gpr[RT(instr)] = value; } } @@ -479,7 +479,7 @@ void JIT::lwu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u32 value = mem.Read32(regs, paddr); + u32 value = mem.Read(regs, paddr); regs.gpr[RT(instr)] = value; } } @@ -491,7 +491,7 @@ void JIT::sb(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write8(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); } } @@ -510,7 +510,7 @@ void JIT::sc(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); regs.gpr[RT(instr)] = 1; } } else { @@ -538,7 +538,7 @@ void JIT::scd(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); regs.gpr[RT(instr)] = 1; } } else { @@ -554,7 +554,7 @@ void JIT::sh(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write16(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -572,7 +572,7 @@ void JIT::sw(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -589,7 +589,7 @@ void JIT::sd(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write64(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -602,9 +602,9 @@ void JIT::sdl(u32 instr) { } else { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); + mem.Write(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); } } @@ -617,9 +617,9 @@ void JIT::sdr(u32 instr) { } else { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift)); + mem.Write(regs, paddr & ~7, (data & ~mask) | (rt << shift)); } } @@ -632,9 +632,9 @@ void JIT::swl(u32 instr) { } else { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); + mem.Write(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); } } @@ -647,9 +647,9 @@ void JIT::swr(u32 instr) { } else { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift)); + mem.Write(regs, paddr & ~3, (data & ~mask) | (rt << shift)); } } diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 05e47776..2abf1993 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -177,7 +177,7 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) { rom.pal = IsROMPAL(); } -u8 Mem::Read8(n64::Registers ®s, u32 paddr) { +template<> u8 Mem::Read(n64::Registers ®s, u32 paddr) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; @@ -199,12 +199,12 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) { } } case REGION_CART: - return mmio.pi.BusRead8(*this, paddr); + return mmio.pi.BusRead(*this, paddr); case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: case 0x04600000 ... 0x048FFFFF: case 0x04300000 ... 0x044FFFFF: - Util::panic("MMIO Read8!\n"); + Util::panic("MMIO Read!\n"); case AI_REGION: { u32 w = mmio.ai.Read(paddr & ~3); int offs = 3 - (paddr & 3); @@ -225,7 +225,7 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) { } } -u16 Mem::Read16(n64::Registers ®s, u32 paddr) { +template<> u16 Mem::Read(n64::Registers ®s, u32 paddr) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; @@ -249,7 +249,7 @@ u16 Mem::Read16(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead16(*this, paddr); + return mmio.pi.BusRead(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -265,7 +265,7 @@ u16 Mem::Read16(n64::Registers ®s, u32 paddr) { } } -u32 Mem::Read32(n64::Registers ®s, u32 paddr) { +template<> u32 Mem::Read(n64::Registers ®s, u32 paddr) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; @@ -289,7 +289,7 @@ u32 Mem::Read32(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead32(*this, paddr); + return mmio.pi.BusRead(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -302,7 +302,7 @@ u32 Mem::Read32(n64::Registers ®s, u32 paddr) { } } -u64 Mem::Read64(n64::Registers ®s, u32 paddr) { +template<> u64 Mem::Read(n64::Registers ®s, u32 paddr) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; @@ -326,7 +326,7 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead64(*this, paddr); + return mmio.pi.BusRead(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -342,7 +342,7 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) { } } -void Mem::Write8(Registers& regs, u32 paddr, u32 val) { +template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = writePages[page]; @@ -366,11 +366,11 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) { } } break; case REGION_CART: - Util::debug("BusWrite8 @ {:08X} = {:02X}", paddr, val); - mmio.pi.BusWrite8(*this, paddr, val); + Util::debug("BusWrite @ {:08X} = {:02X}", paddr, val); + mmio.pi.BusWrite(*this, paddr, val); break; case MMIO_REGION: - Util::panic("MMIO Write8!"); + Util::panic("MMIO Write!"); case PIF_RAM_REGION: val = val << (8 * (3 - (paddr & 3))); paddr = (paddr - PIF_RAM_REGION_START) & ~3; @@ -391,7 +391,7 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) { } } -void Mem::Write16(Registers& regs, u32 paddr, u32 val) { +template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = writePages[page]; @@ -415,11 +415,11 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) { } } break; case REGION_CART: - Util::debug("BusWrite8 @ {:08X} = {:04X}", paddr, val); - mmio.pi.BusWrite16(paddr, val); + Util::debug("BusWrite @ {:08X} = {:04X}", paddr, val); + mmio.pi.BusWrite(*this, paddr, val); break; case MMIO_REGION: - Util::panic("MMIO Write16!"); + Util::panic("MMIO Write!"); case PIF_RAM_REGION: val = val << (16 * !(paddr & 2)); paddr &= ~3; @@ -440,7 +440,7 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) { } } -void Mem::Write32(Registers& regs, u32 paddr, u32 val) { +template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = writePages[page]; @@ -462,8 +462,8 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) { } } break; case REGION_CART: - Util::debug("BusWrite8 @ {:08X} = {:08X}", paddr, val); - mmio.pi.BusWrite32(*this, paddr, val); + Util::debug("BusWrite @ {:08X} = {:08X}", paddr, val); + mmio.pi.BusWrite(*this, paddr, val); break; case MMIO_REGION: mmio.Write(*this, regs, paddr, val); @@ -483,7 +483,7 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) { } } -void Mem::Write64(Registers& regs, u32 paddr, u64 val) { +void Mem::Write(Registers& regs, u32 paddr, u64 val) { const auto page = paddr >> 12; const auto offset = paddr & 0xFFF; const auto pointer = writePages[page]; @@ -506,11 +506,11 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) { } } break; case REGION_CART: - Util::debug("BusWrite8 @ {:08X} = {:016X}", paddr, val); - mmio.pi.BusWrite64(*this, paddr, val); + Util::debug("BusWrite @ {:08X} = {:016X}", paddr, val); + mmio.pi.BusWrite(*this, paddr, val); break; case MMIO_REGION: - Util::panic("MMIO Write64!"); + Util::panic("MMIO Write!"); case PIF_RAM_REGION: Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val)); si.pif.ProcessCommands(*this); @@ -528,14 +528,14 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) { } } -u32 Mem::BackupRead32() const { +template <> u32 Mem::BackupRead(u32 addr) { switch(saveType) { case SAVE_NONE: return 0; case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); return 0; case SAVE_FLASH_1m: - return flash.Read32(); + return flash.Read(addr); case SAVE_SRAM_256k: return 0xFFFFFFFF; default: @@ -543,14 +543,35 @@ u32 Mem::BackupRead32() const { } } -void Mem::BackupWrite32(u32 addr, u32 val) { +template <> u8 Mem::BackupRead(u32 addr) { + switch (saveType) { + case SAVE_NONE: return 0; + case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + return 0; + case SAVE_FLASH_1m: + return flash.Read(addr); + case SAVE_SRAM_256k: + if (saveData.is_mapped()) { + assert(addr < saveData.size()); + return saveData[addr]; + } + else { + Util::panic("Invalid backup Read if save data is not initialized"); + } + default: + Util::panic("Backup read word with unknown save type"); + } +} + +template <> void Mem::BackupWrite(u32 addr, u32 val) { switch(saveType) { case SAVE_NONE: Util::panic("Accessing cartridge with save type SAVE_NONE in write word"); case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); case SAVE_FLASH_1m: - flash.Write32(addr, val); + flash.Write(addr, val); break; case SAVE_SRAM_256k: break; @@ -559,41 +580,21 @@ void Mem::BackupWrite32(u32 addr, u32 val) { } } -u8 Mem::BackupRead8(u32 addr) { - switch(saveType) { - case SAVE_NONE: return 0; - case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); - return 0; - case SAVE_FLASH_1m: - return flash.Read8(addr); - case SAVE_SRAM_256k: - if(saveData.is_mapped()) { - assert(addr < saveData.size()); - return saveData[addr]; - } else { - Util::panic("Invalid backup Read8 if save data is not initialized"); - } - default: - Util::panic("Backup read word with unknown save type"); - } -} - -void Mem::BackupWrite8(u32 addr, u8 val) { +template <> void Mem::BackupWrite(u32 addr, u8 val) { switch(saveType) { case SAVE_NONE: Util::panic("Accessing cartridge with save type SAVE_NONE in write word"); case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); case SAVE_FLASH_1m: - flash.Write8(addr, val); + flash.Write(addr, val); break; case SAVE_SRAM_256k: if(saveData.is_mapped()) { assert(addr < saveData.size()); saveData[addr] = val; } else { - Util::panic("Invalid backup Write8 if save data is not initialized"); + Util::panic("Invalid backup Write if save data is not initialized"); } break; default: diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index d97461a4..d8da8fa9 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -37,7 +37,7 @@ struct ROM { bool pal; }; -enum FlashState : u8 { +enum class FlashState : u8 { Idle, Erase, Write, Read, Status }; @@ -73,10 +73,10 @@ struct Flash { void CommandRead(); std::vector Serialize(); void Deserialize(const std::vector& data); - void Write32(u32 index, u32 val); - void Write8(u32 index, u8 val); - u32 Read8(u32 index) const; - u32 Read32() const; + template + void Write(u32 index, T val); + template + T Read(u32 index) const; }; struct Mem { @@ -94,19 +94,16 @@ struct Mem { std::vector Serialize(); void Deserialize(const std::vector&); - u8 Read8(Registers&, u32); - u16 Read16(Registers&, u32); - u32 Read32(Registers&, u32); - u64 Read64(Registers&, u32); - void Write8(Registers&, u32, u32); - void Write16(Registers&, u32, u32); - void Write32(Registers&, u32, u32); - void Write64(Registers&, u32, u64); + template + T Read(Registers&, u32); + template + void Write(Registers&, u32, u32); + void Write(Registers&, u32, u64); - u32 BackupRead32() const; - void BackupWrite32(u32, u32); - u8 BackupRead8(u32); - void BackupWrite8(u32, u8); + template + T BackupRead(u32); + template + void BackupWrite(u32, T); MMIO mmio; diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 9213069f..8bea976c 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -220,7 +220,7 @@ void Interpreter::lb(u32 instr) { FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s8) mem.Read8(regs, paddr); + regs.gpr[RT(instr)] = (s8) mem.Read(regs, paddr); } } } @@ -239,7 +239,7 @@ void Interpreter::lh(u32 instr) { FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s16) mem.Read16(regs, paddr); + regs.gpr[RT(instr)] = (s16) mem.Read(regs, paddr); } } } @@ -259,7 +259,7 @@ void Interpreter::lw(u32 instr) { FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { if(RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = (s32) mem.Read32(regs, physical); + regs.gpr[RT(instr)] = (s32) mem.Read(regs, physical); } } } @@ -271,7 +271,7 @@ void Interpreter::ll(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - s32 result = mem.Read32(regs, physical); + s32 result = mem.Read(regs, physical); if (check_address_error(0b11, address)) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); return; @@ -295,7 +295,7 @@ void Interpreter::lwl(u32 instr) { } else { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); + 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; @@ -312,7 +312,7 @@ void Interpreter::lwr(u32 instr) { } else { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); + 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; @@ -333,7 +333,7 @@ void Interpreter::ld(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - s64 value = mem.Read64(regs, paddr); + s64 value = mem.Read(regs, paddr); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = value; } @@ -356,7 +356,7 @@ void Interpreter::lld(u32 instr) { FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); } else { if (RT(instr) != 0) [[likely]] { - regs.gpr[RT(instr)] = mem.Read64(regs, paddr); + regs.gpr[RT(instr)] = mem.Read(regs, paddr); } regs.cop0.llbit = true; regs.cop0.LLAddr = paddr >> 4; @@ -373,7 +373,7 @@ void Interpreter::ldl(u32 instr) { } else { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); + 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; @@ -390,7 +390,7 @@ void Interpreter::ldr(u32 instr) { } else { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); + 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; @@ -405,7 +405,7 @@ void Interpreter::lbu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u8 value = mem.Read8(regs, paddr); + u8 value = mem.Read(regs, paddr); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = value; } @@ -424,7 +424,7 @@ void Interpreter::lhu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u16 value = mem.Read16(regs, paddr); + u16 value = mem.Read(regs, paddr); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = value; } @@ -444,7 +444,7 @@ void Interpreter::lwu(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u32 value = mem.Read32(regs, paddr); + u32 value = mem.Read(regs, paddr); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = value; } @@ -458,7 +458,7 @@ void Interpreter::sb(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write8(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); } } @@ -477,7 +477,7 @@ void Interpreter::sc(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = 1; } @@ -509,7 +509,7 @@ void Interpreter::scd(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); + mem.Write(regs, paddr, regs.gpr[RT(instr)]); if (RT(instr) != 0) [[likely]] { regs.gpr[RT(instr)] = 1; } @@ -529,7 +529,7 @@ void Interpreter::sh(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write16(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -547,7 +547,7 @@ void Interpreter::sw(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -564,7 +564,7 @@ void Interpreter::sd(u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write64(regs, physical, regs.gpr[RT(instr)]); + mem.Write(regs, physical, regs.gpr[RT(instr)]); } } @@ -577,9 +577,9 @@ void Interpreter::sdl(u32 instr) { } else { s32 shift = 8 * ((address ^ 0) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); + mem.Write(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); } } @@ -592,9 +592,9 @@ void Interpreter::sdr(u32 instr) { } else { s32 shift = 8 * ((address ^ 7) & 7); u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); + u64 data = mem.Read(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift)); + mem.Write(regs, paddr & ~7, (data & ~mask) | (rt << shift)); } } @@ -607,9 +607,9 @@ void Interpreter::swl(u32 instr) { } else { u32 shift = 8 * ((address ^ 0) & 3); u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); + mem.Write(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); } } @@ -622,9 +622,9 @@ void Interpreter::swr(u32 instr) { } else { u32 shift = 8 * ((address ^ 3) & 3); u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); + u32 data = mem.Read(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift)); + mem.Write(regs, paddr & ~3, (data & ~mask) | (rt << shift)); } } diff --git a/src/backend/core/mem/Flash.cpp b/src/backend/core/mem/Flash.cpp index 6d46804f..577057f6 100644 --- a/src/backend/core/mem/Flash.cpp +++ b/src/backend/core/mem/Flash.cpp @@ -6,7 +6,7 @@ constexpr auto FLASH_SIZE = 1_mb; Flash::Flash(mio::mmap_sink &saveData) : saveData(saveData) {} void Flash::Reset() { - state = Idle; + state = FlashState::Idle; } void Flash::Load(SaveType saveType, const std::string& path) { @@ -136,7 +136,7 @@ void Flash::Deserialize(const std::vector& data) { memcpy(writeBuf, data.data() + index, 128); } -void Flash::Write32(u32 index, u32 val) { +template <> void Flash::Write(u32 index, u32 val) { if(index > 0) { u8 cmd = val >> 24; switch(cmd) { @@ -154,24 +154,24 @@ void Flash::Write32(u32 index, u32 val) { } } -void Flash::Write8(u32 index, u8 val) { +template <> void Flash::Write(u32 index, u8 val) { switch(state) { - case FlashState::Idle: Util::panic("Invalid FlashState::Idle with Write8"); - case FlashState::Status: Util::panic("Invalid FlashState::Status with Write8"); - case FlashState::Erase: Util::panic("Invalid FlashState::Erase with Write8"); + case FlashState::Idle: Util::panic("Invalid FlashState::Idle with Write"); + case FlashState::Status: Util::panic("Invalid FlashState::Status with Write"); + case FlashState::Erase: Util::panic("Invalid FlashState::Erase with Write"); case FlashState::Write: writeBuf[index] = val; break; - case FlashState::Read: Util::panic("Invalid FlashState::Read with Write8"); - default: Util::warn("Invalid flash state on Write8: {:02X}", static_cast(state)); + case FlashState::Read: Util::panic("Invalid FlashState::Read with Write"); + default: Util::warn("Invalid flash state on Write: {:02X}", static_cast(state)); } } -u32 Flash::Read8(u32 index) const { +template <> u8 Flash::Read(u32 index) const { switch (state) { - case Idle: Util::panic("Flash read byte while in state FLASH_STATE_IDLE"); - case Write: Util::panic("Flash read byte while in state FLASH_STATE_WRITE"); - case Read: { + case FlashState::Idle: Util::panic("Flash read byte while in state FLASH_STATE_IDLE"); + case FlashState::Write: Util::panic("Flash read byte while in state FLASH_STATE_WRITE"); + case FlashState::Read: { if(saveData.is_mapped()) { u8 value = saveData[index]; Util::debug("Flash read byte in state read: index {:08X} = {:02X}", index, value); @@ -180,7 +180,7 @@ u32 Flash::Read8(u32 index) const { Util::panic("Accessing flash when not mapped!"); } } - case Status: { + case FlashState::Status: { u32 offset = (7 - (index % 8)) * 8; u8 value = (status >> offset) & 0xFF; Util::debug("Flash read byte in state status: index {:08X} = {:02X}", index, value); @@ -190,7 +190,7 @@ u32 Flash::Read8(u32 index) const { } } -u32 Flash::Read32() const { +template <> u32 Flash::Read(u32 index) const { return status >> 32; } } \ No newline at end of file diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 6116c605..c4abc038 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -48,14 +48,7 @@ bool PI::ReadLatch() { return true; } -template -auto PI::BusRead8(Mem& mem, u32 addr) -> u8 { - if constexpr (!isDma) { - if (!ReadLatch()) [[unlikely]] { - return latch >> 24; - } - } - +template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { switch (addr) { case REGION_PI_UNKNOWN: Util::panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); @@ -65,12 +58,9 @@ auto PI::BusRead8(Mem& mem, u32 addr) -> u8 { Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); return 0xFF; case REGION_PI_SRAM: - return mem.BackupRead8(addr - SREGION_PI_SRAM); + return mem.BackupRead(addr - SREGION_PI_SRAM); case REGION_PI_ROM: { // round to nearest 4 byte boundary, keeping old LSB - if constexpr (!isDma) { - addr = (addr + 2) & ~2; - } u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; if (index > mem.rom.size) { Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size); @@ -83,17 +73,41 @@ auto PI::BusRead8(Mem& mem, u32 addr) -> u8 { } } -template auto PI::BusRead8(Mem& mem, u32 addr) -> u8; -template auto PI::BusRead8(Mem& mem, u32 addr) -> u8; +template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { + if (!ReadLatch()) [[unlikely]] { + return latch >> 24; + } -template -void PI::BusWrite8(Mem& mem, u32 addr, u32 val) { - if constexpr (!isDma) { - int latch_shift = 24 - (addr & 1) * 8; - - if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] { - return; + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + case REGION_PI_64DD_REG: + Util::panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + case REGION_PI_64DD_ROM: + Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_SRAM: + return mem.BackupRead(addr - SREGION_PI_SRAM); + case REGION_PI_ROM: { + addr = (addr + 2) & ~2; + // round to nearest 4 byte boundary, keeping old LSB + u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; + if (index > mem.rom.size) { + Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size); + return 0xFF; } + return mem.rom.cart[index]; + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template<> void PI::BusWrite(Mem& mem, u32 addr, u8 val) { + int latch_shift = 24 - (addr & 1) * 8; + + if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] { + return; } switch (addr) { @@ -109,7 +123,7 @@ void PI::BusWrite8(Mem& mem, u32 addr, u32 val) { case REGION_PI_64DD_ROM: Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); case REGION_PI_SRAM: - mem.BackupWrite8(addr - SREGION_PI_SRAM, val); + mem.BackupWrite(addr - SREGION_PI_SRAM, val); return; case REGION_PI_ROM: Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); @@ -119,10 +133,32 @@ void PI::BusWrite8(Mem& mem, u32 addr, u32 val) { } } -template void PI::BusWrite8(Mem& mem, u32 addr, u32 val); -template void PI::BusWrite8(Mem& mem, u32 addr, u32 val); +template<> void PI::BusWrite(Mem& mem, u32 addr, u8 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + case REGION_PI_64DD_REG: + if (addr == 0x05000020) { + fprintf(stderr, "%c", val); + } + else { + Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + } + return; + case REGION_PI_64DD_ROM: + Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + case REGION_PI_SRAM: + mem.BackupWrite(addr - SREGION_PI_SRAM, val); + return; + case REGION_PI_ROM: + Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + return; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} -auto PI::BusRead16(Mem& mem, u32 addr) -> u16 { +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { if (!ReadLatch()) [[unlikely]] { return latch >> 16; } @@ -149,7 +185,29 @@ auto PI::BusRead16(Mem& mem, u32 addr) -> u16 { } } -void PI::BusWrite16(u32 addr, u16 val) { +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + case REGION_PI_64DD_REG: + Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + case REGION_PI_64DD_ROM: + Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + case REGION_PI_SRAM: + Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + case REGION_PI_ROM: { + u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM; + if (index > mem.rom.size - 1) { + Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); + } + return Util::ReadAccess(mem.rom.cart, index); + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template <> void PI::BusWrite(Mem&, u32 addr, u16 val) { if (!WriteLatch(val << 16)) [[unlikely]] { return; } @@ -171,7 +229,25 @@ void PI::BusWrite16(u32 addr, u16 val) { } } -auto PI::BusRead32(Mem& mem, u32 addr) -> u32 { +template <> void PI::BusWrite(Mem&, u32 addr, u16 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + case REGION_PI_64DD_REG: + Util::panic("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + case REGION_PI_64DD_ROM: + Util::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + case REGION_PI_SRAM: + Util::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + case REGION_PI_ROM: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + break; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { if (!ReadLatch()) [[unlikely]] { return latch; } @@ -187,7 +263,7 @@ auto PI::BusRead32(Mem& mem, u32 addr) -> u32 { Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); return 0xFF; case REGION_PI_SRAM: - return mem.BackupRead32(); + return mem.BackupRead(addr); case REGION_PI_ROM: { u32 index = addr - SREGION_PI_ROM; if (index > mem.rom.size - 3) { // -3 because we're reading an entire word @@ -208,7 +284,41 @@ auto PI::BusRead32(Mem& mem, u32 addr) -> u32 { } } -void PI::BusWrite32(Mem& mem, u32 addr, u32 val) { +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_REG: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_ROM: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_SRAM: + return mem.BackupRead(addr); + case REGION_PI_ROM: { + u32 index = addr - SREGION_PI_ROM; + if (index > mem.rom.size - 3) { // -3 because we're reading an entire word + switch (addr) { + case REGION_CART_ISVIEWER_BUFFER: + return htobe32(Util::ReadAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER)); + case CART_ISVIEWER_FLUSH: + Util::panic("Read from ISViewer flush!"); + } + Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); + return 0; + } + else { + return Util::ReadAccess(mem.rom.cart, index); + } + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template <> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { switch (addr) { case REGION_PI_UNKNOWN: if (!WriteLatch(val)) [[unlikely]] { @@ -232,7 +342,7 @@ void PI::BusWrite32(Mem& mem, u32 addr, u32 val) { if (!WriteLatch(val)) [[unlikely]] { return; } - mem.BackupWrite32(addr - SREGION_PI_SRAM, val); + mem.BackupWrite(addr - SREGION_PI_SRAM, val); return; case REGION_PI_ROM: switch (addr) { @@ -263,7 +373,48 @@ void PI::BusWrite32(Mem& mem, u32 addr, u32 val) { } } -auto PI::BusRead64(Mem& mem, u32 addr) -> u64 { +template <> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + return; + case REGION_PI_64DD_REG: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + return; + case REGION_PI_64DD_ROM: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + return; + case REGION_PI_SRAM: + mem.BackupWrite(addr - SREGION_PI_SRAM, val); + return; + case REGION_PI_ROM: + switch (addr) { + case REGION_CART_ISVIEWER_BUFFER: + Util::WriteAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, be32toh(val)); + break; + case CART_ISVIEWER_FLUSH: { + if (val < CART_ISVIEWER_SIZE) { + char* message = (char*)malloc(val + 1); + memcpy(message, mem.isviewer, val); + message[val] = '\0'; + printf("%s", message); + free(message); + } + else { + Util::panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!", CART_ISVIEWER_SIZE, val); + } + break; + } + default: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + } + return; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { if (!ReadLatch()) [[unlikely]] { return (u64)latch << 32; } @@ -289,7 +440,29 @@ auto PI::BusRead64(Mem& mem, u32 addr) -> u64 { } } -void PI::BusWrite64(Mem& mem, u32 addr, u64 val) { +template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr); + case REGION_PI_64DD_REG: + Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr); + case REGION_PI_64DD_ROM: + Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr); + case REGION_PI_SRAM: + Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + case REGION_PI_ROM: { + u32 index = addr - SREGION_PI_ROM; + if (index > mem.rom.size - 7) { // -7 because we're reading an entire dword + Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); + } + return Util::ReadAccess(mem.rom.cart, index); + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +template <> void PI::BusWrite(Mem& mem, u32 addr, u64 val) { if (!WriteLatch(val >> 32)) [[unlikely]] { return; } @@ -311,6 +484,24 @@ void PI::BusWrite64(Mem& mem, u32 addr, u64 val) { } } +template <> void PI::BusWrite(Mem& mem, u32 addr, u64 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + case REGION_PI_64DD_REG: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val, addr); + case REGION_PI_64DD_ROM: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + case REGION_PI_SRAM: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + case REGION_PI_ROM: + Util::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + break; + default: + Util::panic("Should never end up here! Access to address %08X which did not match any PI bus regions!", addr); + } +} + auto PI::Read(MI& mi, u32 addr) const -> u32 { switch(addr) { case 0x04600000: return dramAddr; @@ -402,7 +593,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { Util::panic("PI DMA RDRAM->CART ADDRESS TOO HIGH"); } for (int i = 0; i < len; i++) { - BusWrite8(mem, cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]); + BusWrite(mem, cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]); } Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); dmaBusy = true; @@ -423,7 +614,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { } for(int i = 0; i < len; i++) { - mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead8(mem, cartAddrInternal + i); + mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead(mem, cartAddrInternal + i); } dmaBusy = true; Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); diff --git a/src/backend/core/mmio/PI.hpp b/src/backend/core/mmio/PI.hpp index 93b77c46..4baa32b0 100644 --- a/src/backend/core/mmio/PI.hpp +++ b/src/backend/core/mmio/PI.hpp @@ -12,16 +12,10 @@ struct PI { void Reset(); auto Read(MI&, u32) const -> u32; void Write(Mem&, Registers&, u32, u32); - template - auto BusRead8(Mem&, u32) -> u8; - template - void BusWrite8(Mem&, u32, u32); - auto BusRead16(Mem&, u32) -> u16; - void BusWrite16(u32, u16); - auto BusRead32(Mem&, u32) -> u32; - void BusWrite32(Mem&, u32, u32); - auto BusRead64(Mem&, u32) -> u64; - void BusWrite64(Mem&, u32, u64); + template + auto BusRead(Mem&, u32) -> T; + template + void BusWrite(Mem&, u32, T); bool ReadLatch(); bool WriteLatch(u32 val); diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index a109d473..1d21615b 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -343,7 +343,7 @@ void PIF::UpdateController() { } void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) { - mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); + mem.Write(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); switch(cicType) { case UNKNOWN_CIC_TYPE: @@ -548,14 +548,14 @@ void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) { regs.gpr[31] = 0xFFFFFFFFA4001554ll; } - mem.Write32(regs, IMEM_REGION_START + 0x00, 0x3C0DBFC0); - mem.Write32(regs, IMEM_REGION_START + 0x04, 0x8DA807FC); - mem.Write32(regs, IMEM_REGION_START + 0x08, 0x25AD07C0); - mem.Write32(regs, IMEM_REGION_START + 0x0C, 0x31080080); - mem.Write32(regs, IMEM_REGION_START + 0x10, 0x5500FFFC); - mem.Write32(regs, IMEM_REGION_START + 0x14, 0x3C0DBFC0); - mem.Write32(regs, IMEM_REGION_START + 0x18, 0x8DA80024); - mem.Write32(regs, IMEM_REGION_START + 0x1C, 0x3C0BB000); + mem.Write(regs, IMEM_REGION_START + 0x00, 0x3C0DBFC0); + mem.Write(regs, IMEM_REGION_START + 0x04, 0x8DA807FC); + mem.Write(regs, IMEM_REGION_START + 0x08, 0x25AD07C0); + mem.Write(regs, IMEM_REGION_START + 0x0C, 0x31080080); + mem.Write(regs, IMEM_REGION_START + 0x10, 0x5500FFFC); + mem.Write(regs, IMEM_REGION_START + 0x14, 0x3C0DBFC0); + mem.Write(regs, IMEM_REGION_START + 0x18, 0x8DA80024); + mem.Write(regs, IMEM_REGION_START + 0x1C, 0x3C0BB000); break; case CIC_NUS_6106_7106: regs.gpr[0] = 0x0000000000000000; @@ -602,7 +602,7 @@ void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) { regs.gpr[22] = (cicSeeds[cicType] >> 8) & 0xFF; regs.cop0.Reset(); - mem.Write32(regs, 0x04300004, 0x01010101); + mem.Write(regs, 0x04300004, 0x01010101); memcpy(mem.mmio.rsp.dmem, mem.rom.cart, 0x1000); regs.SetPC32(s32(0xA4000040)); } @@ -610,16 +610,16 @@ void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) { void PIF::ExecutePIF(Mem& mem, Registers& regs) { CICType cicType = mem.rom.cicType; bool pal = mem.rom.pal; - mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); + mem.Write(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); switch(cicType) { case UNKNOWN_CIC_TYPE: Util::warn("Unknown CIC type!"); break; case CIC_NUS_6101 ... CIC_NUS_6103_7103: - mem.Write32(regs, 0x318, RDRAM_SIZE); + mem.Write(regs, 0x318, RDRAM_SIZE); break; case CIC_NUS_6105_7105: - mem.Write32(regs, 0x3F0, RDRAM_SIZE); + mem.Write(regs, 0x3F0, RDRAM_SIZE); break; case CIC_NUS_6106_7106: break; diff --git a/src/backend/core/registers/cop/cop1instructions.cpp b/src/backend/core/registers/cop/cop1instructions.cpp index 584a9b91..be4bc955 100644 --- a/src/backend/core/registers/cop/cop1instructions.cpp +++ b/src/backend/core/registers/cop/cop1instructions.cpp @@ -15,7 +15,7 @@ template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> s32& { return fgr[index & ~1].int32h; } else { - return fgr[index & ~1].int32; + return fgr[index].int32; } } @@ -989,7 +989,7 @@ void Cop1::lwc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u32 data = mem.Read32(regs, physical); + u32 data = mem.Read(regs, physical); FGR(regs.cop0.status, FT(instr)) = data; } } @@ -1002,7 +1002,7 @@ void Cop1::swc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, physical, FGR(regs.cop0.status, FT(instr))); + mem.Write(regs, physical, FGR(regs.cop0.status, FT(instr))); } } @@ -1020,7 +1020,7 @@ void Cop1::ldc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { - u64 data = mem.Read64(regs, physical); + u64 data = mem.Read(regs, physical); FGR(regs.cop0.status, FT(instr)) = data; } } @@ -1033,7 +1033,7 @@ void Cop1::sdc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write64(regs, physical, FGR(regs.cop0.status, FT(instr))); + mem.Write(regs, physical, FGR(regs.cop0.status, FT(instr))); } }