mirror of https://github.com/mgba-emu/mgba.git
PC-relative disassembling
This commit is contained in:
parent
39e1a85ffc
commit
c8e1a9cd59
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue