Merge branch 'decoder'

Conflicts:
	src/debugger/cli-debugger.c
This commit is contained in:
Jeffrey Pfau 2014-07-12 00:40:40 -07:00
commit aefa5f0ab8
12 changed files with 1887 additions and 507 deletions

458
src/arm/decoder-arm.c Normal file
View File

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

20
src/arm/decoder-inlines.h Normal file
View File

@ -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

329
src/arm/decoder-thumb.c Normal file
View File

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

349
src/arm/decoder.c Normal file
View File

@ -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;
}

200
src/arm/decoder.h Normal file
View File

@ -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

330
src/arm/emitter-arm.h Normal file
View File

@ -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

82
src/arm/emitter-inlines.h Normal file
View File

@ -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

108
src/arm/emitter-thumb.h Normal file
View File

@ -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

View File

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

View File

@ -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)

View File

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

View File

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