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_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 @@ void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
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 @@ static int _decodeRegisterList(int list, char* buffer, int blen) {
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 @@ static int _decodeMemory(struct ARMMemoryAccess memory, char* buffer, int 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 @@ static int _decodeMemory(struct ARMMemoryAccess memory, char* buffer, int blen)
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 @@ static const char* _thumbMnemonicStrings[] = {
"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 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
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 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
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 @@ int ARMDisassembleThumb(uint16_t opcode, char* buffer, int blen) {
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);

View File

@ -47,6 +47,25 @@ enum ARMMemoryFormat {
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 @@ struct ThumbInstructionInfo {
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

View File

@ -144,7 +144,7 @@ static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, en
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);
}
}