Use physical address for indexing into blocks
This commit is contained in:
@@ -6,47 +6,66 @@ namespace n64::JIT {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
Dynarec::~Dynarec() {
|
||||
dumpCode.close();
|
||||
std::free(codeCache);
|
||||
}
|
||||
|
||||
Dynarec::Dynarec() : code(DEFAULT_MAX_CODE_SIZE, AutoGrow) {
|
||||
if(fs::exists("jit.dump")) {
|
||||
fs::remove("jit.dump");
|
||||
}
|
||||
|
||||
dumpCode.open("jit.dump", std::ios::app | std::ios::binary);
|
||||
code.ready();
|
||||
Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) {
|
||||
codeCache = (u8*)Util::aligned_alloc(4096, CODECACHE_SIZE);
|
||||
CodeArray::protect(
|
||||
codeCache,
|
||||
CODECACHE_SIZE,
|
||||
CodeArray::PROTECT_RWE
|
||||
);
|
||||
}
|
||||
|
||||
void Dynarec::Recompile(Registers& regs, Mem& mem) {
|
||||
void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) {
|
||||
bool branch = false, prevBranch = false;
|
||||
u32 start_addr = regs.pc;
|
||||
u32 startPC = pc;
|
||||
u32 loopPC = pc;
|
||||
Fn block = code.getCurr<Fn>();
|
||||
|
||||
if(code.getSize() >= CODECACHE_SIZE) {
|
||||
Util::print("Code cache overflow!\n");
|
||||
code.setSize(code.getSize() & (CODECACHE_SIZE - 1));
|
||||
InvalidateCache();
|
||||
}
|
||||
|
||||
Util::print("Start of block @ PC {:08X}\n", loopPC);
|
||||
code.sub(rsp, 8);
|
||||
|
||||
while(!prevBranch) {
|
||||
instrInBlock++;
|
||||
prevBranch = branch;
|
||||
u32 instr = mem.Read32(regs, start_addr, start_addr);
|
||||
|
||||
start_addr += 4;
|
||||
u32 instr = mem.Read32<false>(regs, loopPC, loopPC);
|
||||
|
||||
code.mov(rdi, (u64)®s);
|
||||
|
||||
Util::print("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC);
|
||||
code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]);
|
||||
code.mov(r9, qword[rdi + REG_OFFSET(pc)]);
|
||||
code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]);
|
||||
code.mov(r8, r9);
|
||||
code.mov(r9, r10);
|
||||
code.add(r10, 4);
|
||||
code.mov(qword[rdi + REG_OFFSET(oldPC)], r8);
|
||||
code.mov(qword[rdi + REG_OFFSET(pc)], r9);
|
||||
code.mov(qword[rdi + REG_OFFSET(nextPC)], r10);
|
||||
|
||||
loopPC += 4;
|
||||
|
||||
branch = Exec(regs, mem, instr);
|
||||
}
|
||||
|
||||
code.add(rsp, 8);
|
||||
code.ret();
|
||||
dumpCode.write(code.getCode<char*>(), code.getSize());
|
||||
u32 pc = regs.pc & 0xffffffff;
|
||||
codeCache[pc >> 20][pc & 0xFFF] = block;
|
||||
block();
|
||||
Util::print("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock);
|
||||
|
||||
blockCache[startPC >> 20][startPC & 0xFFF] = block;
|
||||
blockCache[startPC >> 20][startPC & 0xFFF]();
|
||||
}
|
||||
|
||||
void Dynarec::AllocateOuter(Registers& regs) {
|
||||
u32 pc = regs.pc & 0xffffffff;
|
||||
codeCache[pc >> 20] = (Fn*)calloc(0xFFF, sizeof(Fn));
|
||||
void Dynarec::AllocateOuter(u32 pc) {
|
||||
blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn));
|
||||
}
|
||||
|
||||
int Dynarec::Step(Mem &mem, Registers& regs) {
|
||||
@@ -55,17 +74,20 @@ int Dynarec::Step(Mem &mem, Registers& regs) {
|
||||
regs.prevDelaySlot = regs.delaySlot;
|
||||
regs.delaySlot = false;
|
||||
|
||||
u32 pc = regs.pc & 0xffffffff;
|
||||
u32 pc{};
|
||||
if(!MapVAddr(regs, LOAD, regs.pc, pc)) {
|
||||
Util::panic("[RECOMPILER] Failed to translate PC to physical address (v: {:08X})\n", regs.pc);
|
||||
}
|
||||
|
||||
if(codeCache[pc >> 20]) {
|
||||
if(codeCache[pc >> 20][pc & 0xfff]) {
|
||||
codeCache[pc >> 20][pc & 0xfff]();
|
||||
if(blockCache[pc >> 20]) {
|
||||
if(blockCache[pc >> 20][pc & 0xfff]) {
|
||||
blockCache[pc >> 20][pc & 0xfff]();
|
||||
} else {
|
||||
Recompile(regs, mem);
|
||||
Recompile(regs, mem, pc);
|
||||
}
|
||||
} else {
|
||||
AllocateOuter(regs);
|
||||
Recompile(regs, mem);
|
||||
AllocateOuter(pc);
|
||||
Recompile(regs, mem, pc);
|
||||
}
|
||||
|
||||
return instrInBlock;
|
||||
|
||||
Reference in New Issue
Block a user