all repos — mgba @ c8e1a9cd59ba20c1187368e5e9f68bab47b885ea

mGBA Game Boy Advance Emulator

PC-relative disassembling
Jeffrey Pfau jeffrey@endrift.com
Fri, 01 Nov 2013 22:29:55 -0700
commit

c8e1a9cd59ba20c1187368e5e9f68bab47b885ea

parent

39e1a85ffcfc2b4fea4fd800d5a93b61b309b916

3 files changed, 73 insertions(+), 15 deletions(-)

jump to
M src/arm/decoder-thumb.csrc/arm/decoder-thumb.c

@@ -221,8 +221,9 @@

#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ DEFINE_THUMB_DECODER(B ## COND, B, \ int8_t immediate = opcode; \ - info->op1.immediate += immediate << 1; \ + info->op1.immediate = immediate << 1; \ info->branches = 1; \ + info->condition = ARM_CONDITION_ ## COND; \ info->operandFormat = ARM_OPERAND_IMMEDIATE_1;) DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)

@@ -300,6 +301,7 @@ info->branches = 0;

info->traps = 0; info->accessesSpecialRegisters = 0; info->affectsCPSR = 0; + info->condition = ARM_CONDITION_AL; ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6]; decoder(opcode, info); }

@@ -380,7 +382,11 @@ ADVANCE(1);

return total; } -static int _decodeMemory(struct ARMMemoryAccess memory, char* buffer, int blen) { +static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) { + return snprintf(buffer, blen, "$%08X", address + pc); +} + +static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) { if (blen <= 0) { return 0; }

@@ -389,18 +395,23 @@ strncpy(buffer, "[", blen);

ADVANCE(1); int written; if (memory.format & ARM_MEMORY_REGISTER_BASE) { - written = _decodeRegister(memory.baseReg, buffer, blen); - ADVANCE(written); - if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) { - strncpy(buffer, ", ", blen); - ADVANCE(2); + if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) { + written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen); + ADVANCE(written); + } else { + written = _decodeRegister(memory.baseReg, buffer, blen); + ADVANCE(written); + if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) { + strncpy(buffer, ", ", blen); + ADVANCE(2); + } } } if (memory.format & ARM_MEMORY_POST_INCREMENT) { strncpy(buffer, "], ", blen); ADVANCE(3); } - if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) { + if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) { if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) { written = snprintf(buffer, blen, "#-%i", memory.offset.immediate); ADVANCE(written);

@@ -429,6 +440,25 @@ }

return total; } +static const char* _armConditions[] = { + "eq", + "ne", + "cs", + "cc", + "mi", + "pl", + "vs", + "vc", + "hi", + "ls", + "ge", + "lt", + "gt", + "le", + "al", + "nv" +}; + static const char* _thumbMnemonicStrings[] = { "ill", "adc",

@@ -470,13 +500,17 @@ "swi",

"tst" }; -int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) { +int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) { struct ThumbInstructionInfo info; ARMDecodeThumb(opcode, &info); const char* mnemonic = _thumbMnemonicStrings[info.mnemonic]; int written; int total = 0; - written = snprintf(buffer, blen, "%s ", mnemonic); + const char* cond = ""; + if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) { + cond = _armConditions[info.condition]; + } + written = snprintf(buffer, blen, "%s%s ", mnemonic, cond); ADVANCE(written); switch (info.mnemonic) {

@@ -492,12 +526,16 @@ case THUMB_MN_PUSH:

written = _decodeRegisterList(info.op1.immediate, buffer, blen); ADVANCE(written); break; + case THUMB_MN_B: + written = _decodePCRelative(info.op1.immediate, pc, buffer, blen); + ADVANCE(written); + break; default: if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) { written = snprintf(buffer, blen, "#%i", info.op1.immediate); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) { - written = _decodeMemory(info.memory, buffer, blen); + written = _decodeMemory(info.memory, pc, buffer, blen); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) { written = _decodeRegister(info.op1.reg, buffer, blen);

@@ -511,7 +549,7 @@ if (info.operandFormat & ARM_OPERAND_IMMEDIATE_2) {

written = snprintf(buffer, blen, "#%i", info.op2.immediate); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_MEMORY_2) { - written = _decodeMemory(info.memory, buffer, blen); + written = _decodeMemory(info.memory, pc, buffer, blen); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_REGISTER_2) { written = _decodeRegister(info.op2.reg, buffer, blen);

@@ -525,7 +563,7 @@ if (info.operandFormat & ARM_OPERAND_IMMEDIATE_3) {

written = snprintf(buffer, blen, "#%i", info.op3.immediate); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_MEMORY_3) { - written = _decodeMemory(info.memory, buffer, blen); + written = _decodeMemory(info.memory, pc, buffer, blen); ADVANCE(written); } else if (info.operandFormat & ARM_OPERAND_REGISTER_3) { written = _decodeRegister(info.op1.reg, buffer, blen);
M src/arm/decoder.hsrc/arm/decoder.h

@@ -47,6 +47,25 @@ ARM_MEMORY_POST_INCREMENT = 0x0020,

ARM_MEMORY_OFFSET_SUBTRACT = 0x0040 }; +enum ARMCondition { + ARM_CONDITION_EQ = 0x0, + ARM_CONDITION_NE = 0x1, + ARM_CONDITION_CS = 0x2, + ARM_CONDITION_CC = 0x3, + ARM_CONDITION_MI = 0x4, + ARM_CONDITION_PL = 0x5, + ARM_CONDITION_VS = 0x6, + ARM_CONDITION_VC = 0x7, + ARM_CONDITION_HI = 0x8, + ARM_CONDITION_LS = 0x9, + ARM_CONDITION_GE = 0xA, + ARM_CONDITION_LT = 0xB, + ARM_CONDITION_GT = 0xC, + ARM_CONDITION_LE = 0xD, + ARM_CONDITION_AL = 0xE, + ARM_CONDITION_NV = 0xF +}; + union ARMOperand { struct { uint8_t reg;

@@ -120,9 +139,10 @@ int branches;

int traps; int accessesSpecialRegisters; int affectsCPSR; + int condition; }; void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info); -int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen); +int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen); #endif
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -144,7 +144,7 @@ uint32_t instruction = debugger->d.cpu->memory->load32(debugger->d.cpu->memory, address, 0);

printf("%08X\n", instruction); } else { uint16_t instruction = debugger->d.cpu->memory->loadU16(debugger->d.cpu->memory, address, 0); - ARMDisassembleThumb(instruction, disassembly, sizeof(disassembly)); + ARMDisassembleThumb(instruction, debugger->d.cpu->gprs[ARM_PC] + WORD_SIZE_THUMB, disassembly, sizeof(disassembly)); printf("%04X: %s\n", instruction, disassembly); } }