Improve ARM64 disassembly by merging MOVZ+MOVK. Minor stuff.

This commit is contained in:
Henrik Rydgard 2015-03-08 11:46:35 +01:00
parent 73dd26fb75
commit cc722f09f6
5 changed files with 49 additions and 5 deletions

View file

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

View file

@ -266,6 +266,8 @@ private:
Arm64RegCache gpr;
ArmRegCacheFPU fpr;
Arm64Gen::ARM64FloatEmitter fp;
MIPSState *mips_;
int dontLogBlocks;

View file

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

View file

@ -81,6 +81,12 @@ std::vector<std::string> 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<std::string> DisassembleArm64(const u8 *data, int size) {
std::vector<std::string> lines;
@ -89,7 +95,23 @@ std::vector<std::string> 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<std::string> 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);
}

View file

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