ARM: Start implementing ARMv5 instructions
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014 Jeffrey Pfau +/* Copyright (c) 2013-2016 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this@@ -223,70 +223,6 @@ cpu->cpsr.i = 1;
cpu->cycles += currentCycles; } -static inline void ARMStep(struct ARMCore* cpu) { - uint32_t opcode = cpu->prefetch[0]; - cpu->prefetch[0] = cpu->prefetch[1]; - cpu->gprs[ARM_PC] += WORD_SIZE_ARM; - LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); - - unsigned condition = opcode >> 28; - if (condition != 0xE) { - bool conditionMet = false; - switch (condition) { - case 0x0: - conditionMet = ARM_COND_EQ; - break; - case 0x1: - conditionMet = ARM_COND_NE; - break; - case 0x2: - conditionMet = ARM_COND_CS; - break; - case 0x3: - conditionMet = ARM_COND_CC; - break; - case 0x4: - conditionMet = ARM_COND_MI; - break; - case 0x5: - conditionMet = ARM_COND_PL; - break; - case 0x6: - conditionMet = ARM_COND_VS; - break; - case 0x7: - conditionMet = ARM_COND_VC; - break; - case 0x8: - conditionMet = ARM_COND_HI; - break; - case 0x9: - conditionMet = ARM_COND_LS; - break; - case 0xA: - conditionMet = ARM_COND_GE; - break; - case 0xB: - conditionMet = ARM_COND_LT; - break; - case 0xC: - conditionMet = ARM_COND_GT; - break; - case 0xD: - conditionMet = ARM_COND_LE; - break; - default: - break; - } - if (!conditionMet) { - cpu->cycles += ARM_PREFETCH_CYCLES; - return; - } - } - ARMInstruction instruction = _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; - instruction(cpu, opcode); -} - static inline void ThumbStep(struct ARMCore* cpu) { uint32_t opcode = cpu->prefetch[0]; cpu->prefetch[0] = cpu->prefetch[1];@@ -296,51 +232,119 @@ ThumbInstruction instruction = _thumbTable[opcode >> 6];
instruction(cpu, opcode); } -void ARMRun(struct ARMCore* cpu) { - if (cpu->executionMode == MODE_THUMB) { - ThumbStep(cpu); - } else { - ARMStep(cpu); - } - if (cpu->cycles >= cpu->nextEvent) { - cpu->irqh.processEvents(cpu); - } -} - -void ARMRunLoop(struct ARMCore* cpu) { - if (cpu->executionMode == MODE_THUMB) { - while (cpu->cycles < cpu->nextEvent) { - ThumbStep(cpu); - } - } else { - while (cpu->cycles < cpu->nextEvent) { - ARMStep(cpu); - } - } - cpu->irqh.processEvents(cpu); -} - -int32_t ARMRunCycles(struct ARMCore* cpu, int32_t cycles) { - int32_t startCycles = cpu->cycles; - int32_t endCycles = startCycles + cycles; - - if (cpu->executionMode == MODE_THUMB) { - while (cpu->cycles < cpu->nextEvent && cpu->cycles < endCycles) { - ThumbStep(cpu); - } - } else { - while (cpu->cycles < cpu->nextEvent && cpu->cycles < endCycles) { - ARMStep(cpu); - } +#define ARM_IMPLEMENT(VERSION) \ + static inline void ARM ## VERSION ## Step(struct ARMCore* cpu) { \ + uint32_t opcode = cpu->prefetch[0]; \ + cpu->prefetch[0] = cpu->prefetch[1]; \ + cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \ + LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ + \ + unsigned condition = opcode >> 28; \ + if (condition != 0xE) { \ + bool conditionMet = false; \ + switch (condition) { \ + case 0x0: \ + conditionMet = ARM_COND_EQ; \ + break; \ + case 0x1: \ + conditionMet = ARM_COND_NE; \ + break; \ + case 0x2: \ + conditionMet = ARM_COND_CS; \ + break; \ + case 0x3: \ + conditionMet = ARM_COND_CC; \ + break; \ + case 0x4: \ + conditionMet = ARM_COND_MI; \ + break; \ + case 0x5: \ + conditionMet = ARM_COND_PL; \ + break; \ + case 0x6: \ + conditionMet = ARM_COND_VS; \ + break; \ + case 0x7: \ + conditionMet = ARM_COND_VC; \ + break; \ + case 0x8: \ + conditionMet = ARM_COND_HI; \ + break; \ + case 0x9: \ + conditionMet = ARM_COND_LS; \ + break; \ + case 0xA: \ + conditionMet = ARM_COND_GE; \ + break; \ + case 0xB: \ + conditionMet = ARM_COND_LT; \ + break; \ + case 0xC: \ + conditionMet = ARM_COND_GT; \ + break; \ + case 0xD: \ + conditionMet = ARM_COND_LE; \ + break; \ + default: \ + break; \ + } \ + if (!conditionMet) { \ + cpu->cycles += ARM_PREFETCH_CYCLES; \ + return; \ + } \ + } \ + ARMInstruction instruction = _arm ## VERSION ## Table[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; \ + instruction(cpu, opcode); \ + } \ + \ + void ARM ## VERSION ## Run(struct ARMCore* cpu) { \ + if (cpu->executionMode == MODE_THUMB) { \ + ThumbStep(cpu); \ + } else { \ + ARM ## VERSION ## Step(cpu); \ + } \ + if (cpu->cycles >= cpu->nextEvent) { \ + cpu->irqh.processEvents(cpu); \ + } \ + } \ + \ + void ARM ## VERSION ## RunLoop(struct ARMCore* cpu) { \ + if (cpu->executionMode == MODE_THUMB) { \ + while (cpu->cycles < cpu->nextEvent) { \ + ThumbStep(cpu); \ + } \ + } else { \ + while (cpu->cycles < cpu->nextEvent) { \ + ARM ## VERSION ## Step(cpu); \ + } \ + } \ + cpu->irqh.processEvents(cpu); \ + } \ + \ + int32_t ARM ## VERSION ## RunCycles(struct ARMCore* cpu, int32_t cycles) { \ + int32_t startCycles = cpu->cycles; \ + int32_t endCycles = startCycles + cycles; \ + \ + if (cpu->executionMode == MODE_THUMB) { \ + while (cpu->cycles < cpu->nextEvent && cpu->cycles < endCycles) { \ + ThumbStep(cpu); \ + } \ + } else { \ + while (cpu->cycles < cpu->nextEvent && cpu->cycles < endCycles) { \ + ARM ## VERSION ## Step(cpu); \ + } \ + } \ + \ + endCycles = cpu->cycles - startCycles; \ + if (cpu->cycles >= cpu->nextEvent) { \ + /* TODO: Handle HALT */ \ + cpu->irqh.processEvents(cpu); \ + } \ + return endCycles; \ } - endCycles = cpu->cycles - startCycles; - if (cpu->cycles >= cpu->nextEvent) { - // TODO: Handle HALT - cpu->irqh.processEvents(cpu); - } - return endCycles; -} +ARM_IMPLEMENT(v4) +ARM_IMPLEMENT(v5) void ARMRunFake(struct ARMCore* cpu, uint32_t opcode) { if (cpu->executionMode == MODE_ARM) {
@@ -253,9 +253,12 @@ void ARMRaiseIRQ(struct ARMCore*);
void ARMRaiseSWI(struct ARMCore*); void ARMRaiseUndefined(struct ARMCore*); -void ARMRun(struct ARMCore* cpu); -void ARMRunLoop(struct ARMCore* cpu); -int32_t ARMRunCycles(struct ARMCore* cpu, int32_t cycles); +void ARMv4Run(struct ARMCore* cpu); +void ARMv4RunLoop(struct ARMCore* cpu); +int32_t ARMv4RunCycles(struct ARMCore* cpu, int32_t cycles); +void ARMv5Run(struct ARMCore* cpu); +void ARMv5RunLoop(struct ARMCore* cpu); +int32_t ARMv5RunCycles(struct ARMCore* cpu, int32_t cycles); void ARMRunFake(struct ARMCore* cpu, uint32_t opcode); #endif
@@ -383,6 +383,13 @@ DEFINE_DECODER_ARM(ILL, ILL,
info->operandFormat = ARM_OPERAND_NONE; info->traps = 1;) // Illegal opcode +DEFINE_DECODER_ARM(CLZ, CLZ, + 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;) + DEFINE_DECODER_ARM(MSR, MSR, info->affectsCPSR = 1; info->op1.reg = ARM_CPSR;@@ -446,7 +453,7 @@
typedef void (*ARMDecoder)(uint32_t opcode, struct ARMInstructionInfo* info); static const ARMDecoder _armDecoderTable[0x1000] = { - DECLARE_ARM_EMITTER_BLOCK(_ARMDecode) + DECLARE_ARMV5_EMITTER_BLOCK(_ARMDecode) }; void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info) {
@@ -252,6 +252,7 @@ "bkpt",
"bl", "bx", "cdp", + "clz", "cmn", "cmp", "eor",
@@ -160,6 +160,7 @@ ARM_MN_BKPT,
ARM_MN_BL, ARM_MN_BX, ARM_MN_CDP, + ARM_MN_CLZ, ARM_MN_CMN, ARM_MN_CMP, ARM_MN_EOR,
@@ -75,7 +75,7 @@
#define DECLARE_ARM_SWI_BLOCK(EMITTER) \ DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI)) -#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \ +#define DECLARE_ARMV4_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, STRH, ILL, ILL), \@@ -145,6 +145,264 @@ 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, MRC), \ + DECLARE_ARM_SWI_BLOCK(EMITTER) + +#define DECLARE_ARMV5_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, STRH, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \ + 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, STRHI, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \ + 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, STRHU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \ + 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, STRHIU, ILL, ILL), \ + DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \ + 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, CLZ), \ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
@@ -8,6 +8,7 @@
#include "arm.h" #include "emitter-arm.h" #include "isa-inlines.h" +#include "util/math.h" #define PSR_USER_MASK 0xF0000000 #define PSR_PRIV_MASK 0x000000CF@@ -648,6 +649,11 @@ DEFINE_INSTRUCTION_ARM(STC, ARM_STUB)
// Begin miscellaneous definitions +DEFINE_INSTRUCTION_ARM(CLZ, + int rm = opcode & 0xF; + int rd = (opcode >> 12) & 0xF; + cpu->gprs[rd] = clz32(cpu->gprs[rm]);) + DEFINE_INSTRUCTION_ARM(BKPT, cpu->irqh.bkpt32(cpu, ((opcode >> 4) & 0xFFF0) | (opcode & 0xF))); // Not strictly in ARMv4T, but here for convenience DEFINE_INSTRUCTION_ARM(ILL, ARM_ILL) // Illegal opcode@@ -727,6 +733,10 @@ cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask) | 0x00000010;)
DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF)) -const ARMInstruction _armTable[0x1000] = { - DECLARE_ARM_EMITTER_BLOCK(_ARMInstruction) +const ARMInstruction _armv4Table[0x1000] = { + DECLARE_ARMV4_EMITTER_BLOCK(_ARMInstruction) +}; + +const ARMInstruction _armv5Table[0x1000] = { + DECLARE_ARMV5_EMITTER_BLOCK(_ARMInstruction) };
@@ -13,6 +13,7 @@
struct ARMCore; typedef void (*ARMInstruction)(struct ARMCore*, uint32_t opcode); -extern const ARMInstruction _armTable[0x1000]; +extern const ARMInstruction _armv4Table[0x1000]; +extern const ARMInstruction _armv5Table[0x1000]; #endif
@@ -168,10 +168,10 @@ struct DS* ds = core->board;
int32_t frameCounter = ds->video.frameCounter; while (ds->video.frameCounter == frameCounter) { if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMRunCycles(dscore->arm9, SLICE_CYCLES); + dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES); } if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMRunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; + dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; } } }@@ -179,10 +179,10 @@
static void _DSCoreRunLoop(struct mCore* core) { struct DSCore* dscore = (struct DSCore*) core; if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMRunCycles(dscore->arm9, SLICE_CYCLES); + dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES); } if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMRunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; + dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; } }@@ -191,20 +191,20 @@ struct DSCore* dscore = (struct DSCore*) core;
if (core->cpu == dscore->arm9) { do { if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMRunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; + dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; } if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMRunCycles(dscore->arm9, 1); + dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, 1); break; } } while (dscore->cycleDrift >= SLICE_CYCLES); } else { do { if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMRunCycles(dscore->arm9, SLICE_CYCLES - dscore->cycleDrift); + dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES - dscore->cycleDrift); } if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMRunCycles(dscore->arm7, 1) << 1; + dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, 1) << 1; break; } } while (dscore->cycleDrift < SLICE_CYCLES);
@@ -30,9 +30,9 @@ value |= ds->memory.io7[address >> 1] & 0x000F;
_writeIPCSync(ds->arm9, ds->memory.io9, value); break; default: - mLOG(DS_IO, STUB, "Stub DS7 I/O register write: %06X", address); + mLOG(DS_IO, STUB, "Stub DS7 I/O register write: %06X:%04X", address, value); if (address >= DS7_REG_MAX) { - mLOG(DS_IO, GAME_ERROR, "Write to unused DS7 I/O register: %06X", address); + mLOG(DS_IO, GAME_ERROR, "Write to unused DS7 I/O register: %06X:%04X", address, value); return; } break;@@ -78,9 +78,9 @@ value |= ds->memory.io9[address >> 1] & 0x000F;
_writeIPCSync(ds->arm7, ds->memory.io7, value); break; default: - mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X", address); + mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address, value); if (address >= DS7_REG_MAX) { - mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X", address); + mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X:%04X", address, value); return; } break;
@@ -293,16 +293,16 @@ static void _GBACoreRunFrame(struct mCore* core) {
struct GBA* gba = core->board; int32_t frameCounter = gba->video.frameCounter; while (gba->video.frameCounter == frameCounter) { - ARMRunLoop(core->cpu); + ARMv4RunLoop(core->cpu); } } static void _GBACoreRunLoop(struct mCore* core) { - ARMRunLoop(core->cpu); + ARMv4RunLoop(core->cpu); } static void _GBACoreStep(struct mCore* core) { - ARMRun(core->cpu); + ARMv4Run(core->cpu); } static size_t _GBACoreStateSize(struct mCore* core) {