From d6ac0dc6f526ac111c4e750e282050c034724b76 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 4 Mar 2019 18:28:27 -0800 Subject: [PATCH] LR35902: Support PC-relative opcode decoding --- CHANGES | 1 + include/mgba/internal/lr35902/decoder.h | 3 ++- src/lr35902/decoder.c | 16 +++++++++++----- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 962e2e6a2..c5c787633 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Misc: - Qt: Don't unload ROM immediately if it crashes - Debugger: Add breakpoint and watchpoint listing - Qt: Add missing HEVC NVENC option (fixes mgba.io/i/1323) + - LR35902: Support PC-relative opcode decoding 0.7.1: (2019-02-24) Bugfixes: diff --git a/include/mgba/internal/lr35902/decoder.h b/include/mgba/internal/lr35902/decoder.h index 101a104c3..ba9ceec36 100644 --- a/include/mgba/internal/lr35902/decoder.h +++ b/include/mgba/internal/lr35902/decoder.h @@ -86,6 +86,7 @@ enum { LR35902_OP_FLAG_MEMORY = 2, LR35902_OP_FLAG_INCREMENT = 4, LR35902_OP_FLAG_DECREMENT = 8, + LR35902_OP_FLAG_RELATIVE = 16, }; struct LR35902Operand { @@ -104,7 +105,7 @@ struct LR35902InstructionInfo { }; size_t LR35902Decode(uint8_t opcode, struct LR35902InstructionInfo* info); -int LR35902Disassemble(struct LR35902InstructionInfo* info, char* buffer, int blen); +int LR35902Disassemble(struct LR35902InstructionInfo* info, uint16_t pc, char* buffer, int blen); CXX_GUARD_END diff --git a/src/lr35902/decoder.c b/src/lr35902/decoder.c index 76c6b9f02..089b52c69 100644 --- a/src/lr35902/decoder.c +++ b/src/lr35902/decoder.c @@ -199,6 +199,7 @@ DEFINE_DECODER_LR35902(ADDSP, info->mnemonic = LR35902_MN_ADD; \ DEFINE_DECODER_LR35902(JR ## CONDITION_NAME, \ info->mnemonic = LR35902_MN_JR; \ info->condition = CONDITION; \ + info->op1.flags = LR35902_OP_FLAG_RELATIVE; \ return 1;) #define DEFINE_CALL_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \ @@ -497,7 +498,7 @@ static const char* _lr35902MnemonicStrings[] = { }; -static int _decodeOperand(struct LR35902Operand op, char* buffer, int blen) { +static int _decodeOperand(struct LR35902Operand op, uint16_t pc, char* buffer, int blen) { int total = 0; if (op.flags & LR35902_OP_FLAG_IMPLICIT) { return 0; @@ -511,7 +512,12 @@ static int _decodeOperand(struct LR35902Operand op, char* buffer, int blen) { int written = snprintf(buffer, blen - 1, "%s", _lr35902Registers[op.reg]); ADVANCE(written); } else { - int written = snprintf(buffer, blen - 1, "$%02X", op.immediate); + int written; + if (op.flags & LR35902_OP_FLAG_RELATIVE) { + written = snprintf(buffer, blen - 1, "$%04X", pc + (int8_t) op.immediate); + } else { + written = snprintf(buffer, blen - 1, "$%02X", op.immediate); + } ADVANCE(written); if (op.reg) { strncpy(buffer, "+", blen - 1); @@ -533,7 +539,7 @@ static int _decodeOperand(struct LR35902Operand op, char* buffer, int blen) { return total; } -int LR35902Disassemble(struct LR35902InstructionInfo* info, char* buffer, int blen) { +int LR35902Disassemble(struct LR35902InstructionInfo* info, uint16_t pc, char* buffer, int blen) { const char* mnemonic = _lr35902MnemonicStrings[info->mnemonic]; int written; int total = 0; @@ -553,7 +559,7 @@ int LR35902Disassemble(struct LR35902InstructionInfo* info, char* buffer, int bl } if (info->op1.reg || info->op1.immediate || info->op2.reg || info->op2.immediate) { - written = _decodeOperand(info->op1, buffer, blen); + written = _decodeOperand(info->op1, pc, buffer, blen); ADVANCE(written); } @@ -562,7 +568,7 @@ int LR35902Disassemble(struct LR35902InstructionInfo* info, char* buffer, int bl strncpy(buffer, ", ", blen - 1); ADVANCE(2); } - written = _decodeOperand(info->op2, buffer, blen); + written = _decodeOperand(info->op2, pc, buffer, blen); ADVANCE(written); }