From cc722f09f6e3ffb2142a53ab6b6d3d37d4c0f75e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 Mar 2015 11:46:35 +0100 Subject: [PATCH] Improve ARM64 disassembly by merging MOVZ+MOVK. Minor stuff. --- Core/MIPS/ARM64/Arm64Jit.cpp | 2 +- Core/MIPS/ARM64/Arm64Jit.h | 2 ++ Core/MIPS/JitCommon/JitBlockCache.cpp | 20 ++++++++++++++++++++ Core/MIPS/JitCommon/JitCommon.cpp | 27 +++++++++++++++++++++++---- unittest/TestArm64Emitter.cpp | 3 +++ 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 15802f815f..340a98aef2 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -59,7 +59,7 @@ namespace MIPSComp using namespace Arm64Gen; using namespace Arm64JitConstants; -Arm64Jit::Arm64Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &js, &jo), fpr(mips, &js, &jo), mips_(mips) { +Arm64Jit::Arm64Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &js, &jo), fpr(mips, &js, &jo), mips_(mips), fp(this) { logBlocks = 0; dontLogBlocks = 0; blocks.Init(); diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index 9f468d7c78..d46560a0e6 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -266,6 +266,8 @@ private: Arm64RegCache gpr; ArmRegCacheFPU fpr; + Arm64Gen::ARM64FloatEmitter fp; + MIPSState *mips_; int dontLogBlocks; diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 3bb1cbd544..235468139f 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -49,6 +49,8 @@ #elif defined(_M_IX86) || defined(_M_X64) #include "Common/x64Analyzer.h" #include "Core/MIPS/x86/Asm.h" +#elif defined(ARM64) +#include "Core/MIPS/ARM64/Arm64Asm.h" #else // FakeJit doesn't need an emitter, no blocks will be created #include "Core/MIPS/MIPS.h" @@ -72,6 +74,9 @@ using namespace ArmGen; using namespace ArmJitConstants; #elif defined(_M_X64) || defined(_M_IX86) using namespace Gen; +#elif defined(ARM64) +using namespace Arm64Gen; +using namespace Arm64JitConstants; #endif const u32 INVALID_EXIT = 0xFFFFFFFF; @@ -438,6 +443,9 @@ void JitBlockCache::LinkBlockExits(int i) { } } b.linkStatus[e] = true; +#elif defined(ARM64) + ARM64XEmitter emit(b.exitPtrs[e]); + // TODO ARM64 - must be done before enabling block linking #endif } } @@ -584,6 +592,18 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate) { XEmitter emit((u8 *)b->checkedEntry); emit.MOV(32, M(&mips_->pc), Imm32(b->originalAddress)); emit.JMP(MIPSComp::jit->Asm().dispatcher, true); + +#elif defined(ARM64) + + // Send anyone who tries to run this block back to the dispatcher. + // Not entirely ideal, but .. works. + // Spurious entrances from previously linked blocks can only come through checkedEntry + ARM64XEmitter emit((u8 *)b->checkedEntry); + emit.MOVI2R(SCRATCH1, b->originalAddress); + emit.STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, pc)); + emit.B(MIPSComp::jit->dispatcher); + emit.FlushIcache(); + #endif } diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 5968f85658..8f5581ce9f 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -81,6 +81,12 @@ std::vector DisassembleArm2(const u8 *data, int size) { } #endif +std::string AddAddress(const std::string &buf, uint64_t addr) { + char buf2[16]; + snprintf(buf2, sizeof(buf2), "%04x%08x", addr >> 32, addr & 0xFFFFFFFF); + return std::string(buf2) + " " + buf; +} + #if !defined(ARM) std::vector DisassembleArm64(const u8 *data, int size) { std::vector lines; @@ -89,7 +95,23 @@ std::vector DisassembleArm64(const u8 *data, int size) { int bkpt_count = 0; for (int i = 0; i < size; i += 4) { const u32 *codePtr = (const u32 *)(data + i); + uint64_t addr = (intptr_t)codePtr; u32 inst = codePtr[0]; + u32 next = (i < size - 4) ? codePtr[1] : 0; + // MAGIC SPECIAL CASE for MOVZ+MOVK readability! + if (((inst >> 21) & 0x3FF) == 0x294 && ((next >> 21) & 0x3FF) == 0x395) { + u32 low = (inst >> 5) & 0xFFFF; + u32 hi = (next >> 5) & 0xFFFF; + int reg0 = inst & 0x1F; + int reg1 = next & 0x1F; + char r = (inst >> 31) ? 'x' : 'w'; + if (reg0 == reg1) { + snprintf(temp, sizeof(temp), "movi32 %c%d, %04x%04x", r, reg0, hi, low); + lines.push_back(AddAddress(temp, addr)); + i += 4; + continue; + } + } Arm64Dis((intptr_t)codePtr, inst, temp, sizeof(temp), false); std::string buf = temp; if (buf == "BKPT 1") { @@ -100,10 +122,7 @@ std::vector DisassembleArm64(const u8 *data, int size) { bkpt_count = 0; } if (true) { - uint64_t addr = (intptr_t)(data + i); - char buf2[16]; - snprintf(buf2, sizeof(buf2), "%04x%08x", addr >> 32, addr & 0xFFFFFFFF); - buf = std::string(buf2) + " " + buf; + buf = AddAddress(buf, addr); } lines.push_back(buf); } diff --git a/unittest/TestArm64Emitter.cpp b/unittest/TestArm64Emitter.cpp index 46e634e0fb..aaa2f4bb3a 100644 --- a/unittest/TestArm64Emitter.cpp +++ b/unittest/TestArm64Emitter.cpp @@ -31,9 +31,12 @@ bool TestArm64Emitter() { u32 code[512]; ARM64XEmitter emitter((u8 *)code); + ARM64FloatEmitter fp(&emitter); emitter.ADD(X1, X2, X30); RET(CheckLast(emitter, "8b3e6041 add x1, x2, x30")); emitter.SUB(W1, W2, W30); RET(CheckLast(emitter, "4b3e4041 sub w1, w2, w30")); + // fp.FMUL(Q0, Q1, Q2); + // RET(CheckLast(emitter, "4b3e4041 sub w1, w2, w30")); return true; } \ No newline at end of file