Separate out ISA files
Jeffrey Pfau jeffrey@endrift.com
Sun, 07 Apr 2013 21:15:32 -0700
6 files changed,
758 insertions(+),
746 deletions(-)
M
src/arm.c
→
src/arm.c
@@ -1,17 +1,8 @@
#include "arm.h" -#define ARM_SIGN(I) ((I) >> 31) -#define ARM_ROR(I, ROTATE) (((I) >> ROTATE) | (I << (32 - ROTATE))) +#include "isa-inlines.h" -static inline void _ARMSetMode(struct ARMCore*, enum ExecutionMode); -static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory*, uint32_t address, uint32_t* opcodeOut); -static ARMInstruction _ARMLoadInstructionThumb(struct ARMMemory*, uint32_t address, uint32_t* opcodeOut); static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode); - -static inline void _ARMReadCPSR(struct ARMCore* cpu) { - _ARMSetMode(cpu, cpu->cpsr.t); - ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); -} void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) { if (mode == cpu->privilegeMode) {@@ -49,76 +40,26 @@ }
cpu->privilegeMode = mode; } -static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) { - return mode != MODE_SYSTEM && mode != MODE_USER; -} - static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) { switch (mode) { - case MODE_USER: - case MODE_SYSTEM: - // No banked registers - return BANK_NONE; - case MODE_FIQ: - return BANK_FIQ; - case MODE_IRQ: - return BANK_IRQ; - case MODE_SUPERVISOR: - return BANK_SUPERVISOR; - case MODE_ABORT: - return BANK_ABORT; - case MODE_UNDEFINED: - return BANK_UNDEFINED; - default: - // This should be unreached - return BANK_NONE; - } -} - -// Addressing mode 1 -static inline void _barrelShift(struct ARMCore* cpu, uint32_t opcode) { - // TODO -} - -static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { - int rotate = (opcode & 0x00000F00) >> 7; - int immediate = opcode & 0x000000FF; - if (!rotate) { - cpu->shifterOperand = immediate; - cpu->shifterCarryOut = cpu->cpsr.c; - } else { - cpu->shifterOperand = ARM_ROR(immediate, rotate); - cpu->shifterCarryOut = ARM_SIGN(cpu->shifterOperand); + case MODE_USER: + case MODE_SYSTEM: + // No banked registers + return BANK_NONE; + case MODE_FIQ: + return BANK_FIQ; + case MODE_IRQ: + return BANK_IRQ; + case MODE_SUPERVISOR: + return BANK_SUPERVISOR; + case MODE_ABORT: + return BANK_ABORT; + case MODE_UNDEFINED: + return BANK_UNDEFINED; + default: + // This should be unreached + return BANK_NONE; } -} - -static const ARMInstruction _armTable[0x1000]; - -static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode executionMode) { - if (executionMode == cpu->executionMode) { - return; - } - - cpu->executionMode = executionMode; - switch (executionMode) { - case MODE_ARM: - cpu->cpsr.t = 0; - break; - case MODE_THUMB: - cpu->cpsr.t = 1; - } -} - -static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory* memory, uint32_t address, uint32_t* opcodeOut) { - uint32_t opcode = memory->load32(memory, address); - *opcodeOut = opcode; - return _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; -} - -static ARMInstruction _ARMLoadInstructionThumb(struct ARMMemory* memory, uint32_t address, uint32_t* opcodeOut) { - uint16_t opcode = memory->loadU16(memory, address); - *opcodeOut = opcode; - return 0; } void ARMInit(struct ARMCore* cpu) {@@ -165,670 +106,3 @@
cpu->board->reset(cpu->board); } -#define ARM_COND_EQ (cpu->cpsr.z) -#define ARM_COND_NE (!cpu->cpsr.z) -#define ARM_COND_CS (cpu->cpsr.c) -#define ARM_COND_CC (!cpu->cpsr.c) -#define ARM_COND_MI (cpu->cpsr.n) -#define ARM_COND_PL (!cpu->cpsr.n) -#define ARM_COND_VS (cpu->cpsr.v) -#define ARM_COND_VC (!cpu->cpsr.v) -#define ARM_COND_HI (cpu->cpsr.c && !cpu->cpsr.z) -#define ARM_COND_LS (!cpu->cpsr.c || cpu->cpsr.z) -#define ARM_COND_GE (!cpu->cpsr.n == !cpu->cpsr.v) -#define ARM_COND_LT (!cpu->cpsr.n != !cpu->cpsr.v) -#define ARM_COND_GT (!cpu->cpsr.z && !cpu->cpsr.n == !cpu->cpsr.v) -#define ARM_COND_LE (cpu->cpsr.z || !cpu->cpsr.n != !cpu->cpsr.v) -#define ARM_COND_AL 1 - -void ARMStep(struct ARMCore* cpu) { - // TODO - uint32_t opcode; - ARMInstruction instruction = _ARMLoadInstructionARM(cpu->memory, cpu->gprs[ARM_PC] - WORD_SIZE_ARM, &opcode); - cpu->gprs[ARM_PC] += WORD_SIZE_ARM; - - int condition = opcode >> 28; - if (condition == 0xE) { - instruction(cpu, opcode); - } else { - switch (condition) { - case 0x0: - if (!ARM_COND_EQ) { - return; - } - break; - case 0x1: - if (!ARM_COND_NE) { - return; - } - break; - case 0x2: - if (!ARM_COND_CS) { - return; - } - break; - case 0x3: - if (!ARM_COND_CC) { - return; - } - break; - case 0x4: - if (!ARM_COND_MI) { - return; - } - break; - case 0x5: - if (!ARM_COND_PL) { - return; - } - break; - case 0x6: - if (!ARM_COND_VS) { - return; - } - break; - case 0x7: - if (!ARM_COND_VC) { - return; - } - break; - case 0x8: - if (!ARM_COND_HI) { - return; - } - break; - case 0x9: - if (!ARM_COND_LS) { - return; - } - break; - case 0xA: - if (!ARM_COND_GE) { - return; - } - break; - case 0xB: - if (!ARM_COND_LT) { - return; - } - break; - case 0xC: - if (!ARM_COND_GT) { - return; - } - break; - case 0xD: - if (!ARM_COND_GE) { - return; - } - break; - default: - break; - } - } - instruction(cpu, opcode); -} - -// Instruction definitions -// Beware pre-processor antics - -#define ARM_CARRY_FROM(M, N, D) ((ARM_SIGN((M) | (N))) && !(ARM_SIGN(D))) -#define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N))) -#define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))) && (ARM_SIGN((N) ^ (D)))) -#define ARM_V_SUBTRACTION(M, N, D) ((ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D)))) - -#define ARM_WRITE_PC \ - cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM - -#define ARM_ADDITION_S(M, N, D) \ - if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ - cpu->cpsr = cpu->spsr; \ - _ARMReadCPSR(cpu); \ - } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = ARM_CARRY_FROM(M, N, D); \ - cpu->cpsr.v = ARM_V_ADDITION(M, N, D); \ - } - -#define ARM_SUBTRACTION_S(M, N, D) \ - if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ - cpu->cpsr = cpu->spsr; \ - _ARMReadCPSR(cpu); \ - } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ - cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \ - } - -#define ARM_NEUTRAL_S(M, N, D) \ - if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ - cpu->cpsr = cpu->spsr; \ - _ARMReadCPSR(cpu); \ - } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = cpu->shifterCarryOut; \ - } - -#define ADDR_MODE_2_ADDRESS (address) -#define ADDR_MODE_2_RN (cpu->gprs[rn]) -#define ADDR_MODE_2_RM (cpu->gprs[rm]) -#define ADDR_MODE_2_IMMEDIATE (opcode & 0x00000FFF) -#define ADDR_MODE_2_INDEX(U_OP, M) (cpu->gprs[rn] U_OP M) -#define ADDR_MODE_2_WRITEBACK(ADDR) (cpu->gprs[rn] = ADDR) -#define ADDR_MODE_2_LSL(I) (cpu->gprs[rm] << I) -#define ADDR_MODE_2_LSR(I) (I ? ((uint32_t) cpu->gprs[rm]) >> I : 0) -#define ADDR_MODE_2_ASR(I) (I ? ((int32_t) cpu->gprs[rm]) >> I : ((int32_t) cpu->gprs[rm]) >> 31) -#define ADDR_MODE_2_ROR(I) (I ? ARM_ROR(cpu->gprs[rm], I) : (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1)) - -#define ADDR_MODE_3_ADDRESS ADDR_MODE_2_ADDRESS -#define ADDR_MODE_3_RN ADDR_MODE_2_RN -#define ADDR_MODE_3_RM ADDR_MODE_2_RM -#define ADDR_MODE_3_IMMEDIATE ADDR_MODE_2_IMMEDIATE -#define ADDR_MODE_3_INDEX(U_OP, M) ADDR_MODE_2_INDEX(U_OP, M) -#define ADDR_MODE_3_WRITEBACK(ADDR) ADDR_MODE_2_WRITEBACK(ADDR) - -#define DEFINE_INSTRUCTION_ARM(NAME, BODY) \ - static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \ - BODY; \ - } - -#define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY, POST_BODY) \ - DEFINE_INSTRUCTION_ARM(NAME, \ - int rd = (opcode >> 12) & 0xF; \ - int rn = (opcode >> 16) & 0xF; \ - SHIFTER(cpu, opcode); \ - BODY; \ - S_BODY; \ - POST_BODY; \ - if (rd == ARM_PC) { \ - ARM_WRITE_PC; \ - }) - -#define DEFINE_ALU_INSTRUCTION_ARM(NAME, S_BODY, BODY, POST_BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, , _barrelShift, BODY, POST_BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S, S_BODY, _barrelShift, BODY, POST_BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## I, , _immediate, BODY, POST_BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## SI, S_BODY, _immediate, BODY, POST_BODY) - -#define DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDRESS, WRITEBACK, BODY) \ - DEFINE_INSTRUCTION_ARM(NAME, \ - uint32_t address; \ - int rn = (opcode >> 16) & 0xF; \ - int rd = (opcode >> 12) & 0xF; \ - int rm = opcode & 0xF; \ - address = ADDRESS; \ - BODY; \ - WRITEBACK;) - -#define DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME, SHIFTER, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, SHIFTER(ADDR_MODE_2_RN), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_RM)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, SHIFTER(ADDR_MODE_2_RN), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_RM)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## P, ADDR_MODE_2_INDEX(-, SHIFTER(ADDR_MODE_2_RM)), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PW, ADDR_MODE_2_INDEX(-, SHIFTER(ADDR_MODE_2_RM)), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PU, ADDR_MODE_2_INDEX(+, SHIFTER(ADDR_MODE_2_RM)), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PUW, ADDR_MODE_2_INDEX(+, SHIFTER(ADDR_MODE_2_RM)), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) - - -#define DEFINE_LOAD_STORE_INSTRUCTION_ARM(NAME, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _LSL_, ADDR_MODE_2_LSL, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _LSR_, ADDR_MODE_2_LSR, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _ASR_, ADDR_MODE_2_ASR, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _ROR_, ADDR_MODE_2_ROR, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IP, ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPW, ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ - -#define DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(NAME, BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## P, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE)), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IP, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), , BODY) \ - DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ - -// TODO -#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, ADDRESS, S_PRE, S_POST, BODY) \ - DEFINE_INSTRUCTION_ARM(NAME, \ - BODY;) - -#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, ADDR_MODE_4_DA, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, ADDR_MODE_4_DAW, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, ADDR_MODE_4_DB, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, ADDR_MODE_4_DBW, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, ADDR_MODE_4_IA, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, ADDR_MODE_4_IAW, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, ADDR_MODE_4_IB, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, ADDR_MODE_4_IBW, , , BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, ADDR_MODE_4_DA, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, ADDR_MODE_4_DAW, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, ADDR_MODE_4_DB, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, ADDR_MODE_4_DBW, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, ADDR_MODE_4_IA, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, ADDR_MODE_4_IAW, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, ADDR_MODE_4_IB, S_PRE, S_POST, BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, ADDR_MODE_4_IBW, S_PRE, S_POST, BODY) - -// Begin ALU definitions - -DEFINE_ALU_INSTRUCTION_ARM(ADD, ARM_ADDITION_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->gprs[rn] + cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(ADC, ARM_ADDITION_S(cpu->gprs[rn], shifterOperand, cpu->gprs[rd]), \ - int32_t shifterOperand = cpu->shifterOperand + cpu->cpsr.c; \ - cpu->gprs[rd] = cpu->gprs[rn] + shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->gprs[rn] & cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(BIC, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->gprs[rn] & ~cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(CMN, ARM_ADDITION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ - int32_t aluOut = cpu->gprs[rn] + cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(CMP, ARM_SUBTRACTION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ - int32_t aluOut = cpu->gprs[rn] - cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(EOR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->gprs[rn] ^ cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(MOV, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(MVN, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = ~cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(ORR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ - cpu->gprs[rd] = cpu->gprs[rn] | cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(RSB, ARM_SUBTRACTION_S(cpu->shifterOperand, cpu->gprs[rn], d), \ - int32_t d = cpu->shifterOperand - cpu->gprs[rn];, cpu->gprs[rd] = d) - -DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_S(cpu->shifterOperand, n, d), \ - int32_t n = cpu->gprs[rn] + !cpu->cpsr.c; \ - int32_t d = cpu->shifterOperand - n;, cpu->gprs[rd] = d) - -DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_S(cpu->gprs[rn], shifterOperand, d), \ - int32_t shifterOperand = cpu->shifterOperand + !cpu->cpsr.c; \ - int32_t d = cpu->gprs[rn] - shifterOperand;, cpu->gprs[rd] = d) - -DEFINE_ALU_INSTRUCTION_ARM(SUB, ARM_SUBTRACTION_S(cpu->gprs[rn], cpu->shifterOperand, d), \ - int32_t d = cpu->gprs[rn] - cpu->shifterOperand;, cpu->gprs[rd] = d) - -DEFINE_ALU_INSTRUCTION_ARM(TEQ, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ - int32_t aluOut = cpu->gprs[rn] ^ cpu->shifterOperand;, ) - -DEFINE_ALU_INSTRUCTION_ARM(TST, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ - int32_t aluOut = cpu->gprs[rn] & cpu->shifterOperand;, ) - -// End ALU definitions - -// Begin multiply definitions - -DEFINE_INSTRUCTION_ARM(MLA,) -DEFINE_INSTRUCTION_ARM(MLAS,) -DEFINE_INSTRUCTION_ARM(MUL,) -DEFINE_INSTRUCTION_ARM(MULS,) -DEFINE_INSTRUCTION_ARM(SMLAL,) -DEFINE_INSTRUCTION_ARM(SMLALS,) -DEFINE_INSTRUCTION_ARM(SMULL,) -DEFINE_INSTRUCTION_ARM(SMULLS,) -DEFINE_INSTRUCTION_ARM(UMLAL,) -DEFINE_INSTRUCTION_ARM(UMLALS,) -DEFINE_INSTRUCTION_ARM(UMULL,) -DEFINE_INSTRUCTION_ARM(UMULLS,) - -// End multiply definitions - -// Begin load/store definitions - -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address)) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address)) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRBT,) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, address)) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, address)) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, address)) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRT,) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory->store32(cpu->memory, address, cpu->gprs[rd])) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory->store8(cpu->memory, address, cpu->gprs[rd])) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRBT,) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory->store16(cpu->memory, address, cpu->gprs[rd])) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRT,) - -DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM,) -DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM,) - -DEFINE_INSTRUCTION_ARM(SWP,) -DEFINE_INSTRUCTION_ARM(SWPB,) - -// End load/store definitions - -// Begin branch definitions - -DEFINE_INSTRUCTION_ARM(B, \ - int32_t offset = opcode << 8; \ - offset >>= 6; \ - cpu->gprs[ARM_PC] += offset; \ - ARM_WRITE_PC;) - -DEFINE_INSTRUCTION_ARM(BL,) -DEFINE_INSTRUCTION_ARM(BX,) - -// End branch definitions - -// TODO -DEFINE_INSTRUCTION_ARM(ILL,) // Illegal opcode -DEFINE_INSTRUCTION_ARM(MSR,) -DEFINE_INSTRUCTION_ARM(MRS,) -DEFINE_INSTRUCTION_ARM(MSRI,) -DEFINE_INSTRUCTION_ARM(MRSI,) -DEFINE_INSTRUCTION_ARM(SWI,) - -#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ - EMITTER ## NAME - -#define DO_8(DIRECTIVE) \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE, \ - DIRECTIVE - -#define DO_256(DIRECTIVE) \ - DO_8(DO_8(DIRECTIVE)), \ - DO_8(DO_8(DIRECTIVE)), \ - DO_8(DO_8(DIRECTIVE)), \ - DO_8(DO_8(DIRECTIVE)) - -#define DO_INTERLACE(LEFT, RIGHT) \ - LEFT, \ - RIGHT - -#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) \ - DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU)), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ - DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ - 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, W, N) \ - DO_8(0), \ - DO_8(0) - -#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \ - DO_8(DO_8(DO_INTERLACE(0, 0))), \ - DO_8(DO_8(DO_INTERLACE(0, 0))) - -#define DECLARE_ARM_SWI_BLOCK(EMITTER) \ - DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI)) - -#define DECLARE_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_ARM_ALU_BLOCK(EMITTER, MRS, SWP, STRHP, ILL, 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, ILL), \ - 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_ARM_ALU_BLOCK(EMITTER, MRS, SWPB, STRHIP, ILL, ILL), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \ - DECLARE_ARM_ALU_BLOCK(EMITTER, MSR, ILL, STRHIPW, ILL, 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, MRS), \ - 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, MRS), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ - DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \ - 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_SWI_BLOCK(EMITTER) - -static const ARMInstruction _armTable[0x1000] = { - DECLARE_EMITTER_BLOCK(_ARMInstruction) -};
M
src/arm.h
→
src/arm.h
@@ -49,7 +49,6 @@ BANK_UNDEFINED = 5
}; struct ARMCore; -typedef void (*ARMInstruction)(struct ARMCore*, uint32_t opcode); union PSR { struct {@@ -109,7 +108,6 @@ void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory);
void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board); void ARMReset(struct ARMCore* cpu); -void ARMStep(struct ARMCore* cpu); void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); #endif
A
src/isa-arm.c
@@ -0,0 +1,676 @@
+#include "isa-arm.h" + +#include "arm.h" +#include "isa-inlines.h" + +// Addressing mode 1 +static inline void _barrelShift(struct ARMCore* cpu, uint32_t opcode) { + // TODO +} + +static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { + int rotate = (opcode & 0x00000F00) >> 7; + int immediate = opcode & 0x000000FF; + if (!rotate) { + cpu->shifterOperand = immediate; + cpu->shifterCarryOut = cpu->cpsr.c; + } else { + cpu->shifterOperand = ARM_ROR(immediate, rotate); + cpu->shifterCarryOut = ARM_SIGN(cpu->shifterOperand); + } +} + +static const ARMInstruction _armTable[0x1000]; + +static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory* memory, uint32_t address, uint32_t* opcodeOut) { + uint32_t opcode = memory->load32(memory, address); + *opcodeOut = opcode; + return _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; +} + +void ARMStep(struct ARMCore* cpu) { + // TODO + uint32_t opcode; + ARMInstruction instruction = _ARMLoadInstructionARM(cpu->memory, cpu->gprs[ARM_PC] - WORD_SIZE_ARM, &opcode); + cpu->gprs[ARM_PC] += WORD_SIZE_ARM; + + int condition = opcode >> 28; + if (condition == 0xE) { + instruction(cpu, opcode); + } else { + switch (condition) { + case 0x0: + if (!ARM_COND_EQ) { + return; + } + break; + case 0x1: + if (!ARM_COND_NE) { + return; + } + break; + case 0x2: + if (!ARM_COND_CS) { + return; + } + break; + case 0x3: + if (!ARM_COND_CC) { + return; + } + break; + case 0x4: + if (!ARM_COND_MI) { + return; + } + break; + case 0x5: + if (!ARM_COND_PL) { + return; + } + break; + case 0x6: + if (!ARM_COND_VS) { + return; + } + break; + case 0x7: + if (!ARM_COND_VC) { + return; + } + break; + case 0x8: + if (!ARM_COND_HI) { + return; + } + break; + case 0x9: + if (!ARM_COND_LS) { + return; + } + break; + case 0xA: + if (!ARM_COND_GE) { + return; + } + break; + case 0xB: + if (!ARM_COND_LT) { + return; + } + break; + case 0xC: + if (!ARM_COND_GT) { + return; + } + break; + case 0xD: + if (!ARM_COND_GE) { + return; + } + break; + default: + break; + } + } + instruction(cpu, opcode); +} + +// Instruction definitions +// Beware pre-processor antics + +#define ARM_WRITE_PC \ + cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM + +#define ARM_ADDITION_S(M, N, D) \ + if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + cpu->cpsr = cpu->spsr; \ + _ARMReadCPSR(cpu); \ + } else { \ + cpu->cpsr.n = ARM_SIGN(D); \ + cpu->cpsr.z = !(D); \ + cpu->cpsr.c = ARM_CARRY_FROM(M, N, D); \ + cpu->cpsr.v = ARM_V_ADDITION(M, N, D); \ + } + +#define ARM_SUBTRACTION_S(M, N, D) \ + if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + cpu->cpsr = cpu->spsr; \ + _ARMReadCPSR(cpu); \ + } else { \ + cpu->cpsr.n = ARM_SIGN(D); \ + cpu->cpsr.z = !(D); \ + cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ + cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \ + } + +#define ARM_NEUTRAL_S(M, N, D) \ + if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + cpu->cpsr = cpu->spsr; \ + _ARMReadCPSR(cpu); \ + } else { \ + cpu->cpsr.n = ARM_SIGN(D); \ + cpu->cpsr.z = !(D); \ + cpu->cpsr.c = cpu->shifterCarryOut; \ + } + +#define ADDR_MODE_2_ADDRESS (address) +#define ADDR_MODE_2_RN (cpu->gprs[rn]) +#define ADDR_MODE_2_RM (cpu->gprs[rm]) +#define ADDR_MODE_2_IMMEDIATE (opcode & 0x00000FFF) +#define ADDR_MODE_2_INDEX(U_OP, M) (cpu->gprs[rn] U_OP M) +#define ADDR_MODE_2_WRITEBACK(ADDR) (cpu->gprs[rn] = ADDR) +#define ADDR_MODE_2_LSL(I) (cpu->gprs[rm] << I) +#define ADDR_MODE_2_LSR(I) (I ? ((uint32_t) cpu->gprs[rm]) >> I : 0) +#define ADDR_MODE_2_ASR(I) (I ? ((int32_t) cpu->gprs[rm]) >> I : ((int32_t) cpu->gprs[rm]) >> 31) +#define ADDR_MODE_2_ROR(I) (I ? ARM_ROR(cpu->gprs[rm], I) : (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1)) + +#define ADDR_MODE_3_ADDRESS ADDR_MODE_2_ADDRESS +#define ADDR_MODE_3_RN ADDR_MODE_2_RN +#define ADDR_MODE_3_RM ADDR_MODE_2_RM +#define ADDR_MODE_3_IMMEDIATE ADDR_MODE_2_IMMEDIATE +#define ADDR_MODE_3_INDEX(U_OP, M) ADDR_MODE_2_INDEX(U_OP, M) +#define ADDR_MODE_3_WRITEBACK(ADDR) ADDR_MODE_2_WRITEBACK(ADDR) + +#define DEFINE_INSTRUCTION_ARM(NAME, BODY) \ + static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \ + BODY; \ + } + +#define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY, POST_BODY) \ + DEFINE_INSTRUCTION_ARM(NAME, \ + int rd = (opcode >> 12) & 0xF; \ + int rn = (opcode >> 16) & 0xF; \ + SHIFTER(cpu, opcode); \ + BODY; \ + S_BODY; \ + POST_BODY; \ + if (rd == ARM_PC) { \ + ARM_WRITE_PC; \ + }) + +#define DEFINE_ALU_INSTRUCTION_ARM(NAME, S_BODY, BODY, POST_BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, , _barrelShift, BODY, POST_BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S, S_BODY, _barrelShift, BODY, POST_BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## I, , _immediate, BODY, POST_BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## SI, S_BODY, _immediate, BODY, POST_BODY) + +#define DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDRESS, WRITEBACK, BODY) \ + DEFINE_INSTRUCTION_ARM(NAME, \ + uint32_t address; \ + int rn = (opcode >> 16) & 0xF; \ + int rd = (opcode >> 12) & 0xF; \ + int rm = opcode & 0xF; \ + address = ADDRESS; \ + BODY; \ + WRITEBACK;) + +#define DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME, SHIFTER, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, SHIFTER(ADDR_MODE_2_RN), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_RM)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, SHIFTER(ADDR_MODE_2_RN), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_RM)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## P, ADDR_MODE_2_INDEX(-, SHIFTER(ADDR_MODE_2_RM)), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PW, ADDR_MODE_2_INDEX(-, SHIFTER(ADDR_MODE_2_RM)), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PU, ADDR_MODE_2_INDEX(+, SHIFTER(ADDR_MODE_2_RM)), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PUW, ADDR_MODE_2_INDEX(+, SHIFTER(ADDR_MODE_2_RM)), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) + + +#define DEFINE_LOAD_STORE_INSTRUCTION_ARM(NAME, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _LSL_, ADDR_MODE_2_LSL, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _LSR_, ADDR_MODE_2_LSR, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _ASR_, ADDR_MODE_2_ASR, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_SHIFTER_ARM(NAME ## _ROR_, ADDR_MODE_2_ROR, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IP, ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPW, ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \ + +#define DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(NAME, BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## P, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE)), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IP, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), , BODY) \ + DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \ + +// TODO +#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, ADDRESS, S_PRE, S_POST, BODY) \ + DEFINE_INSTRUCTION_ARM(NAME, \ + BODY;) + +#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, ADDR_MODE_4_DA, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, ADDR_MODE_4_DAW, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, ADDR_MODE_4_DB, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, ADDR_MODE_4_DBW, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, ADDR_MODE_4_IA, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, ADDR_MODE_4_IAW, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, ADDR_MODE_4_IB, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, ADDR_MODE_4_IBW, , , BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, ADDR_MODE_4_DA, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, ADDR_MODE_4_DAW, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, ADDR_MODE_4_DB, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, ADDR_MODE_4_DBW, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, ADDR_MODE_4_IA, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, ADDR_MODE_4_IAW, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, ADDR_MODE_4_IB, S_PRE, S_POST, BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, ADDR_MODE_4_IBW, S_PRE, S_POST, BODY) + +// Begin ALU definitions + +DEFINE_ALU_INSTRUCTION_ARM(ADD, ARM_ADDITION_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->gprs[rn] + cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(ADC, ARM_ADDITION_S(cpu->gprs[rn], shifterOperand, cpu->gprs[rd]), \ + int32_t shifterOperand = cpu->shifterOperand + cpu->cpsr.c; \ + cpu->gprs[rd] = cpu->gprs[rn] + shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->gprs[rn] & cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(BIC, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->gprs[rn] & ~cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(CMN, ARM_ADDITION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ + int32_t aluOut = cpu->gprs[rn] + cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(CMP, ARM_SUBTRACTION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ + int32_t aluOut = cpu->gprs[rn] - cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(EOR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->gprs[rn] ^ cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(MOV, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(MVN, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = ~cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(ORR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), \ + cpu->gprs[rd] = cpu->gprs[rn] | cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(RSB, ARM_SUBTRACTION_S(cpu->shifterOperand, cpu->gprs[rn], d), \ + int32_t d = cpu->shifterOperand - cpu->gprs[rn];, cpu->gprs[rd] = d) + +DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_S(cpu->shifterOperand, n, d), \ + int32_t n = cpu->gprs[rn] + !cpu->cpsr.c; \ + int32_t d = cpu->shifterOperand - n;, cpu->gprs[rd] = d) + +DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_S(cpu->gprs[rn], shifterOperand, d), \ + int32_t shifterOperand = cpu->shifterOperand + !cpu->cpsr.c; \ + int32_t d = cpu->gprs[rn] - shifterOperand;, cpu->gprs[rd] = d) + +DEFINE_ALU_INSTRUCTION_ARM(SUB, ARM_SUBTRACTION_S(cpu->gprs[rn], cpu->shifterOperand, d), \ + int32_t d = cpu->gprs[rn] - cpu->shifterOperand;, cpu->gprs[rd] = d) + +DEFINE_ALU_INSTRUCTION_ARM(TEQ, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ + int32_t aluOut = cpu->gprs[rn] ^ cpu->shifterOperand;, ) + +DEFINE_ALU_INSTRUCTION_ARM(TST, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), \ + int32_t aluOut = cpu->gprs[rn] & cpu->shifterOperand;, ) + +// End ALU definitions + +// Begin multiply definitions + +DEFINE_INSTRUCTION_ARM(MLA,) +DEFINE_INSTRUCTION_ARM(MLAS,) +DEFINE_INSTRUCTION_ARM(MUL,) +DEFINE_INSTRUCTION_ARM(MULS,) +DEFINE_INSTRUCTION_ARM(SMLAL,) +DEFINE_INSTRUCTION_ARM(SMLALS,) +DEFINE_INSTRUCTION_ARM(SMULL,) +DEFINE_INSTRUCTION_ARM(SMULLS,) +DEFINE_INSTRUCTION_ARM(UMLAL,) +DEFINE_INSTRUCTION_ARM(UMLALS,) +DEFINE_INSTRUCTION_ARM(UMULL,) +DEFINE_INSTRUCTION_ARM(UMULLS,) + +// End multiply definitions + +// Begin load/store definitions + +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address)) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address)) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRBT,) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, address)) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, address)) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, address)) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRT,) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory->store32(cpu->memory, address, cpu->gprs[rd])) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory->store8(cpu->memory, address, cpu->gprs[rd])) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRBT,) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory->store16(cpu->memory, address, cpu->gprs[rd])) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRT,) + +DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM,) +DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM,) + +DEFINE_INSTRUCTION_ARM(SWP,) +DEFINE_INSTRUCTION_ARM(SWPB,) + +// End load/store definitions + +// Begin branch definitions + +DEFINE_INSTRUCTION_ARM(B, \ + int32_t offset = opcode << 8; \ + offset >>= 6; \ + cpu->gprs[ARM_PC] += offset; \ + ARM_WRITE_PC;) + +DEFINE_INSTRUCTION_ARM(BL,) +DEFINE_INSTRUCTION_ARM(BX,) + +// End branch definitions + +// TODO +DEFINE_INSTRUCTION_ARM(ILL,) // Illegal opcode +DEFINE_INSTRUCTION_ARM(MSR,) +DEFINE_INSTRUCTION_ARM(MRS,) +DEFINE_INSTRUCTION_ARM(MSRI,) +DEFINE_INSTRUCTION_ARM(MRSI,) +DEFINE_INSTRUCTION_ARM(SWI,) + +#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ + EMITTER ## NAME + +#define DO_8(DIRECTIVE) \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE, \ + DIRECTIVE + +#define DO_256(DIRECTIVE) \ + DO_8(DO_8(DIRECTIVE)), \ + DO_8(DO_8(DIRECTIVE)), \ + DO_8(DO_8(DIRECTIVE)), \ + DO_8(DO_8(DIRECTIVE)) + +#define DO_INTERLACE(LEFT, RIGHT) \ + LEFT, \ + RIGHT + +#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) \ + DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU)), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + 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, W, N) \ + DO_8(0), \ + DO_8(0) + +#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \ + DO_8(DO_8(DO_INTERLACE(0, 0))), \ + DO_8(DO_8(DO_INTERLACE(0, 0))) + +#define DECLARE_ARM_SWI_BLOCK(EMITTER) \ + DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI)) + +#define DECLARE_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_ARM_ALU_BLOCK(EMITTER, MRS, SWP, STRHP, ILL, 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, ILL), \ + 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_ARM_ALU_BLOCK(EMITTER, MRS, SWPB, STRHIP, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, MSR, ILL, STRHIPW, ILL, 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, MRS), \ + 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, MRS), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \ + DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \ + 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_SWI_BLOCK(EMITTER) + +static const ARMInstruction _armTable[0x1000] = { + DECLARE_EMITTER_BLOCK(_ARMInstruction) +};
A
src/isa-arm.h
@@ -0,0 +1,11 @@
+#ifndef ISA_ARM_H +#define ISA_ARM_H + +#include <stdint.h> + +struct ARMCore; + +void ARMStep(struct ARMCore* cpu); +typedef void (*ARMInstruction)(struct ARMCore*, uint32_t opcode); + +#endif
A
src/isa-inlines.h
@@ -0,0 +1,52 @@
+#ifndef ISA_INLINES_H +#define ISA_INLINES_H + +#define ARM_COND_EQ (cpu->cpsr.z) +#define ARM_COND_NE (!cpu->cpsr.z) +#define ARM_COND_CS (cpu->cpsr.c) +#define ARM_COND_CC (!cpu->cpsr.c) +#define ARM_COND_MI (cpu->cpsr.n) +#define ARM_COND_PL (!cpu->cpsr.n) +#define ARM_COND_VS (cpu->cpsr.v) +#define ARM_COND_VC (!cpu->cpsr.v) +#define ARM_COND_HI (cpu->cpsr.c && !cpu->cpsr.z) +#define ARM_COND_LS (!cpu->cpsr.c || cpu->cpsr.z) +#define ARM_COND_GE (!cpu->cpsr.n == !cpu->cpsr.v) +#define ARM_COND_LT (!cpu->cpsr.n != !cpu->cpsr.v) +#define ARM_COND_GT (!cpu->cpsr.z && !cpu->cpsr.n == !cpu->cpsr.v) +#define ARM_COND_LE (cpu->cpsr.z || !cpu->cpsr.n != !cpu->cpsr.v) +#define ARM_COND_AL 1 + +#define ARM_SIGN(I) ((I) >> 31) +#define ARM_ROR(I, ROTATE) (((I) >> ROTATE) | (I << (32 - ROTATE))) + +#define ARM_CARRY_FROM(M, N, D) ((ARM_SIGN((M) | (N))) && !(ARM_SIGN(D))) +#define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N))) +#define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))) && (ARM_SIGN((N) ^ (D)))) +#define ARM_V_SUBTRACTION(M, N, D) ((ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D)))) + +static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) { + return mode != MODE_SYSTEM && mode != MODE_USER; +} + +static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode executionMode) { + if (executionMode == cpu->executionMode) { + return; + } + + cpu->executionMode = executionMode; + switch (executionMode) { + case MODE_ARM: + cpu->cpsr.t = 0; + break; + case MODE_THUMB: + cpu->cpsr.t = 1; + } +} + +static inline void _ARMReadCPSR(struct ARMCore* cpu) { + _ARMSetMode(cpu, cpu->cpsr.t); + ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); +} + +#endif
M
src/main.c
→
src/main.c
@@ -1,5 +1,6 @@
#include "arm.h" #include "gba.h" +#include "isa-arm.h" #include <sys/stat.h> #include <fcntl.h>