Use a more modern and clean paradigm for read/write handlers

asdasd
This commit is contained in:
SimoneN64
2023-11-14 12:44:08 +01:00
parent 091557478a
commit 25cfd49e64
12 changed files with 383 additions and 200 deletions

View File

@@ -40,7 +40,7 @@ int Interpreter::Step() {
return 1;
}
u32 instruction = mem.Read32(regs, paddr);
u32 instruction = mem.Read<u32>(regs, paddr);
if(ShouldServiceInterrupt()) {
FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);

View File

@@ -57,7 +57,7 @@ Fn JIT::Recompile() {
goto _epilogue;
}
u32 instr = mem.Read32(regs, paddr);
u32 instr = mem.Read<u32>(regs, paddr);
stable = isStable(instr);
Emit(instr);

View File

@@ -98,7 +98,7 @@ private:
};
u8 Read8(u64 addr) {
return mem.Read8(regs, addr);
return mem.Read<u8>(regs, addr);
}
std::vector<u8> Serialize() override { return {}; }

View File

@@ -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<u16>(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<u32>(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<u32>(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<u32>(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<u32>(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<u64>(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<u64>(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<u64>(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<u64>(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<u8>(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<u16>(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<u32>(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<u8>(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<u32>(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<u32>(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<u16>(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<u32>(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<u64>(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<u64>(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<u32>(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift));
mem.Write<u32>(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<u32>(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift));
mem.Write<u32>(regs, paddr & ~3, (data & ~mask) | (rt << shift));
}
}

View File

@@ -177,7 +177,7 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) {
rom.pal = IsROMPAL();
}
u8 Mem::Read8(n64::Registers &regs, u32 paddr) {
template<> u8 Mem::Read(n64::Registers &regs, 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 &regs, u32 paddr) {
}
}
case REGION_CART:
return mmio.pi.BusRead8<false>(*this, paddr);
return mmio.pi.BusRead<u8, false>(*this, paddr);
case 0x04040000 ... 0x040FFFFF:
case 0x04100000 ... 0x041FFFFF:
case 0x04600000 ... 0x048FFFFF:
case 0x04300000 ... 0x044FFFFF:
Util::panic("MMIO Read8!\n");
Util::panic("MMIO Read<u8>!\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 &regs, u32 paddr) {
}
}
u16 Mem::Read16(n64::Registers &regs, u32 paddr) {
template<> u16 Mem::Read(n64::Registers &regs, 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 &regs, u32 paddr) {
case MMIO_REGION:
return mmio.Read(paddr);
case REGION_CART:
return mmio.pi.BusRead16(*this, paddr);
return mmio.pi.BusRead<u16, false>(*this, paddr);
case PIF_ROM_REGION:
return Util::ReadAccess<u16>(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START);
case PIF_RAM_REGION:
@@ -265,7 +265,7 @@ u16 Mem::Read16(n64::Registers &regs, u32 paddr) {
}
}
u32 Mem::Read32(n64::Registers &regs, u32 paddr) {
template<> u32 Mem::Read(n64::Registers &regs, 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 &regs, u32 paddr) {
case MMIO_REGION:
return mmio.Read(paddr);
case REGION_CART:
return mmio.pi.BusRead32(*this, paddr);
return mmio.pi.BusRead<u32, false>(*this, paddr);
case PIF_ROM_REGION:
return Util::ReadAccess<u32>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
case PIF_RAM_REGION:
@@ -302,7 +302,7 @@ u32 Mem::Read32(n64::Registers &regs, u32 paddr) {
}
}
u64 Mem::Read64(n64::Registers &regs, u32 paddr) {
template<> u64 Mem::Read(n64::Registers &regs, 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 &regs, u32 paddr) {
case MMIO_REGION:
return mmio.Read(paddr);
case REGION_CART:
return mmio.pi.BusRead64(*this, paddr);
return mmio.pi.BusRead<u64, false>(*this, paddr);
case PIF_ROM_REGION:
return Util::ReadAccess<u64>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
case PIF_RAM_REGION:
@@ -342,7 +342,7 @@ u64 Mem::Read64(n64::Registers &regs, u32 paddr) {
}
}
void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
template<> void Mem::Write<u8>(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<false>(*this, paddr, val);
Util::debug("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
mmio.pi.BusWrite<u8, false>(*this, paddr, val);
break;
case MMIO_REGION:
Util::panic("MMIO Write8!");
Util::panic("MMIO Write<u8>!");
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<u16>(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<u8> @ {:08X} = {:04X}", paddr, val);
mmio.pi.BusWrite<u16, false>(*this, paddr, val);
break;
case MMIO_REGION:
Util::panic("MMIO Write16!");
Util::panic("MMIO Write<u16>!");
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<u32>(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<u8> @ {:08X} = {:08X}", paddr, val);
mmio.pi.BusWrite<u32, false>(*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<u8> @ {:08X} = {:016X}", paddr, val);
mmio.pi.BusWrite<u64, false>(*this, paddr, val);
break;
case MMIO_REGION:
Util::panic("MMIO Write64!");
Util::panic("MMIO Write!");
case PIF_RAM_REGION:
Util::WriteAccess<u64>(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<u32>(addr);
case SAVE_SRAM_256k:
return 0xFFFFFFFF;
default:
@@ -543,57 +543,58 @@ u32 Mem::BackupRead32() const {
}
}
void Mem::BackupWrite32(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);
break;
case SAVE_SRAM_256k:
break;
default:
Util::panic("Backup read word with unknown save type");
}
}
u8 Mem::BackupRead8(u32 addr) {
switch(saveType) {
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.Read8(addr);
return flash.Read<u8>(addr);
case SAVE_SRAM_256k:
if(saveData.is_mapped()) {
if (saveData.is_mapped()) {
assert(addr < saveData.size());
return saveData[addr];
} else {
Util::panic("Invalid backup Read8 if save data is not initialized");
}
else {
Util::panic("Invalid backup Read<u8> 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, 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.Write8(addr, val);
flash.Write<u32>(addr, val);
break;
case SAVE_SRAM_256k:
break;
default:
Util::panic("Backup read word with unknown save type");
}
}
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.Write<u8>(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<u8> if save data is not initialized");
}
break;
default:

View File

@@ -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<u8> Serialize();
void Deserialize(const std::vector<u8>& data);
void Write32(u32 index, u32 val);
void Write8(u32 index, u8 val);
u32 Read8(u32 index) const;
u32 Read32() const;
template <typename T>
void Write(u32 index, T val);
template <typename T>
T Read(u32 index) const;
};
struct Mem {
@@ -94,19 +94,16 @@ struct Mem {
std::vector<u8> Serialize();
void Deserialize(const std::vector<u8>&);
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 <typename T>
T Read(Registers&, u32);
template <typename T>
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 <typename T>
T BackupRead(u32);
template <typename T>
void BackupWrite(u32, T);
MMIO mmio;

View File

@@ -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<u8>(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<u16>(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<u32>(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<u32>(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<u32>(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<u32>(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<u64>(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<u64>(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<u64>(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<u64>(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<u8>(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<u16>(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<u32>(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<u8>(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<u32>(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<u32>(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<u16>(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<u32>(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<u64>(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<u64>(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<u32>(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift));
mem.Write<u32>(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<u32>(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift));
mem.Write<u32>(regs, paddr & ~3, (data & ~mask) | (rt << shift));
}
}

View File

@@ -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<u8>& 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<u8>");
case FlashState::Status: Util::panic("Invalid FlashState::Status with Write<u8>");
case FlashState::Erase: Util::panic("Invalid FlashState::Erase with Write<u8>");
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<u8>(state));
case FlashState::Read: Util::panic("Invalid FlashState::Read with Write<u8>");
default: Util::warn("Invalid flash state on Write<u8>: {:02X}", static_cast<u8>(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;
}
}

View File

@@ -48,14 +48,7 @@ bool PI::ReadLatch() {
return true;
}
template<bool isDma>
auto PI::BusRead8(Mem& mem, u32 addr) -> u8 {
if constexpr (!isDma) {
if (!ReadLatch()) [[unlikely]] {
return latch >> 24;
}
}
template<> auto PI::BusRead<u8, true>(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<u8>(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,18 +73,42 @@ auto PI::BusRead8(Mem& mem, u32 addr) -> u8 {
}
}
template auto PI::BusRead8<true>(Mem& mem, u32 addr) -> u8;
template auto PI::BusRead8<false>(Mem& mem, u32 addr) -> u8;
template<> auto PI::BusRead<u8, false>(Mem& mem, u32 addr) -> u8 {
if (!ReadLatch()) [[unlikely]] {
return latch >> 24;
}
template<bool isDma>
void PI::BusWrite8(Mem& mem, u32 addr, u32 val) {
if constexpr (!isDma) {
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<u8>(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<u8, false>(Mem& mem, u32 addr, u8 val) {
int latch_shift = 24 - (addr & 1) * 8;
if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] {
return;
}
}
switch (addr) {
case REGION_PI_UNKNOWN:
@@ -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<u8>(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<true>(Mem& mem, u32 addr, u32 val);
template void PI::BusWrite8<false>(Mem& mem, u32 addr, u32 val);
template<> void PI::BusWrite<u8, true>(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<u8>(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<u16, false>(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<u16, true>(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<u16>(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<u16, false>(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<u16, true>(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<u32, false>(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<u32>(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<u32, true>(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<u32>(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<u32>(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<u32>(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<u32, false>(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<u32>(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<u32, true>(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<u32>(addr - SREGION_PI_SRAM, val);
return;
case REGION_PI_ROM:
switch (addr) {
case REGION_CART_ISVIEWER_BUFFER:
Util::WriteAccess<u32>(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<u64, false>(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<u64, true>(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<u64>(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<u64, false>(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<u64, true>(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<true>(mem, cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]);
BusWrite<u8, true>(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<true>(mem, cartAddrInternal + i);
mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead<u8, true>(mem, cartAddrInternal + i);
}
dmaBusy = true;
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);

View File

@@ -12,16 +12,10 @@ struct PI {
void Reset();
auto Read(MI&, u32) const -> u32;
void Write(Mem&, Registers&, u32, u32);
template<bool isDma>
auto BusRead8(Mem&, u32) -> u8;
template<bool isDma>
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<typename T, bool isDma>
auto BusRead(Mem&, u32) -> T;
template<typename T, bool isDma>
void BusWrite(Mem&, u32, T);
bool ReadLatch();
bool WriteLatch(u32 val);

View File

@@ -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<u32>(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<u32>(regs, IMEM_REGION_START + 0x00, 0x3C0DBFC0);
mem.Write<u32>(regs, IMEM_REGION_START + 0x04, 0x8DA807FC);
mem.Write<u32>(regs, IMEM_REGION_START + 0x08, 0x25AD07C0);
mem.Write<u32>(regs, IMEM_REGION_START + 0x0C, 0x31080080);
mem.Write<u32>(regs, IMEM_REGION_START + 0x10, 0x5500FFFC);
mem.Write<u32>(regs, IMEM_REGION_START + 0x14, 0x3C0DBFC0);
mem.Write<u32>(regs, IMEM_REGION_START + 0x18, 0x8DA80024);
mem.Write<u32>(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<u32>(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<u32>(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<u32>(regs, 0x318, RDRAM_SIZE);
break;
case CIC_NUS_6105_7105:
mem.Write32(regs, 0x3F0, RDRAM_SIZE);
mem.Write<u32>(regs, 0x3F0, RDRAM_SIZE);
break;
case CIC_NUS_6106_7106:
break;

View File

@@ -15,7 +15,7 @@ template<> auto Cop1::FGR<s32>(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<u32>(regs, physical);
FGR<u32>(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<u32>(regs.cop0.status, FT(instr)));
mem.Write<u32>(regs, physical, FGR<u32>(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<u64>(regs, physical);
FGR<u64>(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<u64>(regs.cop0.status, FT(instr)));
mem.Write(regs, physical, FGR<u64>(regs.cop0.status, FT(instr)));
}
}