PC-relative disassembling

This commit is contained in:
Jeffrey Pfau 2013-11-01 22:29:55 -07:00
parent 39e1a85ffc
commit c8e1a9cd59
3 changed files with 73 additions and 15 deletions

View File

@ -221,8 +221,9 @@ DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA)
#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ #define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
DEFINE_THUMB_DECODER(B ## COND, B, \ DEFINE_THUMB_DECODER(B ## COND, B, \
int8_t immediate = opcode; \ int8_t immediate = opcode; \
info->op1.immediate += immediate << 1; \ info->op1.immediate = immediate << 1; \
info->branches = 1; \ info->branches = 1; \
info->condition = ARM_CONDITION_ ## COND; \
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;) info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
DEFINE_CONDITIONAL_BRANCH_THUMB(EQ) DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
@ -300,6 +301,7 @@ void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
info->traps = 0; info->traps = 0;
info->accessesSpecialRegisters = 0; info->accessesSpecialRegisters = 0;
info->affectsCPSR = 0; info->affectsCPSR = 0;
info->condition = ARM_CONDITION_AL;
ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6]; ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
decoder(opcode, info); decoder(opcode, info);
} }
@ -380,7 +382,11 @@ static int _decodeRegisterList(int list, char* buffer, int blen) {
return total; 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) { if (blen <= 0) {
return 0; return 0;
} }
@ -389,18 +395,23 @@ static int _decodeMemory(struct ARMMemoryAccess memory, char* buffer, int blen)
ADVANCE(1); ADVANCE(1);
int written; int written;
if (memory.format & ARM_MEMORY_REGISTER_BASE) { if (memory.format & ARM_MEMORY_REGISTER_BASE) {
written = _decodeRegister(memory.baseReg, buffer, blen); if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
ADVANCE(written); written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) { ADVANCE(written);
strncpy(buffer, ", ", blen); } else {
ADVANCE(2); 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) { if (memory.format & ARM_MEMORY_POST_INCREMENT) {
strncpy(buffer, "], ", blen); strncpy(buffer, "], ", blen);
ADVANCE(3); 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) { if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
written = snprintf(buffer, blen, "#-%i", memory.offset.immediate); written = snprintf(buffer, blen, "#-%i", memory.offset.immediate);
ADVANCE(written); ADVANCE(written);
@ -429,6 +440,25 @@ static int _decodeMemory(struct ARMMemoryAccess memory, char* buffer, int blen)
return total; 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[] = { static const char* _thumbMnemonicStrings[] = {
"ill", "ill",
"adc", "adc",
@ -470,13 +500,17 @@ static const char* _thumbMnemonicStrings[] = {
"tst" "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; struct ThumbInstructionInfo info;
ARMDecodeThumb(opcode, &info); ARMDecodeThumb(opcode, &info);
const char* mnemonic = _thumbMnemonicStrings[info.mnemonic]; const char* mnemonic = _thumbMnemonicStrings[info.mnemonic];
int written; int written;
int total = 0; 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); ADVANCE(written);
switch (info.mnemonic) { switch (info.mnemonic) {
@ -492,12 +526,16 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
written = _decodeRegisterList(info.op1.immediate, buffer, blen); written = _decodeRegisterList(info.op1.immediate, buffer, blen);
ADVANCE(written); ADVANCE(written);
break; break;
case THUMB_MN_B:
written = _decodePCRelative(info.op1.immediate, pc, buffer, blen);
ADVANCE(written);
break;
default: default:
if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) { if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) {
written = snprintf(buffer, blen, "#%i", info.op1.immediate); written = snprintf(buffer, blen, "#%i", info.op1.immediate);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_MEMORY_1) { } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) {
written = _decodeMemory(info.memory, buffer, blen); written = _decodeMemory(info.memory, pc, buffer, blen);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_REGISTER_1) { } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) {
written = _decodeRegister(info.op1.reg, buffer, blen); written = _decodeRegister(info.op1.reg, buffer, blen);
@ -511,7 +549,7 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
written = snprintf(buffer, blen, "#%i", info.op2.immediate); written = snprintf(buffer, blen, "#%i", info.op2.immediate);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_MEMORY_2) { } else if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
written = _decodeMemory(info.memory, buffer, blen); written = _decodeMemory(info.memory, pc, buffer, blen);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_REGISTER_2) { } else if (info.operandFormat & ARM_OPERAND_REGISTER_2) {
written = _decodeRegister(info.op2.reg, buffer, blen); written = _decodeRegister(info.op2.reg, buffer, blen);
@ -525,7 +563,7 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
written = snprintf(buffer, blen, "#%i", info.op3.immediate); written = snprintf(buffer, blen, "#%i", info.op3.immediate);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_MEMORY_3) { } else if (info.operandFormat & ARM_OPERAND_MEMORY_3) {
written = _decodeMemory(info.memory, buffer, blen); written = _decodeMemory(info.memory, pc, buffer, blen);
ADVANCE(written); ADVANCE(written);
} else if (info.operandFormat & ARM_OPERAND_REGISTER_3) { } else if (info.operandFormat & ARM_OPERAND_REGISTER_3) {
written = _decodeRegister(info.op1.reg, buffer, blen); written = _decodeRegister(info.op1.reg, buffer, blen);

View File

@ -47,6 +47,25 @@ enum ARMMemoryFormat {
ARM_MEMORY_OFFSET_SUBTRACT = 0x0040 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 { union ARMOperand {
struct { struct {
uint8_t reg; uint8_t reg;
@ -120,9 +139,10 @@ struct ThumbInstructionInfo {
int traps; int traps;
int accessesSpecialRegisters; int accessesSpecialRegisters;
int affectsCPSR; int affectsCPSR;
int condition;
}; };
void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info); 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 #endif

View File

@ -144,7 +144,7 @@ static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, en
printf("%08X\n", instruction); printf("%08X\n", instruction);
} else { } else {
uint16_t instruction = debugger->d.cpu->memory->loadU16(debugger->d.cpu->memory, address, 0); 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); printf("%04X: %s\n", instruction, disassembly);
} }
} }