mirror of https://github.com/mgba-emu/mgba.git
Begin work on ARM disassembler
This commit is contained in:
parent
ba4874f8b7
commit
a09d8649ee
|
@ -0,0 +1,417 @@
|
||||||
|
#include "decoder.h"
|
||||||
|
|
||||||
|
#include "arm.h"
|
||||||
|
#include "decoder-inlines.h"
|
||||||
|
#include "emitter-arm.h"
|
||||||
|
#include "isa-inlines.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_SHIFT(OP) \
|
||||||
|
info->op3.reg = opcode & 0x0000000F; \
|
||||||
|
info->op3.shifterOp = ARM_SHIFT_ ## OP; \
|
||||||
|
info->op3.shifterImm = (opcode >> 7) & 0x1F; \
|
||||||
|
info->operandFormat |= ARM_OPERAND_REGISTER_3 | \
|
||||||
|
ARM_OPERAND_SHIFT_IMMEDIATE_3;
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_SHIFTR(OP) \
|
||||||
|
info->op3.reg = opcode & 0x0000000F; \
|
||||||
|
info->op3.shifterOp = ARM_SHIFT_ ## OP; \
|
||||||
|
info->op3.shifterReg = (opcode >> 8) & 0xF; \
|
||||||
|
++info->iCycles; \
|
||||||
|
info->operandFormat |= ARM_OPERAND_REGISTER_3 | \
|
||||||
|
ARM_OPERAND_SHIFT_REGISTER_3;
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_LSL \
|
||||||
|
ADDR_MODE_1_SHIFT(LSL) \
|
||||||
|
if (!info->op3.shifterImm) { \
|
||||||
|
info->operandFormat &= ~ARM_OPERAND_SHIFT_REGISTER_3; \
|
||||||
|
info->op3.shifterOp = ARM_SHIFT_NONE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_LSR ADDR_MODE_1_SHIFT(LSR)
|
||||||
|
#define ADDR_MODE_1_ASR ADDR_MODE_1_SHIFT(ASR)
|
||||||
|
#define ADDR_MODE_1_ROR \
|
||||||
|
ADDR_MODE_1_SHIFT(ROR) \
|
||||||
|
if (!info->op3.shifterImm) { \
|
||||||
|
info->op3.shifterOp = ARM_SHIFT_RRX; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_LSLR ADDR_MODE_1_SHIFTR(LSL)
|
||||||
|
#define ADDR_MODE_1_LSRR ADDR_MODE_1_SHIFTR(LSR)
|
||||||
|
#define ADDR_MODE_1_ASRR ADDR_MODE_1_SHIFTR(ASR)
|
||||||
|
#define ADDR_MODE_1_RORR ADDR_MODE_1_SHIFTR(ROR)
|
||||||
|
|
||||||
|
#define ADDR_MODE_1_IMM \
|
||||||
|
int rotate = (opcode & 0x00000F00) >> 7; \
|
||||||
|
int immediate = opcode & 0x000000FF; \
|
||||||
|
info->op3.immediate = ARM_ROR(immediate, rotate); \
|
||||||
|
info->operandFormat |= ARM_OPERAND_IMMEDIATE_3;
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_SHIFT(OP) \
|
||||||
|
info->memory.format |= ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_SHIFTED_OFFSET; \
|
||||||
|
info->memory.offset.shifterOp = ARM_SHIFT_ ## OP; \
|
||||||
|
info->memory.offset.shifterImm = (opcode >> 7) & 0x1F; \
|
||||||
|
info->memory.offset.reg = opcode & 0x0000000F;
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_LSL \
|
||||||
|
ADDR_MODE_2_SHIFT(LSL) \
|
||||||
|
if (!info->memory.offset.shifterImm) { \
|
||||||
|
info->memory.format &= ~ARM_MEMORY_SHIFTED_OFFSET; \
|
||||||
|
info->memory.offset.shifterOp = ARM_SHIFT_NONE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_LSR ADDR_MODE_2_SHIFT(LSR) \
|
||||||
|
if (!info->memory.offset.shifterImm) { \
|
||||||
|
info->memory.offset.shifterImm = 32; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_ASR ADDR_MODE_2_SHIFT(ASR) \
|
||||||
|
if (!info->memory.offset.shifterImm) { \
|
||||||
|
info->memory.offset.shifterImm = 32; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_ROR \
|
||||||
|
ADDR_MODE_2_SHIFT(ROR) \
|
||||||
|
if (!info->memory.offset.shifterImm) { \
|
||||||
|
info->memory.offset.shifterOp = ARM_SHIFT_RRX; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDR_MODE_2_IMM \
|
||||||
|
info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
|
||||||
|
info->memory.offset.immediate = opcode & 0x00000FFF;
|
||||||
|
|
||||||
|
#define ADDR_MODE_3_REG \
|
||||||
|
info->memory.format |= ARM_MEMORY_REGISTER_OFFSET; \
|
||||||
|
info->memory.offset.reg = opcode & 0x0000000F;
|
||||||
|
|
||||||
|
#define ADDR_MODE_3_IMM \
|
||||||
|
info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
|
||||||
|
info->memory.offset.immediate = (opcode & 0x0000000F) | ((opcode & 0x00000F00) >> 4);
|
||||||
|
|
||||||
|
#define DEFINE_DECODER_ARM(NAME, MNEMONIC, BODY) \
|
||||||
|
static void _ARMDecode ## NAME (uint32_t opcode, struct ARMInstructionInfo* info) { \
|
||||||
|
UNUSED(opcode); \
|
||||||
|
info->mnemonic = ARM_MN_ ## MNEMONIC; \
|
||||||
|
BODY; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_ALU_DECODER_EX_ARM(NAME, MNEMONIC, S, SHIFTER, OTHER_AFFECTED) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, MNEMONIC, \
|
||||||
|
info->op1.reg = (opcode >> 12) & 0xF; \
|
||||||
|
info->op2.reg = (opcode >> 16) & 0xF; \
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||||
|
OTHER_AFFECTED | \
|
||||||
|
ARM_OPERAND_REGISTER_2; \
|
||||||
|
info->affectsCPSR = S; \
|
||||||
|
SHIFTER; \
|
||||||
|
if (info->op1.reg == ARM_PC) { \
|
||||||
|
info->branches = 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define DEFINE_ALU_DECODER_ARM(NAME) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 0, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSLR, NAME, 0, ADDR_MODE_1_LSLR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSLR, NAME, 1, ADDR_MODE_1_LSLR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 0, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSRR, NAME, 0, ADDR_MODE_1_LSRR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSRR, NAME, 1, ADDR_MODE_1_LSRR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 0, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASRR, NAME, 0, ADDR_MODE_1_ASRR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASRR, NAME, 1, ADDR_MODE_1_ASRR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 0, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _RORR, NAME, 0, ADDR_MODE_1_RORR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## S_RORR, NAME, 1, ADDR_MODE_1_RORR, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 0, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## SI, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1)
|
||||||
|
|
||||||
|
#define DEFINE_ALU_DECODER_S_ONLY_ARM(NAME) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSLR, NAME, 1, ADDR_MODE_1_LSLR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSRR, NAME, 1, ADDR_MODE_1_LSRR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASRR, NAME, 1, ADDR_MODE_1_ASRR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## _RORR, NAME, 1, ADDR_MODE_1_RORR, ARM_OPERAND_NONE) \
|
||||||
|
DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_NONE)
|
||||||
|
|
||||||
|
#define DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S, OTHER_AFFECTED) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, MNEMONIC, \
|
||||||
|
info->op1.reg = (opcode >> 16) & 0xF; \
|
||||||
|
info->op2.reg = opcode & 0xF; \
|
||||||
|
info->op3.reg = (opcode >> 8) & 0xF; \
|
||||||
|
info->op4.reg = (opcode >> 12) & 0xF; \
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||||
|
ARM_OPERAND_AFFECTED_1 | \
|
||||||
|
ARM_OPERAND_REGISTER_2 | \
|
||||||
|
ARM_OPERAND_REGISTER_3 | \
|
||||||
|
OTHER_AFFECTED; \
|
||||||
|
info->affectsCPSR = S; \
|
||||||
|
if (info->op1.reg == ARM_PC) { \
|
||||||
|
info->branches = 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, MNEMONIC, \
|
||||||
|
info->op1.reg = (opcode >> 12) & 0xF; \
|
||||||
|
info->op2.reg = (opcode >> 16) & 0xF; \
|
||||||
|
info->op3.reg = opcode & 0xF; \
|
||||||
|
info->op4.reg = (opcode >> 8) & 0xF; \
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||||
|
ARM_OPERAND_AFFECTED_1 | \
|
||||||
|
ARM_OPERAND_REGISTER_2 | \
|
||||||
|
ARM_OPERAND_AFFECTED_2 | \
|
||||||
|
ARM_OPERAND_REGISTER_3 | \
|
||||||
|
ARM_OPERAND_REGISTER_4; \
|
||||||
|
info->affectsCPSR = S; \
|
||||||
|
if (info->op1.reg == ARM_PC) { \
|
||||||
|
info->branches = 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define DEFINE_MULTIPLY_DECODER_ARM(NAME, OTHER_AFFECTED) \
|
||||||
|
DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0, OTHER_AFFECTED) \
|
||||||
|
DEFINE_MULTIPLY_DECODER_EX_ARM(NAME ## S, NAME, 1, OTHER_AFFECTED)
|
||||||
|
|
||||||
|
#define DEFINE_LONG_MULTIPLY_DECODER_ARM(NAME) \
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0) \
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME ## S, NAME, 1)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, ADDRESSING_MODE, ADDRESSING_DECODING, CYCLES, TYPE) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, MNEMONIC, \
|
||||||
|
info->op1.reg = (opcode >> 12) & 0xF; \
|
||||||
|
info->memory.baseReg = (opcode >> 16) & 0xF; \
|
||||||
|
info->memory.width = TYPE; \
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||||
|
ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
|
||||||
|
ARM_OPERAND_MEMORY_2; \
|
||||||
|
info->memory.format = ARM_MEMORY_REGISTER_BASE | ADDRESSING_MODE; \
|
||||||
|
ADDRESSING_DECODING; \
|
||||||
|
CYCLES;)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
|
||||||
|
ARM_MEMORY_POST_INCREMENT | \
|
||||||
|
ARM_MEMORY_WRITEBACK | \
|
||||||
|
ARM_MEMORY_OFFSET_SUBTRACT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \
|
||||||
|
ARM_MEMORY_POST_INCREMENT | \
|
||||||
|
ARM_MEMORY_WRITEBACK, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## P, MNEMONIC, \
|
||||||
|
ARM_MEMORY_PRE_INCREMENT | \
|
||||||
|
ARM_MEMORY_OFFSET_SUBTRACT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PW, MNEMONIC, \
|
||||||
|
ARM_MEMORY_PRE_INCREMENT | \
|
||||||
|
ARM_MEMORY_WRITEBACK | \
|
||||||
|
ARM_MEMORY_OFFSET_SUBTRACT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PU, MNEMONIC, \
|
||||||
|
ARM_MEMORY_PRE_INCREMENT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PUW, MNEMONIC, \
|
||||||
|
ARM_MEMORY_PRE_INCREMENT | \
|
||||||
|
ARM_MEMORY_WRITEBACK, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDR_MODE_3_REG, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_3_IMM, CYCLES, TYPE)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
|
||||||
|
ARM_MEMORY_POST_INCREMENT | \
|
||||||
|
ARM_MEMORY_OFFSET_SUBTRACT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \
|
||||||
|
ARM_MEMORY_POST_INCREMENT, \
|
||||||
|
ADDRESSING_MODE, CYCLES, TYPE)
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_T_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE) \
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE)
|
||||||
|
|
||||||
|
#define DECREMENT_AFTER uint32_t addr = cpu->gprs[rn]
|
||||||
|
#define INCREMENT_AFTER uint32_t addr = cpu->gprs[rn]
|
||||||
|
#define DECREMENT_BEFORE uint32_t addr = cpu->gprs[rn] - 4
|
||||||
|
#define INCREMENT_BEFORE uint32_t addr = cpu->gprs[rn] + 4
|
||||||
|
#define DECREMENT_AFTERW cpu->gprs[rn] = addr
|
||||||
|
#define INCREMENT_AFTERW cpu->gprs[rn] = addr
|
||||||
|
#define DECREMENT_BEFOREW cpu->gprs[rn] = addr + 4
|
||||||
|
#define INCREMENT_BEFOREW cpu->gprs[rn] = addr - 4
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME, MNEMONIC, DIRECTION, WRITEBACK) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, MNEMONIC, \
|
||||||
|
info->memory.baseReg = (opcode >> 16) & 0xF; \
|
||||||
|
info->op1.immediate = opcode & 0x0000FFFF; \
|
||||||
|
info->branches = info->op1.immediate & (1 << ARM_PC); \
|
||||||
|
info->operandFormat = ARM_OPERAND_MEMORY_1; \
|
||||||
|
info->memory.format = ARM_MEMORY_REGISTER_BASE | \
|
||||||
|
ARM_MEMORY_WRITEBACK | \
|
||||||
|
ARM_MEMORY_ ## DIRECTION;)
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DA, NAME, DECREMENT_AFTER, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DB, NAME, DECREMENT_BEFORE, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IA, NAME, INCREMENT_AFTER, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IB, NAME, INCREMENT_BEFORE, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDA, NAME, DECREMENT_AFTER, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDB, NAME, DECREMENT_BEFORE, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIA, NAME, INCREMENT_AFTER, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIB, NAME, INCREMENT_BEFORE, 0) \
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK)
|
||||||
|
|
||||||
|
#define DEFINE_SWP_DECODER_ARM(NAME, TYPE) \
|
||||||
|
DEFINE_DECODER_ARM(NAME, SWP, \
|
||||||
|
info->memory.baseReg = (opcode >> 16) & 0xF; \
|
||||||
|
info->op1.reg = (opcode >> 12) & 0xF; \
|
||||||
|
info->op2.reg = opcode & 0xF; \
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||||
|
ARM_OPERAND_AFFECTED_1 | \
|
||||||
|
ARM_OPERAND_REGISTER_2 | \
|
||||||
|
ARM_OPERAND_MEMORY_3; \
|
||||||
|
info->memory.format = ARM_MEMORY_REGISTER_BASE; \
|
||||||
|
info->memory.width = TYPE;)
|
||||||
|
|
||||||
|
DEFINE_ALU_DECODER_ARM(ADD)
|
||||||
|
DEFINE_ALU_DECODER_ARM(ADC)
|
||||||
|
DEFINE_ALU_DECODER_ARM(AND)
|
||||||
|
DEFINE_ALU_DECODER_ARM(BIC)
|
||||||
|
DEFINE_ALU_DECODER_S_ONLY_ARM(CMN)
|
||||||
|
DEFINE_ALU_DECODER_S_ONLY_ARM(CMP)
|
||||||
|
DEFINE_ALU_DECODER_ARM(EOR)
|
||||||
|
DEFINE_ALU_DECODER_ARM(MOV)
|
||||||
|
DEFINE_ALU_DECODER_ARM(MVN)
|
||||||
|
DEFINE_ALU_DECODER_ARM(ORR)
|
||||||
|
DEFINE_ALU_DECODER_ARM(RSB)
|
||||||
|
DEFINE_ALU_DECODER_ARM(RSC)
|
||||||
|
DEFINE_ALU_DECODER_ARM(SBC)
|
||||||
|
DEFINE_ALU_DECODER_ARM(SUB)
|
||||||
|
DEFINE_ALU_DECODER_S_ONLY_ARM(TEQ)
|
||||||
|
DEFINE_ALU_DECODER_S_ONLY_ARM(TST)
|
||||||
|
|
||||||
|
// TOOD: Estimate cycles
|
||||||
|
DEFINE_MULTIPLY_DECODER_ARM(MLA, ARM_OPERAND_REGISTER_4)
|
||||||
|
DEFINE_MULTIPLY_DECODER_ARM(MUL, ARM_OPERAND_NONE)
|
||||||
|
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_ARM(SMLAL)
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_ARM(SMULL)
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_ARM(UMLAL)
|
||||||
|
DEFINE_LONG_MULTIPLY_DECODER_ARM(UMULL)
|
||||||
|
|
||||||
|
// Begin load/store definitions
|
||||||
|
|
||||||
|
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDR, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
|
||||||
|
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRB, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
|
||||||
|
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
|
||||||
|
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
|
||||||
|
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
|
||||||
|
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STR, STR, STORE_CYCLES, ARM_ACCESS_WORD)
|
||||||
|
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STRB, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
|
||||||
|
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
|
||||||
|
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_BYTE)
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_ARM(LDRT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_WORD)
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_BYTE)
|
||||||
|
DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_WORD)
|
||||||
|
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(LDM)
|
||||||
|
DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(STM)
|
||||||
|
|
||||||
|
DEFINE_SWP_DECODER_ARM(SWP, ARM_ACCESS_WORD)
|
||||||
|
DEFINE_SWP_DECODER_ARM(SWPB, ARM_ACCESS_BYTE)
|
||||||
|
|
||||||
|
// End load/store definitions
|
||||||
|
|
||||||
|
// Begin branch definitions
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(B, B,
|
||||||
|
int32_t offset = opcode << 8;
|
||||||
|
info->op1.immediate = offset >> 6;
|
||||||
|
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||||
|
info->branches = 1;)
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(BL, BL,
|
||||||
|
int32_t offset = opcode << 8;
|
||||||
|
info->op1.immediate = offset >> 6;
|
||||||
|
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||||
|
info->branches = 1;)
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(BX, BX,
|
||||||
|
info->op1.reg = opcode & 0x0000000F;
|
||||||
|
info->operandFormat = ARM_OPERAND_REGISTER_1;
|
||||||
|
info->branches = 1;)
|
||||||
|
|
||||||
|
// End branch definitions
|
||||||
|
|
||||||
|
// Begin coprocessor definitions
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(CDP, ILL,)
|
||||||
|
DEFINE_DECODER_ARM(LDC, ILL,)
|
||||||
|
DEFINE_DECODER_ARM(STC, ILL,)
|
||||||
|
DEFINE_DECODER_ARM(MCR, ILL,)
|
||||||
|
DEFINE_DECODER_ARM(MRC, ILL,)
|
||||||
|
|
||||||
|
// Begin miscellaneous definitions
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(BKPT, BKPT,) // Not strictly in ARMv4T, but here for convenience
|
||||||
|
DEFINE_DECODER_ARM(ILL, ILL,) // Illegal opcode
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(MSR, MSR, info->affectsCPSR = 1;)
|
||||||
|
DEFINE_DECODER_ARM(MSRR, MSR, info->affectsCPSR = 1;)
|
||||||
|
DEFINE_DECODER_ARM(MRS, MRS, info->affectsCPSR = 1;)
|
||||||
|
DEFINE_DECODER_ARM(MRSR, MRS, info->affectsCPSR = 1;)
|
||||||
|
DEFINE_DECODER_ARM(MSRI, MSR, info->affectsCPSR = 1;)
|
||||||
|
DEFINE_DECODER_ARM(MSRRI, MSR, info->affectsCPSR = 1;)
|
||||||
|
|
||||||
|
DEFINE_DECODER_ARM(SWI, SWI,
|
||||||
|
info->op1.immediate = opcode & 0xFFFFFF;
|
||||||
|
info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
|
||||||
|
info->traps = 1;)
|
||||||
|
|
||||||
|
typedef void (*ARMDecoder)(uint32_t opcode, struct ARMInstructionInfo* info);
|
||||||
|
|
||||||
|
static const ARMDecoder _armDecoderTable[0x1000] = {
|
||||||
|
DECLARE_ARM_EMITTER_BLOCK(_ARMDecode)
|
||||||
|
};
|
||||||
|
|
||||||
|
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info) {
|
||||||
|
info->opcode = opcode;
|
||||||
|
info->branches = 0;
|
||||||
|
info->traps = 0;
|
||||||
|
info->affectsCPSR = 0;
|
||||||
|
info->condition = opcode >> 28;
|
||||||
|
info->sDataCycles = 0;
|
||||||
|
info->nDataCycles = 0;
|
||||||
|
info->sInstructionCycles = 1;
|
||||||
|
info->nInstructionCycles = 0;
|
||||||
|
info->iCycles = 0;
|
||||||
|
info->cCycles = 0;
|
||||||
|
ARMDecoder decoder = _armDecoderTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
|
||||||
|
decoder(opcode, info);
|
||||||
|
}
|
|
@ -8,15 +8,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define ADVANCE(AMOUNT) \
|
|
||||||
if (AMOUNT > blen) { \
|
|
||||||
buffer[blen - 1] = '\0'; \
|
|
||||||
return total; \
|
|
||||||
} \
|
|
||||||
total += AMOUNT; \
|
|
||||||
buffer += AMOUNT; \
|
|
||||||
blen -= AMOUNT;
|
|
||||||
|
|
||||||
#define LOAD_CYCLES \
|
#define LOAD_CYCLES \
|
||||||
info->iCycles = 1; \
|
info->iCycles = 1; \
|
||||||
info->nDataCycles = 1;
|
info->nDataCycles = 1;
|
||||||
|
@ -26,152 +17,4 @@
|
||||||
info->nInstructionCycles = 1; \
|
info->nInstructionCycles = 1; \
|
||||||
info->nDataCycles = 1;
|
info->nDataCycles = 1;
|
||||||
|
|
||||||
static int _decodeRegister(int reg, char* buffer, int blen);
|
|
||||||
static int _decodeRegisterList(int list, char* buffer, int blen);
|
|
||||||
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
|
|
||||||
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
|
|
||||||
|
|
||||||
static const char* _armConditions[] = {
|
|
||||||
"eq",
|
|
||||||
"ne",
|
|
||||||
"cs",
|
|
||||||
"cc",
|
|
||||||
"mi",
|
|
||||||
"pl",
|
|
||||||
"vs",
|
|
||||||
"vc",
|
|
||||||
"hi",
|
|
||||||
"ls",
|
|
||||||
"ge",
|
|
||||||
"lt",
|
|
||||||
"gt",
|
|
||||||
"le",
|
|
||||||
"al",
|
|
||||||
"nv"
|
|
||||||
};
|
|
||||||
|
|
||||||
static int _decodeRegister(int reg, char* buffer, int blen) {
|
|
||||||
switch (reg) {
|
|
||||||
case ARM_SP:
|
|
||||||
strncpy(buffer, "sp", blen - 1);
|
|
||||||
return 2;
|
|
||||||
case ARM_LR:
|
|
||||||
strncpy(buffer, "lr", blen - 1);
|
|
||||||
return 2;
|
|
||||||
case ARM_PC:
|
|
||||||
strncpy(buffer, "pc", blen - 1);
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
return snprintf(buffer, blen - 1, "r%i", reg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _decodeRegisterList(int list, char* buffer, int blen) {
|
|
||||||
if (blen <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int total = 0;
|
|
||||||
strncpy(buffer, "{", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
int i;
|
|
||||||
int start = -1;
|
|
||||||
int end = -1;
|
|
||||||
int written;
|
|
||||||
for (i = 0; i <= ARM_PC; ++i) {
|
|
||||||
if (list & 1) {
|
|
||||||
if (start < 0) {
|
|
||||||
start = i;
|
|
||||||
end = i;
|
|
||||||
} else if (end + 1 == i) {
|
|
||||||
end = i;
|
|
||||||
} else {
|
|
||||||
if (end > start) {
|
|
||||||
written = _decodeRegister(start, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
strncpy(buffer, "-", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
written = _decodeRegister(end, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
strncpy(buffer, ",", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
start = i;
|
|
||||||
end = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list >>= 1;
|
|
||||||
}
|
|
||||||
if (start >= 0) {
|
|
||||||
if (end > start) {
|
|
||||||
written = _decodeRegister(start, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
strncpy(buffer, "-", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
written = _decodeRegister(end, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
strncpy(buffer, "}", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
|
|
||||||
return snprintf(buffer, blen - 1, "$%08X", address + pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
|
|
||||||
if (blen <= 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int total = 0;
|
|
||||||
strncpy(buffer, "[", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
int written;
|
|
||||||
if (memory.format & ARM_MEMORY_REGISTER_BASE) {
|
|
||||||
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 - 1);
|
|
||||||
ADVANCE(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (memory.format & ARM_MEMORY_POST_INCREMENT) {
|
|
||||||
strncpy(buffer, "], ", blen - 1);
|
|
||||||
ADVANCE(3);
|
|
||||||
}
|
|
||||||
if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
|
|
||||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
|
||||||
written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else {
|
|
||||||
written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
|
|
||||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
|
||||||
strncpy(buffer, "-", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
written = _decodeRegister(memory.offset.reg, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
// TODO: shifted registers
|
|
||||||
|
|
||||||
if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
|
||||||
strncpy(buffer, "]", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
if (memory.format & ARM_MEMORY_PRE_INCREMENT) {
|
|
||||||
strncpy(buffer, "!", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -326,158 +326,3 @@ void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
|
||||||
ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
|
ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
|
||||||
decoder(opcode, info);
|
decoder(opcode, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* armMnemonicStrings[] = {
|
|
||||||
"ill",
|
|
||||||
"adc",
|
|
||||||
"add",
|
|
||||||
"and",
|
|
||||||
"asr",
|
|
||||||
"b",
|
|
||||||
"bic",
|
|
||||||
"bkpt",
|
|
||||||
"bl",
|
|
||||||
"blh",
|
|
||||||
"bx",
|
|
||||||
"cmn",
|
|
||||||
"cmp",
|
|
||||||
"eor",
|
|
||||||
"ldm",
|
|
||||||
"ldr",
|
|
||||||
"lsl",
|
|
||||||
"lsr",
|
|
||||||
"mla",
|
|
||||||
"mov",
|
|
||||||
"mul",
|
|
||||||
"mvn",
|
|
||||||
"neg",
|
|
||||||
"orr",
|
|
||||||
"ror",
|
|
||||||
"rsb",
|
|
||||||
"rsc",
|
|
||||||
"sbc",
|
|
||||||
"smlal",
|
|
||||||
"smull"
|
|
||||||
"stm",
|
|
||||||
"str",
|
|
||||||
"sub",
|
|
||||||
"swi",
|
|
||||||
"teq",
|
|
||||||
"tst",
|
|
||||||
"umlal",
|
|
||||||
"umull",
|
|
||||||
|
|
||||||
"ill"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* armDirectionStrings[] = {
|
|
||||||
"da",
|
|
||||||
"ia",
|
|
||||||
"db",
|
|
||||||
"da"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* armAccessTypeStrings[] = {
|
|
||||||
"",
|
|
||||||
"b",
|
|
||||||
"h",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"sb",
|
|
||||||
"sh",
|
|
||||||
""
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
|
|
||||||
struct ARMInstructionInfo info;
|
|
||||||
ARMDecodeThumb(opcode, &info);
|
|
||||||
const char* mnemonic = armMnemonicStrings[info.mnemonic];
|
|
||||||
int written;
|
|
||||||
int total = 0;
|
|
||||||
const char* cond = "";
|
|
||||||
if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) {
|
|
||||||
cond = _armConditions[info.condition];
|
|
||||||
}
|
|
||||||
const char* flags = "";
|
|
||||||
switch (info.mnemonic) {
|
|
||||||
case ARM_MN_LDM:
|
|
||||||
case ARM_MN_STM:
|
|
||||||
flags = armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info.memory.format)];
|
|
||||||
break;
|
|
||||||
case ARM_MN_LDR:
|
|
||||||
case ARM_MN_STR:
|
|
||||||
flags = armAccessTypeStrings[info.memory.width];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, flags, cond);
|
|
||||||
ADVANCE(written);
|
|
||||||
|
|
||||||
switch (info.mnemonic) {
|
|
||||||
case ARM_MN_LDM:
|
|
||||||
case ARM_MN_STM:
|
|
||||||
written = _decodeRegister(info.memory.baseReg, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
if (info.memory.format & ARM_MEMORY_WRITEBACK) {
|
|
||||||
strncpy(buffer, "!", blen - 1);
|
|
||||||
ADVANCE(1);
|
|
||||||
}
|
|
||||||
strncpy(buffer, ", ", blen - 1);
|
|
||||||
ADVANCE(2);
|
|
||||||
written = _decodeRegisterList(info.op1.immediate, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
break;
|
|
||||||
case ARM_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 - 1, "#%i", info.op1.immediate);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_MEMORY_1) {
|
|
||||||
written = _decodeMemory(info.memory, pc, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_REGISTER_1) {
|
|
||||||
written = _decodeRegister(info.op1.reg, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
if (info.operandFormat & ARM_OPERAND_2) {
|
|
||||||
strncpy(buffer, ", ", blen);
|
|
||||||
ADVANCE(2);
|
|
||||||
}
|
|
||||||
if (info.operandFormat & ARM_OPERAND_IMMEDIATE_2) {
|
|
||||||
written = snprintf(buffer, blen - 1, "#%i", info.op2.immediate);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
|
|
||||||
written = _decodeMemory(info.memory, pc, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_REGISTER_2) {
|
|
||||||
written = _decodeRegister(info.op2.reg, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
if (info.operandFormat & ARM_OPERAND_3) {
|
|
||||||
strncpy(buffer, ", ", blen - 1);
|
|
||||||
ADVANCE(2);
|
|
||||||
}
|
|
||||||
if (info.operandFormat & ARM_OPERAND_IMMEDIATE_3) {
|
|
||||||
written = snprintf(buffer, blen - 1, "#%i", info.op3.immediate);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_MEMORY_3) {
|
|
||||||
written = _decodeMemory(info.memory, pc, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
} else if (info.operandFormat & ARM_OPERAND_REGISTER_3) {
|
|
||||||
written = _decodeRegister(info.op1.reg, buffer, blen);
|
|
||||||
ADVANCE(written);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buffer[blen - 1] = '\0';
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,327 @@
|
||||||
|
#include "decoder.h"
|
||||||
|
|
||||||
|
#include "decoder-inlines.h"
|
||||||
|
|
||||||
|
#define ADVANCE(AMOUNT) \
|
||||||
|
if (AMOUNT > blen) { \
|
||||||
|
buffer[blen - 1] = '\0'; \
|
||||||
|
return total; \
|
||||||
|
} \
|
||||||
|
total += AMOUNT; \
|
||||||
|
buffer += AMOUNT; \
|
||||||
|
blen -= AMOUNT;
|
||||||
|
|
||||||
|
static int _decodeRegister(int reg, char* buffer, int blen);
|
||||||
|
static int _decodeRegisterList(int list, char* buffer, int blen);
|
||||||
|
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
|
||||||
|
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
|
||||||
|
|
||||||
|
static const char* _armConditions[] = {
|
||||||
|
"eq",
|
||||||
|
"ne",
|
||||||
|
"cs",
|
||||||
|
"cc",
|
||||||
|
"mi",
|
||||||
|
"pl",
|
||||||
|
"vs",
|
||||||
|
"vc",
|
||||||
|
"hi",
|
||||||
|
"ls",
|
||||||
|
"ge",
|
||||||
|
"lt",
|
||||||
|
"gt",
|
||||||
|
"le",
|
||||||
|
"al",
|
||||||
|
"nv"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _decodeRegister(int reg, char* buffer, int blen) {
|
||||||
|
switch (reg) {
|
||||||
|
case ARM_SP:
|
||||||
|
strncpy(buffer, "sp", blen - 1);
|
||||||
|
return 2;
|
||||||
|
case ARM_LR:
|
||||||
|
strncpy(buffer, "lr", blen - 1);
|
||||||
|
return 2;
|
||||||
|
case ARM_PC:
|
||||||
|
strncpy(buffer, "pc", blen - 1);
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return snprintf(buffer, blen - 1, "r%i", reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _decodeRegisterList(int list, char* buffer, int blen) {
|
||||||
|
if (blen <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int total = 0;
|
||||||
|
strncpy(buffer, "{", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
int i;
|
||||||
|
int start = -1;
|
||||||
|
int end = -1;
|
||||||
|
int written;
|
||||||
|
for (i = 0; i <= ARM_PC; ++i) {
|
||||||
|
if (list & 1) {
|
||||||
|
if (start < 0) {
|
||||||
|
start = i;
|
||||||
|
end = i;
|
||||||
|
} else if (end + 1 == i) {
|
||||||
|
end = i;
|
||||||
|
} else {
|
||||||
|
if (end > start) {
|
||||||
|
written = _decodeRegister(start, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
strncpy(buffer, "-", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
written = _decodeRegister(end, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
strncpy(buffer, ",", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
start = i;
|
||||||
|
end = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list >>= 1;
|
||||||
|
}
|
||||||
|
if (start >= 0) {
|
||||||
|
if (end > start) {
|
||||||
|
written = _decodeRegister(start, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
strncpy(buffer, "-", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
written = _decodeRegister(end, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
strncpy(buffer, "}", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
|
||||||
|
return snprintf(buffer, blen - 1, "$%08X", address + pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
|
||||||
|
if (blen <= 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int total = 0;
|
||||||
|
strncpy(buffer, "[", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
int written;
|
||||||
|
if (memory.format & ARM_MEMORY_REGISTER_BASE) {
|
||||||
|
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 - 1);
|
||||||
|
ADVANCE(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (memory.format & ARM_MEMORY_POST_INCREMENT) {
|
||||||
|
strncpy(buffer, "], ", blen - 1);
|
||||||
|
ADVANCE(3);
|
||||||
|
}
|
||||||
|
if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
|
||||||
|
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||||
|
written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else {
|
||||||
|
written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
|
||||||
|
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||||
|
strncpy(buffer, "-", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
written = _decodeRegister(memory.offset.reg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
// TODO: shifted registers
|
||||||
|
|
||||||
|
if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
||||||
|
strncpy(buffer, "]", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
if ((memory.format & (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) == (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) {
|
||||||
|
strncpy(buffer, "!", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* _armMnemonicStrings[] = {
|
||||||
|
"ill",
|
||||||
|
"adc",
|
||||||
|
"add",
|
||||||
|
"and",
|
||||||
|
"asr",
|
||||||
|
"b",
|
||||||
|
"bic",
|
||||||
|
"bkpt",
|
||||||
|
"bl",
|
||||||
|
"blh",
|
||||||
|
"bx",
|
||||||
|
"cmn",
|
||||||
|
"cmp",
|
||||||
|
"eor",
|
||||||
|
"ldm",
|
||||||
|
"ldr",
|
||||||
|
"lsl",
|
||||||
|
"lsr",
|
||||||
|
"mla",
|
||||||
|
"mov",
|
||||||
|
"mrs",
|
||||||
|
"msr",
|
||||||
|
"mul",
|
||||||
|
"mvn",
|
||||||
|
"neg",
|
||||||
|
"orr",
|
||||||
|
"ror",
|
||||||
|
"rsb",
|
||||||
|
"rsc",
|
||||||
|
"sbc",
|
||||||
|
"smlal",
|
||||||
|
"smull",
|
||||||
|
"stm",
|
||||||
|
"str",
|
||||||
|
"sub",
|
||||||
|
"swi",
|
||||||
|
"swp",
|
||||||
|
"teq",
|
||||||
|
"tst",
|
||||||
|
"umlal",
|
||||||
|
"umull",
|
||||||
|
|
||||||
|
"ill"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* _armDirectionStrings[] = {
|
||||||
|
"da",
|
||||||
|
"ia",
|
||||||
|
"db",
|
||||||
|
"da"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* _armAccessTypeStrings[] = {
|
||||||
|
"",
|
||||||
|
"b",
|
||||||
|
"h",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"sb",
|
||||||
|
"sh",
|
||||||
|
""
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen) {
|
||||||
|
const char* mnemonic = _armMnemonicStrings[info->mnemonic];
|
||||||
|
int written;
|
||||||
|
int total = 0;
|
||||||
|
const char* cond = "";
|
||||||
|
if (info->condition != ARM_CONDITION_AL && info->condition < ARM_CONDITION_NV) {
|
||||||
|
cond = _armConditions[info->condition];
|
||||||
|
}
|
||||||
|
const char* flags = "";
|
||||||
|
switch (info->mnemonic) {
|
||||||
|
case ARM_MN_LDM:
|
||||||
|
case ARM_MN_STM:
|
||||||
|
flags = _armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info->memory.format)];
|
||||||
|
break;
|
||||||
|
case ARM_MN_LDR:
|
||||||
|
case ARM_MN_STR:
|
||||||
|
case ARM_MN_SWP:
|
||||||
|
flags = _armAccessTypeStrings[info->memory.width];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, flags, cond);
|
||||||
|
ADVANCE(written);
|
||||||
|
|
||||||
|
switch (info->mnemonic) {
|
||||||
|
case ARM_MN_LDM:
|
||||||
|
case ARM_MN_STM:
|
||||||
|
written = _decodeRegister(info->memory.baseReg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
if (info->memory.format & ARM_MEMORY_WRITEBACK) {
|
||||||
|
strncpy(buffer, "!", blen - 1);
|
||||||
|
ADVANCE(1);
|
||||||
|
}
|
||||||
|
strncpy(buffer, ", ", blen - 1);
|
||||||
|
ADVANCE(2);
|
||||||
|
written = _decodeRegisterList(info->op1.immediate, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
break;
|
||||||
|
case ARM_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 - 1, "#%i", info->op1.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_MEMORY_1) {
|
||||||
|
written = _decodeMemory(info->memory, pc, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_REGISTER_1) {
|
||||||
|
written = _decodeRegister(info->op1.reg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
if (info->operandFormat & ARM_OPERAND_2) {
|
||||||
|
strncpy(buffer, ", ", blen);
|
||||||
|
ADVANCE(2);
|
||||||
|
}
|
||||||
|
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {
|
||||||
|
written = snprintf(buffer, blen - 1, "#%i", info->op2.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_MEMORY_2) {
|
||||||
|
written = _decodeMemory(info->memory, pc, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_REGISTER_2) {
|
||||||
|
written = _decodeRegister(info->op2.reg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
if (info->operandFormat & ARM_OPERAND_3) {
|
||||||
|
strncpy(buffer, ", ", blen - 1);
|
||||||
|
ADVANCE(2);
|
||||||
|
}
|
||||||
|
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {
|
||||||
|
written = snprintf(buffer, blen - 1, "#%i", info->op3.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_MEMORY_3) {
|
||||||
|
written = _decodeMemory(info->memory, pc, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_REGISTER_3) {
|
||||||
|
written = _decodeRegister(info->op3.reg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {
|
||||||
|
written = snprintf(buffer, blen - 1, "#%i", info->op4.immediate);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_MEMORY_4) {
|
||||||
|
written = _decodeMemory(info->memory, pc, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
} else if (info->operandFormat & ARM_OPERAND_REGISTER_4) {
|
||||||
|
written = _decodeRegister(info->op4.reg, buffer, blen);
|
||||||
|
ADVANCE(written);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer[blen - 1] = '\0';
|
||||||
|
return total;
|
||||||
|
}
|
|
@ -106,7 +106,9 @@ enum ARMMemoryAccessType {
|
||||||
ARM_ACCESS_HALFWORD = 2,
|
ARM_ACCESS_HALFWORD = 2,
|
||||||
ARM_ACCESS_SIGNED_HALFWORD = 10,
|
ARM_ACCESS_SIGNED_HALFWORD = 10,
|
||||||
ARM_ACCESS_BYTE = 1,
|
ARM_ACCESS_BYTE = 1,
|
||||||
ARM_ACCESS_SIGNED_BYTE = 9
|
ARM_ACCESS_SIGNED_BYTE = 9,
|
||||||
|
ARM_ACCESS_TRANSLATED_WORD = 20,
|
||||||
|
ARM_ACCESS_TRANSLATED_BYTE = 17
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ARMMemoryAccess {
|
struct ARMMemoryAccess {
|
||||||
|
@ -137,6 +139,8 @@ enum ARMMnemonic {
|
||||||
ARM_MN_LSR,
|
ARM_MN_LSR,
|
||||||
ARM_MN_MLA,
|
ARM_MN_MLA,
|
||||||
ARM_MN_MOV,
|
ARM_MN_MOV,
|
||||||
|
ARM_MN_MRS,
|
||||||
|
ARM_MN_MSR,
|
||||||
ARM_MN_MUL,
|
ARM_MN_MUL,
|
||||||
ARM_MN_MVN,
|
ARM_MN_MVN,
|
||||||
ARM_MN_NEG,
|
ARM_MN_NEG,
|
||||||
|
@ -151,6 +155,7 @@ enum ARMMnemonic {
|
||||||
ARM_MN_STR,
|
ARM_MN_STR,
|
||||||
ARM_MN_SUB,
|
ARM_MN_SUB,
|
||||||
ARM_MN_SWI,
|
ARM_MN_SWI,
|
||||||
|
ARM_MN_SWP,
|
||||||
ARM_MN_TEQ,
|
ARM_MN_TEQ,
|
||||||
ARM_MN_TST,
|
ARM_MN_TST,
|
||||||
ARM_MN_UMLAL,
|
ARM_MN_UMLAL,
|
||||||
|
@ -180,7 +185,8 @@ struct ARMInstructionInfo {
|
||||||
int cCycles;
|
int cCycles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);
|
||||||
void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info);
|
void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info);
|
||||||
int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen);
|
int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -138,13 +138,17 @@ static void _printHex(struct CLIDebugger* debugger, struct DebugVector* dv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
||||||
char disassembly[32];
|
char disassembly[48];
|
||||||
|
struct ARMInstructionInfo info;
|
||||||
if (mode == MODE_ARM) {
|
if (mode == MODE_ARM) {
|
||||||
uint32_t instruction = debugger->d.cpu->memory->load32(debugger->d.cpu->memory, address, 0);
|
uint32_t instruction = debugger->d.cpu->memory->load32(debugger->d.cpu->memory, address, 0);
|
||||||
printf("%08X\n", instruction);
|
ARMDecodeARM(instruction, &info);
|
||||||
|
ARMDisassemble(&info, debugger->d.cpu->gprs[ARM_PC] + WORD_SIZE_ARM, disassembly, sizeof(disassembly));
|
||||||
|
printf("%08X: %s\n", instruction, disassembly);
|
||||||
} 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, debugger->d.cpu->gprs[ARM_PC] + WORD_SIZE_THUMB, disassembly, sizeof(disassembly));
|
ARMDecodeThumb(instruction, &info);
|
||||||
|
ARMDisassemble(&info, 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