Better management of RDRAM accesses

This commit is contained in:
SimoneN64
2024-07-05 23:50:30 +02:00
parent c463358ec4
commit cdbb251be1
7 changed files with 270 additions and 307 deletions

View File

@@ -9,16 +9,6 @@
namespace n64 {
Mem::Mem(Registers& regs, ParallelRDP& parallel) : flash(saveData), mmio(*this, regs, parallel) {
memset(readPages, 0, PAGE_COUNT);
memset(writePages, 0, PAGE_COUNT);
for(u64 i = 0; i < RDRAM_SIZE / PAGE_SIZE; i++) {
const auto addr = (i * PAGE_SIZE) & RDRAM_DSIZE;
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
readPages[i] = pointer;
writePages[i] = pointer;
}
rom.cart.resize(CART_SIZE);
std::fill(rom.cart.begin(), rom.cart.end(), 0);
}
@@ -33,15 +23,6 @@ void Mem::Reset() {
saveData.unmap();
}
mmio.Reset();
memset(readPages, 0, PAGE_COUNT);
memset(writePages, 0, PAGE_COUNT);
for(u64 i = 0; i < RDRAM_SIZE / PAGE_SIZE; i++) {
const auto addr = (i * PAGE_SIZE) & RDRAM_DSIZE;
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
readPages[i] = pointer;
writePages[i] = pointer;
}
}
void Mem::LoadSRAM(SaveType save_type, fs::path path) {
@@ -187,17 +168,11 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) {
}
template<> u8 Mem::Read(n64::Registers &regs, u32 paddr) {
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
SI& si = mmio.si;
if(pointer) {
return ((u8*)pointer)[BYTE_ADDRESS(offset)];
} else {
switch (paddr) {
case RDRAM_REGION:
return mmio.rdp.rdram[BYTE_ADDRESS(paddr)];
return mmio.rdp.ReadRDRAM<u8>(paddr);
case RSP_MEM_REGION: {
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return src[BYTE_ADDRESS(paddr & 0xfff)];
@@ -227,20 +202,13 @@ template<> u8 Mem::Read(n64::Registers &regs, u32 paddr) {
Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc);
}
}
}
template<> u16 Mem::Read(n64::Registers &regs, u32 paddr) {
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
SI& si = mmio.si;
if(pointer) {
return Util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
} else {
switch (paddr) {
case RDRAM_REGION:
return Util::ReadAccess<u16>(mmio.rdp.rdram, HALF_ADDRESS(paddr));
return mmio.rdp.ReadRDRAM<u16>(paddr);
case RSP_MEM_REGION: {
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u16>(src, HALF_ADDRESS(paddr & 0xfff));
@@ -262,20 +230,13 @@ template<> u16 Mem::Read(n64::Registers &regs, u32 paddr) {
Util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc);
}
}
}
template<> u32 Mem::Read(n64::Registers &regs, u32 paddr) {
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
SI& si = mmio.si;
if(pointer) {
return Util::ReadAccess<u32>((u8*)pointer, offset);
} else {
switch(paddr) {
case RDRAM_REGION:
return Util::ReadAccess<u32>(mmio.rdp.rdram, paddr);
return mmio.rdp.ReadRDRAM<u32>(paddr);
case RSP_MEM_REGION: {
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u32>(src, paddr & 0xfff);
@@ -294,20 +255,13 @@ template<> u32 Mem::Read(n64::Registers &regs, u32 paddr) {
Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc);
}
}
}
template<> u64 Mem::Read(n64::Registers &regs, u32 paddr) {
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
SI& si = mmio.si;
if(pointer) {
return Util::ReadAccess<u64>((u8*)pointer, offset);
} else {
switch (paddr) {
case RDRAM_REGION:
return Util::ReadAccess<u64>(mmio.rdp.rdram, paddr);
return mmio.rdp.ReadRDRAM<u64>(paddr);
case RSP_MEM_REGION: {
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u64>(src, paddr & 0xfff);
@@ -329,20 +283,13 @@ template<> u64 Mem::Read(n64::Registers &regs, u32 paddr) {
Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc);
}
}
}
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];
SI& si = mmio.si;
if(pointer) {
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
} else {
switch (paddr) {
case RDRAM_REGION:
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
mmio.rdp.WriteRDRAM<u8>(paddr, val);
break;
case RSP_MEM_REGION: {
val = val << (8 * (3 - (paddr & 3)));
@@ -374,20 +321,13 @@ template<> void Mem::Write<u8>(Registers& regs, u32 paddr, u32 val) {
(u64) regs.pc);
}
}
}
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];
SI& si = mmio.si;
if(pointer) {
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
} else {
switch (paddr) {
case RDRAM_REGION:
Util::WriteAccess<u16>(mmio.rdp.rdram, HALF_ADDRESS(paddr), val);
mmio.rdp.WriteRDRAM<u16>(paddr, val);
break;
case RSP_MEM_REGION: {
val = val << (16 * !(paddr & 2));
@@ -419,20 +359,13 @@ template<> void Mem::Write<u16>(Registers& regs, u32 paddr, u32 val) {
(u64) regs.pc);
}
}
}
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];
SI& si = mmio.si;
if(pointer) {
Util::WriteAccess<u32>((u8*)pointer, offset, val);
} else {
switch(paddr) {
case RDRAM_REGION:
Util::WriteAccess<u32>(mmio.rdp.rdram, paddr, val);
mmio.rdp.WriteRDRAM<u32>(paddr, val);
break;
case RSP_MEM_REGION: {
auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
@@ -458,20 +391,13 @@ template<> void Mem::Write<u32>(Registers& regs, u32 paddr, u32 val) {
default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64)regs.pc);
}
}
}
void Mem::Write(Registers& regs, u32 paddr, u64 val) {
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = writePages[page];
SI& si = mmio.si;
if(pointer) {
Util::WriteAccess<u64>((u8*)pointer, offset, val);
} else {
switch (paddr) {
case RDRAM_REGION:
Util::WriteAccess<u64>(mmio.rdp.rdram, paddr, val);
mmio.rdp.WriteRDRAM<u64>(paddr, val);
break;
case RSP_MEM_REGION: {
auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
@@ -499,7 +425,6 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) {
(u64) regs.pc);
}
}
}
template <> u32 Mem::BackupRead<u32>(u32 addr) {
switch(saveType) {

View File

@@ -132,7 +132,6 @@ struct Mem {
Util::SwapBuffer32(temp);
Util::WriteFileBinary(temp, "dmem.bin");
}
uintptr_t writePages[PAGE_COUNT]{}, readPages[PAGE_COUNT]{};
ROM rom;
SaveType saveType = SAVE_NONE;
Flash flash;

View File

@@ -18,6 +18,54 @@ void RDP::Reset() {
memset(cmd_buf, 0, 0x100000);
}
template<> void RDP::WriteRDRAM<u8>(size_t idx, u8 v) {
size_t real = BYTE_ADDRESS(idx);
if(real < RDRAM_SIZE) {
rdram[real] = v;
}
}
template<> void RDP::WriteRDRAM<u16>(size_t idx, u16 v) {
size_t real = HALF_ADDRESS(idx);
if(real < RDRAM_SIZE) {
Util::WriteAccess<u16>(rdram, real, v);
}
}
template<> void RDP::WriteRDRAM<u32>(size_t idx, u32 v) {
if(idx < RDRAM_SIZE) {
Util::WriteAccess<u32>(rdram, idx, v);
}
}
template<> void RDP::WriteRDRAM<u64>(size_t idx, u64 v) {
if(idx < RDRAM_SIZE) {
Util::WriteAccess<u64>(rdram, idx, v);
}
}
template<> u8 RDP::ReadRDRAM<u8>(size_t idx) {
size_t real = BYTE_ADDRESS(idx);
if(real >= RDRAM_SIZE) return 0;
return rdram[real];
}
template<> u16 RDP::ReadRDRAM<u16>(size_t idx) {
size_t real = HALF_ADDRESS(idx);
if(real >= RDRAM_SIZE) return 0;
return Util::ReadAccess<u16>(rdram, real);
}
template<> u32 RDP::ReadRDRAM<u32>(size_t idx) {
if(idx >= RDRAM_SIZE) return 0;
return Util::ReadAccess<u32>(rdram, idx);
}
template<> u64 RDP::ReadRDRAM<u64>(size_t idx) {
if(idx >= RDRAM_SIZE) return 0;
return Util::ReadAccess<u64>(rdram, idx);
}
static const int cmd_lens[64] = {
2, 2, 2, 2, 2, 2, 2, 2, 8, 12, 24, 28, 24, 28, 40, 44,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

View File

@@ -59,7 +59,6 @@ struct RDP {
RDP(Mem&, ParallelRDP&);
void Reset();
std::vector<u8> rdram{};
[[nodiscard]] auto Read(u32 addr) const -> u32;
void Write(u32 addr, u32 val);
void WriteStatus(u32 val);
@@ -81,7 +80,16 @@ struct RDP {
}
RunCommand();
}
template<typename T>
void WriteRDRAM(size_t, T);
template<typename T>
T ReadRDRAM(size_t);
private:
friend struct Mem;
friend struct MMIO;
std::vector<u8> rdram{};
Mem& mem;
ParallelRDP& parallel;
};

View File

@@ -84,7 +84,7 @@ void AI::Step(u32 cpuCycles, float volumeL, float volumeR) {
if(dmaLen[0] && dmaEnable) {
u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF;
dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF);
u32 data = Util::ReadAccess<u32>(mem.mmio.rdp.rdram, dmaAddr[0] & RDRAM_DSIZE);
u32 data = mem.mmio.rdp.ReadRDRAM<u32>(dmaAddr[0]);
s16 l = s16(data >> 16);
s16 r = s16(data);

View File

@@ -427,20 +427,14 @@ u32 PI::AccessTiming(u8 domain, u32 length) const {
void PI::Write(u32 addr, u32 val) {
MI& mi = mem.mmio.mi;
switch(addr) {
case 0x04600000: dramAddr = val & 0x00FFFFFE; break;
case 0x04600000: dramAddr = val & 0x00FFFFFC; break;
case 0x04600004: cartAddr = val & 0xFFFFFFFE; break;
case 0x04600008: {
rdLen = val & 0x00FFFFFF;
s32 len = val + 1;
for (int i = 0; i < len; i++) {
u32 address = BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE;
if (address < RDRAM_SIZE) {
BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.rdram[address]);
}
else {
BusWrite<u8, true>(cartAddr + i, 0);
}
BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
dramAddr += len;
dramAddr = (dramAddr + 7) & ~7;
@@ -460,10 +454,7 @@ void PI::Write(u32 addr, u32 val) {
}
for(u32 i = 0; i < len; i++) {
u32 address = BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE;
if (address < RDRAM_SIZE) {
mem.mmio.rdp.rdram[address] = BusRead<u8, true>(cartAddr + i);
}
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i));
}
dramAddr += len;
dramAddr = (dramAddr + 7) & ~7;

View File

@@ -38,20 +38,12 @@ void SI::DMA() {
if (toDram) {
pif.ProcessCommands(mem);
for(int i = 0; i < 64; i++) {
u32 addr = dramAddr + i;
if(addr < RDRAM_SIZE) {
mem.mmio.rdp.rdram[BYTE_ADDRESS(addr)] = pif.Read(pifAddr + i);
}
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
}
Util::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
} else {
for(int i = 0; i < 64; i++) {
u32 addr = dramAddr + i;
if(addr < RDRAM_SIZE) {
pif.Write(pifAddr + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(addr)]);
} else {
pif.Write(pifAddr + i, 0);
}
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
Util::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
pif.ProcessCommands(mem);