Refactor RSP

This commit is contained in:
SimoneN64
2024-05-13 20:32:07 +02:00
committed by Simone
parent e07f4880e6
commit 5148a836a1
7 changed files with 87 additions and 83 deletions

View File

@@ -85,7 +85,7 @@ void Core::Run(float volumeL, float volumeR) {
while(mmio.rsp.steps > 0) { while(mmio.rsp.steps > 0) {
mmio.rsp.steps--; mmio.rsp.steps--;
mmio.rsp.Step(regs, mem); mmio.rsp.Step();
} }
} }

View File

@@ -32,7 +32,7 @@ u32 MMIO::Read(u32 addr) {
void MMIO::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { void MMIO::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
switch (addr) { switch (addr) {
case RSP_REGION: rsp.Write(mem, regs, addr, val); break; case RSP_REGION: rsp.Write(addr, val); break;
case RDP_REGION: rdp.Write(mi, regs, rsp, addr, val); break; case RDP_REGION: rdp.Write(mi, regs, rsp, addr, val); break;
case MI_REGION: mi.Write(regs, addr, val); break; case MI_REGION: mi.Write(regs, addr, val); break;
case VI_REGION: vi.Write(mi, regs, addr, val); break; case VI_REGION: vi.Write(mi, regs, addr, val); break;

View File

@@ -13,7 +13,7 @@ struct Mem;
struct Registers; struct Registers;
struct MMIO { struct MMIO {
MMIO(Mem& mem, Registers& regs) : mi(regs), si(mem, regs) {} MMIO(Mem& mem, Registers& regs) : mi(regs), si(mem, regs), rsp(mem, regs) {}
void Reset(); void Reset();
VI vi; VI vi;

View File

@@ -4,7 +4,7 @@
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {
RSP::RSP() { RSP::RSP(Mem& mem, Registers& regs) : mem(mem), regs(regs) {
Reset(); Reset();
} }
@@ -83,7 +83,8 @@ auto RSP::Read(u32 addr) -> u32{
} }
} }
void RSP::WriteStatus(MI& mi, Registers& regs, u32 value) { void RSP::WriteStatus(u32 value) {
MI& mi = mem.mmio.mi;
auto write = SPStatusWrite{.raw = value}; auto write = SPStatusWrite{.raw = value};
if(write.clearHalt && !write.setHalt) { if(write.clearHalt && !write.setHalt) {
spStatus.halt = false; spStatus.halt = false;
@@ -109,20 +110,19 @@ void RSP::WriteStatus(MI& mi, Registers& regs, u32 value) {
CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7);
} }
void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) { void RSP::Write(u32 addr, u32 value) {
MI& mi = mem.mmio.mi;
switch (addr) { switch (addr) {
case 0x04040000: spDMASPAddr.raw = value & 0x1FF8; break; case 0x04040000: spDMASPAddr.raw = value & 0x1FF8; break;
case 0x04040004: spDMADRAMAddr.raw = value & 0xFFFFF8; break; case 0x04040004: spDMADRAMAddr.raw = value & 0xFFFFF8; break;
case 0x04040008: { case 0x04040008: {
spDMALen.raw = value; spDMALen.raw = value;
DMAtoRSP(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); DMAtoRSP(mem.GetRDRAM());
} break; } break;
case 0x0404000C: { case 0x0404000C: {
spDMALen.raw = value; spDMALen.raw = value;
DMAtoRDRAM(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); DMAtoRDRAM(mem.GetRDRAM());
} break; } break;
case 0x04040010: WriteStatus(mi, regs, value); break; case 0x04040010: WriteStatus(value); break;
case 0x0404001C: ReleaseSemaphore(); break; case 0x0404001C: ReleaseSemaphore(); break;
case 0x04080000: case 0x04080000:
if(spStatus.halt) { if(spStatus.halt) {
@@ -132,4 +132,64 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, value); Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, value);
} }
} }
void RSP::DMAtoRDRAM(std::vector<u8>& rdram) {
u32 length = spDMALen.len + 1;
length = (length + 0x7) & ~0x7;
std::vector<u8>& dst = rdram;
std::array<u8, DMEM_SIZE>& src = spDMASPAddr.bank ? imem : dmem;
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
for (u32 i = 0; i < spDMALen.count + 1; i++) {
for(u32 j = 0; j < length; j++) {
dst[dram_address + j] = src[(mem_address + j) & 0xFFF];
}
int skip = i == spDMALen.count ? 0 : spDMALen.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
mem_address += length;
mem_address &= 0xFF8;
}
lastSuccessfulSPAddr.address = mem_address;
lastSuccessfulSPAddr.bank = spDMASPAddr.bank;
lastSuccessfulDRAMAddr.address = dram_address;
spDMALen.raw = 0xFF8 | (spDMALen.skip << 20);
}
void RSP::DMAtoRSP(std::vector<u8>& rdram) {
u32 length = spDMALen.len + 1;
length = (length + 0x7) & ~0x7;
std::vector<u8>& src = rdram;
std::array<u8, DMEM_SIZE>& dst = spDMASPAddr.bank ? imem : dmem;
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
for (u32 i = 0; i < spDMALen.count + 1; i++) {
for(u32 j = 0; j < length; j++) {
dst[(mem_address + j) & 0xFFF] = src[dram_address + j];
}
int skip = i == spDMALen.count ? 0 : spDMALen.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
mem_address += length;
mem_address &= 0xFF8;
}
lastSuccessfulSPAddr.address = mem_address;
lastSuccessfulSPAddr.bank = spDMASPAddr.bank;
lastSuccessfulDRAMAddr.address = dram_address;
spDMALen.raw = 0xFF8 | (spDMALen.skip << 20);
}
} }

View File

@@ -113,21 +113,21 @@ struct Registers;
} while(0) } while(0)
struct RSP { struct RSP {
RSP(); RSP(Mem&, Registers&);
void Reset(); void Reset();
FORCE_INLINE void Step(Registers& regs, Mem& mem) { FORCE_INLINE void Step() {
gpr[0] = 0; gpr[0] = 0;
u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE); u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
oldPC = pc & 0xFFC; oldPC = pc & 0xFFC;
pc = nextPC & 0xFFC; pc = nextPC & 0xFFC;
nextPC += 4; nextPC += 4;
Exec(regs, mem, instr); Exec(instr);
} }
auto Read(u32 addr) -> u32; auto Read(u32 addr) -> u32;
void Write(Mem& mem, Registers& regs, u32 addr, u32 value); void Write(u32 addr, u32 value);
void Exec(Registers& regs, Mem& mem, u32 instr); void Exec(u32 instr);
SPStatus spStatus{}; SPStatus spStatus{};
u16 oldPC{}, pc{}, nextPC{}; u16 oldPC{}, pc{}, nextPC{};
SPDMASPAddr spDMASPAddr{}; SPDMASPAddr spDMASPAddr{};
@@ -354,72 +354,16 @@ struct RSP {
void vnor(u32 instr); void vnor(u32 instr);
void vzero(u32 instr); void vzero(u32 instr);
void mfc0(RDP& rdp, u32 instr); void mfc0(RDP& rdp, u32 instr);
void mtc0(Registers& regs, Mem& mem, u32 instr); void mtc0(u32 instr);
void mfc2(u32 instr); void mfc2(u32 instr);
void mtc2(u32 instr); void mtc2(u32 instr);
FORCE_INLINE void DMAtoRDRAM(SPDMALen len, std::vector<u8>& rdram, RSP& rsp, bool bank) { void DMAtoRDRAM(std::vector<u8>& rdram);
u32 length = len.len + 1; void DMAtoRSP(std::vector<u8>& rdram);
void WriteStatus(u32 value);
length = (length + 0x7) & ~0x7;
std::vector<u8>& dst = rdram;
std::array<u8, DMEM_SIZE>& src = bank ? rsp.imem : rsp.dmem;
u32 mem_address = rsp.spDMASPAddr.address & 0xFF8;
u32 dram_address = rsp.spDMADRAMAddr.address & 0xFFFFF8;
for (u32 i = 0; i < len.count + 1; i++) {
for(u32 j = 0; j < length; j++) {
dst[dram_address + j] = src[(mem_address + j) & 0xFFF];
}
int skip = i == len.count ? 0 : len.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
mem_address += length;
mem_address &= 0xFF8;
}
rsp.lastSuccessfulSPAddr.address = mem_address;
rsp.lastSuccessfulSPAddr.bank = bank;
rsp.lastSuccessfulDRAMAddr.address = dram_address;
rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20);
}
FORCE_INLINE void DMAtoRSP(SPDMALen len, std::vector<u8>& rdram, RSP& rsp, bool bank) {
u32 length = len.len + 1;
length = (length + 0x7) & ~0x7;
std::vector<u8>& src = rdram;
std::array<u8, DMEM_SIZE>& dst = bank ? rsp.imem : rsp.dmem;
u32 mem_address = rsp.spDMASPAddr.address & 0xFF8;
u32 dram_address = rsp.spDMADRAMAddr.address & 0xFFFFF8;
for (u32 i = 0; i < len.count + 1; i++) {
for(u32 j = 0; j < length; j++) {
dst[(mem_address + j) & 0xFFF] = src[dram_address + j];
}
int skip = i == len.count ? 0 : len.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
mem_address += length;
mem_address &= 0xFF8;
}
rsp.lastSuccessfulSPAddr.address = mem_address;
rsp.lastSuccessfulSPAddr.bank = bank;
rsp.lastSuccessfulDRAMAddr.address = dram_address;
rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20);
}
void WriteStatus(MI& mi, Registers& regs, u32 value);
private: private:
Registers& regs;
Mem& mem;
FORCE_INLINE void branch(u16 address, bool cond) { FORCE_INLINE void branch(u16 address, bool cond) {
if(cond) { if(cond) {
nextPC = address & 0xFFC; nextPC = address & 0xFFC;

View File

@@ -177,7 +177,7 @@ FORCE_INLINE void cop0(Registers& regs, Mem& mem, u32 instr) {
if((instr & 0x7FF) == 0) { if((instr & 0x7FF) == 0) {
switch (mask) { switch (mask) {
case 0x00: rsp.mfc0(rdp, instr); break; case 0x00: rsp.mfc0(rdp, instr); break;
case 0x04: rsp.mtc0(regs, mem, instr); break; case 0x04: rsp.mtc0(instr); break;
default: Util::panic("Unhandled RSP COP0 ({:05b})", mask); default: Util::panic("Unhandled RSP COP0 ({:05b})", mask);
} }
} else { } else {
@@ -185,7 +185,7 @@ FORCE_INLINE void cop0(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void RSP::Exec(Registers &regs, Mem& mem, u32 instr) { void RSP::Exec(u32 instr) {
u8 mask = (instr >> 26) & 0x3F; u8 mask = (instr >> 26) & 0x3F;
MMIO& mmio = mem.mmio; MMIO& mmio = mem.mmio;
MI& mi = mmio.mi; MI& mi = mmio.mi;

View File

@@ -60,13 +60,13 @@ FORCE_INLINE void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) {
case 1: rsp.spDMADRAMAddr.raw = val; break; case 1: rsp.spDMADRAMAddr.raw = val; break;
case 2: case 2:
rsp.spDMALen.raw = val; rsp.spDMALen.raw = val;
rsp.DMAtoRSP(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); rsp.DMAtoRSP(mem.GetRDRAM());
break; break;
case 3: case 3:
rsp.spDMALen.raw = val; rsp.spDMALen.raw = val;
rsp.DMAtoRDRAM(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); rsp.DMAtoRDRAM(mem.GetRDRAM());
break; break;
case 4: rsp.WriteStatus(mi, regs, val); break; case 4: rsp.WriteStatus(val); break;
case 7: case 7:
if(val == 0) { if(val == 0) {
ReleaseSemaphore(rsp); ReleaseSemaphore(rsp);
@@ -1776,7 +1776,7 @@ void RSP::mfc0(RDP& rdp, u32 instr) {
gpr[RT(instr)] = GetCop0Reg(*this, rdp, RD(instr)); gpr[RT(instr)] = GetCop0Reg(*this, rdp, RD(instr));
} }
void RSP::mtc0(Registers& regs, Mem& mem, u32 instr) { void RSP::mtc0(u32 instr) {
SetCop0Reg(regs, mem, RD(instr), gpr[RT(instr)]); SetCop0Reg(regs, mem, RD(instr), gpr[RT(instr)]);
} }