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 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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue