Basic software fastmem + update parallel-rdp

This commit is contained in:
CocoSimone
2022-12-12 03:44:16 +01:00
parent 69d5166db7
commit dc858560ad
4 changed files with 384 additions and 234 deletions

View File

@@ -10,6 +10,28 @@ Mem::Mem() {
} }
void Mem::Reset() { void Mem::Reset() {
readPages.resize(PAGE_COUNT);
writePages.resize(PAGE_COUNT);
std::fill(readPages.begin(), readPages.end(), 0);
std::fill(writePages.begin(), writePages.end(), 0);
for(int i = 0; i < 2048; i++) {
const auto pointer = (uintptr_t) &mmio.rdp.dram[(i * PAGE_SIZE) & RDRAM_DSIZE];
readPages[i + 0x80000] = pointer;
readPages[i + 0xA0000] = pointer;
writePages[i + 0x80000] = pointer;
writePages[i + 0xA0000] = pointer;
}
readPages[0x84000] = (uintptr_t) &mmio.rsp.dmem[0];
readPages[0xA4000] = (uintptr_t) &mmio.rsp.dmem[0];
readPages[0x84001] = (uintptr_t) &mmio.rsp.imem[0];
readPages[0xA4001] = (uintptr_t) &mmio.rsp.imem[0];
writePages[0x84000] = (uintptr_t) &mmio.rsp.dmem[0];
writePages[0xA4000] = (uintptr_t) &mmio.rsp.dmem[0];
writePages[0x84001] = (uintptr_t) &mmio.rsp.imem[0];
writePages[0xA4001] = (uintptr_t) &mmio.rsp.imem[0];
sram.resize(SRAM_SIZE); sram.resize(SRAM_SIZE);
std::fill(sram.begin(), sram.end(), 0); std::fill(sram.begin(), sram.end(), 0);
romMask = 0; romMask = 0;
@@ -72,133 +94,183 @@ template bool MapVAddr<false>(Registers& regs, TLBAccessType accessType, u64 vad
template <bool tlb> template <bool tlb>
u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) { u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = readPages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: return ((u8*)pointer)[BYTE_ADDRESS(offset)];
return mmio.rdp.dram[BYTE_ADDRESS(paddr)]; } else {
case 0x04000000 ... 0x0403FFFF: u32 paddr = vaddr;
if((paddr >> 12) & 1) if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE]; HandleTLBException(regs, vaddr);
else FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
return mmio.rsp.dmem[BYTE_ADDRESS(paddr) & DMEM_DSIZE]; }
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04600000 ... 0x048FFFFF: case 0x04300000 ... 0x044FFFFF: return 0xff; switch (paddr) {
case 0x04500000 ... 0x045FFFFF: { case 0x00000000 ... 0x007FFFFF:
u32 w = mmio.ai.Read(paddr & ~3); return mmio.rdp.dram[BYTE_ADDRESS(paddr)];
int offs = 3 - (paddr & 3); case 0x04000000 ... 0x0403FFFF:
return (w >> (offs * 8)) & 0xff; if ((paddr >> 12) & 1)
return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE];
else
return mmio.rsp.dmem[BYTE_ADDRESS(paddr) & DMEM_DSIZE];
case 0x04040000 ... 0x040FFFFF:
case 0x04100000 ... 0x041FFFFF:
case 0x04600000 ... 0x048FFFFF:
case 0x04300000 ... 0x044FFFFF:
return 0xff;
case 0x04500000 ... 0x045FFFFF: {
u32 w = mmio.ai.Read(paddr & ~3);
int offs = 3 - (paddr & 3);
return (w >> (offs * 8)) & 0xff;
}
case 0x10000000 ... 0x1FBFFFFF:
paddr = (paddr + 2) & ~2;
return cart[BYTE_ADDRESS(paddr) & romMask];
case 0x1FC00000 ... 0x1FC007BF:
return pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
case 0x1FC007C0 ... 0x1FC007FF:
return pifRam[paddr - 0x1FC007C0];
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x04900000 ... 0x0FFFFFFF:
case 0x1FC00800 ... 0xFFFFFFFF:
return 0;
default:
util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
} }
case 0x10000000 ... 0x1FBFFFFF:
paddr = (paddr + 2) & ~2;
return cart[BYTE_ADDRESS(paddr) & romMask];
case 0x1FC00000 ... 0x1FC007BF:
return pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
case 0x1FC007C0 ... 0x1FC007FF:
return pifRam[paddr - 0x1FC007C0];
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
default:
util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64)regs.pc);
} }
} }
template <bool tlb> template <bool tlb>
u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) { u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = readPages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: return util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr)); } else {
case 0x04000000 ... 0x0403FFFF: u32 paddr = vaddr;
if((paddr >> 12) & 1) if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); HandleTLBException(regs, vaddr);
else FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
return util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE); }
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: switch (paddr) {
return mmio.Read(paddr); case 0x00000000 ... 0x007FFFFF:
case 0x10000000 ... 0x1FBFFFFF: return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr));
paddr = (paddr + 2) & ~3; case 0x04000000 ... 0x0403FFFF:
return util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask); if ((paddr >> 12) & 1)
case 0x1FC00000 ... 0x1FC007BF: return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
return util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000); else
case 0x1FC007C0 ... 0x1FC007FF: return util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE);
return be16toh(util::ReadAccess<u16>(pifRam, paddr - 0x1FC007C0)); case 0x04040000 ... 0x040FFFFF:
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; case 0x04300000 ... 0x044FFFFF:
default: util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64)regs.pc); case 0x04500000 ... 0x048FFFFF:
return mmio.Read(paddr);
case 0x10000000 ... 0x1FBFFFFF:
paddr = (paddr + 2) & ~3;
return util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
case 0x1FC00000 ... 0x1FC007BF:
return util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
case 0x1FC007C0 ... 0x1FC007FF:
return be16toh(util::ReadAccess<u16>(pifRam, paddr - 0x1FC007C0));
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x04900000 ... 0x0FFFFFFF:
case 0x1FC00800 ... 0xFFFFFFFF:
return 0;
default:
util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
}
} }
} }
template <bool tlb> template <bool tlb>
u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) { u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = readPages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: return util::ReadAccess<u32>((u8*)pointer, offset);
return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr); } else {
case 0x04000000 ... 0x0403FFFF: u32 paddr = vaddr;
if((paddr >> 12) & 1) if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE); HandleTLBException(regs, vaddr);
else FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
return util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE); }
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: switch(paddr) {
return mmio.Read(paddr); case 0x00000000 ... 0x007FFFFF:
case 0x10000000 ... 0x1FBFFFFF: return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr);
return util::ReadAccess<u32>(cart.data(), paddr & romMask); case 0x04000000 ... 0x0403FFFF:
case 0x1FC00000 ... 0x1FC007BF: if((paddr >> 12) & 1)
return util::ReadAccess<u32>(pifBootrom, paddr - 0x1FC00000); return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
case 0x1FC007C0 ... 0x1FC007FF: else
return be32toh(util::ReadAccess<u32>(pifRam, paddr - 0x1FC007C0)); return util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF:
default: return mmio.Read(paddr);
util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc); case 0x10000000 ... 0x1FBFFFFF:
return util::ReadAccess<u32>(cart.data(), paddr & romMask);
case 0x1FC00000 ... 0x1FC007BF:
return util::ReadAccess<u32>(pifBootrom, paddr - 0x1FC00000);
case 0x1FC007C0 ... 0x1FC007FF:
return be32toh(util::ReadAccess<u32>(pifRam, paddr - 0x1FC007C0));
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
default:
util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
}
} }
} }
template <bool tlb> template <bool tlb>
u64 Mem::Read64(n64::Registers &regs, u64 vaddr, s64 pc) { u64 Mem::Read64(n64::Registers &regs, u64 vaddr, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = readPages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: return util::ReadAccess<u64>((u8*)pointer, offset);
return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr); } else {
case 0x04000000 ... 0x0403FFFF: u32 paddr = vaddr;
if((paddr >> 12) & 1) if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE); HandleTLBException(regs, vaddr);
else FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
return util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE); }
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: switch (paddr) {
return mmio.Read(paddr); case 0x00000000 ... 0x007FFFFF:
case 0x10000000 ... 0x1FBFFFFF: return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr);
return util::ReadAccess<u64>(cart.data(), paddr & romMask); case 0x04000000 ... 0x0403FFFF:
case 0x1FC00000 ... 0x1FC007BF: if ((paddr >> 12) & 1)
return util::ReadAccess<u64>(pifBootrom, paddr - 0x1FC00000); return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
case 0x1FC007C0 ... 0x1FC007FF: else
return be64toh(util::ReadAccess<u64>(pifRam, paddr - 0x1FC007C0)); return util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: case 0x04040000 ... 0x040FFFFF:
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; case 0x04100000 ... 0x041FFFFF:
default: util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64)regs.pc); case 0x04300000 ... 0x044FFFFF:
case 0x04500000 ... 0x048FFFFF:
return mmio.Read(paddr);
case 0x10000000 ... 0x1FBFFFFF:
return util::ReadAccess<u64>(cart.data(), paddr & romMask);
case 0x1FC00000 ... 0x1FC007BF:
return util::ReadAccess<u64>(pifBootrom, paddr - 0x1FC00000);
case 0x1FC007C0 ... 0x1FC007FF:
return be64toh(util::ReadAccess<u64>(pifRam, paddr - 0x1FC007C0));
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x04900000 ... 0x0FFFFFFF:
case 0x1FC00800 ... 0xFFFFFFFF:
return 0;
default:
util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
}
} }
} }
@@ -213,150 +285,211 @@ template u64 Mem::Read64<true>(n64::Registers &regs, u64 vaddr, s64 pc);
template <bool tlb> template <bool tlb>
void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = writePages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: ((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val; } else {
break; u32 paddr = vaddr;
case 0x04000000 ... 0x0403FFFF: if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
val = val << (8 * (3 - (paddr & 3))); HandleTLBException(regs, vaddr);
paddr = (paddr & DMEM_DSIZE) & ~3; FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
if(paddr & 0x1000) }
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else switch (paddr) {
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); case 0x00000000 ... 0x007FFFFF:
break; mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val;
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: break;
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write8!\n"); case 0x04000000 ... 0x0403FFFF:
case 0x10000000 ... 0x13FFFFFF: break; val = val << (8 * (3 - (paddr & 3)));
case 0x1FC007C0 ... 0x1FC007FF: paddr = (paddr & DMEM_DSIZE) & ~3;
val = val << (8 * (3 - (paddr & 3))); if (paddr & 0x1000)
paddr = (paddr - 0x1FC007C0) & ~3; util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
util::WriteAccess<u32>(pifRam, paddr, htobe32(val)); else
ProcessPIFCommands(pifRam, mmio.si.controller, *this); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
break; break;
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: case 0x04040000 ... 0x040FFFFF:
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; case 0x04300000 ... 0x044FFFFF:
default: case 0x04500000 ... 0x048FFFFF:
util::panic("Unimplemented 8-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc); util::panic("MMIO Write8!\n");
case 0x10000000 ... 0x13FFFFFF:
break;
case 0x1FC007C0 ... 0x1FC007FF:
val = val << (8 * (3 - (paddr & 3)));
paddr = (paddr - 0x1FC007C0) & ~3;
util::WriteAccess<u32>(pifRam, paddr, htobe32(val));
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
break;
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x08000000 ... 0x0FFFFFFF:
case 0x04900000 ... 0x07FFFFFF:
case 0x1FC00800 ... 0x7FFFFFFF:
case 0x80000000 ... 0xFFFFFFFF:
break;
default:
util::panic("Unimplemented 8-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
(u64) regs.pc);
}
} }
} }
template <bool tlb> template <bool tlb>
void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) { void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = writePages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
util::WriteAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val); } else {
break; u32 paddr = vaddr;
case 0x04000000 ... 0x0403FFFF: if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
val = val << (16 * !(paddr & 2)); HandleTLBException(regs, vaddr);
paddr &= ~3; FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
if(paddr & 0x1000) }
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else switch (paddr) {
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); case 0x00000000 ... 0x007FFFFF:
break; util::WriteAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val);
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: break;
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write16!\n"); case 0x04000000 ... 0x0403FFFF:
case 0x10000000 ... 0x13FFFFFF: break; val = val << (16 * !(paddr & 2));
case 0x1FC007C0 ... 0x1FC007FF: paddr &= ~3;
val = val << (16 * !(paddr & 2)); if (paddr & 0x1000)
paddr &= ~3; util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val)); else
ProcessPIFCommands(pifRam, mmio.si.controller, *this); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
break; break;
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: case 0x04040000 ... 0x040FFFFF:
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; case 0x04300000 ... 0x044FFFFF:
default: util::panic("Unimplemented 16-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc); case 0x04500000 ... 0x048FFFFF:
util::panic("MMIO Write16!\n");
case 0x10000000 ... 0x13FFFFFF:
break;
case 0x1FC007C0 ... 0x1FC007FF:
val = val << (16 * !(paddr & 2));
paddr &= ~3;
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
break;
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x08000000 ... 0x0FFFFFFF:
case 0x04900000 ... 0x07FFFFFF:
case 0x1FC00800 ... 0x7FFFFFFF:
case 0x80000000 ... 0xFFFFFFFF:
break;
default:
util::panic("Unimplemented 16-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
(u64) regs.pc);
}
} }
} }
template <bool tlb> template <bool tlb>
void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) { void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = writePages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: util::WriteAccess<u32>((u8*)pointer, offset, val);
util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr, val); } else {
break; u32 paddr = vaddr;
case 0x04000000 ... 0x0403FFFF: if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
if(paddr & 0x1000) HandleTLBException(regs, vaddr);
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
else }
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
break; switch(paddr) {
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: case 0x00000000 ... 0x007FFFFF:
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break; util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr, val);
case 0x10000000 ... 0x13FF0013: break; break;
case 0x13FF0014: { case 0x04000000 ... 0x0403FFFF:
if(val < ISVIEWER_SIZE) { if(paddr & 0x1000)
char* message = (char*)calloc(val + 1, 1); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
memcpy(message, isviewer, val); else
fmt::print("{}", message); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
free(message); break;
} case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
} break; case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break;
case 0x13FF0020 ... 0x13FFFFFF: case 0x10000000 ... 0x13FF0013: break;
util::WriteAccess<u32>(isviewer, paddr - 0x13FF0020, htobe32(val)); case 0x13FF0014: {
break; if(val < ISVIEWER_SIZE) {
case 0x1FC007C0 ... 0x1FC007FF: char* message = (char*)calloc(val + 1, 1);
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val)); memcpy(message, isviewer, val);
ProcessPIFCommands(pifRam, mmio.si.controller, *this); fmt::print("{}", message);
break; free(message);
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: }
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF: } break;
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; case 0x13FF0020 ... 0x13FFFFFF:
default: util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc); util::WriteAccess<u32>(isviewer, paddr - 0x13FF0020, htobe32(val));
break;
case 0x1FC007C0 ... 0x1FC007FF:
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
break;
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF:
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break;
default: util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc);
}
} }
} }
template <bool tlb> template <bool tlb>
void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) { void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
u32 paddr = vaddr; const auto page = (vaddr & 0xFFFFFFFF) >> 12;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) { const auto offset = vaddr & 0xFFF;
HandleTLBException(regs, vaddr); const auto pointer = writePages[page];
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch(paddr) { if(pointer) {
case 0x00000000 ... 0x007FFFFF: util::WriteAccess<u64>((u8*)pointer, offset, val);
util::WriteAccess<u64>(mmio.rdp.dram.data(), paddr, val); } else {
break; u32 paddr = vaddr;
case 0x04000000 ... 0x0403FFFF: if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
val >>= 32; HandleTLBException(regs, vaddr);
if(paddr & 0x1000) FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); }
else
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); switch (paddr) {
break; case 0x00000000 ... 0x007FFFFF:
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: util::WriteAccess<u64>(mmio.rdp.dram.data(), paddr, val);
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write64!\n"); break;
case 0x10000000 ... 0x13FFFFFF: break; case 0x04000000 ... 0x0403FFFF:
case 0x1FC007C0 ... 0x1FC007FF: val >>= 32;
util::WriteAccess<u64>(pifRam, paddr - 0x1FC007C0, htobe64(val)); if (paddr & 0x1000)
ProcessPIFCommands(pifRam, mmio.si.controller, *this); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
break; else
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF: break;
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; case 0x04040000 ... 0x040FFFFF:
default: util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc); case 0x04100000 ... 0x041FFFFF:
case 0x04300000 ... 0x044FFFFF:
case 0x04500000 ... 0x048FFFFF:
util::panic("MMIO Write64!\n");
case 0x10000000 ... 0x13FFFFFF:
break;
case 0x1FC007C0 ... 0x1FC007FF:
util::WriteAccess<u64>(pifRam, paddr - 0x1FC007C0, htobe64(val));
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
break;
case 0x00800000 ... 0x03FFFFFF:
case 0x04200000 ... 0x042FFFFF:
case 0x08000000 ... 0x0FFFFFFF:
case 0x04900000 ... 0x07FFFFFF:
case 0x1FC00800 ... 0x7FFFFFFF:
case 0x80000000 ... 0xFFFFFFFF:
break;
default:
util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
(u64) regs.pc);
}
} }
} }

