SAZDFsdff

This commit is contained in:
2026-06-03 18:05:35 +02:00
parent 12e81e73e8
commit b037de4c3d
9 changed files with 632 additions and 608 deletions
+56 -52
View File
@@ -96,7 +96,54 @@ u32 Interpreter::Step() {
return 1; return 1;
} }
u32 Interpreter::CacheBlock(u32 addr) { bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLOCK> &code, u32 len, u32 blockAddr) {
if (!Core::GetInstance().idleSkip)
return false;
u32 lastInstructionIndex = len - 1;
auto delay = code[lastInstructionIndex];
if (len == 2) {
// branch or jump to itself
// _nop
auto branch = code[lastInstructionIndex - 1];
return ((branch.IsBranch() && branch.offset() == -4) || (branch.target() == ((blockAddr >> 2) & 0x3FFFFFF))) &&
delay.instr.raw == 0;
}
if (len == 3) {
// load reg1, [some location]
// bcond reg2
// _andi reg2, reg1, immediate
auto branch = code[lastInstructionIndex - 1];
auto load = code[lastInstructionIndex - 2]; // load
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
load.rt() == delay.rs() && delay.rt() == branch.rs();
}
if (len == 4) {
// load reg2, [reg1(offset)]
// andi reg3, reg2, immediate
// bcond reg3, reg4
// _nop
auto branch = code[lastInstructionIndex - 1];
auto andi = code[lastInstructionIndex - 2]; // andi
auto load = code[lastInstructionIndex - 3]; // load
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
load.rt() == andi.rs() && andi.rt() == branch.rs();
}
return false;
}
u32 Interpreter::CacheBlock(u64 addr) {
u32 blockAddr = addr; u32 blockAddr = addr;
CachedLine<Instruction> line; CachedLine<Instruction> line;
@@ -104,7 +151,9 @@ u32 Interpreter::CacheBlock(u32 addr) {
bool fetchDelaySlot = false; bool fetchDelaySlot = false;
for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) { for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) {
Instruction instr = mem.Read<u32>(addr); Instruction instr;
if (!Fetch(instr, addr))
return i + 1;
addr += 4; addr += 4;
line.code[i] = instr; line.code[i] = instr;
@@ -127,46 +176,7 @@ u32 Interpreter::CacheBlock(u32 addr) {
} }
} }
if (Core::GetInstance().idleSkip) { line.idleSkip = DetectIdleLoop(line.code, i, blockAddr);
auto delay = line.code[i - 1];
if (i == 2) {
// branch to itself
// _nop
auto branch = line.code[i - 2];
line.idleSkip = branch.IsBranch() && branch.offset() == -4 && delay.instr.raw == 0;
}
if (i == 3) {
// load reg1, [some location]
// bcond reg2
// _andi reg2, reg1, immediate
auto branch = line.code[i - 2];
auto load = line.code[i - 3]; // load
line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
load.rt() == delay.rs() && delay.rt() == branch.rs();
}
if (i == 4) {
// load reg2, [reg1(offset)]
// andi reg3, reg2, immediate
// bcond reg3, reg4
// _nop
auto branch = line.code[i - 2];
auto andi = line.code[i - 3]; // andi
auto load = line.code[i - 4]; // load
line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
load.rt() == andi.rs() && andi.rt() == branch.rs();
}
}
line.cycles = i; line.cycles = i;
line.len = i; line.len = i;
cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line); cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line);
@@ -175,21 +185,15 @@ u32 Interpreter::CacheBlock(u32 addr) {
} }
u32 Interpreter::ExecuteCached() { u32 Interpreter::ExecuteCached() {
u32 addr; u64 addr = regs.pc;
auto &blocks = cachedState.blocks; auto &blocks = cachedState.blocks;
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, addr)) { if (!blocks[CACHE_GET_BLOCK((u32)addr)]) {
regs.cop0.HandleTLBException(regs.pc); blocks[CACHE_GET_BLOCK((u32)addr)] = new CachedBlock<Instruction>(cachedState.MAX_LINES / 4);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
return 1;
}
if (!blocks[CACHE_GET_BLOCK(addr)]) {
blocks[CACHE_GET_BLOCK(addr)] = new CachedBlock<Instruction>(cachedState.MAX_LINES / 4);
return CacheBlock(addr); return CacheBlock(addr);
} }
const auto line = blocks[CACHE_GET_BLOCK(addr)]->lines[CACHE_GET_LINE(addr)]; const auto line = blocks[CACHE_GET_BLOCK((u32)addr)]->lines[CACHE_GET_LINE((u32)addr)];
if (line) { if (line) {
cachedState.exception = false; cachedState.exception = false;
// i copy the block cycles here in case the block evicts itself when executing which would set the cycles to // i copy the block cycles here in case the block evicts itself when executing which would set the cycles to
+2 -1
View File
@@ -13,7 +13,8 @@ struct Interpreter final {
u32 ExecuteCached(); u32 ExecuteCached();
bool FetchThenMaybeAdvance(Instruction &); bool FetchThenMaybeAdvance(Instruction &);
bool MaybeAdvance(); bool MaybeAdvance();
u32 CacheBlock(u32 addr); u32 CacheBlock(u64 addr);
bool DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLOCK> &, u32, u32);
void SignalException(u32 addr) { cachedState.exception = true; } void SignalException(u32 addr) { cachedState.exception = true; }
-4
View File
@@ -278,7 +278,6 @@ void Mem::Write<u8>(u32 paddr, u32 val) {
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u8>(paddr, val); mmio.rdp.WriteRDRAM<u8>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return; return;
} }
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
@@ -325,7 +324,6 @@ void Mem::Write<u16>(u32 paddr, u32 val) {
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u16>(paddr, val); mmio.rdp.WriteRDRAM<u16>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return; return;
} }
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
@@ -372,7 +370,6 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u32>(paddr, val); mmio.rdp.WriteRDRAM<u32>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return; return;
} }
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
@@ -416,7 +413,6 @@ void Mem::Write(const u32 paddr, u64 val) {
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u64>(paddr, val); mmio.rdp.WriteRDRAM<u64>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return; return;
} }
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
-1
View File
@@ -117,7 +117,6 @@ void RSP::DMA<true>() {
for (u32 j = 0; j < length; j++) { for (u32 j = 0; j < length; j++) {
mem.mmio.rdp.WriteRDRAM<u8>(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]); mem.mmio.rdp.WriteRDRAM<u8>(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]);
} }
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dram_address, dram_address + length);
const int skip = i == spDMALen.count ? 0 : spDMALen.skip; const int skip = i == spDMALen.count ? 0 : spDMALen.skip;
@@ -1310,6 +1310,7 @@ void Cop1::swc1(const Instruction instr) {
regs.cop0.HandleTLBException(addr); regs.cop0.HandleTLBException(addr);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft())); mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
} }
} }
@@ -1337,6 +1338,7 @@ void Cop1::sdc1(const Instruction instr) {
regs.cop0.HandleTLBException(addr); regs.cop0.HandleTLBException(addr);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft())); mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
} }
} }
@@ -409,6 +409,7 @@ void Interpreter::sb(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt())); mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
} }
} }
@@ -432,6 +433,7 @@ void Interpreter::sc(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt())); mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1); regs.Write(instr.rt(), 1);
} }
@@ -464,6 +466,7 @@ void Interpreter::scd(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt())); mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1); regs.Write(instr.rt(), 1);
} }
@@ -480,6 +483,7 @@ void Interpreter::sh(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write<u16>(physical, regs.Read<s64>(instr.rt())); mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
} }
} }
@@ -498,6 +502,7 @@ void Interpreter::sw(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write<u32>(physical, regs.Read<s64>(instr.rt())); mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
} }
} }
@@ -515,6 +520,7 @@ void Interpreter::sd(const Instruction instr) {
regs.cop0.HandleTLBException(address); regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else { } else {
cachedState.EvictCachedBlock(address);
mem.Write(physical, regs.Read<s64>(instr.rt())); mem.Write(physical, regs.Read<s64>(instr.rt()));
} }
} }
@@ -531,6 +537,7 @@ void Interpreter::sdl(const Instruction instr) {
const u64 data = mem.Read<u64>(paddr & ~7); const u64 data = mem.Read<u64>(paddr & ~7);
const u64 rt = regs.Read<s64>(instr.rt()); const u64 rt = regs.Read<s64>(instr.rt());
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift)); mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
cachedState.EvictCachedBlock(address);
} }
} }
@@ -546,6 +553,7 @@ void Interpreter::sdr(const Instruction instr) {
const u64 data = mem.Read<u64>(paddr & ~7); const u64 data = mem.Read<u64>(paddr & ~7);
const u64 rt = regs.Read<s64>(instr.rt()); const u64 rt = regs.Read<s64>(instr.rt());
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift)); mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
cachedState.EvictCachedBlock(address);
} }
} }
@@ -561,6 +569,7 @@ void Interpreter::swl(const Instruction instr) {
const u32 data = mem.Read<u32>(paddr & ~3); const u32 data = mem.Read<u32>(paddr & ~3);
const u32 rt = regs.Read<s64>(instr.rt()); const u32 rt = regs.Read<s64>(instr.rt());
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift)); mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
cachedState.EvictCachedBlock(address);
} }
} }
@@ -576,6 +585,7 @@ void Interpreter::swr(const Instruction instr) {
const u32 data = mem.Read<u32>(paddr & ~3); const u32 data = mem.Read<u32>(paddr & ~3);
const u32 rt = regs.Read<s64>(instr.rt()); const u32 rt = regs.Read<s64>(instr.rt());
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift)); mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
cachedState.EvictCachedBlock(address);
} }
} }
+4 -1
View File
@@ -507,6 +507,9 @@ void PI::DMA<false>() {
n64::Mem &mem = n64::Core::GetMem(); n64::Mem &mem = n64::Core::GetMem();
const s32 len = rdLen + 1; const s32 len = rdLen + 1;
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
}
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i)); BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
@@ -539,7 +542,7 @@ void PI::DMA<true>() {
for (u32 i = 0; i < len; i++) { for (u32 i = 0; i < len; i++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i)); mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i));
} }
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + len);
dramAddr += len; dramAddr += len;
dramAddr = (dramAddr + 7) & ~7; dramAddr = (dramAddr + 7) & ~7;
cartAddr += len; cartAddr += len;
File diff suppressed because it is too large Load Diff
-1
View File
@@ -78,7 +78,6 @@ void SI::Write(u32 addr, u32 val) {
status.dmaBusy = true; status.dmaBusy = true;
toDram = true; toDram = true;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA); Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + 64);
break; break;
case 0x04800010: case 0x04800010:
pifAddr = val & 0x1FFFFFFF; pifAddr = val & 0x1FFFFFFF;