From 782c68cf004c23dff5d1479a2ebcfe00041ccdde Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 14 May 2016 10:30:17 +0200 Subject: [PATCH 1/6] JitArm64: Clean up LWZ idle skipping. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 1 + .../Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 31031ef70c..903cfe9067 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -467,6 +467,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; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index b5ba689d21..7bdb250c20 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -446,11 +446,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)); From 95ebb2991fc59dfe34d07df8fec8591aac00c901 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 14 May 2016 01:28:22 +0200 Subject: [PATCH 2/6] JitArm64: Check Exceptions on mtmsr. --- Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 3bcb89a10a..49a869fa13 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -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) From 37e2e92e33bde8350ad358e6164be8811771169b Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 14 May 2016 14:38:57 +0200 Subject: [PATCH 3/6] JitArm64: Handle ISI excepction. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 40 ++++++++++++-------- Source/Core/Core/PowerPC/JitArm64/Jit.h | 2 +- Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp | 6 ++- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 903cfe9067..dd08cfc6fe 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -364,15 +364,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 +374,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 +411,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(); @@ -602,9 +613,6 @@ 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); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index a791b279e4..6bf30e351a 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -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(); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp index 02cf15f1a0..378b3c8768 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp @@ -46,6 +46,8 @@ void JitArm64::GenerateAsm() dispatcherNoCheck = GetCodePtr(); + STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); + // 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 @@ -63,11 +65,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); From 5db61b4bbbac70158a02ab26bac78f8c21060c66 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 14 May 2016 14:40:26 +0200 Subject: [PATCH 4/6] JitArm64: Fix broken block handling. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index dd08cfc6fe..7cc24a9e7d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -615,7 +615,8 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB if (code_block.m_broken) { - printf("Broken Block going to 0x%08x\n", nextPC); + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); WriteExit(nextPC); } From 8e902abca385dcd7e9c633ede01d318b19636970 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 14 May 2016 11:31:17 +0200 Subject: [PATCH 5/6] JitArm64: Implement DSI exception. Ok, this falls back on all memory instructions, but it's a way to start. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 25 +++++++++++++------ .../PowerPC/JitArm64/JitArm64_LoadStore.cpp | 7 ++++-- .../JitArm64/JitArm64_LoadStoreFloating.cpp | 2 ++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 7cc24a9e7d..a8795bb4ed 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -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" @@ -590,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. @@ -604,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); } } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index 7bdb250c20..c4053ff779 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -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; @@ -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; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp index f27367f297..69ed5811d3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp @@ -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; From c5e8238cc721c123a4e04a706524d13523545b7e Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 19 May 2016 19:41:56 +0200 Subject: [PATCH 6/6] JitArm64: Fix dispatcher with MMU. --- Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp | 36 ++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp index 378b3c8768..11cfe363fd 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp @@ -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,14 +47,36 @@ void JitArm64::GenerateAsm() dispatcherNoCheck = GetCodePtr(); - STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); + FixupBranch exram, vmem, not_exram, not_vmem; + ARM64Reg pc_masked = W25; + ARM64Reg cache_base = X27; - // 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 + // 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); - MOVI2R(X27, (u64)jit->GetBlockCache()->iCache.data()); - LDR(W27, X27, EncodeRegTo64(DISPATCHER_PC)); + 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. @@ -65,6 +88,7 @@ void JitArm64::GenerateAsm() SetJumpTarget(JitBlock); + STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); MOVI2R(X30, (u64)&::Jit); BLR(X30);