all repos — mgba @ aefa5f0ab8511dd2f72d3ded479327268072e536

mGBA Game Boy Advance Emulator

Merge branch 'decoder'

Conflicts:
	src/debugger/cli-debugger.c
Jeffrey Pfau jeffrey@endrift.com
Sat, 12 Jul 2014 00:40:40 -0700
commit

aefa5f0ab8511dd2f72d3ded479327268072e536

parent

6c1476403ef5b90bedef9840d7ef08244eaac37b

A src/arm/decoder-arm.c

@@ -0,0 +1,458 @@

+#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, SKIPPED) \ + 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 (SKIPPED == 1) { \ + info->operandFormat &= ~ARM_OPERAND_1; \ + } else if (SKIPPED == 2) { \ + info->operandFormat &= ~ARM_OPERAND_2; \ + } \ + if (info->op1.reg == ARM_PC) { \ + info->branches = 1; \ + }) + +#define DEFINE_ALU_DECODER_ARM(NAME, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 0, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSLR, NAME, 0, ADDR_MODE_1_LSLR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSLR, NAME, 1, ADDR_MODE_1_LSLR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 0, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSRR, NAME, 0, ADDR_MODE_1_LSRR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSRR, NAME, 1, ADDR_MODE_1_LSRR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 0, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASRR, NAME, 0, ADDR_MODE_1_ASRR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASRR, NAME, 1, ADDR_MODE_1_ASRR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 0, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _RORR, NAME, 0, ADDR_MODE_1_RORR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S_RORR, NAME, 1, ADDR_MODE_1_RORR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 0, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## SI, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED) + +#define DEFINE_ALU_DECODER_S_ONLY_ARM(NAME) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSLR, NAME, 1, ADDR_MODE_1_LSLR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSRR, NAME, 1, ADDR_MODE_1_LSRR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASRR, NAME, 1, ADDR_MODE_1_ASRR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## _RORR, NAME, 1, ADDR_MODE_1_RORR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_NONE, 1) + +#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 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, 0) +DEFINE_ALU_DECODER_ARM(ADC, 0) +DEFINE_ALU_DECODER_ARM(AND, 0) +DEFINE_ALU_DECODER_ARM(BIC, 0) +DEFINE_ALU_DECODER_S_ONLY_ARM(CMN) +DEFINE_ALU_DECODER_S_ONLY_ARM(CMP) +DEFINE_ALU_DECODER_ARM(EOR, 0) +DEFINE_ALU_DECODER_ARM(MOV, 2) +DEFINE_ALU_DECODER_ARM(MVN, 2) +DEFINE_ALU_DECODER_ARM(ORR, 0) +DEFINE_ALU_DECODER_ARM(RSB, 0) +DEFINE_ALU_DECODER_ARM(RSC, 0) +DEFINE_ALU_DECODER_ARM(SBC, 0) +DEFINE_ALU_DECODER_ARM(SUB, 0) +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, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(LDC, ILL, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(STC, ILL, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(MCR, ILL, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(MRC, ILL, info->operandFormat = ARM_OPERAND_NONE;) + +// Begin miscellaneous definitions + +DEFINE_DECODER_ARM(BKPT, BKPT, info->operandFormat = ARM_OPERAND_NONE;) // Not strictly in ARMv4T, but here for convenience +DEFINE_DECODER_ARM(ILL, ILL, info->operandFormat = ARM_OPERAND_NONE;) // Illegal opcode + +DEFINE_DECODER_ARM(MSR, MSR, + info->affectsCPSR = 1; + info->op1.reg = ARM_CPSR; + info->op2.reg = opcode & 0x0000000F; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_REGISTER_2;) + +DEFINE_DECODER_ARM(MSRR, MSR, + info->op1.reg = ARM_SPSR; + info->op2.reg = opcode & 0x0000000F; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_REGISTER_2;) + +DEFINE_DECODER_ARM(MRS, MRS, info->affectsCPSR = 1; + info->affectsCPSR = 1; + info->op1.reg = (opcode >> 12) & 0xF; + info->op2.reg = ARM_CPSR; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_REGISTER_2;) + +DEFINE_DECODER_ARM(MRSR, MRS, info->affectsCPSR = 1; + info->affectsCPSR = 1; + info->op1.reg = (opcode >> 12) & 0xF; + info->op2.reg = ARM_SPSR; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_REGISTER_2;) + +DEFINE_DECODER_ARM(MSRI, MSR, info->affectsCPSR = 1; + int rotate = (opcode & 0x00000F00) >> 7; + int32_t operand = ARM_ROR(opcode & 0x000000FF, rotate); + info->affectsCPSR = 1; + info->op1.reg = ARM_CPSR; + info->op2.immediate = operand; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_IMMEDIATE_2;) + +DEFINE_DECODER_ARM(MSRRI, MSR, info->affectsCPSR = 1; + int rotate = (opcode & 0x00000F00) >> 7; + int32_t operand = ARM_ROR(opcode & 0x000000FF, rotate); + info->affectsCPSR = 1; + info->op1.reg = ARM_SPSR; + info->op2.immediate = operand; + info->operandFormat = ARM_OPERAND_REGISTER_1 | + ARM_OPERAND_AFFECTED_1 | + ARM_OPERAND_IMMEDIATE_2;) + +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->execMode = MODE_ARM; + 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); +}
A src/arm/decoder-inlines.h

@@ -0,0 +1,20 @@

+#ifndef ARM_DECODER_INLINES_H +#define ARM_DECODER_INLINES_H + +#include "decoder.h" + +#include "arm.h" + +#include <stdio.h> +#include <string.h> + +#define LOAD_CYCLES \ + info->iCycles = 1; \ + info->nDataCycles = 1; + +#define STORE_CYCLES \ + info->sInstructionCycles = 0; \ + info->nInstructionCycles = 1; \ + info->nDataCycles = 1; + +#endif
A src/arm/decoder-thumb.c

@@ -0,0 +1,329 @@

+#include "decoder.h" + +#include "arm.h" +#include "decoder-inlines.h" +#include "emitter-thumb.h" +#include "isa-inlines.h" + +#include <stdio.h> +#include <string.h> + +#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \ + static void _ThumbDecode ## NAME (uint16_t opcode, struct ARMInstructionInfo* info) { \ + UNUSED(opcode); \ + info->mnemonic = ARM_MN_ ## MNEMONIC; \ + BODY; \ + } + +#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op3.immediate = IMMEDIATE; \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, CYCLES, WIDTH) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->memory.baseReg = (opcode >> 3) & 0x0007; \ + info->memory.offset.immediate = IMMEDIATE * WIDTH; \ + info->memory.width = (enum ARMMemoryAccessType) WIDTH; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_MEMORY_2; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_IMMEDIATE_OFFSET; \ + CYCLES) + +#define DEFINE_IMMEDIATE_5_DECODER_MEM_LOAD_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \ + DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, LOAD_CYCLES, WIDTH) + +#define DEFINE_IMMEDIATE_5_DECODER_MEM_STORE_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \ + DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, STORE_CYCLES, WIDTH) + +#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE, WIDTH) \ + COUNT_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC, WIDTH) + +DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA,) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA,) +DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA,) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM_LOAD, 4) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDR, MEM_LOAD, 1) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDR, MEM_LOAD, 2) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM_STORE, 4) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STR, MEM_STORE, 1) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STR, MEM_STORE, 2) + +#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->op3.reg = RM; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_REGISTER_3;) + +#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \ + COUNT_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME) + +DEFINE_DATA_FORM_1_DECODER_THUMB(ADD) +DEFINE_DATA_FORM_1_DECODER_THUMB(SUB) + +#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->op3.immediate = IMMEDIATE; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \ + COUNT_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME) + +DEFINE_DATA_FORM_2_DECODER_THUMB(ADD) +DEFINE_DATA_FORM_2_DECODER_THUMB(SUB) + +#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->op2.immediate = opcode & 0x00FF; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_IMMEDIATE_2;) + +#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \ + COUNT_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED) + +DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1) + +#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_REGISTER_2;) + +DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1) + +#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = (opcode & 0x0007) | H1; \ + info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \ + info->branches = info->op1.reg == ARM_PC; \ + info->affectsCPSR = CPSR; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_REGISTER_2;) + + +#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR) + +DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0) +DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1) +DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->op2.reg = REG; \ + info->op3.immediate = (opcode & 0x00FF) << 2; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, CYCLES) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->memory.baseReg = REG; \ + info->memory.offset.immediate = (opcode & 0x00FF) << 2; \ + info->memory.width = ARM_ACCESS_WORD; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_MEMORY_2; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_IMMEDIATE_OFFSET; \ + CYCLES;) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_LOAD_THUMB(NAME, RD, MNEMONIC, REG) \ + DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, LOAD_CYCLES) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_STORE_THUMB(NAME, RD, MNEMONIC, REG) \ + DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, STORE_CYCLES) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \ + COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG) + +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM_LOAD, ARM_PC) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM_LOAD, ARM_SP) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM_STORE, ARM_SP) + +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP) + +#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->memory.offset.reg = RM; \ + info->op1.reg = opcode & 0x0007; \ + info->memory.baseReg = (opcode >> 3) & 0x0007; \ + 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 | \ + ARM_MEMORY_REGISTER_OFFSET; \ + CYCLES;) + +#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \ + COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE) + +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD) + +// TODO: Estimate memory cycles +#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->memory.baseReg = RN; \ + info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \ + info->branches = info->op1.immediate & (1 << ARM_PC); \ + info->operandFormat = ARM_OPERAND_MEMORY_1; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_WRITEBACK | \ + DIRECTION;) + +#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \ + COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_MEMORY_INCREMENT_AFTER, 0) + +DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM) + +#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ + DEFINE_THUMB_DECODER(B ## COND, B, \ + int8_t immediate = opcode; \ + info->op1.immediate = immediate << 1; \ + info->branches = 1; \ + info->condition = ARM_CONDITION_ ## COND; \ + info->operandFormat = ARM_OPERAND_IMMEDIATE_1;) + +DEFINE_CONDITIONAL_BRANCH_THUMB(EQ) +DEFINE_CONDITIONAL_BRANCH_THUMB(NE) +DEFINE_CONDITIONAL_BRANCH_THUMB(CS) +DEFINE_CONDITIONAL_BRANCH_THUMB(CC) +DEFINE_CONDITIONAL_BRANCH_THUMB(MI) +DEFINE_CONDITIONAL_BRANCH_THUMB(PL) +DEFINE_CONDITIONAL_BRANCH_THUMB(VS) +DEFINE_CONDITIONAL_BRANCH_THUMB(VC) +DEFINE_CONDITIONAL_BRANCH_THUMB(LS) +DEFINE_CONDITIONAL_BRANCH_THUMB(HI) +DEFINE_CONDITIONAL_BRANCH_THUMB(GE) +DEFINE_CONDITIONAL_BRANCH_THUMB(LT) +DEFINE_CONDITIONAL_BRANCH_THUMB(GT) +DEFINE_CONDITIONAL_BRANCH_THUMB(LE) + +#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = ARM_SP; \ + info->op2.immediate = (opcode & 0x7F) << 2; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_IMMEDIATE_2;) + +DEFINE_SP_MODIFY_THUMB(ADD7, ADD) +DEFINE_SP_MODIFY_THUMB(SUB4, SUB) + +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR) + +DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;) +DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;) + +DEFINE_THUMB_DECODER(B, B, + int16_t immediate = (opcode & 0x07FF) << 5; + info->op1.immediate = (((int32_t) immediate) >> 4); + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(BL1, BLH, + int16_t immediate = (opcode & 0x07FF) << 5; + info->op1.immediate = (((int32_t) immediate) << 7); + info->operandFormat = ARM_OPERAND_IMMEDIATE_1;) + +DEFINE_THUMB_DECODER(BL2, BL, + info->op1.immediate = (opcode & 0x07FF) << 1; + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(BX, BX, + info->op1.reg = (opcode >> 3) & 0xF; + info->operandFormat = ARM_OPERAND_REGISTER_1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(SWI, SWI, + info->op1.immediate = opcode & 0xFF; + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->traps = 1;) + +typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info); + +static const ThumbDecoder _thumbDecoderTable[0x400] = { + DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode) +}; + +void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) { + info->execMode = MODE_THUMB; + info->opcode = opcode; + info->branches = 0; + info->traps = 0; + info->affectsCPSR = 0; + info->condition = ARM_CONDITION_AL; + info->sDataCycles = 0; + info->nDataCycles = 0; + info->sInstructionCycles = 1; + info->nInstructionCycles = 0; + info->iCycles = 0; + info->cCycles = 0; + ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6]; + decoder(opcode, info); +}
A src/arm/decoder.c

@@ -0,0 +1,349 @@

+#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; + case ARM_CPSR: + strncpy(buffer, "cpsr", blen - 1); + return 4; + case ARM_SPSR: + strncpy(buffer, "spsr", blen - 1); + return 4; + 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; + case ARM_MN_ADD: + case ARM_MN_ADC: + case ARM_MN_AND: + case ARM_MN_BIC: + case ARM_MN_EOR: + case ARM_MN_MOV: + case ARM_MN_MVN: + case ARM_MN_ORR: + case ARM_MN_RSB: + case ARM_MN_RSC: + case ARM_MN_SBC: + case ARM_MN_SUB: + if (info->affectsCPSR && info->execMode == MODE_ARM) { + flags = "s"; + } + break; + default: + break; + } + written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, cond, flags); + 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; +}
A src/arm/decoder.h

@@ -0,0 +1,200 @@

+#ifndef ARM_DECODER_H +#define ARM_DECODER_H + +#include "arm.h" + +#include <stdint.h> + +// Bit 0: a register is involved with this operand +// Bit 1: an immediate is invovled with this operand +// Bit 2: a memory access is invovled with this operand +// Bit 3: the destination of this operand is affected by this opcode +// Bit 4: this operand is shifted by a register +// Bit 5: this operand is shifted by an immediate +enum ARMOperandFormat { + ARM_OPERAND_NONE = 0x00000000, + ARM_OPERAND_REGISTER_1 = 0x00000001, + ARM_OPERAND_IMMEDIATE_1 = 0x00000002, + ARM_OPERAND_MEMORY_1 = 0x00000004, + ARM_OPERAND_AFFECTED_1 = 0x00000008, + ARM_OPERAND_SHIFT_REGISTER_1 = 0x00000010, + ARM_OPERAND_SHIFT_IMMEDIATE_1 = 0x00000020, + ARM_OPERAND_1 = 0x000000FF, + + ARM_OPERAND_REGISTER_2 = 0x00000100, + ARM_OPERAND_IMMEDIATE_2 = 0x00000200, + ARM_OPERAND_MEMORY_2 = 0x00000400, + ARM_OPERAND_AFFECTED_2 = 0x00000800, + ARM_OPERAND_SHIFT_REGISTER_2 = 0x00001000, + ARM_OPERAND_SHIFT_IMMEDIATE_2 = 0x00002000, + ARM_OPERAND_2 = 0x0000FF00, + + ARM_OPERAND_REGISTER_3 = 0x00010000, + ARM_OPERAND_IMMEDIATE_3 = 0x00020000, + ARM_OPERAND_MEMORY_3 = 0x00040000, + ARM_OPERAND_AFFECTED_3 = 0x00080000, + ARM_OPERAND_SHIFT_REGISTER_3 = 0x00100000, + ARM_OPERAND_SHIFT_IMMEDIATE_3 = 0x00200000, + ARM_OPERAND_3 = 0x00FF0000, + + ARM_OPERAND_REGISTER_4 = 0x01000000, + ARM_OPERAND_IMMEDIATE_4 = 0x02000000, + ARM_OPERAND_MEMORY_4 = 0x04000000, + ARM_OPERAND_AFFECTED_4 = 0x08000000, + ARM_OPERAND_SHIFT_REGISTER_4 = 0x10000000, + ARM_OPERAND_SHIFT_IMMEDIATE_4 = 0x20000000, + ARM_OPERAND_4 = 0xFF000000 +}; + +enum ARMMemoryFormat { + ARM_MEMORY_REGISTER_BASE = 0x0001, + ARM_MEMORY_IMMEDIATE_OFFSET = 0x0002, + ARM_MEMORY_REGISTER_OFFSET = 0x0004, + ARM_MEMORY_SHIFTED_OFFSET = 0x0008, + ARM_MEMORY_PRE_INCREMENT = 0x0010, + ARM_MEMORY_POST_INCREMENT = 0x0020, + ARM_MEMORY_OFFSET_SUBTRACT = 0x0040, + ARM_MEMORY_WRITEBACK = 0x0080, + ARM_MEMORY_DECREMENT_AFTER = 0x0000, + ARM_MEMORY_INCREMENT_AFTER = 0x0100, + ARM_MEMORY_DECREMENT_BEFORE = 0x0200, + ARM_MEMORY_INCREMENT_BEFORE = 0x0300, +}; + +#define MEMORY_FORMAT_TO_DIRECTION(F) (((F) >> 8) & 0x7) + +enum ARMCondition { + ARM_CONDITION_EQ = 0x0, + ARM_CONDITION_NE = 0x1, + ARM_CONDITION_CS = 0x2, + ARM_CONDITION_CC = 0x3, + ARM_CONDITION_MI = 0x4, + ARM_CONDITION_PL = 0x5, + ARM_CONDITION_VS = 0x6, + ARM_CONDITION_VC = 0x7, + ARM_CONDITION_HI = 0x8, + ARM_CONDITION_LS = 0x9, + ARM_CONDITION_GE = 0xA, + ARM_CONDITION_LT = 0xB, + ARM_CONDITION_GT = 0xC, + ARM_CONDITION_LE = 0xD, + ARM_CONDITION_AL = 0xE, + ARM_CONDITION_NV = 0xF +}; + +enum ARMShifterOperation { + ARM_SHIFT_NONE = 0, + ARM_SHIFT_LSL, + ARM_SHIFT_LSR, + ARM_SHIFT_ASR, + ARM_SHIFT_ROR, + ARM_SHIFT_RRX +}; + +union ARMOperand { + struct { + uint8_t reg; + enum ARMShifterOperation shifterOp; + union { + uint8_t shifterReg; + uint8_t shifterImm; + }; + }; + int32_t immediate; +}; + +enum ARMMemoryAccessType { + ARM_ACCESS_WORD = 4, + ARM_ACCESS_HALFWORD = 2, + ARM_ACCESS_SIGNED_HALFWORD = 10, + ARM_ACCESS_BYTE = 1, + ARM_ACCESS_SIGNED_BYTE = 9, + ARM_ACCESS_TRANSLATED_WORD = 20, + ARM_ACCESS_TRANSLATED_BYTE = 17 +}; + +struct ARMMemoryAccess { + uint8_t baseReg; + uint16_t format; + union ARMOperand offset; + enum ARMMemoryAccessType width; +}; + +enum ARMMnemonic { + ARM_MN_ILL = 0, + ARM_MN_ADC, + ARM_MN_ADD, + ARM_MN_AND, + ARM_MN_ASR, + ARM_MN_B, + ARM_MN_BIC, + ARM_MN_BKPT, + ARM_MN_BL, + ARM_MN_BLH, + ARM_MN_BX, + ARM_MN_CMN, + ARM_MN_CMP, + ARM_MN_EOR, + ARM_MN_LDM, + ARM_MN_LDR, + 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, + ARM_MN_ORR, + ARM_MN_ROR, + ARM_MN_RSB, + ARM_MN_RSC, + ARM_MN_SBC, + ARM_MN_SMLAL, + ARM_MN_SMULL, + ARM_MN_STM, + ARM_MN_STR, + ARM_MN_SUB, + ARM_MN_SWI, + ARM_MN_SWP, + ARM_MN_TEQ, + ARM_MN_TST, + ARM_MN_UMLAL, + ARM_MN_UMULL, + + ARM_MN_MAX +}; + +enum { + ARM_CPSR = 16, + ARM_SPSR = 17 +}; + +struct ARMInstructionInfo { + enum ExecutionMode execMode; + uint32_t opcode; + enum ARMMnemonic mnemonic; + union ARMOperand op1; + union ARMOperand op2; + union ARMOperand op3; + union ARMOperand op4; + struct ARMMemoryAccess memory; + int operandFormat; + int branches; + int traps; + int affectsCPSR; + int condition; + int sDataCycles; + int nDataCycles; + int sInstructionCycles; + int nInstructionCycles; + int iCycles; + int cCycles; +}; + +void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info); +void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info); +int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen); + +#endif
A src/arm/emitter-arm.h

@@ -0,0 +1,330 @@

+#ifndef EMITTER_ARM_H +#define EMITTER_ARM_H + +#include "emitter-inlines.h" + +#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ + EMITTER ## NAME + +#define DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ALU) \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)), \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)) + +#define DECLARE_ARM_ALU_BLOCK(EMITTER, ALU, EX1, EX2, EX3, EX4) \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSLR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSRR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASRR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _RORR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX4) + +#define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)), \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)) + +#define DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, NAME, P, U, W) \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL) + +#define DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, NAME, MODE, W) \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)), \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)) + +#define DECLARE_ARM_BRANCH_BLOCK(EMITTER, NAME) \ + DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) + +// TODO: Support coprocessors +#define DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, NAME, P, U, N, W) \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) + +#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \ + DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2)))) + +#define DECLARE_ARM_SWI_BLOCK(EMITTER) \ + DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI)) + +#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \ + DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, ILL, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, ILL, ILL, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \ + DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, BX), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \ + DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \ + DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \ + DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \ + DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \ + DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \ + DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \ + DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \ + DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \ + DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \ + DECLARE_ARM_SWI_BLOCK(EMITTER) + +#endif
A src/arm/emitter-inlines.h

@@ -0,0 +1,82 @@

+#ifndef EMITTER_INLINES_H +#define EMITTER_INLINES_H + +#define DO_4(DIRECTIVE) \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE + +#define DO_8(DIRECTIVE) \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE + +#define DO_256(DIRECTIVE) \ + DO_4(DO_8(DO_8(DIRECTIVE))) + +#define DO_INTERLACE(LEFT, RIGHT) \ + LEFT, \ + RIGHT + +#define APPLY(F, ...) F(__VA_ARGS__) + +#define COUNT_1(EMITTER, PREFIX, ...) \ + EMITTER(PREFIX ## 0, 0, __VA_ARGS__) \ + EMITTER(PREFIX ## 1, 1, __VA_ARGS__) + +#define COUNT_2(EMITTER, PREFIX, ...) \ + COUNT_1(EMITTER, PREFIX, __VA_ARGS__) \ + EMITTER(PREFIX ## 2, 2, __VA_ARGS__) \ + EMITTER(PREFIX ## 3, 3, __VA_ARGS__) + +#define COUNT_3(EMITTER, PREFIX, ...) \ + COUNT_2(EMITTER, PREFIX, __VA_ARGS__) \ + EMITTER(PREFIX ## 4, 4, __VA_ARGS__) \ + EMITTER(PREFIX ## 5, 5, __VA_ARGS__) \ + EMITTER(PREFIX ## 6, 6, __VA_ARGS__) \ + EMITTER(PREFIX ## 7, 7, __VA_ARGS__) + +#define COUNT_4(EMITTER, PREFIX, ...) \ + COUNT_3(EMITTER, PREFIX, __VA_ARGS__) \ + EMITTER(PREFIX ## 8, 8, __VA_ARGS__) \ + EMITTER(PREFIX ## 9, 9, __VA_ARGS__) \ + EMITTER(PREFIX ## A, 10, __VA_ARGS__) \ + EMITTER(PREFIX ## B, 11, __VA_ARGS__) \ + EMITTER(PREFIX ## C, 12, __VA_ARGS__) \ + EMITTER(PREFIX ## D, 13, __VA_ARGS__) \ + EMITTER(PREFIX ## E, 14, __VA_ARGS__) \ + EMITTER(PREFIX ## F, 15, __VA_ARGS__) + +#define COUNT_5(EMITTER, PREFIX, ...) \ + COUNT_4(EMITTER, PREFIX ## 0, __VA_ARGS__) \ + EMITTER(PREFIX ## 10, 16, __VA_ARGS__) \ + EMITTER(PREFIX ## 11, 17, __VA_ARGS__) \ + EMITTER(PREFIX ## 12, 18, __VA_ARGS__) \ + EMITTER(PREFIX ## 13, 19, __VA_ARGS__) \ + EMITTER(PREFIX ## 14, 20, __VA_ARGS__) \ + EMITTER(PREFIX ## 15, 21, __VA_ARGS__) \ + EMITTER(PREFIX ## 16, 22, __VA_ARGS__) \ + EMITTER(PREFIX ## 17, 23, __VA_ARGS__) \ + EMITTER(PREFIX ## 18, 24, __VA_ARGS__) \ + EMITTER(PREFIX ## 19, 25, __VA_ARGS__) \ + EMITTER(PREFIX ## 1A, 26, __VA_ARGS__) \ + EMITTER(PREFIX ## 1B, 27, __VA_ARGS__) \ + EMITTER(PREFIX ## 1C, 28, __VA_ARGS__) \ + EMITTER(PREFIX ## 1D, 29, __VA_ARGS__) \ + EMITTER(PREFIX ## 1E, 30, __VA_ARGS__) \ + EMITTER(PREFIX ## 1F, 31, __VA_ARGS__) \ + +#define DUMMY(X, ...) X, +#define DUMMY_4(...) \ + DUMMY(__VA_ARGS__) \ + DUMMY(__VA_ARGS__) \ + DUMMY(__VA_ARGS__) \ + DUMMY(__VA_ARGS__) + +#endif
A src/arm/emitter-thumb.h

@@ -0,0 +1,108 @@

+#ifndef EMITTER_THUMB_H +#define EMITTER_THUMB_H + +#include "emitter-inlines.h" + +#define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \ + EMITTER ## NAME + +#define DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, NAME) \ + DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 00), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 01), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 10), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 11) + +#define DECLARE_THUMB_EMITTER_BLOCK(EMITTER) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LSL1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LSR1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ASR1_)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD3_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB3_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD1_)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB1_)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, MOV1_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, CMP1_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD2_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB2_R)) \ + DECLARE_INSTRUCTION_THUMB(EMITTER, AND), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, EOR), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, LSL2), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, LSR2), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ASR2), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ADC), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, SBC), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ROR), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, TST), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, NEG), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, CMP2), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, CMN), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ORR), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, MUL), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, BIC), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, MVN), \ + DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, ADD4), \ + DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, CMP3), \ + DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, MOV3), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR3_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STR2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRH2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRB2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRSB_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRH2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRB2_R)) \ + APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRSH_R)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STR1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRB1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRB1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRH1_)) \ + APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRH1_)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, STR3_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR4_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD5_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD6_R)) \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ADD7), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, ADD7), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, SUB4), \ + DECLARE_INSTRUCTION_THUMB(EMITTER, SUB4), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, PUSH)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, PUSHR)), \ + DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POP)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POPR)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BKPT)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, STMIA_R)) \ + APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDMIA_R)) \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BEQ)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BNE)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BCS)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BCC)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BMI)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BPL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BVS)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BVC)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BHI)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLS)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BGE)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLT)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BGT)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLE)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ + DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, SWI)), \ + DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, B))), \ + DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL))), \ + DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BL1))), \ + DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BL2))) \ + +#endif
M src/arm/isa-arm.csrc/arm/isa-arm.c

@@ -1,6 +1,7 @@

#include "isa-arm.h" #include "arm.h" +#include "emitter-arm.h" #include "isa-inlines.h" enum {

@@ -703,330 +704,6 @@ mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK;

cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask);) DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF)) - -#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ - EMITTER ## NAME - -#define DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ALU) \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)), \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)) - -#define DECLARE_ARM_ALU_BLOCK(EMITTER, ALU, EX1, EX2, EX3, EX4) \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSLR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSRR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASRR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _RORR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX4) - -#define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)), \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)) - -#define DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, NAME, P, U, W) \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL) - -#define DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, NAME, MODE, W) \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)), \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)) - -#define DECLARE_ARM_BRANCH_BLOCK(EMITTER, NAME) \ - DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) - -// TODO: Support coprocessors -#define DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, NAME, P, U, N, W) \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) - -#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \ - DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2)))) - -#define DECLARE_ARM_SWI_BLOCK(EMITTER) \ - DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI)) - -#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \ - DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, ILL, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, ILL, ILL, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \ - DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, BX), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \ - DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \ - DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \ - DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \ - DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \ - DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \ - DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \ - DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \ - DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \ - DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \ - DECLARE_ARM_SWI_BLOCK(EMITTER) const ARMInstruction _armTable[0x1000] = { DECLARE_ARM_EMITTER_BLOCK(_ARMInstruction)
M src/arm/isa-inlines.hsrc/arm/isa-inlines.h

@@ -5,29 +5,6 @@ #include "common.h"

#include "arm.h" -#define DO_4(DIRECTIVE) \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE - -#define DO_8(DIRECTIVE) \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE - -#define DO_256(DIRECTIVE) \ - DO_4(DO_8(DO_8(DIRECTIVE))) - -#define DO_INTERLACE(LEFT, RIGHT) \ - LEFT, \ - RIGHT - #define ARM_COND_EQ (cpu->cpsr.z) #define ARM_COND_NE (!cpu->cpsr.z) #define ARM_COND_CS (cpu->cpsr.c)
M src/arm/isa-thumb.csrc/arm/isa-thumb.c

@@ -1,6 +1,7 @@

#include "isa-thumb.h" #include "isa-inlines.h" +#include "emitter-thumb.h" // Instruction definitions // Beware pre-processor insanity

@@ -37,54 +38,6 @@ #define THUMB_PREFETCH_CYCLES (1 + cpu->memory.activePrefetchCycles16)

#define THUMB_STORE_POST_BODY \ currentCycles += cpu->memory.activeNonseqCycles16 - cpu->memory.activePrefetchCycles16; - -#define APPLY(F, ...) F(__VA_ARGS__) - -#define COUNT_1(EMITTER, PREFIX, ...) \ - EMITTER(PREFIX ## 0, 0, __VA_ARGS__) \ - EMITTER(PREFIX ## 1, 1, __VA_ARGS__) - -#define COUNT_2(EMITTER, PREFIX, ...) \ - COUNT_1(EMITTER, PREFIX, __VA_ARGS__) \ - EMITTER(PREFIX ## 2, 2, __VA_ARGS__) \ - EMITTER(PREFIX ## 3, 3, __VA_ARGS__) - -#define COUNT_3(EMITTER, PREFIX, ...) \ - COUNT_2(EMITTER, PREFIX, __VA_ARGS__) \ - EMITTER(PREFIX ## 4, 4, __VA_ARGS__) \ - EMITTER(PREFIX ## 5, 5, __VA_ARGS__) \ - EMITTER(PREFIX ## 6, 6, __VA_ARGS__) \ - EMITTER(PREFIX ## 7, 7, __VA_ARGS__) - -#define COUNT_4(EMITTER, PREFIX, ...) \ - COUNT_3(EMITTER, PREFIX, __VA_ARGS__) \ - EMITTER(PREFIX ## 8, 8, __VA_ARGS__) \ - EMITTER(PREFIX ## 9, 9, __VA_ARGS__) \ - EMITTER(PREFIX ## A, 10, __VA_ARGS__) \ - EMITTER(PREFIX ## B, 11, __VA_ARGS__) \ - EMITTER(PREFIX ## C, 12, __VA_ARGS__) \ - EMITTER(PREFIX ## D, 13, __VA_ARGS__) \ - EMITTER(PREFIX ## E, 14, __VA_ARGS__) \ - EMITTER(PREFIX ## F, 15, __VA_ARGS__) - -#define COUNT_5(EMITTER, PREFIX, ...) \ - COUNT_4(EMITTER, PREFIX ## 0, __VA_ARGS__) \ - EMITTER(PREFIX ## 10, 16, __VA_ARGS__) \ - EMITTER(PREFIX ## 11, 17, __VA_ARGS__) \ - EMITTER(PREFIX ## 12, 18, __VA_ARGS__) \ - EMITTER(PREFIX ## 13, 19, __VA_ARGS__) \ - EMITTER(PREFIX ## 14, 20, __VA_ARGS__) \ - EMITTER(PREFIX ## 15, 21, __VA_ARGS__) \ - EMITTER(PREFIX ## 16, 22, __VA_ARGS__) \ - EMITTER(PREFIX ## 17, 23, __VA_ARGS__) \ - EMITTER(PREFIX ## 18, 24, __VA_ARGS__) \ - EMITTER(PREFIX ## 19, 25, __VA_ARGS__) \ - EMITTER(PREFIX ## 1A, 26, __VA_ARGS__) \ - EMITTER(PREFIX ## 1B, 27, __VA_ARGS__) \ - EMITTER(PREFIX ## 1C, 28, __VA_ARGS__) \ - EMITTER(PREFIX ## 1D, 29, __VA_ARGS__) \ - EMITTER(PREFIX ## 1E, 30, __VA_ARGS__) \ - EMITTER(PREFIX ## 1F, 31, __VA_ARGS__) \ #define DEFINE_INSTRUCTION_THUMB(NAME, BODY) \ static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \

