Merge pull request #3854 from degasus/arm
JitArm64: Implement MMU handling.
This commit is contained in:
commit
ff4bc5f33d
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "Common/Arm64Emitter.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/PerformanceCounter.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -364,15 +365,9 @@ void JitArm64::Jit(u32)
|
|||
{
|
||||
ClearCache();
|
||||
}
|
||||
int block_num = blocks.AllocateBlock(PowerPC::ppcState.pc);
|
||||
JitBlock *b = blocks.GetBlock(block_num);
|
||||
const u8* BlockPtr = DoJit(PowerPC::ppcState.pc, &code_buffer, b);
|
||||
blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr);
|
||||
}
|
||||
|
||||
const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
|
||||
{
|
||||
int blockSize = code_buf->GetSize();
|
||||
int blockSize = code_buffer.GetSize();
|
||||
u32 em_address = PowerPC::ppcState.pc;
|
||||
|
||||
if (SConfig::GetInstance().bEnableDebugging)
|
||||
{
|
||||
|
@ -380,6 +375,28 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
blockSize = 1;
|
||||
}
|
||||
|
||||
// Analyze the block, collect all instructions it is made of (including inlining,
|
||||
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
|
||||
u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, blockSize);
|
||||
|
||||
if (code_block.m_memory_exception)
|
||||
{
|
||||
// Address of instruction could not be translated
|
||||
NPC = nextPC;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
WARN_LOG(POWERPC, "ISI exception at 0x%08x", nextPC);
|
||||
return;
|
||||
}
|
||||
|
||||
int block_num = blocks.AllocateBlock(em_address);
|
||||
JitBlock *b = blocks.GetBlock(block_num);
|
||||
const u8* BlockPtr = DoJit(em_address, &code_buffer, b, nextPC);
|
||||
blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr);
|
||||
}
|
||||
|
||||
const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b, u32 nextPC)
|
||||
{
|
||||
if (em_address == 0)
|
||||
{
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
|
@ -395,11 +412,6 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
js.skipInstructions = 0;
|
||||
js.curBlock = b;
|
||||
|
||||
u32 nextPC = em_address;
|
||||
// Analyze the block, collect all instructions it is made of (including inlining,
|
||||
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
|
||||
nextPC = analyzer.Analyze(em_address, &code_block, code_buf, blockSize);
|
||||
|
||||
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
|
||||
|
||||
const u8 *start = GetCodePtr();
|
||||
|
@ -467,6 +479,7 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
js.compilerPC = ops[i].address;
|
||||
js.op = &ops[i];
|
||||
js.instructionNumber = i;
|
||||
js.instructionsLeft = (code_block.m_num_instructions - 1) - i;
|
||||
const GekkoOPInfo *opinfo = ops[i].opinfo;
|
||||
js.downcountAmount += opinfo->numCycles;
|
||||
|
||||
|
@ -578,12 +591,6 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
js.firstFPInstructionFound = true;
|
||||
}
|
||||
|
||||
if (jo.memcheck && (opinfo->flags & FL_USE_FPU))
|
||||
{
|
||||
// Don't do this yet
|
||||
BRK(0x7777);
|
||||
}
|
||||
|
||||
JitArm64Tables::CompileInstruction(ops[i]);
|
||||
|
||||
// If we have a register that will never be used again, flush it.
|
||||
|
@ -592,8 +599,22 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
|
||||
if (jo.memcheck && (opinfo->flags & FL_LOADSTORE))
|
||||
{
|
||||
// Don't do this yet
|
||||
BRK(0x666);
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||
FixupBranch noException = TBZ(WA, IntLog2(EXCEPTION_DSI));
|
||||
|
||||
FixupBranch handleException = B();
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(handleException);
|
||||
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
|
||||
WriteExceptionExit(js.compilerPC);
|
||||
|
||||
SwitchToNearCode();
|
||||
SetJumpTarget(noException);
|
||||
gpr.Unlock(WA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,12 +622,10 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
js.skipInstructions = 0;
|
||||
}
|
||||
|
||||
if (code_block.m_memory_exception)
|
||||
BRK(0x500);
|
||||
|
||||
if (code_block.m_broken)
|
||||
{
|
||||
printf("Broken Block going to 0x%08x\n", nextPC);
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
WriteExit(nextPC);
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ private:
|
|||
void SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 offset, bool update);
|
||||
void SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset);
|
||||
|
||||
const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b);
|
||||
const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b, u32 nextPC);
|
||||
|
||||
void DoDownCount();
|
||||
void Cleanup();
|
||||
|
|
|
@ -375,6 +375,7 @@ void JitArm64::lXX(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreOff);
|
||||
FALLBACK_IF(jo.memcheck);
|
||||
|
||||
u32 a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
s32 offset = inst.SIMM_16;
|
||||
|
@ -446,11 +447,11 @@ void JitArm64::lXX(UGeckoInstruction inst)
|
|||
|
||||
// LWZ idle skipping
|
||||
if (SConfig::GetInstance().bSkipIdle &&
|
||||
inst.OPCD == 32 &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
PowerPC::HostRead_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
inst.OPCD == 32 && MergeAllowedNextInstructions(2) &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 && // lwz r0, XXXX(r13)
|
||||
(js.op[1].inst.hex == 0x28000000 ||
|
||||
(SConfig::GetInstance().bWii && js.op[1].inst.hex == 0x2C000000)) && // cmpXwi r0,0
|
||||
js.op[2].inst.hex == 0x4182fff8) // beq -8
|
||||
{
|
||||
// if it's still 0, we can wait until the next event
|
||||
FixupBranch noIdle = CBNZ(gpr.R(d));
|
||||
|
@ -480,6 +481,7 @@ void JitArm64::stX(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreOff);
|
||||
FALLBACK_IF(jo.memcheck);
|
||||
|
||||
u32 a = inst.RA, b = inst.RB, s = inst.RS;
|
||||
s32 offset = inst.SIMM_16;
|
||||
|
@ -557,7 +559,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreOff);
|
||||
FALLBACK_IF(!jo.fastmem);
|
||||
FALLBACK_IF(!jo.fastmem || jo.memcheck);
|
||||
|
||||
u32 a = inst.RA;
|
||||
|
||||
|
@ -643,7 +645,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreOff);
|
||||
FALLBACK_IF(!jo.fastmem);
|
||||
FALLBACK_IF(!jo.fastmem || jo.memcheck);
|
||||
|
||||
u32 a = inst.RA;
|
||||
|
||||
|
@ -803,6 +805,7 @@ void JitArm64::dcbz(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreOff);
|
||||
FALLBACK_IF(jo.memcheck);
|
||||
|
||||
int a = inst.RA, b = inst.RB;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreFloatingOff);
|
||||
FALLBACK_IF(jo.memcheck);
|
||||
|
||||
u32 a = inst.RA, b = inst.RB;
|
||||
|
||||
|
@ -210,6 +211,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
|||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITLoadStoreFloatingOff);
|
||||
FALLBACK_IF(jo.memcheck);
|
||||
|
||||
u32 a = inst.RA, b = inst.RB;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void JitArm64::mtmsr(UGeckoInstruction inst)
|
|||
gpr.Flush(FlushMode::FLUSH_ALL);
|
||||
fpr.Flush(FlushMode::FLUSH_ALL);
|
||||
|
||||
WriteExit(js.compilerPC + 4);
|
||||
WriteExceptionExit(js.compilerPC + 4, true);
|
||||
}
|
||||
|
||||
void JitArm64::mfmsr(UGeckoInstruction inst)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Common/Arm64Emitter.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/JitRegister.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
@ -46,12 +47,36 @@ void JitArm64::GenerateAsm()
|
|||
|
||||
dispatcherNoCheck = GetCodePtr();
|
||||
|
||||
// This block of code gets the address of the compiled block of code
|
||||
// It runs though to the compiling portion if it isn't found
|
||||
BFM(DISPATCHER_PC, WSP, 3, 2); // Wipe the top 3 bits. Same as PC & JIT_ICACHE_MASK
|
||||
FixupBranch exram, vmem, not_exram, not_vmem;
|
||||
ARM64Reg pc_masked = W25;
|
||||
ARM64Reg cache_base = X27;
|
||||
|
||||
MOVI2R(X27, (u64)jit->GetBlockCache()->iCache.data());
|
||||
LDR(W27, X27, EncodeRegTo64(DISPATCHER_PC));
|
||||
// VMEM
|
||||
not_vmem = TBZ(DISPATCHER_PC, IntLog2(JIT_ICACHE_VMEM_BIT));
|
||||
ANDI2R(pc_masked, DISPATCHER_PC, JIT_ICACHE_MASK);
|
||||
MOVI2R(cache_base, (u64)jit->GetBlockCache()->iCacheVMEM.data());
|
||||
vmem = B();
|
||||
SetJumpTarget(not_vmem);
|
||||
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
// Wii EX-RAM
|
||||
not_exram = TBZ(DISPATCHER_PC, IntLog2(JIT_ICACHE_EXRAM_BIT));
|
||||
ANDI2R(pc_masked, DISPATCHER_PC, JIT_ICACHEEX_MASK);
|
||||
MOVI2R(cache_base, (u64)jit->GetBlockCache()->iCacheEx.data());
|
||||
exram = B();
|
||||
SetJumpTarget(not_exram);
|
||||
}
|
||||
|
||||
// Common memory
|
||||
ANDI2R(pc_masked, DISPATCHER_PC, JIT_ICACHE_MASK);
|
||||
MOVI2R(cache_base, (u64)jit->GetBlockCache()->iCache.data());
|
||||
|
||||
SetJumpTarget(vmem);
|
||||
if (SConfig::GetInstance().bWii)
|
||||
SetJumpTarget(exram);
|
||||
|
||||
LDR(W27, cache_base, EncodeRegTo64(pc_masked));
|
||||
|
||||
FixupBranch JitBlock = TBNZ(W27, 7); // Test the 7th bit
|
||||
// Success, it is our Jitblock.
|
||||
|
@ -64,10 +89,11 @@ void JitArm64::GenerateAsm()
|
|||
SetJumpTarget(JitBlock);
|
||||
|
||||
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
|
||||
MOVI2R(X30, (u64)&::Jit);
|
||||
BLR(X30);
|
||||
|
||||
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
|
||||
B(dispatcherNoCheck);
|
||||
|
||||
SetJumpTarget(bail);
|
||||
|
|
Loading…
Reference in New Issue