diff --git a/external/parallel-rdp/parallel-rdp-standalone b/external/parallel-rdp/parallel-rdp-standalone index cc7c8801..6559addc 160000 --- a/external/parallel-rdp/parallel-rdp-standalone +++ b/external/parallel-rdp/parallel-rdp-standalone @@ -1 +1 @@ -Subproject commit cc7c8801f7cb39c5af58a04f079837a54305c9b6 +Subproject commit 6559addc5d510ae593af59371d6b95a232c05554 diff --git a/src/n64/core/Mem.cpp b/src/n64/core/Mem.cpp index f55cd325..ea9959e6 100644 --- a/src/n64/core/Mem.cpp +++ b/src/n64/core/Mem.cpp @@ -10,6 +10,28 @@ Mem::Mem() { } 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); std::fill(sram.begin(), sram.end(), 0); romMask = 0; @@ -72,133 +94,183 @@ template bool MapVAddr(Registers& regs, TLBAccessType accessType, u64 vad template u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = readPages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - return mmio.rdp.dram[BYTE_ADDRESS(paddr)]; - case 0x04000000 ... 0x0403FFFF: - 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; + if(pointer) { + return ((u8*)pointer)[BYTE_ADDRESS(offset)]; + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + return mmio.rdp.dram[BYTE_ADDRESS(paddr)]; + case 0x04000000 ... 0x0403FFFF: + 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 u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = readPages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr)); - case 0x04000000 ... 0x0403FFFF: - if((paddr >> 12) & 1) - return util::ReadAccess(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); - else - return util::ReadAccess(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE); - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: - return mmio.Read(paddr); - case 0x10000000 ... 0x1FBFFFFF: - paddr = (paddr + 2) & ~3; - return util::ReadAccess(cart.data(), HALF_ADDRESS(paddr) & romMask); - case 0x1FC00000 ... 0x1FC007BF: - return util::ReadAccess(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000); - case 0x1FC007C0 ... 0x1FC007FF: - return be16toh(util::ReadAccess(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); + if(pointer) { + return util::ReadAccess((u8*)pointer, HALF_ADDRESS(offset)); + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + return util::ReadAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr)); + case 0x04000000 ... 0x0403FFFF: + if ((paddr >> 12) & 1) + return util::ReadAccess(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); + else + return util::ReadAccess(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE); + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + return mmio.Read(paddr); + case 0x10000000 ... 0x1FBFFFFF: + paddr = (paddr + 2) & ~3; + return util::ReadAccess(cart.data(), HALF_ADDRESS(paddr) & romMask); + case 0x1FC00000 ... 0x1FC007BF: + return util::ReadAccess(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000); + case 0x1FC007C0 ... 0x1FC007FF: + return be16toh(util::ReadAccess(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 u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = readPages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), paddr); - case 0x04000000 ... 0x0403FFFF: - if((paddr >> 12) & 1) - return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); - else - return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: - return mmio.Read(paddr); - case 0x10000000 ... 0x1FBFFFFF: - return util::ReadAccess(cart.data(), paddr & romMask); - case 0x1FC00000 ... 0x1FC007BF: - return util::ReadAccess(pifBootrom, paddr - 0x1FC00000); - case 0x1FC007C0 ... 0x1FC007FF: - return be32toh(util::ReadAccess(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); + if(pointer) { + return util::ReadAccess((u8*)pointer, offset); + } else { + u32 paddr = vaddr; + if(!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + switch(paddr) { + case 0x00000000 ... 0x007FFFFF: + return util::ReadAccess(mmio.rdp.dram.data(), paddr); + case 0x04000000 ... 0x0403FFFF: + if((paddr >> 12) & 1) + return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); + else + return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); + case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: + return mmio.Read(paddr); + case 0x10000000 ... 0x1FBFFFFF: + return util::ReadAccess(cart.data(), paddr & romMask); + case 0x1FC00000 ... 0x1FC007BF: + return util::ReadAccess(pifBootrom, paddr - 0x1FC00000); + case 0x1FC007C0 ... 0x1FC007FF: + return be32toh(util::ReadAccess(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 u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = readPages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), paddr); - case 0x04000000 ... 0x0403FFFF: - if((paddr >> 12) & 1) - return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); - else - return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: - return mmio.Read(paddr); - case 0x10000000 ... 0x1FBFFFFF: - return util::ReadAccess(cart.data(), paddr & romMask); - case 0x1FC00000 ... 0x1FC007BF: - return util::ReadAccess(pifBootrom, paddr - 0x1FC00000); - case 0x1FC007C0 ... 0x1FC007FF: - return be64toh(util::ReadAccess(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); + if(pointer) { + return util::ReadAccess((u8*)pointer, offset); + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + return util::ReadAccess(mmio.rdp.dram.data(), paddr); + case 0x04000000 ... 0x0403FFFF: + if ((paddr >> 12) & 1) + return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); + else + return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + return mmio.Read(paddr); + case 0x10000000 ... 0x1FBFFFFF: + return util::ReadAccess(cart.data(), paddr & romMask); + case 0x1FC00000 ... 0x1FC007BF: + return util::ReadAccess(pifBootrom, paddr - 0x1FC00000); + case 0x1FC007C0 ... 0x1FC007FF: + return be64toh(util::ReadAccess(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(n64::Registers ®s, u64 vaddr, s64 pc); template void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = writePages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val; - break; - case 0x04000000 ... 0x0403FFFF: - val = val << (8 * (3 - (paddr & 3))); - paddr = (paddr & DMEM_DSIZE) & ~3; - if(paddr & 0x1000) - util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - else - util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - break; - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write8!\n"); - case 0x10000000 ... 0x13FFFFFF: break; - case 0x1FC007C0 ... 0x1FC007FF: - val = val << (8 * (3 - (paddr & 3))); - paddr = (paddr - 0x1FC007C0) & ~3; - util::WriteAccess(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); + if(pointer) { + ((u8*)pointer)[BYTE_ADDRESS(offset)] = val; + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val; + break; + case 0x04000000 ... 0x0403FFFF: + val = val << (8 * (3 - (paddr & 3))); + paddr = (paddr & DMEM_DSIZE) & ~3; + if (paddr & 0x1000) + util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + util::panic("MMIO Write8!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + val = val << (8 * (3 - (paddr & 3))); + paddr = (paddr - 0x1FC007C0) & ~3; + util::WriteAccess(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 void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = writePages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val); - break; - case 0x04000000 ... 0x0403FFFF: - val = val << (16 * !(paddr & 2)); - paddr &= ~3; - if(paddr & 0x1000) - util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - else - util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - break; - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write16!\n"); - case 0x10000000 ... 0x13FFFFFF: break; - case 0x1FC007C0 ... 0x1FC007FF: - val = val << (16 * !(paddr & 2)); - paddr &= ~3; - util::WriteAccess(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); + if(pointer) { + util::WriteAccess((u8*)pointer, HALF_ADDRESS(offset), val); + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + util::WriteAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val); + break; + case 0x04000000 ... 0x0403FFFF: + val = val << (16 * !(paddr & 2)); + paddr &= ~3; + if (paddr & 0x1000) + util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + util::panic("MMIO Write16!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + val = val << (16 * !(paddr & 2)); + paddr &= ~3; + util::WriteAccess(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 void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = writePages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), paddr, val); - break; - case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) - util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - else - util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - break; - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break; - case 0x10000000 ... 0x13FF0013: break; - case 0x13FF0014: { - if(val < ISVIEWER_SIZE) { - char* message = (char*)calloc(val + 1, 1); - memcpy(message, isviewer, val); - fmt::print("{}", message); - free(message); - } - } break; - case 0x13FF0020 ... 0x13FFFFFF: - util::WriteAccess(isviewer, paddr - 0x13FF0020, htobe32(val)); - break; - case 0x1FC007C0 ... 0x1FC007FF: - util::WriteAccess(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); + if(pointer) { + util::WriteAccess((u8*)pointer, offset, val); + } else { + u32 paddr = vaddr; + if(!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + switch(paddr) { + case 0x00000000 ... 0x007FFFFF: + util::WriteAccess(mmio.rdp.dram.data(), paddr, val); + break; + case 0x04000000 ... 0x0403FFFF: + if(paddr & 0x1000) + util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break; + case 0x10000000 ... 0x13FF0013: break; + case 0x13FF0014: { + if(val < ISVIEWER_SIZE) { + char* message = (char*)calloc(val + 1, 1); + memcpy(message, isviewer, val); + fmt::print("{}", message); + free(message); + } + } break; + case 0x13FF0020 ... 0x13FFFFFF: + util::WriteAccess(isviewer, paddr - 0x13FF0020, htobe32(val)); + break; + case 0x1FC007C0 ... 0x1FC007FF: + util::WriteAccess(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 void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) { - u32 paddr = vaddr; - if(!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } + const auto page = (vaddr & 0xFFFFFFFF) >> 12; + const auto offset = vaddr & 0xFFF; + const auto pointer = writePages[page]; - switch(paddr) { - case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), paddr, val); - break; - case 0x04000000 ... 0x0403FFFF: - val >>= 32; - if(paddr & 0x1000) - util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - else - util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - break; - case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: - case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: util::panic("MMIO Write64!\n"); - case 0x10000000 ... 0x13FFFFFF: break; - case 0x1FC007C0 ... 0x1FC007FF: - util::WriteAccess(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); + if(pointer) { + util::WriteAccess((u8*)pointer, offset, val); + } else { + u32 paddr = vaddr; + if (!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + util::WriteAccess(mmio.rdp.dram.data(), paddr, val); + break; + case 0x04000000 ... 0x0403FFFF: + val >>= 32; + if (paddr & 0x1000) + util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + util::panic("MMIO Write64!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + util::WriteAccess(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); + } } } diff --git a/src/n64/core/Mem.hpp b/src/n64/core/Mem.hpp index bc0885ee..8dbe3a28 100644 --- a/src/n64/core/Mem.hpp +++ b/src/n64/core/Mem.hpp @@ -82,6 +82,7 @@ private: std::vector cart, sram; u8 pifBootrom[PIF_BOOTROM_SIZE]{}; u8 isviewer[ISVIEWER_SIZE]{}; + std::vector writePages, readPages; size_t romMask; void SetCICType(u32& cicType, u32 checksum) { diff --git a/src/n64/memory_regions.hpp b/src/n64/memory_regions.hpp index cc9f920f..856de750 100644 --- a/src/n64/memory_regions.hpp +++ b/src/n64/memory_regions.hpp @@ -29,4 +29,20 @@ #define SRAM_REGION 0x08000000 ... 0x0FFFFFFF #define CART_REGION 0x10000000 ... 0x1FBFFFFF #define PIF_ROM_REGION 0x1FC00000 ... 0x1FC007BF -#define PIF_RAM_REGION 0x1FC007C0 ... 0x1FC007FF \ No newline at end of file +#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)) \ No newline at end of file