Refactor RSP
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 ®s, 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;
|
||||||
|
|||||||
@@ -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)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user