mirror of https://github.com/mgba-emu/mgba.git
Debugger: Merge Thumb BL instructions when disassembling (fixes #133)
This commit is contained in:
parent
99d75ee9ed
commit
6d43fb7890
1
CHANGES
1
CHANGES
|
@ -78,6 +78,7 @@ Misc:
|
|||
- GBA: Improve accuracy of event timing
|
||||
- Debugger: Clean up GDB stub network interfacing
|
||||
- Debugger: Simplify debugger state machine to play nicer with the GBA thread loop
|
||||
- Debugger: Merge Thumb BL instructions when disassembling
|
||||
|
||||
0.1.0: (2014-12-13)
|
||||
- Initial release
|
||||
|
|
|
@ -290,14 +290,21 @@ DEFINE_THUMB_DECODER(B, B,
|
|||
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||
info->branchType = ARM_BRANCH;)
|
||||
|
||||
DEFINE_THUMB_DECODER(BL1, BLH,
|
||||
DEFINE_THUMB_DECODER(BL1, BL,
|
||||
int16_t immediate = (opcode & 0x07FF) << 5;
|
||||
info->op1.immediate = (((int32_t) immediate) << 7);
|
||||
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
|
||||
info->op1.reg = ARM_LR;
|
||||
info->op2.reg = ARM_PC;
|
||||
info->op3.immediate = (((int32_t) immediate) << 7);
|
||||
info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 |
|
||||
ARM_OPERAND_REGISTER_2 | ARM_OPERAND_AFFECTED_2 |
|
||||
ARM_OPERAND_IMMEDIATE_3;)
|
||||
|
||||
DEFINE_THUMB_DECODER(BL2, BL,
|
||||
info->op1.immediate = (opcode & 0x07FF) << 1;
|
||||
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||
info->op1.reg = ARM_PC;
|
||||
info->op2.reg = ARM_LR;
|
||||
info->op3.immediate = (opcode & 0x07FF) << 1;
|
||||
info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 |
|
||||
ARM_OPERAND_REGISTER_2 | ARM_OPERAND_IMMEDIATE_3;
|
||||
info->branchType = ARM_BRANCH_LINKED;)
|
||||
|
||||
DEFINE_THUMB_DECODER(BX, BX,
|
||||
|
@ -332,3 +339,33 @@ void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
|
|||
ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
|
||||
decoder(opcode, info);
|
||||
}
|
||||
|
||||
bool ARMDecodeThumbCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2, struct ARMInstructionInfo* out) {
|
||||
if (info1->execMode != MODE_THUMB || info1->mnemonic != ARM_MN_BL) {
|
||||
return false;
|
||||
}
|
||||
if (info2->execMode != MODE_THUMB || info2->mnemonic != ARM_MN_BL) {
|
||||
return false;
|
||||
}
|
||||
if (info1->op1.reg != ARM_LR || info1->op2.reg != ARM_PC) {
|
||||
return false;
|
||||
}
|
||||
if (info2->op1.reg != ARM_PC || info2->op2.reg != ARM_LR) {
|
||||
return false;
|
||||
}
|
||||
out->op1.immediate = info1->op3.immediate | info2->op3.immediate;
|
||||
out->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||
out->execMode = MODE_THUMB;
|
||||
out->mnemonic = ARM_MN_BL;
|
||||
out->branchType = ARM_BRANCH_LINKED;
|
||||
out->traps = 0;
|
||||
out->affectsCPSR = 0;
|
||||
out->condition = ARM_CONDITION_AL;
|
||||
out->sDataCycles = 0;
|
||||
out->nDataCycles = 0;
|
||||
out->sInstructionCycles = 2;
|
||||
out->nInstructionCycles = 0;
|
||||
out->iCycles = 0;
|
||||
out->cCycles = 0;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -223,7 +223,6 @@ static const char* _armMnemonicStrings[] = {
|
|||
"bic",
|
||||
"bkpt",
|
||||
"bl",
|
||||
"blh",
|
||||
"bx",
|
||||
"cmn",
|
||||
"cmp",
|
||||
|
@ -355,8 +354,11 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
|
|||
}
|
||||
break;
|
||||
case ARM_MN_B:
|
||||
written = _decodePCRelative(info->op1.immediate, pc, buffer, blen);
|
||||
ADVANCE(written);
|
||||
case ARM_MN_BL:
|
||||
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
|
||||
written = _decodePCRelative(info->op1.immediate, pc, buffer, blen);
|
||||
ADVANCE(written);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
|
||||
|
|
|
@ -138,7 +138,6 @@ enum ARMMnemonic {
|
|||
ARM_MN_BIC,
|
||||
ARM_MN_BKPT,
|
||||
ARM_MN_BL,
|
||||
ARM_MN_BLH,
|
||||
ARM_MN_BX,
|
||||
ARM_MN_CMN,
|
||||
ARM_MN_CMP,
|
||||
|
@ -203,6 +202,7 @@ struct ARMInstructionInfo {
|
|||
|
||||
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);
|
||||
void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info);
|
||||
bool ARMDecodeThumbCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2, struct ARMInstructionInfo* out);
|
||||
int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
|
|||
|
||||
static void _breakIntoDefault(int signal);
|
||||
static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode);
|
||||
static void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
|
||||
static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
|
||||
|
||||
static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||
{ "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
|
||||
|
@ -172,8 +172,7 @@ static void _disassembleMode(struct CLIDebugger* debugger, struct CLIDebugVector
|
|||
|
||||
int i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
_printLine(debugger, address, mode);
|
||||
address += wordSize;
|
||||
address += _printLine(debugger, address, mode);;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +237,7 @@ static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
||||
static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
||||
char disassembly[48];
|
||||
struct ARMInstructionInfo info;
|
||||
printf("%08X: ", address);
|
||||
|
@ -247,11 +246,23 @@ static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, en
|
|||
ARMDecodeARM(instruction, &info);
|
||||
ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly));
|
||||
printf("%08X\t%s\n", instruction, disassembly);
|
||||
return WORD_SIZE_ARM;
|
||||
} else {
|
||||
struct ARMInstructionInfo info2;
|
||||
struct ARMInstructionInfo combined;
|
||||
uint16_t instruction = debugger->d.cpu->memory.load16(debugger->d.cpu, address, 0);
|
||||
uint16_t instruction2 = debugger->d.cpu->memory.load16(debugger->d.cpu, address + WORD_SIZE_THUMB, 0);
|
||||
ARMDecodeThumb(instruction, &info);
|
||||
ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
|
||||
printf("%04X\t%s\n", instruction, disassembly);
|
||||
ARMDecodeThumb(instruction2, &info2);
|
||||
if (ARMDecodeThumbCombine(&info, &info2, &combined)) {
|
||||
ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
|
||||
printf("%04X %04X\t%s\n", instruction, instruction2, disassembly);
|
||||
return WORD_SIZE_THUMB * 2;
|
||||
} else {
|
||||
ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
|
||||
printf("%04X \t%s\n", instruction, disassembly);
|
||||
return WORD_SIZE_THUMB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue