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;
}
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;
CachedLine<Instruction> line;
@@ -104,7 +151,9 @@ u32 Interpreter::CacheBlock(u32 addr) {
bool fetchDelaySlot = false;
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;
line.code[i] = instr;
@@ -127,46 +176,7 @@ u32 Interpreter::CacheBlock(u32 addr) {
}
}
if (Core::GetInstance().idleSkip) {
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.idleSkip = DetectIdleLoop(line.code, i, blockAddr);
line.cycles = i;
line.len = i;
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 addr;
u64 addr = regs.pc;
auto &blocks = cachedState.blocks;
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, addr)) {
regs.cop0.HandleTLBException(regs.pc);
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);
if (!blocks[CACHE_GET_BLOCK((u32)addr)]) {
blocks[CACHE_GET_BLOCK((u32)addr)] = new CachedBlock<Instruction>(cachedState.MAX_LINES / 4);
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) {
cachedState.exception = false;
// 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();
bool FetchThenMaybeAdvance(Instruction &);
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; }
-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)) {
mmio.rdp.WriteRDRAM<u8>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return;
}
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)) {
mmio.rdp.WriteRDRAM<u16>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return;
}
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)) {
mmio.rdp.WriteRDRAM<u32>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return;
}
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)) {
mmio.rdp.WriteRDRAM<u64>(paddr, val);
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
return;
}
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++) {
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;
@@ -1310,6 +1310,7 @@ void Cop1::swc1(const Instruction instr) {
regs.cop0.HandleTLBException(addr);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
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.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
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.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
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.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1);
}
@@ -464,6 +466,7 @@ void Interpreter::scd(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1);
}
@@ -480,6 +483,7 @@ void Interpreter::sh(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
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.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
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.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
cachedState.EvictCachedBlock(address);
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 rt = regs.Read<s64>(instr.rt());
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 rt = regs.Read<s64>(instr.rt());
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 rt = regs.Read<s64>(instr.rt());
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 rt = regs.Read<s64>(instr.rt());
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();
const s32 len = rdLen + 1;
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++) {
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++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i));
}
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + len);
dramAddr += len;
dramAddr = (dramAddr + 7) & ~7;
cartAddr += len;
+21 -11
View File
@@ -166,7 +166,7 @@ FORCE_INLINE u8 DataCRC(const u8 *data) {
#define BCD_DECODE(x) (((x) >> 4) * 10 + ((x) & 15))
void PIF::ConfigureJoyBusFrame() {
n64::Mem& mem = n64::Core::GetMem();
n64::Mem &mem = n64::Core::GetMem();
channel = 0;
int i = 0;
while (i < 63) {
@@ -218,19 +218,27 @@ void PIF::ConfigureJoyBusFrame() {
case 6:
res[0] = 0x00;
res[1] = 0x10;
res[2] = 0x80;
res[2] = 0x00;
break;
case 7: {
case 7:
{
const u8 commandStart = packet[COMMAND_START];
switch (commandStart) {
case 0:
memset(res, 0, 8);
res[1] = 0x06;
break;
case 1:
memset(res, 0, 8);
break;
case 3:
memset(res, 0, 8);
break;
case 2:
{
auto now = std::time(nullptr);
const auto *gmtm = gmtime(&now);
res[0] = BCD_ENCODE(gmtm->tm_sec);
res[1] = BCD_ENCODE(gmtm->tm_min);
res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80;
@@ -239,15 +247,15 @@ void PIF::ConfigureJoyBusFrame() {
res[5] = BCD_ENCODE(gmtm->tm_mon);
res[6] = BCD_ENCODE(gmtm->tm_year);
res[7] = (gmtm->tm_year - 1900) >= 100 ? 1 : 0;
res[8] = 0x80;
}
break;
default:
panic("Invalid read RTC block {}", commandStart);
}
} break;
}
break;
case 8:
res[0] = 0x00;
memset(res, 0, 8);
break;
default:
panic("Invalid PIF command: {:X}", commandIndex);
@@ -294,6 +302,8 @@ void PIF::MempakRead(const u8 *cmd, u8 *res) {
case ACCESSORY_MEMPACK:
if (offset <= MEMPAK_SIZE - 0x20) {
std::copy_n(mempak.begin() + offset, 32, res);
} else {
memset(res, 0, 32);
}
break;
case ACCESSORY_RUMBLE_PACK:
@@ -332,7 +342,7 @@ void PIF::MempakWrite(u8 *cmd, u8 *res) {
}
void PIF::EepromRead(const u8 *cmd, u8 *res) const {
n64::Mem& mem = n64::Core::GetMem();
n64::Mem &mem = n64::Core::GetMem();
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
const u8 offset = cmd[3];
@@ -347,7 +357,7 @@ void PIF::EepromRead(const u8 *cmd, u8 *res) const {
}
void PIF::EepromWrite(const u8 *cmd, u8 *res) {
n64::Mem& mem = n64::Core::GetMem();
n64::Mem &mem = n64::Core::GetMem();
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
const u8 offset = cmd[3];
@@ -364,8 +374,8 @@ void PIF::EepromWrite(const u8 *cmd, u8 *res) {
}
void PIF::HLE(const bool pal, const CICType cicType) const {
n64::Mem& mem = n64::Core::GetMem();
n64::Registers& regs = n64::Core::GetRegs();
n64::Mem &mem = n64::Core::GetMem();
n64::Registers &regs = n64::Core::GetRegs();
mem.Write<u32>(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
switch (cicType) {
@@ -631,7 +641,7 @@ void PIF::HLE(const bool pal, const CICType cicType) const {
}
void PIF::Execute() const {
n64::Mem& mem = n64::Core::GetMem();
n64::Mem &mem = n64::Core::GetMem();
const CICType cicType = mem.rom.cicType;
const bool pal = mem.rom.pal;
mem.Write<u32>(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
-1
View File
@@ -78,7 +78,6 @@ void SI::Write(u32 addr, u32 val) {
status.dmaBusy = true;
toDram = true;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + 64);
break;
case 0x04800010:
pifAddr = val & 0x1FFFFFFF;