src/arm/arm.c (view raw)
1#include "arm.h"
2
3#include "isa-arm.h"
4#include "isa-inlines.h"
5#include "isa-thumb.h"
6
7static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode);
8
9void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) {
10 if (mode == cpu->privilegeMode) {
11 // Not switching modes after all
12 return;
13 }
14
15 enum RegisterBank newBank = _ARMSelectBank(mode);
16 enum RegisterBank oldBank = _ARMSelectBank(cpu->privilegeMode);
17 if (newBank != oldBank) {
18 // Switch banked registers
19 if (mode == MODE_FIQ || cpu->privilegeMode == MODE_FIQ) {
20 int oldFIQBank = oldBank == BANK_FIQ;
21 int newFIQBank = newBank == BANK_FIQ;
22 cpu->bankedRegisters[oldFIQBank][2] = cpu->gprs[8];
23 cpu->bankedRegisters[oldFIQBank][3] = cpu->gprs[9];
24 cpu->bankedRegisters[oldFIQBank][4] = cpu->gprs[10];
25 cpu->bankedRegisters[oldFIQBank][5] = cpu->gprs[11];
26 cpu->bankedRegisters[oldFIQBank][6] = cpu->gprs[12];
27 cpu->gprs[8] = cpu->bankedRegisters[newFIQBank][2];
28 cpu->gprs[9] = cpu->bankedRegisters[newFIQBank][3];
29 cpu->gprs[10] = cpu->bankedRegisters[newFIQBank][4];
30 cpu->gprs[11] = cpu->bankedRegisters[newFIQBank][5];
31 cpu->gprs[12] = cpu->bankedRegisters[newFIQBank][6];
32 }
33 cpu->bankedRegisters[oldBank][0] = cpu->gprs[ARM_SP];
34 cpu->bankedRegisters[oldBank][1] = cpu->gprs[ARM_LR];
35 cpu->gprs[ARM_SP] = cpu->bankedRegisters[newBank][0];
36 cpu->gprs[ARM_LR] = cpu->bankedRegisters[newBank][1];
37
38 cpu->bankedSPSRs[oldBank] = cpu->spsr.packed;
39 cpu->spsr.packed = cpu->bankedSPSRs[newBank];
40
41 }
42 cpu->privilegeMode = mode;
43}
44
45static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) {
46 switch (mode) {
47 case MODE_USER:
48 case MODE_SYSTEM:
49 // No banked registers
50 return BANK_NONE;
51 case MODE_FIQ:
52 return BANK_FIQ;
53 case MODE_IRQ:
54 return BANK_IRQ;
55 case MODE_SUPERVISOR:
56 return BANK_SUPERVISOR;
57 case MODE_ABORT:
58 return BANK_ABORT;
59 case MODE_UNDEFINED:
60 return BANK_UNDEFINED;
61 default:
62 // This should be unreached
63 return BANK_NONE;
64 }
65}
66
67void ARMInit(struct ARMCore* cpu) {
68 cpu->memory = 0;
69 cpu->board = 0;
70}
71
72void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory) {
73 cpu->memory = memory;
74}
75
76void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board) {
77 cpu->board = board;
78 board->cpu = cpu;
79}
80
81void ARMReset(struct ARMCore* cpu) {
82 int i;
83 for (i = 0; i < 16; ++i) {
84 cpu->gprs[i] = 0;
85 }
86 for (i = 0; i < 6; ++i) {
87 cpu->bankedRegisters[i][0] = 0;
88 cpu->bankedRegisters[i][1] = 0;
89 cpu->bankedRegisters[i][2] = 0;
90 cpu->bankedRegisters[i][3] = 0;
91 cpu->bankedRegisters[i][4] = 0;
92 cpu->bankedRegisters[i][5] = 0;
93 cpu->bankedRegisters[i][6] = 0;
94 cpu->bankedSPSRs[i] = 0;
95 }
96
97 cpu->cpsr.packed = MODE_SYSTEM;
98 cpu->spsr.packed = 0;
99
100 cpu->cyclesToEvent = 0;
101
102 cpu->shifterOperand = 0;
103 cpu->shifterCarryOut = 0;
104
105 cpu->executionMode = MODE_THUMB;
106 _ARMSetMode(cpu, MODE_ARM);
107
108 cpu->board->reset(cpu->board);
109}
110
111void ARMRun(struct ARMCore* cpu) {
112 if (cpu->executionMode == MODE_THUMB) {
113 ThumbStep(cpu);
114 } else {
115 ARMStep(cpu);
116 }
117}