Merge pull request #3854 from degasus/arm

JitArm64: Implement MMU handling.
This commit is contained in:
Markus Wick 2016-05-21 08:46:22 +02:00
commit ff4bc5f33d
6 changed files with 90 additions and 40 deletions

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);