src/arm/arm-version.c (view raw)
1/* Copyright (c) 2013-2020 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#ifndef VERSION
7#error VERSION is undeclared
8#else
9// The C preprocessor is kinda bad at when it expands variables, so the indirection is needed
10#define CONCAT(X, Y, Z) X ## Y ## Z
11#define PREFIX_ARM(B, C) CONCAT(ARMv, B, C)
12#define PREFIX_THUMB(B, C) CONCAT(Thumbv, B, C)
13#define ARM(SUFFIX) PREFIX_ARM(VERSION, SUFFIX)
14#define Thumb(SUFFIX) PREFIX_THUMB(VERSION, SUFFIX)
15#endif
16
17static inline void ARM(Step)(struct ARMCore* cpu) {
18 uint32_t opcode = cpu->prefetch[0];
19 cpu->prefetch[0] = cpu->prefetch[1];
20 cpu->gprs[ARM_PC] += WORD_SIZE_ARM;
21 LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
22
23 ARMInstruction instruction;
24 unsigned condition = opcode >> 28;
25 if (condition != 0xE) {
26 bool conditionMet = false;
27 switch (condition) {
28 case 0x0:
29 conditionMet = ARM_COND_EQ;
30 break;
31 case 0x1:
32 conditionMet = ARM_COND_NE;
33 break;
34 case 0x2:
35 conditionMet = ARM_COND_CS;
36 break;
37 case 0x3:
38 conditionMet = ARM_COND_CC;
39 break;
40 case 0x4:
41 conditionMet = ARM_COND_MI;
42 break;
43 case 0x5:
44 conditionMet = ARM_COND_PL;
45 break;
46 case 0x6:
47 conditionMet = ARM_COND_VS;
48 break;
49 case 0x7:
50 conditionMet = ARM_COND_VC;
51 break;
52 case 0x8:
53 conditionMet = ARM_COND_HI;
54 break;
55 case 0x9:
56 conditionMet = ARM_COND_LS;
57 break;
58 case 0xA:
59 conditionMet = ARM_COND_GE;
60 break;
61 case 0xB:
62 conditionMet = ARM_COND_LT;
63 break;
64 case 0xC:
65 conditionMet = ARM_COND_GT;
66 break;
67 case 0xD:
68 conditionMet = ARM_COND_LE;
69 break;
70 default:
71#if VERSION > 4
72 instruction = ARM(FInstructionTable)[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
73 instruction(cpu, opcode);
74#endif
75 return;
76 }
77 if (!conditionMet) {
78 cpu->cycles += ARM_PREFETCH_CYCLES;
79 return;
80 }
81 }
82 instruction = ARM(InstructionTable)[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
83 instruction(cpu, opcode);
84}
85
86static inline void Thumb(Step)(struct ARMCore* cpu) {
87 uint32_t opcode = cpu->prefetch[0];
88 cpu->prefetch[0] = cpu->prefetch[1];
89 cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
90 LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
91 ThumbInstruction instruction = Thumb(InstructionTable)[opcode >> 6];
92 instruction(cpu, opcode);
93}
94
95void ARM(Run)(struct ARMCore* cpu) {
96 while (cpu->cycles >= cpu->nextEvent) {
97 cpu->irqh.processEvents(cpu);
98 }
99 if (cpu->executionMode == MODE_THUMB) {
100 Thumb(Step)(cpu);
101 } else {
102 ARM(Step)(cpu);
103 }
104}
105
106void ARM(RunLoop)(struct ARMCore* cpu) {
107 if (cpu->executionMode == MODE_THUMB) {
108 while (cpu->cycles < cpu->nextEvent) {
109 Thumb(Step)(cpu);
110 }
111 } else {
112 while (cpu->cycles < cpu->nextEvent) {
113 ARM(Step)(cpu);
114 }
115 }
116 cpu->irqh.processEvents(cpu);
117}
118
119#undef ARM
120#undef Thumb
121#undef PREFIX_ARM
122#undef PREFIX_THUMB
123#undef CONCAT
124#undef VERSION