ARM64 disassembler improvements (show many kinds of branch targets properly)

This commit is contained in:
Henrik Rydgard 2015-10-10 11:27:28 +02:00
parent 4c4e95743a
commit 8914cd9914
6 changed files with 76 additions and 11 deletions

View File

@ -18,6 +18,17 @@
#include "Common.h"
#include "StringUtils.h"
void truncate_cpy(char *dest, size_t destSize, const char *src) {
size_t len = strlen(src);
if (len >= destSize - 1) {
memcpy(dest, src, destSize - 1);
dest[destSize - 1] = '\0';
} else {
memcpy(dest, src, len);
dest[len] = '\0';
}
}
long parseHexLong(std::string s) {
long value = 0;

View File

@ -22,6 +22,8 @@
#include "Common.h"
void truncate_cpy(char *dest, size_t destSize, const char *src);
long parseHexLong(std::string s);
long parseLong(std::string s);
std::string StringFromFormat(const char* format, ...);

View File

@ -19,6 +19,7 @@
#include "profiler/profiler.h"
#include "Common/ChunkFile.h"
#include "Common/CPUDetect.h"
#include "Common/StringUtils.h"
#include "Core/Reporting.h"
#include "Core/Config.h"
@ -350,8 +351,39 @@ void Arm64Jit::AddContinuedBlock(u32 dest) {
}
bool Arm64Jit::DescribeCodePtr(const u8 *ptr, std::string &name) {
// TODO: Not used by anything yet (except the modified VerySleepy on Windows)
return false;
// Used in disassembly viewer.
if (ptr == applyRoundingMode)
name = "applyRoundingMode";
else if (ptr == updateRoundingMode)
name = "updateRoundingMode";
else if (ptr == dispatcher)
name = "dispatcher";
else if (ptr == dispatcherPCInSCRATCH1)
name = "dispatcher (PC in SCRATCH1)";
else if (ptr == dispatcherNoCheck)
name = "dispatcherNoCheck";
else if (ptr == enterDispatcher)
name = "enterDispatcher";
else if (ptr == restoreRoundingMode)
name = "restoreRoundingMode";
else if (ptr == saveStaticRegisters)
name = "saveStaticRegisters";
else if (ptr == loadStaticRegisters)
name = "loadStaticRegisters";
else {
u32 addr = blocks.GetAddressFromBlockPtr(ptr);
std::vector<int> numbers;
blocks.GetBlockNumbersFromAddress(addr, &numbers);
if (!numbers.empty()) {
const JitBlock *block = blocks.GetBlock(numbers[0]);
if (block) {
name = StringFromFormat("(block %d at %08x)", numbers[0], block->originalAddress);
return true;
}
}
return false;
}
return true;
}
void Arm64Jit::Comp_RunBlock(MIPSOpcode op) {
@ -385,7 +417,7 @@ bool Arm64Jit::ReplaceJalTo(u32 dest) {
QuickCallFunction(SCRATCH1_64, (const void *)(entry->replaceFunc));
ApplyRoundingMode();
LoadStaticRegisters();
WriteDownCountR(W0);
WriteDownCountR(W0); // W0 is the return value from entry->replaceFunc. Neither LoadStaticRegisters nor ApplyRoundingMode can trash it.
}
js.compilerPC += 4;

View File

@ -94,6 +94,18 @@ std::string AddAddress(const std::string &buf, uint64_t addr) {
}
#if defined(ARM64) || defined(DISASM_ALL)
static bool Arm64SymbolCallback(char *buffer, int bufsize, uint8_t *address) {
if (MIPSComp::jit) {
std::string name;
if (MIPSComp::jit->DescribeCodePtr(address, name)) {
truncate_cpy(buffer, bufsize, name.c_str());
return true;
}
}
return false;
}
std::vector<std::string> DisassembleArm64(const u8 *data, int size) {
std::vector<std::string> lines;
@ -118,7 +130,7 @@ std::vector<std::string> DisassembleArm64(const u8 *data, int size) {
continue;
}
}
Arm64Dis((intptr_t)codePtr, inst, temp, sizeof(temp), false);
Arm64Dis((intptr_t)codePtr, inst, temp, sizeof(temp), false, Arm64SymbolCallback);
std::string buf = temp;
if (buf == "BKPT 1") {
bkpt_count++;

View File

@ -25,6 +25,7 @@
#include "Common/Arm64Emitter.h"
#include "Common/StringUtils.h"
#include "Core/Util/DisArm64.h"
struct Instruction {
char text[128];
@ -200,14 +201,19 @@ static const char *GetSystemRegName(int o0, int op1, int CRn, int CRm, int op2)
}
}
static void BranchExceptionAndSystem(uint32_t w, uint64_t addr, Instruction *instr) {
static void BranchExceptionAndSystem(uint32_t w, uint64_t addr, Instruction *instr, SymbolCallback symbolCallback) {
char buffer[128];
int Rt = w & 0x1f;
int Rn = (w >> 5) & 0x1f;
if (((w >> 26) & 0x1F) == 5) {
// Unconditional branch / branch+link
int offset = SignExtend26(w) << 2;
uint64_t target = addr + offset;
snprintf(instr->text, sizeof(instr->text), "b%s %04x%08x", (w >> 31) ? "l" : "", (uint32_t)(target >> 32), (uint32_t)(target & 0xFFFFFFFF));
if (symbolCallback && symbolCallback(buffer, sizeof(buffer), (uint8_t *)(uintptr_t)target)) {
snprintf(instr->text, sizeof(instr->text), "b%s %s", (w >> 31) ? "l" : "", buffer);
} else {
snprintf(instr->text, sizeof(instr->text), "b%s %04x%08x", (w >> 31) ? "l" : "", (uint32_t)(target >> 32), (uint32_t)(target & 0xFFFFFFFF));
}
} else if (((w >> 25) & 0x3F) == 0x1A) {
// Compare and branch
int op = (w >> 24) & 1;
@ -994,7 +1000,7 @@ static void FPandASIMD2(uint32_t w, uint64_t addr, Instruction *instr) {
}
}
static void DisassembleInstruction(uint32_t w, uint64_t addr, Instruction *instr) {
static void DisassembleInstruction(uint32_t w, uint64_t addr, Instruction *instr, SymbolCallback symbolCallback) {
memset(instr, 0, sizeof(*instr));
// Identify the main encoding groups. See C3.1 A64 instruction index by encoding
@ -1007,7 +1013,7 @@ static void DisassembleInstruction(uint32_t w, uint64_t addr, Instruction *instr
DataProcessingImmediate(w, addr, instr);
break;
case 0xA: case 0xB:
BranchExceptionAndSystem(w, addr, instr);
BranchExceptionAndSystem(w, addr, instr, symbolCallback);
break;
case 4: case 6: case 0xC: case 0xE:
LoadStore(w, addr, instr);
@ -1024,9 +1030,9 @@ static void DisassembleInstruction(uint32_t w, uint64_t addr, Instruction *instr
}
}
void Arm64Dis(uint64_t addr, uint32_t w, char *output, int bufsize, bool includeWord) {
void Arm64Dis(uint64_t addr, uint32_t w, char *output, int bufsize, bool includeWord, SymbolCallback symbolCallback) {
Instruction instr;
DisassembleInstruction(w, addr, &instr);
DisassembleInstruction(w, addr, &instr, symbolCallback);
char temp[256];
if (includeWord) {
snprintf(output, bufsize, "%08x\t%s", w, instr.text);

View File

@ -20,5 +20,7 @@
#include <stdint.h>
void Arm64Dis(uint64_t addr, uint32_t w, char *output, int bufsize, bool includeWord);
typedef bool (*SymbolCallback)(char *buffer, int bufsize, uint8_t *address);
void Arm64Dis(uint64_t addr, uint32_t w, char *output, int bufsize, bool includeWord, SymbolCallback symbolCallback = nullptr);