Map physical addresses for fastmem + minor optimization

This commit is contained in:
CocoSimone
2022-12-16 23:13:58 +01:00
parent dc858560ad
commit 08e0903fa0
9 changed files with 137 additions and 112 deletions

View File

@@ -53,8 +53,6 @@ target_include_directories(gadolinium PRIVATE
${SDL2_INCLUDE_DIR}
)
set_target_properties(gadolinium PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
file(COPY ${PROJECT_SOURCE_DIR}/../resources/ DESTINATION ${PROJECT_BINARY_DIR}/resources/)
file(REMOVE
${PROJECT_BINARY_DIR}/resources/mario.png
@@ -66,4 +64,21 @@ if(WIN32)
add_compile_options(/EHa)
endif()
if(${CMAKE_BUILD_TYPE} MATCHES Release)
set_property(TARGET gadolinium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
if(WIN32)
add_compile_options(/O2)
else()
add_compile_options(-O3)
endif()
else()
if(WIN32)
add_compile_options(/Od)
else()
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
add_compile_options(-g)
endif()
endif()
target_link_libraries(gadolinium PRIVATE discord-rpc SDL2::SDL2main SDL2::SDL2 capstone-static nfd parallel-rdp fmt::fmt imgui nlohmann_json::nlohmann_json)

View File

@@ -15,7 +15,7 @@ struct Window {
[[nodiscard]] bool gotClosed(SDL_Event event);
ImFont *uiFont{}, *codeFont{};
u32 windowID{};
float volumeL = 0.01, volumeR = 0.01;
float volumeL = 0.0, volumeR = 0.0;
void LoadROM(n64::Core& core, const std::string& path);
private:
bool lockVolume = true;

View File

@@ -16,21 +16,16 @@ void Mem::Reset() {
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;
const auto addr = (i * PAGE_SIZE) & RDRAM_DSIZE;
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
readPages[i] = pointer;
writePages[i] = 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];
readPages[0x4000] = (uintptr_t) &mmio.rsp.dmem[0];
readPages[0x4001] = (uintptr_t) &mmio.rsp.imem[0];
writePages[0x4000] = (uintptr_t) &mmio.rsp.dmem[0];
writePages[0x4001] = (uintptr_t) &mmio.rsp.imem[0];
sram.resize(SRAM_SIZE);
std::fill(sram.begin(), sram.end(), 0);
@@ -94,22 +89,22 @@ template bool MapVAddr<false>(Registers& regs, TLBAccessType accessType, u64 vad
template <bool tlb>
u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
return ((u8*)pointer)[BYTE_ADDRESS(offset)];
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(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)];
return mmio.rdp.rdram[BYTE_ADDRESS(paddr)];
case 0x04000000 ... 0x0403FFFF:
if ((paddr >> 12) & 1)
return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE];
@@ -145,22 +140,22 @@ u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) {
template <bool tlb>
u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
return util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch (paddr) {
case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr));
return util::ReadAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr));
case 0x04000000 ... 0x0403FFFF:
if ((paddr >> 12) & 1)
return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
@@ -191,22 +186,22 @@ u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) {
template <bool tlb>
u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
return util::ReadAccess<u32>((u8*)pointer, offset);
} else {
u32 paddr = vaddr;
if(!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch(paddr) {
case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr);
return util::ReadAccess<u32>(mmio.rdp.rdram.data(), paddr);
case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1)
return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
@@ -231,22 +226,22 @@ u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) {
template <bool tlb>
u64 Mem::Read64(n64::Registers &regs, u64 vaddr, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
const auto page = paddr >> 12;
const auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
return util::ReadAccess<u64>((u8*)pointer, offset);
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
switch (paddr) {
case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr);
return util::ReadAccess<u64>(mmio.rdp.rdram.data(), paddr);
case 0x04000000 ... 0x0403FFFF:
if ((paddr >> 12) & 1)
return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
@@ -285,22 +280,27 @@ template u64 Mem::Read64<true>(n64::Registers &regs, u64 vaddr, s64 pc);
template <bool tlb>
void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
const auto pointer = writePages[page];
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc);
}
const auto page = paddr >> 12;
auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
val = val << (8 * (3 - (paddr & 3)));
offset = (offset & DMEM_DSIZE) & ~3;
}
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
} else {
switch (paddr) {
case 0x00000000 ... 0x007FFFFF:
mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val;
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
break;
case 0x04000000 ... 0x0403FFFF:
val = val << (8 * (3 - (paddr & 3)));
@@ -339,22 +339,27 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
template <bool tlb>
void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
const auto pointer = writePages[page];
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
const auto page = paddr >> 12;
auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
val = val << (16 * !(paddr & 2));
offset &= ~3;
}
util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
} else {
switch (paddr) {
case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val);
util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
break;
case 0x04000000 ... 0x0403FFFF:
val = val << (16 * !(paddr & 2));
@@ -393,22 +398,22 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
template <bool tlb>
void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
const auto pointer = writePages[page];
u32 paddr = vaddr;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
const auto page = paddr >> 12;
auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
util::WriteAccess<u32>((u8*)pointer, offset, val);
} else {
u32 paddr = vaddr;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch(paddr) {
case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr, val);
util::WriteAccess<u32>(mmio.rdp.rdram.data(), paddr, val);
break;
case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000)
@@ -444,22 +449,25 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
template <bool tlb>
void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
const auto page = (vaddr & 0xFFFFFFFF) >> 12;
const auto offset = vaddr & 0xFFF;
const auto pointer = writePages[page];
u32 paddr = vaddr;
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
const auto page = paddr >> 12;
auto offset = paddr & 0xFFF;
const auto pointer = readPages[page];
if(pointer) {
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
val >>= 32;
}
util::WriteAccess<u64>((u8*)pointer, offset, val);
} else {
u32 paddr = vaddr;
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
HandleTLBException(regs, vaddr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc);
}
switch (paddr) {
case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u64>(mmio.rdp.dram.data(), paddr, val);
util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
break;
case 0x04000000 ... 0x0403FFFF:
val >>= 32;

View File

@@ -20,7 +20,7 @@ struct Mem {
void Reset();
CartInfo LoadROM(const std::string&);
[[nodiscard]] auto GetRDRAM() -> u8* {
return mmio.rdp.dram.data();
return mmio.rdp.rdram.data();
}
template <bool tlb = true>
@@ -46,7 +46,7 @@ struct Mem {
inline void DumpRDRAM() const {
FILE *fp = fopen("rdram.dump", "wb");
u8 *temp = (u8*)calloc(RDRAM_SIZE, 1);
memcpy(temp, mmio.rdp.dram.data(), RDRAM_SIZE);
memcpy(temp, mmio.rdp.rdram.data(), RDRAM_SIZE);
util::SwapBuffer32(RDRAM_SIZE, temp);
fwrite(temp, 1, RDRAM_SIZE, fp);
free(temp);
@@ -72,6 +72,7 @@ struct Mem {
free(temp);
fclose(fp);
}
std::vector<uintptr_t> writePages, readPages;
private:
friend struct SI;
friend struct PI;
@@ -82,7 +83,6 @@ private:
std::vector<u8> cart, sram;
u8 pifBootrom[PIF_BOOTROM_SIZE]{};
u8 isviewer[ISVIEWER_SIZE]{};
std::vector<uintptr_t> writePages, readPages;
size_t romMask;
void SetCICType(u32& cicType, u32 checksum) {

View File

@@ -11,8 +11,8 @@ RDP::RDP() {
void RDP::Reset() {
dpc.status.raw = 0x80;
dram.resize(RDRAM_SIZE);
std::fill(dram.begin(), dram.end(), 0);
rdram.resize(RDRAM_SIZE);
std::fill(rdram.begin(), rdram.end(), 0);
memset(cmd_buf, 0, 0x100000);
}
@@ -144,7 +144,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
return;
}
for (int i = 0; i < len; i += 4) {
u32 cmd = util::ReadAccess<u32>(dram.data(), current + i);
u32 cmd = util::ReadAccess<u32>(rdram.data(), current + i);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
}

View File

@@ -57,7 +57,7 @@ struct RDP {
RDP();
void Reset();
std::vector<u8> dram;
std::vector<u8> rdram;
[[nodiscard]] auto Read(u32 addr) const -> u32;
void Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val);
void WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val);

View File

@@ -81,17 +81,19 @@ void AI::Step(Mem& mem, Registers& regs, int cpuCycles, float volumeL, float vol
}
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.dram.data(), dmaAddr[0] & RDRAM_DSIZE);
s16 l = s16(data >> 16);
s16 r = s16(data);
if(volumeR > 0 && volumeL > 0) {
u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF;
dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF);
u32 data = util::ReadAccess<u32>(mem.mmio.rdp.rdram.data(), dmaAddr[0] & RDRAM_DSIZE);
s16 l = s16(data >> 16);
s16 r = s16(data);
PushSample((float)l / INT16_MAX, volumeL, (float)r / INT16_MAX, volumeR);
PushSample((float) l / INT16_MAX, volumeL, (float) r / INT16_MAX, volumeR);
u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF;
dmaAddr[0] = (dmaAddr[0] & ~0x1FFF) | addrLo;
dmaAddrCarry = addrLo == 0;
u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF;
dmaAddr[0] = (dmaAddr[0] & ~0x1FFF) | addrLo;
dmaAddrCarry = addrLo == 0;
}
dmaLen[0] -= 4;
}

View File

@@ -52,7 +52,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
}
rdLen = len;
for(int i = 0; i < len; i++) {
mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask] = mem.mmio.rdp.dram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE];
mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE];
}
dramAddr = dram_addr + len;
cartAddr = cart_addr + len;
@@ -68,7 +68,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
}
wrLen = len;
for(int i = 0; i < len; i++) {
mem.mmio.rdp.dram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask];
mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask];
}
dramAddr = dram_addr + len;
cartAddr = cart_addr + len;

View File

@@ -39,11 +39,11 @@ void DMA(Mem& mem, Registers& regs) {
if(si.toDram) {
ProcessPIFCommands(mem.pifRam, si.controller, mem);
for(int i = 0; i < 64; i++) {
mem.mmio.rdp.dram[BYTE_ADDRESS(si.dramAddr + i)] = mem.pifRam[i];
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = mem.pifRam[i];
}
} else {
for(int i = 0; i < 64; i++) {
mem.pifRam[i] = mem.mmio.rdp.dram[BYTE_ADDRESS(si.dramAddr + i)];
mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
}
util::logdebug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
ProcessPIFCommands(mem.pifRam, si.controller, mem);