diff --git a/Core/MIPS/ARM64/Arm64IRCompBranch.cpp b/Core/MIPS/ARM64/Arm64IRCompBranch.cpp index c7bb4ae110..223bb4e61a 100644 --- a/Core/MIPS/ARM64/Arm64IRCompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64IRCompBranch.cpp @@ -51,7 +51,23 @@ void Arm64JitBackend::CompIR_Exit(IRInst inst) { exitReg = regs_.MapGPR(inst.src1); FlushAll(); MOV(SCRATCH1, exitReg); - B(dispatcherPCInSCRATCH1_); + // The dispatcher's lookup, here: each of these then has its own indirect branch, which the + // CPU predicts far better than one shared by every jr. Anything unusual goes the long way. + MovToPC(SCRATCH1); + { + // Out of the downcount, or no block yet: the dispatcher, with the PC stored. + FixupBranch inTime = TBZ(DOWNCOUNTREG, 31); + B(hooks_.dispatcher); + SetJumpTarget(inTime); + ANDI2R(SCRATCH1, SCRATCH1, Memory::BLOCK_SHADOW_ENTRY_MASK); + MOVP2R(SCRATCH2_64, Memory::blockShadow); + LDR(SCRATCH1, SCRATCH2_64, SCRATCH1_64); + FixupBranch found = CBNZ(SCRATCH1); + B(dispatcherNoCheck_); + SetJumpTarget(found); + ADD(SCRATCH1_64, JITBASEREG, SCRATCH1_64); + BR(SCRATCH1_64); + } break; case IROp::ExitToPC: diff --git a/Core/MIPS/ARM64/Arm64IRJit.cpp b/Core/MIPS/ARM64/Arm64IRJit.cpp index 471010b0d9..772f067829 100644 --- a/Core/MIPS/ARM64/Arm64IRJit.cpp +++ b/Core/MIPS/ARM64/Arm64IRJit.cpp @@ -75,8 +75,19 @@ bool Arm64JitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num) { // An accurate dot product can flush several registers around its call. size_t sizeEstimate = 0; const IRInst *estimateInsts = irBlockCache->GetBlockInstructionPtr(*block); - for (int i = 0; i < block->GetNumIRInstructions(); ++i) - sizeEstimate += estimateInsts[i].op == IROp::Vec4VfpuDot || estimateInsts[i].op == IROp::Vec4VfpuMultiDot ? 96 : 32; + for (int i = 0; i < block->GetNumIRInstructions(); ++i) { + switch (estimateInsts[i].op) { + case IROp::Vec4VfpuDot: + case IROp::Vec4VfpuMultiDot: + // The jump to a register looks up the block itself. + case IROp::ExitToReg: + sizeEstimate += 96; + break; + default: + sizeEstimate += 32; + break; + } + } BeginWrite(std::min(GetSpaceLeft(), sizeEstimate)); u32 startPC = block->GetOriginalStart();