@@ -470,115 +423,6 @@ ARM_WRITE_PC;

}) DEFINE_INSTRUCTION_THUMB(SWI, cpu->irqh.swi16(cpu, opcode & 0xFF)) - -#define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \ - EMITTER ## NAME - -#define DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, NAME) \ - DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 00), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 01), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 10), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, NAME ## 11) - -#define DUMMY(X, ...) X, -#define DUMMY_4(...) \ - DUMMY(__VA_ARGS__) \ - DUMMY(__VA_ARGS__) \ - DUMMY(__VA_ARGS__) \ - DUMMY(__VA_ARGS__) - -#define DECLARE_THUMB_EMITTER_BLOCK(EMITTER) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LSL1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LSR1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ASR1_)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD3_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB3_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD1_)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB1_)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, MOV1_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, CMP1_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD2_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, SUB2_R)) \ - DECLARE_INSTRUCTION_THUMB(EMITTER, AND), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, EOR), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, LSL2), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, LSR2), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ASR2), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ADC), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, SBC), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ROR), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, TST), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, NEG), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, CMP2), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, CMN), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ORR), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, MUL), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, BIC), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, MVN), \ - DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, ADD4), \ - DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, CMP3), \ - DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, MOV3), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR3_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STR2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRH2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRB2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRSB_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRH2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRB2_R)) \ - APPLY(COUNT_3, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRSH_R)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STR1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRB1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRB1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, STRH1_)) \ - APPLY(COUNT_5, DUMMY, DECLARE_INSTRUCTION_THUMB(EMITTER, LDRH1_)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, STR3_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDR4_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD5_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, ADD6_R)) \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ADD7), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ADD7), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, SUB4), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, SUB4), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, PUSH)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, PUSHR)), \ - DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POP)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POPR)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BKPT)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, STMIA_R)) \ - APPLY(COUNT_3, DUMMY_4, DECLARE_INSTRUCTION_THUMB(EMITTER, LDMIA_R)) \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BEQ)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BNE)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BCS)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BCC)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BMI)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BPL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BVS)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BVC)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BHI)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLS)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BGE)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLT)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BGT)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BLE)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, SWI)), \ - DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, B))), \ - DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL))), \ - DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BL1))), \ - DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BL2))) const ThumbInstruction _thumbTable[0x400] = { DECLARE_THUMB_EMITTER_BLOCK(_ThumbInstruction)
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -1,4 +1,5 @@

#include "cli-debugger.h" +#include "decoder.h" #include <signal.h>

@@ -132,13 +133,18 @@ printf("\n");

} static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { - // TODO: write a disassembler + char disassembly[48]; + struct ARMInstructionInfo info; if (mode == MODE_ARM) { uint32_t instruction = debugger->d.cpu->memory.load32(debugger->d.cpu, 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, address, 0); - printf("%04X\n", instruction); + ARMDecodeThumb(instruction, &info); + ARMDisassemble(&info, debugger->d.cpu->gprs[ARM_PC] + WORD_SIZE_THUMB, disassembly, sizeof(disassembly)); + printf("%04X: %s\n", instruction, disassembly); } }