all repos — mgba @ a09d8649ee508e87e3d9629f2116b5c6528416ba

mGBA Game Boy Advance Emulator

Begin work on ARM disassembler
Jeffrey Pfau jeffrey@endrift.com
Fri, 11 Jul 2014 03:50:29 -0700
commit

a09d8649ee508e87e3d9629f2116b5c6528416ba

parent

ba4874f8b7f19b6c843a0d6ada709408452c8c0e

A src/arm/decoder-arm.c

@@ -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); +}
M src/arm/decoder-inlines.hsrc/arm/decoder-inlines.h

@@ -8,15 +8,6 @@

#include <stdio.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 \ info->iCycles = 1; \ info->nDataCycles = 1;

@@ -25,153 +16,5 @@ #define STORE_CYCLES \

info->sInstructionCycles = 0; \ info->nInstructionCycles = 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
M src/arm/decoder-thumb.csrc/arm/decoder-thumb.c

@@ -326,158 +326,3 @@ info->cCycles = 0;

ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6]; 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; -}
A src/arm/decoder.c

@@ -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; +}
M src/arm/decoder.hsrc/arm/decoder.h

@@ -106,7 +106,9 @@ ARM_ACCESS_WORD = 4,

ARM_ACCESS_HALFWORD = 2, ARM_ACCESS_SIGNED_HALFWORD = 10, 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 {

@@ -137,6 +139,8 @@ ARM_MN_LSL,

ARM_MN_LSR, ARM_MN_MLA, ARM_MN_MOV, + ARM_MN_MRS, + ARM_MN_MSR, ARM_MN_MUL, ARM_MN_MVN, ARM_MN_NEG,

@@ -151,6 +155,7 @@ ARM_MN_STM,

ARM_MN_STR, ARM_MN_SUB, ARM_MN_SWI, + ARM_MN_SWP, ARM_MN_TEQ, ARM_MN_TST, ARM_MN_UMLAL,

@@ -180,7 +185,8 @@ int iCycles;

int cCycles; }; +void ARMDecodeARM(uint32_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
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -138,13 +138,17 @@ printf("\n");

} 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) { 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 { 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); } }