mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'decoder'
Conflicts: src/debugger/cli-debugger.c
This commit is contained in:
commit
aefa5f0ab8
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,6 +1,7 @@
|
|||
#include "isa-arm.h"
|
||||
|
||||
#include "arm.h"
|
||||
#include "emitter-arm.h"
|
||||
#include "isa-inlines.h"
|
||||
|
||||
enum {
|
||||
|
@ -704,330 +705,6 @@ DEFINE_INSTRUCTION_ARM(MSRRI,
|
|||
|
||||
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)
|
||||
};
|
||||
|
|
|
@ -5,29 +5,6 @@
|
|||
|
||||
#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)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "isa-thumb.h"
|
||||
|
||||
#include "isa-inlines.h"
|
||||
#include "emitter-thumb.h"
|
||||
|
||||
// Instruction definitions
|
||||
// Beware pre-processor insanity
|
||||
|
@ -38,54 +39,6 @@
|
|||
#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) { \
|
||||
int currentCycles = THUMB_PREFETCH_CYCLES; \
|
||||
|
@ -471,115 +424,6 @@ DEFINE_INSTRUCTION_THUMB(BX,
|
|||
|
||||
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)
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "cli-debugger.h"
|
||||
#include "decoder.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
|
@ -132,13 +133,18 @@ static void _printHex(struct CLIDebugger* debugger, struct DebugVector* dv) {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue