make idle loop detection a little more specific with where the load goes
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include <Core.hpp>
|
#include <Core.hpp>
|
||||||
#include <Scheduler.hpp>
|
#include <Scheduler.hpp>
|
||||||
|
#include <mem/Utils.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
Interpreter::Interpreter(Mem &mem, Registers ®s) : regs(regs), mem(mem) {}
|
Interpreter::Interpreter(Mem &mem, Registers ®s) : regs(regs), mem(mem) {}
|
||||||
@@ -118,11 +119,18 @@ bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLO
|
|||||||
// _andi reg2, reg1, immediate
|
// _andi reg2, reg1, immediate
|
||||||
|
|
||||||
auto branch = code[lastInstructionIndex - 1];
|
auto branch = code[lastInstructionIndex - 1];
|
||||||
auto load = code[lastInstructionIndex - 2]; // load
|
auto load = code[lastInstructionIndex - 2];
|
||||||
|
bool isLoad = load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU;
|
||||||
|
if (isLoad) {
|
||||||
|
const s16 offset = load;
|
||||||
|
const u64 address = regs.Read<s64>(load.rs()) + offset;
|
||||||
|
u32 paddr;
|
||||||
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr))
|
||||||
|
panic("Failed to translate load address in DetectIdleLoop");
|
||||||
|
|
||||||
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
return isLoad && delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
|
||||||
delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
|
load.rt() == delay.rs() && delay.rt() == branch.rs() && IsAddressMMIOorRDRAM(paddr);
|
||||||
load.rt() == delay.rs() && delay.rt() == branch.rs();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 4) {
|
if (len == 4) {
|
||||||
@@ -132,12 +140,19 @@ bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLO
|
|||||||
// _nop
|
// _nop
|
||||||
|
|
||||||
auto branch = code[lastInstructionIndex - 1];
|
auto branch = code[lastInstructionIndex - 1];
|
||||||
auto andi = code[lastInstructionIndex - 2]; // andi
|
auto andi = code[lastInstructionIndex - 2];
|
||||||
auto load = code[lastInstructionIndex - 3]; // load
|
auto load = code[lastInstructionIndex - 3];
|
||||||
|
const s16 offset = load;
|
||||||
|
const u64 address = regs.Read<s64>(load.rs()) + offset;
|
||||||
|
bool isLoad = load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU;
|
||||||
|
if (isLoad) {
|
||||||
|
u32 paddr;
|
||||||
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr))
|
||||||
|
panic("Failed to translate load address in DetectIdleLoop");
|
||||||
|
|
||||||
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
return isLoad && andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
|
||||||
andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
|
load.rt() == andi.rs() && andi.rt() == branch.rs() && IsAddressMMIOorRDRAM(paddr);
|
||||||
load.rt() == andi.rs() && andi.rt() == branch.rs();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common.hpp>
|
||||||
|
#include <ircolib/mem_access.hpp>
|
||||||
|
#include <MemoryRegions.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
static bool IsAddressMMIOorRDRAM(u32 addr) {
|
||||||
|
if (ircolib::IsInsideRange(addr, RDRAM_REGION_START, RDRAM_REGION_END))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ircolib::IsInsideRange(addr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
|
||||||
|
ircolib::IsInsideRange(addr, MMIO_REGION_START_2, MMIO_REGION_END_2))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace n64
|
||||||
@@ -4,12 +4,13 @@
|
|||||||
int main(const int argc, char **argv) {
|
int main(const int argc, char **argv) {
|
||||||
KaizenGui kaizenGui;
|
KaizenGui kaizenGui;
|
||||||
cflags::cflags flags;
|
cflags::cflags flags;
|
||||||
flags.add_string_callback('\0', "rom", [&kaizenGui](const std::string& v) { kaizenGui.LoadROM(v); }, "Rom to launch from command-line");
|
flags.add_string_callback(
|
||||||
flags.add_string_callback('\0', "movie", [](const std::string& v) { KaizenGui::LoadTAS(v); }, "Mupen Movie to replay");
|
'\0', "rom", [&kaizenGui](const std::string &v) { kaizenGui.LoadROM(v); }, "Rom to launch from command-line");
|
||||||
|
flags.add_string_callback(
|
||||||
|
'\0', "movie", [](const std::string &v) { KaizenGui::LoadTAS(v); }, "Mupen Movie to replay");
|
||||||
|
|
||||||
if(!flags.parse(argc, argv)) {
|
if (!flags.parse(argc, argv))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
kaizenGui.run();
|
kaizenGui.run();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user