summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2016-05-21 08:46:22 +0200
committerMarkus Wick <degasus@users.noreply.github.com>2016-05-21 08:46:22 +0200
commitff4bc5f33d6bfaab38d651b0706c77d705cf6c5c (patch)
tree4f5275e849d64e7765d141fcb84846ca6defae8e /Source/Core
parent25f88bf751749f03ecbde8b8ca353059f7caf7e7 (diff)
parentc5e8238cc721c123a4e04a706524d13523545b7e (diff)
Merge pull request #3854 from degasus/arm
JitArm64: Implement MMU handling.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.cpp69
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.h2
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp17
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStoreFloating.cpp2
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp2
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp38
6 files changed, 90 insertions, 40 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
index 31031ef70c..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"
@@ -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);
}
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/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp
index b5ba689d21..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;
@@ -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;
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;
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)
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp
index 02cf15f1a0..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,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);