View File

@@ -82,6 +82,7 @@ private:
std::vector<u8> cart, sram; std::vector<u8> cart, sram;
u8 pifBootrom[PIF_BOOTROM_SIZE]{}; u8 pifBootrom[PIF_BOOTROM_SIZE]{};
u8 isviewer[ISVIEWER_SIZE]{}; u8 isviewer[ISVIEWER_SIZE]{};
std::vector<uintptr_t> writePages, readPages;
size_t romMask; size_t romMask;
void SetCICType(u32& cicType, u32 checksum) { void SetCICType(u32& cicType, u32 checksum) {

View File

@@ -30,3 +30,19 @@
#define CART_REGION 0x10000000 ... 0x1FBFFFFF #define CART_REGION 0x10000000 ... 0x1FBFFFFF
#define PIF_ROM_REGION 0x1FC00000 ... 0x1FC007BF #define PIF_ROM_REGION 0x1FC00000 ... 0x1FC007BF
#define PIF_RAM_REGION 0x1FC007C0 ... 0x1FC007FF #define PIF_RAM_REGION 0x1FC007C0 ... 0x1FC007FF
constexpr size_t operator""_kb(unsigned long long int x) {
return 1024ULL * x;
}
constexpr size_t operator""_mb(unsigned long long int x) {
return 1024_kb * x;
}
constexpr size_t operator""_gb(unsigned long long int x) {
return 1024_mb * x;
}
#define ADDRESS_RANGE_SIZE 4_gb
#define PAGE_SIZE 4_kb
#define PAGE_COUNT ((ADDRESS_RANGE_SIZE) / (PAGE_SIZE))