rlm@1
|
1 #ifdef C_CORE
|
rlm@1
|
2 #define NEG(i) ((i) >> 31)
|
rlm@1
|
3 #define POS(i) ((~(i)) >> 31)
|
rlm@1
|
4 #define ADDCARRY(a, b, c) \
|
rlm@1
|
5 C_FLAG = ((NEG(a) & NEG(b)) | \
|
rlm@1
|
6 (NEG(a) & POS(c)) | \
|
rlm@1
|
7 (NEG(b) & POS(c))) ? true : false;
|
rlm@1
|
8 #define ADDOVERFLOW(a, b, c) \
|
rlm@1
|
9 V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \
|
rlm@1
|
10 (POS(a) & POS(b) & NEG(c))) ? true : false;
|
rlm@1
|
11 #define SUBCARRY(a, b, c) \
|
rlm@1
|
12 C_FLAG = ((NEG(a) & POS(b)) | \
|
rlm@1
|
13 (NEG(a) & POS(c)) | \
|
rlm@1
|
14 (POS(b) & POS(c))) ? true : false;
|
rlm@1
|
15 #define SUBOVERFLOW(a, b, c) \
|
rlm@1
|
16 V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \
|
rlm@1
|
17 (POS(a) & NEG(b) & NEG(c))) ? true : false;
|
rlm@1
|
18 #define ADD_RD_RS_RN \
|
rlm@1
|
19 { \
|
rlm@1
|
20 u32 lhs = reg[source].I; \
|
rlm@1
|
21 u32 rhs = value; \
|
rlm@1
|
22 u32 res = lhs + rhs; \
|
rlm@1
|
23 reg[dest].I = res; \
|
rlm@1
|
24 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
25 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
26 ADDCARRY(lhs, rhs, res); \
|
rlm@1
|
27 ADDOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
28 }
|
rlm@1
|
29 #define ADD_RD_RS_O3 \
|
rlm@1
|
30 { \
|
rlm@1
|
31 u32 lhs = reg[source].I; \
|
rlm@1
|
32 u32 rhs = value; \
|
rlm@1
|
33 u32 res = lhs + rhs; \
|
rlm@1
|
34 reg[dest].I = res; \
|
rlm@1
|
35 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
36 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
37 ADDCARRY(lhs, rhs, res); \
|
rlm@1
|
38 ADDOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
39 }
|
rlm@1
|
40 #define ADD_RN_O8(d) \
|
rlm@1
|
41 { \
|
rlm@1
|
42 u32 lhs = reg[(d)].I; \
|
rlm@1
|
43 u32 rhs = (opcode & 255); \
|
rlm@1
|
44 u32 res = lhs + rhs; \
|
rlm@1
|
45 reg[(d)].I = res; \
|
rlm@1
|
46 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
47 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
48 ADDCARRY(lhs, rhs, res); \
|
rlm@1
|
49 ADDOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
50 }
|
rlm@1
|
51 #define CMN_RD_RS \
|
rlm@1
|
52 { \
|
rlm@1
|
53 u32 lhs = reg[dest].I; \
|
rlm@1
|
54 u32 rhs = value; \
|
rlm@1
|
55 u32 res = lhs + rhs; \
|
rlm@1
|
56 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
57 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
58 ADDCARRY(lhs, rhs, res); \
|
rlm@1
|
59 ADDOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
60 }
|
rlm@1
|
61 #define ADC_RD_RS \
|
rlm@1
|
62 { \
|
rlm@1
|
63 u32 lhs = reg[dest].I; \
|
rlm@1
|
64 u32 rhs = value; \
|
rlm@1
|
65 u32 res = lhs + rhs + (u32)C_FLAG; \
|
rlm@1
|
66 reg[dest].I = res; \
|
rlm@1
|
67 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
68 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
69 ADDCARRY(lhs, rhs, res); \
|
rlm@1
|
70 ADDOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
71 }
|
rlm@1
|
72 #define SUB_RD_RS_RN \
|
rlm@1
|
73 { \
|
rlm@1
|
74 u32 lhs = reg[source].I; \
|
rlm@1
|
75 u32 rhs = value; \
|
rlm@1
|
76 u32 res = lhs - rhs; \
|
rlm@1
|
77 reg[dest].I = res; \
|
rlm@1
|
78 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
79 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
80 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
81 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
82 }
|
rlm@1
|
83 #define SUB_RD_RS_O3 \
|
rlm@1
|
84 { \
|
rlm@1
|
85 u32 lhs = reg[source].I; \
|
rlm@1
|
86 u32 rhs = value; \
|
rlm@1
|
87 u32 res = lhs - rhs; \
|
rlm@1
|
88 reg[dest].I = res; \
|
rlm@1
|
89 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
90 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
91 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
92 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
93 }
|
rlm@1
|
94 #define SUB_RN_O8(d) \
|
rlm@1
|
95 { \
|
rlm@1
|
96 u32 lhs = reg[(d)].I; \
|
rlm@1
|
97 u32 rhs = (opcode & 255); \
|
rlm@1
|
98 u32 res = lhs - rhs; \
|
rlm@1
|
99 reg[(d)].I = res; \
|
rlm@1
|
100 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
101 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
102 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
103 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
104 }
|
rlm@1
|
105 #define CMP_RN_O8(d) \
|
rlm@1
|
106 { \
|
rlm@1
|
107 u32 lhs = reg[(d)].I; \
|
rlm@1
|
108 u32 rhs = (opcode & 255); \
|
rlm@1
|
109 u32 res = lhs - rhs; \
|
rlm@1
|
110 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
111 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
112 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
113 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
114 }
|
rlm@1
|
115 #define SBC_RD_RS \
|
rlm@1
|
116 { \
|
rlm@1
|
117 u32 lhs = reg[dest].I; \
|
rlm@1
|
118 u32 rhs = value; \
|
rlm@1
|
119 u32 res = lhs - rhs - !((u32)C_FLAG); \
|
rlm@1
|
120 reg[dest].I = res; \
|
rlm@1
|
121 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
122 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
123 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
124 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
125 }
|
rlm@1
|
126 #define LSL_RD_RM_I5 \
|
rlm@1
|
127 { \
|
rlm@1
|
128 C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \
|
rlm@1
|
129 value = reg[source].I << shift; \
|
rlm@1
|
130 }
|
rlm@1
|
131 #define LSL_RD_RS \
|
rlm@1
|
132 { \
|
rlm@1
|
133 C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \
|
rlm@1
|
134 value = reg[dest].I << value; \
|
rlm@1
|
135 }
|
rlm@1
|
136 #define LSR_RD_RM_I5 \
|
rlm@1
|
137 { \
|
rlm@1
|
138 C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \
|
rlm@1
|
139 value = reg[source].I >> shift; \
|
rlm@1
|
140 }
|
rlm@1
|
141 #define LSR_RD_RS \
|
rlm@1
|
142 { \
|
rlm@1
|
143 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
|
rlm@1
|
144 value = reg[dest].I >> value; \
|
rlm@1
|
145 }
|
rlm@1
|
146 #define ASR_RD_RM_I5 \
|
rlm@1
|
147 { \
|
rlm@1
|
148 C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \
|
rlm@1
|
149 value = (s32)reg[source].I >> (int)shift; \
|
rlm@1
|
150 }
|
rlm@1
|
151 #define ASR_RD_RS \
|
rlm@1
|
152 { \
|
rlm@1
|
153 C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \
|
rlm@1
|
154 value = (s32)reg[dest].I >> (int)value; \
|
rlm@1
|
155 }
|
rlm@1
|
156 #define ROR_RD_RS \
|
rlm@1
|
157 { \
|
rlm@1
|
158 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
|
rlm@1
|
159 value = ((reg[dest].I << (32 - value)) | \
|
rlm@1
|
160 (reg[dest].I >> value)); \
|
rlm@1
|
161 }
|
rlm@1
|
162 #define NEG_RD_RS \
|
rlm@1
|
163 { \
|
rlm@1
|
164 u32 lhs = reg[source].I; \
|
rlm@1
|
165 u32 rhs = 0; \
|
rlm@1
|
166 u32 res = rhs - lhs; \
|
rlm@1
|
167 reg[dest].I = res; \
|
rlm@1
|
168 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
169 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
170 SUBCARRY(rhs, lhs, res); \
|
rlm@1
|
171 SUBOVERFLOW(rhs, lhs, res); \
|
rlm@1
|
172 }
|
rlm@1
|
173 #define CMP_RD_RS \
|
rlm@1
|
174 { \
|
rlm@1
|
175 u32 lhs = reg[dest].I; \
|
rlm@1
|
176 u32 rhs = value; \
|
rlm@1
|
177 u32 res = lhs - rhs; \
|
rlm@1
|
178 Z_FLAG = (res == 0) ? true : false; \
|
rlm@1
|
179 N_FLAG = NEG(res) ? true : false; \
|
rlm@1
|
180 SUBCARRY(lhs, rhs, res); \
|
rlm@1
|
181 SUBOVERFLOW(lhs, rhs, res); \
|
rlm@1
|
182 }
|
rlm@1
|
183 #else
|
rlm@1
|
184 #ifdef __GNUC__
|
rlm@1
|
185 #ifdef __POWERPC__
|
rlm@1
|
186 #define ADD_RD_RS_RN \
|
rlm@1
|
187 { \
|
rlm@1
|
188 register int Flags; \
|
rlm@1
|
189 register int Result; \
|
rlm@1
|
190 asm volatile ("addco. %0, %2, %3\n" \
|
rlm@1
|
191 "mcrxr cr1\n" \
|
rlm@1
|
192 "mfcr %1\n" \
|
rlm@1
|
193 : "=r" (Result), \
|
rlm@1
|
194 "=r" (Flags) \
|
rlm@1
|
195 : "r" (reg[source].I), \
|
rlm@1
|
196 "r" (value) \
|
rlm@1
|
197 ); \
|
rlm@1
|
198 reg[dest].I = Result; \
|
rlm@1
|
199 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
200 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
201 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
202 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
203 }
|
rlm@1
|
204 #define ADD_RD_RS_O3 ADD_RD_RS_RN
|
rlm@1
|
205 #define ADD_RN_O8(d) \
|
rlm@1
|
206 { \
|
rlm@1
|
207 register int Flags; \
|
rlm@1
|
208 register int Result; \
|
rlm@1
|
209 asm volatile ("addco. %0, %2, %3\n" \
|
rlm@1
|
210 "mcrxr cr1\n" \
|
rlm@1
|
211 "mfcr %1\n" \
|
rlm@1
|
212 : "=r" (Result), \
|
rlm@1
|
213 "=r" (Flags) \
|
rlm@1
|
214 : "r" (reg[(d)].I), \
|
rlm@1
|
215 "r" (opcode & 255) \
|
rlm@1
|
216 ); \
|
rlm@1
|
217 reg[(d)].I = Result; \
|
rlm@1
|
218 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
219 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
220 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
221 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
222 }
|
rlm@1
|
223 #define CMN_RD_RS \
|
rlm@1
|
224 { \
|
rlm@1
|
225 register int Flags; \
|
rlm@1
|
226 register int Result; \
|
rlm@1
|
227 asm volatile ("addco. %0, %2, %3\n" \
|
rlm@1
|
228 "mcrxr cr1\n" \
|
rlm@1
|
229 "mfcr %1\n" \
|
rlm@1
|
230 : "=r" (Result), \
|
rlm@1
|
231 "=r" (Flags) \
|
rlm@1
|
232 : "r" (reg[dest].I), \
|
rlm@1
|
233 "r" (value) \
|
rlm@1
|
234 ); \
|
rlm@1
|
235 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
236 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
237 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
238 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
239 }
|
rlm@1
|
240 #define ADC_RD_RS \
|
rlm@1
|
241 { \
|
rlm@1
|
242 register int Flags; \
|
rlm@1
|
243 register int Result; \
|
rlm@1
|
244 asm volatile ("mtspr xer, %4\n" \
|
rlm@1
|
245 "addeo. %0, %2, %3\n" \
|
rlm@1
|
246 "mcrxr cr1\n" \
|
rlm@1
|
247 "mfcr %1\n" \
|
rlm@1
|
248 : "=r" (Result), \
|
rlm@1
|
249 "=r" (Flags) \
|
rlm@1
|
250 : "r" (reg[dest].I), \
|
rlm@1
|
251 "r" (value), \
|
rlm@1
|
252 "r" (C_FLAG << 29) \
|
rlm@1
|
253 ); \
|
rlm@1
|
254 reg[dest].I = Result; \
|
rlm@1
|
255 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
256 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
257 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
258 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
259 }
|
rlm@1
|
260 #define SUB_RD_RS_RN \
|
rlm@1
|
261 { \
|
rlm@1
|
262 register int Flags; \
|
rlm@1
|
263 register int Result; \
|
rlm@1
|
264 asm volatile ("subco. %0, %2, %3\n" \
|
rlm@1
|
265 "mcrxr cr1\n" \
|
rlm@1
|
266 "mfcr %1\n" \
|
rlm@1
|
267 : "=r" (Result), \
|
rlm@1
|
268 "=r" (Flags) \
|
rlm@1
|
269 : "r" (reg[source].I), \
|
rlm@1
|
270 "r" (value) \
|
rlm@1
|
271 ); \
|
rlm@1
|
272 reg[dest].I = Result; \
|
rlm@1
|
273 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
274 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
275 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
276 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
277 }
|
rlm@1
|
278 #define SUB_RD_RS_O3 SUB_RD_RS_RN
|
rlm@1
|
279 #define SUB_RN_O8(d) \
|
rlm@1
|
280 { \
|
rlm@1
|
281 register int Flags; \
|
rlm@1
|
282 register int Result; \
|
rlm@1
|
283 asm volatile ("subco. %0, %2, %3\n" \
|
rlm@1
|
284 "mcrxr cr1\n" \
|
rlm@1
|
285 "mfcr %1\n" \
|
rlm@1
|
286 : "=r" (Result), \
|
rlm@1
|
287 "=r" (Flags) \
|
rlm@1
|
288 : "r" (reg[(d)].I), \
|
rlm@1
|
289 "r" (opcode & 255) \
|
rlm@1
|
290 ); \
|
rlm@1
|
291 reg[(d)].I = Result; \
|
rlm@1
|
292 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
293 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
294 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
295 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
296 }
|
rlm@1
|
297 #define CMP_RN_O8(d) \
|
rlm@1
|
298 { \
|
rlm@1
|
299 register int Flags; \
|
rlm@1
|
300 register int Result; \
|
rlm@1
|
301 asm volatile ("subco. %0, %2, %3\n" \
|
rlm@1
|
302 "mcrxr cr1\n" \
|
rlm@1
|
303 "mfcr %1\n" \
|
rlm@1
|
304 : "=r" (Result), \
|
rlm@1
|
305 "=r" (Flags) \
|
rlm@1
|
306 : "r" (reg[(d)].I), \
|
rlm@1
|
307 "r" (opcode & 255) \
|
rlm@1
|
308 ); \
|
rlm@1
|
309 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
310 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
311 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
312 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
313 }
|
rlm@1
|
314 #define SBC_RD_RS \
|
rlm@1
|
315 { \
|
rlm@1
|
316 register int Flags; \
|
rlm@1
|
317 register int Result; \
|
rlm@1
|
318 asm volatile ("mtspr xer, %4\n" \
|
rlm@1
|
319 "subfeo. %0, %3, %2\n" \
|
rlm@1
|
320 "mcrxr cr1\n" \
|
rlm@1
|
321 "mfcr %1\n" \
|
rlm@1
|
322 : "=r" (Result), \
|
rlm@1
|
323 "=r" (Flags) \
|
rlm@1
|
324 : "r" (reg[dest].I), \
|
rlm@1
|
325 "r" (value), \
|
rlm@1
|
326 "r" (C_FLAG << 29) \
|
rlm@1
|
327 ); \
|
rlm@1
|
328 reg[dest].I = Result; \
|
rlm@1
|
329 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
330 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
331 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
332 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
333 }
|
rlm@1
|
334 #define LSL_RD_RM_I5 \
|
rlm@1
|
335 { \
|
rlm@1
|
336 C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \
|
rlm@1
|
337 value = reg[source].I << shift; \
|
rlm@1
|
338 }
|
rlm@1
|
339 #define LSL_RD_RS \
|
rlm@1
|
340 { \
|
rlm@1
|
341 C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \
|
rlm@1
|
342 value = reg[dest].I << value; \
|
rlm@1
|
343 }
|
rlm@1
|
344 #define LSR_RD_RM_I5 \
|
rlm@1
|
345 { \
|
rlm@1
|
346 C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \
|
rlm@1
|
347 value = reg[source].I >> shift; \
|
rlm@1
|
348 }
|
rlm@1
|
349 #define LSR_RD_RS \
|
rlm@1
|
350 { \
|
rlm@1
|
351 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
|
rlm@1
|
352 value = reg[dest].I >> value; \
|
rlm@1
|
353 }
|
rlm@1
|
354 #define ASR_RD_RM_I5 \
|
rlm@1
|
355 { \
|
rlm@1
|
356 C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \
|
rlm@1
|
357 value = (s32)reg[source].I >> (int)shift; \
|
rlm@1
|
358 }
|
rlm@1
|
359 #define ASR_RD_RS \
|
rlm@1
|
360 { \
|
rlm@1
|
361 C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \
|
rlm@1
|
362 value = (s32)reg[dest].I >> (int)value; \
|
rlm@1
|
363 }
|
rlm@1
|
364 #define ROR_RD_RS \
|
rlm@1
|
365 { \
|
rlm@1
|
366 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
|
rlm@1
|
367 value = ((reg[dest].I << (32 - value)) | \
|
rlm@1
|
368 (reg[dest].I >> value)); \
|
rlm@1
|
369 }
|
rlm@1
|
370 #define NEG_RD_RS \
|
rlm@1
|
371 { \
|
rlm@1
|
372 register int Flags; \
|
rlm@1
|
373 register int Result; \
|
rlm@1
|
374 asm volatile ("subfco. %0, %2, %3\n" \
|
rlm@1
|
375 "mcrxr cr1\n" \
|
rlm@1
|
376 "mfcr %1\n" \
|
rlm@1
|
377 : "=r" (Result), \
|
rlm@1
|
378 "=r" (Flags) \
|
rlm@1
|
379 : "r" (reg[source].I), \
|
rlm@1
|
380 "r" (0) \
|
rlm@1
|
381 ); \
|
rlm@1
|
382 reg[dest].I = Result; \
|
rlm@1
|
383 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
384 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
385 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
386 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
387 }
|
rlm@1
|
388 #define CMP_RD_RS \
|
rlm@1
|
389 { \
|
rlm@1
|
390 register int Flags; \
|
rlm@1
|
391 register int Result; \
|
rlm@1
|
392 asm volatile ("subco. %0, %2, %3\n" \
|
rlm@1
|
393 "mcrxr cr1\n" \
|
rlm@1
|
394 "mfcr %1\n" \
|
rlm@1
|
395 : "=r" (Result), \
|
rlm@1
|
396 "=r" (Flags) \
|
rlm@1
|
397 : "r" (reg[dest].I), \
|
rlm@1
|
398 "r" (value) \
|
rlm@1
|
399 ); \
|
rlm@1
|
400 Z_FLAG = (Flags >> 29) & 1; \
|
rlm@1
|
401 N_FLAG = (Flags >> 31) & 1; \
|
rlm@1
|
402 C_FLAG = (Flags >> 25) & 1; \
|
rlm@1
|
403 V_FLAG = (Flags >> 26) & 1; \
|
rlm@1
|
404 }
|
rlm@1
|
405 #else
|
rlm@1
|
406 #define ADD_RD_RS_RN \
|
rlm@1
|
407 asm ("add %1, %%ebx;" \
|
rlm@1
|
408 "setsb N_FLAG;" \
|
rlm@1
|
409 "setzb Z_FLAG;" \
|
rlm@1
|
410 "setcb C_FLAG;" \
|
rlm@1
|
411 "setob V_FLAG;" \
|
rlm@1
|
412 : "=b" (reg[dest].I) \
|
rlm@1
|
413 : "r" (value), "b" (reg[source].I));
|
rlm@1
|
414 #define ADD_RD_RS_O3 \
|
rlm@1
|
415 asm ("add %1, %%ebx;" \
|
rlm@1
|
416 "setsb N_FLAG;" \
|
rlm@1
|
417 "setzb Z_FLAG;" \
|
rlm@1
|
418 "setcb C_FLAG;" \
|
rlm@1
|
419 "setob V_FLAG;" \
|
rlm@1
|
420 : "=b" (reg[dest].I) \
|
rlm@1
|
421 : "r" (value), "b" (reg[source].I));
|
rlm@1
|
422 #define ADD_RN_O8(d) \
|
rlm@1
|
423 asm ("add %1, %%ebx;" \
|
rlm@1
|
424 "setsb N_FLAG;" \
|
rlm@1
|
425 "setzb Z_FLAG;" \
|
rlm@1
|
426 "setcb C_FLAG;" \
|
rlm@1
|
427 "setob V_FLAG;" \
|
rlm@1
|
428 : "=b" (reg[(d)].I) \
|
rlm@1
|
429 : "r" (opcode & 255), "b" (reg[(d)].I));
|
rlm@1
|
430 #define CMN_RD_RS \
|
rlm@1
|
431 asm ("add %0, %1;" \
|
rlm@1
|
432 "setsb N_FLAG;" \
|
rlm@1
|
433 "setzb Z_FLAG;" \
|
rlm@1
|
434 "setcb C_FLAG;" \
|
rlm@1
|
435 "setob V_FLAG;" \
|
rlm@1
|
436 : \
|
rlm@1
|
437 : "r" (value), "r" (reg[dest].I) : "1");
|
rlm@1
|
438 #define ADC_RD_RS \
|
rlm@1
|
439 asm ("bt $0, C_FLAG;" \
|
rlm@1
|
440 "adc %1, %%ebx;" \
|
rlm@1
|
441 "setsb N_FLAG;" \
|
rlm@1
|
442 "setzb Z_FLAG;" \
|
rlm@1
|
443 "setcb C_FLAG;" \
|
rlm@1
|
444 "setob V_FLAG;" \
|
rlm@1
|
445 : "=b" (reg[dest].I) \
|
rlm@1
|
446 : "r" (value), "b" (reg[dest].I));
|
rlm@1
|
447 #define SUB_RD_RS_RN \
|
rlm@1
|
448 asm ("sub %1, %%ebx;" \
|
rlm@1
|
449 "setsb N_FLAG;" \
|
rlm@1
|
450 "setzb Z_FLAG;" \
|
rlm@1
|
451 "setncb C_FLAG;" \
|
rlm@1
|
452 "setob V_FLAG;" \
|
rlm@1
|
453 : "=b" (reg[dest].I) \
|
rlm@1
|
454 : "r" (value), "b" (reg[source].I));
|
rlm@1
|
455 #define SUB_RD_RS_O3 \
|
rlm@1
|
456 asm ("sub %1, %%ebx;" \
|
rlm@1
|
457 "setsb N_FLAG;" \
|
rlm@1
|
458 "setzb Z_FLAG;" \
|
rlm@1
|
459 "setncb C_FLAG;" \
|
rlm@1
|
460 "setob V_FLAG;" \
|
rlm@1
|
461 : "=b" (reg[dest].I) \
|
rlm@1
|
462 : "r" (value), "b" (reg[source].I));
|
rlm@1
|
463 #define SUB_RN_O8(d) \
|
rlm@1
|
464 asm ("sub %1, %%ebx;" \
|
rlm@1
|
465 "setsb N_FLAG;" \
|
rlm@1
|
466 "setzb Z_FLAG;" \
|
rlm@1
|
467 "setncb C_FLAG;" \
|
rlm@1
|
468 "setob V_FLAG;" \
|
rlm@1
|
469 : "=b" (reg[(d)].I) \
|
rlm@1
|
470 : "r" (opcode & 255), "b" (reg[(d)].I));
|
rlm@1
|
471 #define CMP_RN_O8(d) \
|
rlm@1
|
472 asm ("sub %0, %1;" \
|
rlm@1
|
473 "setsb N_FLAG;" \
|
rlm@1
|
474 "setzb Z_FLAG;" \
|
rlm@1
|
475 "setncb C_FLAG;" \
|
rlm@1
|
476 "setob V_FLAG;" \
|
rlm@1
|
477 : \
|
rlm@1
|
478 : "r" (opcode & 255), "r" (reg[(d)].I) : "1");
|
rlm@1
|
479 #define SBC_RD_RS \
|
rlm@1
|
480 asm volatile ("bt $0, C_FLAG;" \
|
rlm@1
|
481 "cmc;" \
|
rlm@1
|
482 "sbb %1, %%ebx;" \
|
rlm@1
|
483 "setsb N_FLAG;" \
|
rlm@1
|
484 "setzb Z_FLAG;" \
|
rlm@1
|
485 "setncb C_FLAG;" \
|
rlm@1
|
486 "setob V_FLAG;" \
|
rlm@1
|
487 : "=b" (reg[dest].I) \
|
rlm@1
|
488 : "r" (value), "b" (reg[dest].I) : "cc", "memory");
|
rlm@1
|
489 #define LSL_RD_RM_I5 \
|
rlm@1
|
490 asm ("shl %%cl, %%eax;" \
|
rlm@1
|
491 "setcb C_FLAG;" \
|
rlm@1
|
492 : "=a" (value) \
|
rlm@1
|
493 : "a" (reg[source].I), "c" (shift));
|
rlm@1
|
494 #define LSL_RD_RS \
|
rlm@1
|
495 asm ("shl %%cl, %%eax;" \
|
rlm@1
|
496 "setcb C_FLAG;" \
|
rlm@1
|
497 : "=a" (value) \
|
rlm@1
|
498 : "a" (reg[dest].I), "c" (value));
|
rlm@1
|
499 #define LSR_RD_RM_I5 \
|
rlm@1
|
500 asm ("shr %%cl, %%eax;" \
|
rlm@1
|
501 "setcb C_FLAG;" \
|
rlm@1
|
502 : "=a" (value) \
|
rlm@1
|
503 : "a" (reg[source].I), "c" (shift));
|
rlm@1
|
504 #define LSR_RD_RS \
|
rlm@1
|
505 asm ("shr %%cl, %%eax;" \
|
rlm@1
|
506 "setcb C_FLAG;" \
|
rlm@1
|
507 : "=a" (value) \
|
rlm@1
|
508 : "a" (reg[dest].I), "c" (value));
|
rlm@1
|
509 #define ASR_RD_RM_I5 \
|
rlm@1
|
510 asm ("sar %%cl, %%eax;" \
|
rlm@1
|
511 "setcb C_FLAG;" \
|
rlm@1
|
512 : "=a" (value) \
|
rlm@1
|
513 : "a" (reg[source].I), "c" (shift));
|
rlm@1
|
514 #define ASR_RD_RS \
|
rlm@1
|
515 asm ("sar %%cl, %%eax;" \
|
rlm@1
|
516 "setcb C_FLAG;" \
|
rlm@1
|
517 : "=a" (value) \
|
rlm@1
|
518 : "a" (reg[dest].I), "c" (value));
|
rlm@1
|
519 #define ROR_RD_RS \
|
rlm@1
|
520 asm ("ror %%cl, %%eax;" \
|
rlm@1
|
521 "setcb C_FLAG;" \
|
rlm@1
|
522 : "=a" (value) \
|
rlm@1
|
523 : "a" (reg[dest].I), "c" (value));
|
rlm@1
|
524 #define NEG_RD_RS \
|
rlm@1
|
525 asm ("neg %%ebx;" \
|
rlm@1
|
526 "setsb N_FLAG;" \
|
rlm@1
|
527 "setzb Z_FLAG;" \
|
rlm@1
|
528 "setncb C_FLAG;" \
|
rlm@1
|
529 "setob V_FLAG;" \
|
rlm@1
|
530 : "=b" (reg[dest].I) \
|
rlm@1
|
531 : "b" (reg[source].I));
|
rlm@1
|
532 #define CMP_RD_RS \
|
rlm@1
|
533 asm ("sub %0, %1;" \
|
rlm@1
|
534 "setsb N_FLAG;" \
|
rlm@1
|
535 "setzb Z_FLAG;" \
|
rlm@1
|
536 "setncb C_FLAG;" \
|
rlm@1
|
537 "setob V_FLAG;" \
|
rlm@1
|
538 : \
|
rlm@1
|
539 : "r" (value), "r" (reg[dest].I) : "1");
|
rlm@1
|
540 #endif
|
rlm@1
|
541 #else
|
rlm@1
|
542 #define ADD_RD_RS_RN \
|
rlm@1
|
543 { \
|
rlm@1
|
544 __asm mov eax, source \
|
rlm@1
|
545 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
546 __asm add ebx, value \
|
rlm@1
|
547 __asm mov eax, dest \
|
rlm@1
|
548 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
549 __asm sets byte ptr N_FLAG \
|
rlm@1
|
550 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
551 __asm setc byte ptr C_FLAG \
|
rlm@1
|
552 __asm seto byte ptr V_FLAG \
|
rlm@1
|
553 }
|
rlm@1
|
554 #define ADD_RD_RS_O3 \
|
rlm@1
|
555 { \
|
rlm@1
|
556 __asm mov eax, source \
|
rlm@1
|
557 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
558 __asm add ebx, value \
|
rlm@1
|
559 __asm mov eax, dest \
|
rlm@1
|
560 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
561 __asm sets byte ptr N_FLAG \
|
rlm@1
|
562 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
563 __asm setc byte ptr C_FLAG \
|
rlm@1
|
564 __asm seto byte ptr V_FLAG \
|
rlm@1
|
565 }
|
rlm@1
|
566 #define ADD_RN_O8(d) \
|
rlm@1
|
567 { \
|
rlm@1
|
568 __asm mov ebx, opcode \
|
rlm@1
|
569 __asm and ebx, 255 \
|
rlm@1
|
570 __asm add dword ptr [OFFSET reg + 4 * (d)], ebx \
|
rlm@1
|
571 __asm sets byte ptr N_FLAG \
|
rlm@1
|
572 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
573 __asm setc byte ptr C_FLAG \
|
rlm@1
|
574 __asm seto byte ptr V_FLAG \
|
rlm@1
|
575 }
|
rlm@1
|
576 #define CMN_RD_RS \
|
rlm@1
|
577 { \
|
rlm@1
|
578 __asm mov eax, dest \
|
rlm@1
|
579 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
580 __asm add ebx, value \
|
rlm@1
|
581 __asm sets byte ptr N_FLAG \
|
rlm@1
|
582 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
583 __asm setc byte ptr C_FLAG \
|
rlm@1
|
584 __asm seto byte ptr V_FLAG \
|
rlm@1
|
585 }
|
rlm@1
|
586 #define ADC_RD_RS \
|
rlm@1
|
587 { \
|
rlm@1
|
588 __asm mov ebx, dest \
|
rlm@1
|
589 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
|
rlm@1
|
590 __asm bt word ptr C_FLAG, 0 \
|
rlm@1
|
591 __asm adc ebx, value \
|
rlm@1
|
592 __asm mov eax, dest \
|
rlm@1
|
593 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
594 __asm sets byte ptr N_FLAG \
|
rlm@1
|
595 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
596 __asm setc byte ptr C_FLAG \
|
rlm@1
|
597 __asm seto byte ptr V_FLAG \
|
rlm@1
|
598 }
|
rlm@1
|
599 #define SUB_RD_RS_RN \
|
rlm@1
|
600 { \
|
rlm@1
|
601 __asm mov eax, source \
|
rlm@1
|
602 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
603 __asm sub ebx, value \
|
rlm@1
|
604 __asm mov eax, dest \
|
rlm@1
|
605 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
606 __asm sets byte ptr N_FLAG \
|
rlm@1
|
607 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
608 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
609 __asm seto byte ptr V_FLAG \
|
rlm@1
|
610 }
|
rlm@1
|
611 #define SUB_RD_RS_O3 \
|
rlm@1
|
612 { \
|
rlm@1
|
613 __asm mov eax, source \
|
rlm@1
|
614 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
615 __asm sub ebx, value \
|
rlm@1
|
616 __asm mov eax, dest \
|
rlm@1
|
617 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
618 __asm sets byte ptr N_FLAG \
|
rlm@1
|
619 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
620 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
621 __asm seto byte ptr V_FLAG \
|
rlm@1
|
622 }
|
rlm@1
|
623 #define SUB_RN_O8(d) \
|
rlm@1
|
624 { \
|
rlm@1
|
625 __asm mov ebx, opcode \
|
rlm@1
|
626 __asm and ebx, 255 \
|
rlm@1
|
627 __asm sub dword ptr [OFFSET reg + 4 * (d)], ebx \
|
rlm@1
|
628 __asm sets byte ptr N_FLAG \
|
rlm@1
|
629 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
630 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
631 __asm seto byte ptr V_FLAG \
|
rlm@1
|
632 }
|
rlm@1
|
633 #define CMP_RN_O8(d) \
|
rlm@1
|
634 { \
|
rlm@1
|
635 __asm mov eax, dword ptr [OFFSET reg + 4 * (d)] \
|
rlm@1
|
636 __asm mov ebx, opcode \
|
rlm@1
|
637 __asm and ebx, 255 \
|
rlm@1
|
638 __asm sub eax, ebx \
|
rlm@1
|
639 __asm sets byte ptr N_FLAG \
|
rlm@1
|
640 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
641 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
642 __asm seto byte ptr V_FLAG \
|
rlm@1
|
643 }
|
rlm@1
|
644 #define SBC_RD_RS \
|
rlm@1
|
645 { \
|
rlm@1
|
646 __asm mov ebx, dest \
|
rlm@1
|
647 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
|
rlm@1
|
648 __asm mov eax, value \
|
rlm@1
|
649 __asm bt word ptr C_FLAG, 0 \
|
rlm@1
|
650 __asm cmc \
|
rlm@1
|
651 __asm sbb ebx, eax \
|
rlm@1
|
652 __asm mov eax, dest \
|
rlm@1
|
653 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
654 __asm sets byte ptr N_FLAG \
|
rlm@1
|
655 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
656 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
657 __asm seto byte ptr V_FLAG \
|
rlm@1
|
658 }
|
rlm@1
|
659 #define LSL_RD_RM_I5 \
|
rlm@1
|
660 { \
|
rlm@1
|
661 __asm mov eax, source \
|
rlm@1
|
662 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
663 __asm mov cl, byte ptr shift \
|
rlm@1
|
664 __asm shl eax, cl \
|
rlm@1
|
665 __asm mov value, eax \
|
rlm@1
|
666 __asm setc byte ptr C_FLAG \
|
rlm@1
|
667 }
|
rlm@1
|
668 #define LSL_RD_RS \
|
rlm@1
|
669 { \
|
rlm@1
|
670 __asm mov eax, dest \
|
rlm@1
|
671 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
672 __asm mov cl, byte ptr value \
|
rlm@1
|
673 __asm shl eax, cl \
|
rlm@1
|
674 __asm mov value, eax \
|
rlm@1
|
675 __asm setc byte ptr C_FLAG \
|
rlm@1
|
676 }
|
rlm@1
|
677 #define LSR_RD_RM_I5 \
|
rlm@1
|
678 { \
|
rlm@1
|
679 __asm mov eax, source \
|
rlm@1
|
680 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
681 __asm mov cl, byte ptr shift \
|
rlm@1
|
682 __asm shr eax, cl \
|
rlm@1
|
683 __asm mov value, eax \
|
rlm@1
|
684 __asm setc byte ptr C_FLAG \
|
rlm@1
|
685 }
|
rlm@1
|
686 #define LSR_RD_RS \
|
rlm@1
|
687 { \
|
rlm@1
|
688 __asm mov eax, dest \
|
rlm@1
|
689 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
690 __asm mov cl, byte ptr value \
|
rlm@1
|
691 __asm shr eax, cl \
|
rlm@1
|
692 __asm mov value, eax \
|
rlm@1
|
693 __asm setc byte ptr C_FLAG \
|
rlm@1
|
694 }
|
rlm@1
|
695 #define ASR_RD_RM_I5 \
|
rlm@1
|
696 { \
|
rlm@1
|
697 __asm mov eax, source \
|
rlm@1
|
698 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
699 __asm mov cl, byte ptr shift \
|
rlm@1
|
700 __asm sar eax, cl \
|
rlm@1
|
701 __asm mov value, eax \
|
rlm@1
|
702 __asm setc byte ptr C_FLAG \
|
rlm@1
|
703 }
|
rlm@1
|
704 #define ASR_RD_RS \
|
rlm@1
|
705 { \
|
rlm@1
|
706 __asm mov eax, dest \
|
rlm@1
|
707 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
708 __asm mov cl, byte ptr value \
|
rlm@1
|
709 __asm sar eax, cl \
|
rlm@1
|
710 __asm mov value, eax \
|
rlm@1
|
711 __asm setc byte ptr C_FLAG \
|
rlm@1
|
712 }
|
rlm@1
|
713 #define ROR_RD_RS \
|
rlm@1
|
714 { \
|
rlm@1
|
715 __asm mov eax, dest \
|
rlm@1
|
716 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
717 __asm mov cl, byte ptr value \
|
rlm@1
|
718 __asm ror eax, cl \
|
rlm@1
|
719 __asm mov value, eax \
|
rlm@1
|
720 __asm setc byte ptr C_FLAG \
|
rlm@1
|
721 }
|
rlm@1
|
722 #define NEG_RD_RS \
|
rlm@1
|
723 { \
|
rlm@1
|
724 __asm mov ebx, source \
|
rlm@1
|
725 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
|
rlm@1
|
726 __asm neg ebx \
|
rlm@1
|
727 __asm mov eax, dest \
|
rlm@1
|
728 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
|
rlm@1
|
729 __asm sets byte ptr N_FLAG \
|
rlm@1
|
730 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
731 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
732 __asm seto byte ptr V_FLAG \
|
rlm@1
|
733 }
|
rlm@1
|
734 #define CMP_RD_RS \
|
rlm@1
|
735 { \
|
rlm@1
|
736 __asm mov eax, dest \
|
rlm@1
|
737 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
|
rlm@1
|
738 __asm sub ebx, value \
|
rlm@1
|
739 __asm sets byte ptr N_FLAG \
|
rlm@1
|
740 __asm setz byte ptr Z_FLAG \
|
rlm@1
|
741 __asm setnc byte ptr C_FLAG \
|
rlm@1
|
742 __asm seto byte ptr V_FLAG \
|
rlm@1
|
743 }
|
rlm@1
|
744 #endif
|
rlm@1
|
745 #endif
|
rlm@1
|
746
|
rlm@1
|
747 u32 opcode = CPUReadHalfWordQuick(armNextPC);
|
rlm@1
|
748 clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15];
|
rlm@1
|
749 #ifndef FINAL_VERSION
|
rlm@1
|
750 if (armNextPC == stop)
|
rlm@1
|
751 {
|
rlm@1
|
752 armNextPC = armNextPC++;
|
rlm@1
|
753 }
|
rlm@1
|
754 #endif
|
rlm@1
|
755
|
rlm@1
|
756 armNextPC = reg[15].I;
|
rlm@1
|
757 reg[15].I += 2;
|
rlm@1
|
758
|
rlm@1
|
759 switch (opcode >> 8)
|
rlm@1
|
760 {
|
rlm@1
|
761 case 0x00:
|
rlm@1
|
762 case 0x01:
|
rlm@1
|
763 case 0x02:
|
rlm@1
|
764 case 0x03:
|
rlm@1
|
765 case 0x04:
|
rlm@1
|
766 case 0x05:
|
rlm@1
|
767 case 0x06:
|
rlm@1
|
768 case 0x07:
|
rlm@1
|
769 {
|
rlm@1
|
770 // LSL Rd, Rm, #Imm 5
|
rlm@1
|
771 int dest = opcode & 0x07;
|
rlm@1
|
772 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
773 int shift = (opcode >> 6) & 0x1f;
|
rlm@1
|
774 u32 value;
|
rlm@1
|
775
|
rlm@1
|
776 if (shift)
|
rlm@1
|
777 {
|
rlm@1
|
778 LSL_RD_RM_I5;
|
rlm@1
|
779 }
|
rlm@1
|
780 else
|
rlm@1
|
781 {
|
rlm@1
|
782 value = reg[source].I;
|
rlm@1
|
783 }
|
rlm@1
|
784 reg[dest].I = value;
|
rlm@1
|
785 // C_FLAG set above
|
rlm@1
|
786 N_FLAG = (value & 0x80000000 ? true : false);
|
rlm@1
|
787 Z_FLAG = (value ? false : true);
|
rlm@1
|
788 }
|
rlm@1
|
789 break;
|
rlm@1
|
790 case 0x08:
|
rlm@1
|
791 case 0x09:
|
rlm@1
|
792 case 0x0a:
|
rlm@1
|
793 case 0x0b:
|
rlm@1
|
794 case 0x0c:
|
rlm@1
|
795 case 0x0d:
|
rlm@1
|
796 case 0x0e:
|
rlm@1
|
797 case 0x0f:
|
rlm@1
|
798 {
|
rlm@1
|
799 // LSR Rd, Rm, #Imm 5
|
rlm@1
|
800 int dest = opcode & 0x07;
|
rlm@1
|
801 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
802 int shift = (opcode >> 6) & 0x1f;
|
rlm@1
|
803 u32 value;
|
rlm@1
|
804
|
rlm@1
|
805 if (shift)
|
rlm@1
|
806 {
|
rlm@1
|
807 LSR_RD_RM_I5;
|
rlm@1
|
808 }
|
rlm@1
|
809 else
|
rlm@1
|
810 {
|
rlm@1
|
811 C_FLAG = reg[source].I & 0x80000000 ? true : false;
|
rlm@1
|
812 value = 0;
|
rlm@1
|
813 }
|
rlm@1
|
814 reg[dest].I = value;
|
rlm@1
|
815 // C_FLAG set above
|
rlm@1
|
816 N_FLAG = (value & 0x80000000 ? true : false);
|
rlm@1
|
817 Z_FLAG = (value ? false : true);
|
rlm@1
|
818 }
|
rlm@1
|
819 break;
|
rlm@1
|
820 case 0x10:
|
rlm@1
|
821 case 0x11:
|
rlm@1
|
822 case 0x12:
|
rlm@1
|
823 case 0x13:
|
rlm@1
|
824 case 0x14:
|
rlm@1
|
825 case 0x15:
|
rlm@1
|
826 case 0x16:
|
rlm@1
|
827 case 0x17:
|
rlm@1
|
828 {
|
rlm@1
|
829 // ASR Rd, Rm, #Imm 5
|
rlm@1
|
830 int dest = opcode & 0x07;
|
rlm@1
|
831 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
832 int shift = (opcode >> 6) & 0x1f;
|
rlm@1
|
833 u32 value;
|
rlm@1
|
834
|
rlm@1
|
835 if (shift)
|
rlm@1
|
836 {
|
rlm@1
|
837 ASR_RD_RM_I5;
|
rlm@1
|
838 }
|
rlm@1
|
839 else
|
rlm@1
|
840 {
|
rlm@1
|
841 if (reg[source].I & 0x80000000)
|
rlm@1
|
842 {
|
rlm@1
|
843 value = 0xFFFFFFFF;
|
rlm@1
|
844 C_FLAG = true;
|
rlm@1
|
845 }
|
rlm@1
|
846 else
|
rlm@1
|
847 {
|
rlm@1
|
848 value = 0;
|
rlm@1
|
849 C_FLAG = false;
|
rlm@1
|
850 }
|
rlm@1
|
851 }
|
rlm@1
|
852 reg[dest].I = value;
|
rlm@1
|
853 // C_FLAG set above
|
rlm@1
|
854 N_FLAG = (value & 0x80000000 ? true : false);
|
rlm@1
|
855 Z_FLAG = (value ? false : true);
|
rlm@1
|
856 }
|
rlm@1
|
857 break;
|
rlm@1
|
858 case 0x18:
|
rlm@1
|
859 case 0x19:
|
rlm@1
|
860 {
|
rlm@1
|
861 // ADD Rd, Rs, Rn
|
rlm@1
|
862 int dest = opcode & 0x07;
|
rlm@1
|
863 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
864 u32 value = reg[(opcode >> 6) & 0x07].I;
|
rlm@1
|
865 ADD_RD_RS_RN;
|
rlm@1
|
866 }
|
rlm@1
|
867 break;
|
rlm@1
|
868 case 0x1a:
|
rlm@1
|
869 case 0x1b:
|
rlm@1
|
870 {
|
rlm@1
|
871 // SUB Rd, Rs, Rn
|
rlm@1
|
872 int dest = opcode & 0x07;
|
rlm@1
|
873 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
874 u32 value = reg[(opcode >> 6) & 0x07].I;
|
rlm@1
|
875 SUB_RD_RS_RN;
|
rlm@1
|
876 }
|
rlm@1
|
877 break;
|
rlm@1
|
878 case 0x1c:
|
rlm@1
|
879 case 0x1d:
|
rlm@1
|
880 {
|
rlm@1
|
881 // ADD Rd, Rs, #Offset3
|
rlm@1
|
882 int dest = opcode & 0x07;
|
rlm@1
|
883 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
884 u32 value = (opcode >> 6) & 7;
|
rlm@1
|
885 ADD_RD_RS_O3;
|
rlm@1
|
886 }
|
rlm@1
|
887 break;
|
rlm@1
|
888 case 0x1e:
|
rlm@1
|
889 case 0x1f:
|
rlm@1
|
890 {
|
rlm@1
|
891 // SUB Rd, Rs, #Offset3
|
rlm@1
|
892 int dest = opcode & 0x07;
|
rlm@1
|
893 int source = (opcode >> 3) & 0x07;
|
rlm@1
|
894 u32 value = (opcode >> 6) & 7;
|
rlm@1
|
895 SUB_RD_RS_O3;
|
rlm@1
|
896 }
|
rlm@1
|
897 break;
|
rlm@1
|
898 case 0x20:
|
rlm@1
|
899 // MOV R0, #Offset8
|
rlm@1
|
900 reg[0].I = opcode & 255;
|
rlm@1
|
901 N_FLAG = false;
|
rlm@1
|
902 Z_FLAG = (reg[0].I ? false : true);
|
rlm@1
|
903 break;
|
rlm@1
|
904 case 0x21:
|
rlm@1
|
905 // MOV R1, #Offset8
|
rlm@1
|
906 reg[1].I = opcode & 255;
|
rlm@1
|
907 N_FLAG = false;
|
rlm@1
|
908 Z_FLAG = (reg[1].I ? false : true);
|
rlm@1
|
909 break;
|
rlm@1
|
910 case 0x22:
|
rlm@1
|
911 // MOV R2, #Offset8
|
rlm@1
|
912 reg[2].I = opcode & 255;
|
rlm@1
|
913 N_FLAG = false;
|
rlm@1
|
914 Z_FLAG = (reg[2].I ? false : true);
|
rlm@1
|
915 break;
|
rlm@1
|
916 case 0x23:
|
rlm@1
|
917 // MOV R3, #Offset8
|
rlm@1
|
918 reg[3].I = opcode & 255;
|
rlm@1
|
919 N_FLAG = false;
|
rlm@1
|
920 Z_FLAG = (reg[3].I ? false : true);
|
rlm@1
|
921 break;
|
rlm@1
|
922 case 0x24:
|
rlm@1
|
923 // MOV R4, #Offset8
|
rlm@1
|
924 reg[4].I = opcode & 255;
|
rlm@1
|
925 N_FLAG = false;
|
rlm@1
|
926 Z_FLAG = (reg[4].I ? false : true);
|
rlm@1
|
927 break;
|
rlm@1
|
928 case 0x25:
|
rlm@1
|
929 // MOV R5, #Offset8
|
rlm@1
|
930 reg[5].I = opcode & 255;
|
rlm@1
|
931 N_FLAG = false;
|
rlm@1
|
932 Z_FLAG = (reg[5].I ? false : true);
|
rlm@1
|
933 break;
|
rlm@1
|
934 case 0x26:
|
rlm@1
|
935 // MOV R6, #Offset8
|
rlm@1
|
936 reg[6].I = opcode & 255;
|
rlm@1
|
937 N_FLAG = false;
|
rlm@1
|
938 Z_FLAG = (reg[6].I ? false : true);
|
rlm@1
|
939 break;
|
rlm@1
|
940 case 0x27:
|
rlm@1
|
941 // MOV R7, #Offset8
|
rlm@1
|
942 reg[7].I = opcode & 255;
|
rlm@1
|
943 N_FLAG = false;
|
rlm@1
|
944 Z_FLAG = (reg[7].I ? false : true);
|
rlm@1
|
945 break;
|
rlm@1
|
946 case 0x28:
|
rlm@1
|
947 // CMP R0, #Offset8
|
rlm@1
|
948 CMP_RN_O8(0);
|
rlm@1
|
949 break;
|
rlm@1
|
950 case 0x29:
|
rlm@1
|
951 // CMP R1, #Offset8
|
rlm@1
|
952 CMP_RN_O8(1);
|
rlm@1
|
953 break;
|
rlm@1
|
954 case 0x2a:
|
rlm@1
|
955 // CMP R2, #Offset8
|
rlm@1
|
956 CMP_RN_O8(2);
|
rlm@1
|
957 break;
|
rlm@1
|
958 case 0x2b:
|
rlm@1
|
959 // CMP R3, #Offset8
|
rlm@1
|
960 CMP_RN_O8(3);
|
rlm@1
|
961 break;
|
rlm@1
|
962 case 0x2c:
|
rlm@1
|
963 // CMP R4, #Offset8
|
rlm@1
|
964 CMP_RN_O8(4);
|
rlm@1
|
965 break;
|
rlm@1
|
966 case 0x2d:
|
rlm@1
|
967 // CMP R5, #Offset8
|
rlm@1
|
968 CMP_RN_O8(5);
|
rlm@1
|
969 break;
|
rlm@1
|
970 case 0x2e:
|
rlm@1
|
971 // CMP R6, #Offset8
|
rlm@1
|
972 CMP_RN_O8(6);
|
rlm@1
|
973 break;
|
rlm@1
|
974 case 0x2f:
|
rlm@1
|
975 // CMP R7, #Offset8
|
rlm@1
|
976 CMP_RN_O8(7);
|
rlm@1
|
977 break;
|
rlm@1
|
978 case 0x30:
|
rlm@1
|
979 // ADD R0,#Offset8
|
rlm@1
|
980 ADD_RN_O8(0);
|
rlm@1
|
981 break;
|
rlm@1
|
982 case 0x31:
|
rlm@1
|
983 // ADD R1,#Offset8
|
rlm@1
|
984 ADD_RN_O8(1);
|
rlm@1
|
985 break;
|
rlm@1
|
986 case 0x32:
|
rlm@1
|
987 // ADD R2,#Offset8
|
rlm@1
|
988 ADD_RN_O8(2);
|
rlm@1
|
989 break;
|
rlm@1
|
990 case 0x33:
|
rlm@1
|
991 // ADD R3,#Offset8
|
rlm@1
|
992 ADD_RN_O8(3);
|
rlm@1
|
993 break;
|
rlm@1
|
994 case 0x34:
|
rlm@1
|
995 // ADD R4,#Offset8
|
rlm@1
|
996 ADD_RN_O8(4);
|
rlm@1
|
997 break;
|
rlm@1
|
998 case 0x35:
|
rlm@1
|
999 // ADD R5,#Offset8
|
rlm@1
|
1000 ADD_RN_O8(5);
|
rlm@1
|
1001 break;
|
rlm@1
|
1002 case 0x36:
|
rlm@1
|
1003 // ADD R6,#Offset8
|
rlm@1
|
1004 ADD_RN_O8(6);
|
rlm@1
|
1005 break;
|
rlm@1
|
1006 case 0x37:
|
rlm@1
|
1007 // ADD R7,#Offset8
|
rlm@1
|
1008 ADD_RN_O8(7);
|
rlm@1
|
1009 break;
|
rlm@1
|
1010 case 0x38:
|
rlm@1
|
1011 // SUB R0,#Offset8
|
rlm@1
|
1012 SUB_RN_O8(0);
|
rlm@1
|
1013 break;
|
rlm@1
|
1014 case 0x39:
|
rlm@1
|
1015 // SUB R1,#Offset8
|
rlm@1
|
1016 SUB_RN_O8(1);
|
rlm@1
|
1017 break;
|
rlm@1
|
1018 case 0x3a:
|
rlm@1
|
1019 // SUB R2,#Offset8
|
rlm@1
|
1020 SUB_RN_O8(2);
|
rlm@1
|
1021 break;
|
rlm@1
|
1022 case 0x3b:
|
rlm@1
|
1023 // SUB R3,#Offset8
|
rlm@1
|
1024 SUB_RN_O8(3);
|
rlm@1
|
1025 break;
|
rlm@1
|
1026 case 0x3c:
|
rlm@1
|
1027 // SUB R4,#Offset8
|
rlm@1
|
1028 SUB_RN_O8(4);
|
rlm@1
|
1029 break;
|
rlm@1
|
1030 case 0x3d:
|
rlm@1
|
1031 // SUB R5,#Offset8
|
rlm@1
|
1032 SUB_RN_O8(5);
|
rlm@1
|
1033 break;
|
rlm@1
|
1034 case 0x3e:
|
rlm@1
|
1035 // SUB R6,#Offset8
|
rlm@1
|
1036 SUB_RN_O8(6);
|
rlm@1
|
1037 break;
|
rlm@1
|
1038 case 0x3f:
|
rlm@1
|
1039 // SUB R7,#Offset8
|
rlm@1
|
1040 SUB_RN_O8(7);
|
rlm@1
|
1041 break;
|
rlm@1
|
1042 case 0x40:
|
rlm@1
|
1043 switch ((opcode >> 6) & 3)
|
rlm@1
|
1044 {
|
rlm@1
|
1045 case 0x00:
|
rlm@1
|
1046 {
|
rlm@1
|
1047 // AND Rd, Rs
|
rlm@1
|
1048 int dest = opcode & 7;
|
rlm@1
|
1049 reg[dest].I &= reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1050 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1051 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1052 #ifdef BKPT_SUPPORT
|
rlm@1
|
1053 #define THUMB_CONSOLE_OUTPUT(a, b) \
|
rlm@1
|
1054 if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \
|
rlm@1
|
1055 extern void (*dbgOutput)(char *, u32); \
|
rlm@1
|
1056 dbgOutput((a), (b)); \
|
rlm@1
|
1057 }
|
rlm@1
|
1058 #else
|
rlm@1
|
1059 #define THUMB_CONSOLE_OUTPUT(a, b)
|
rlm@1
|
1060 #endif
|
rlm@1
|
1061 THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
|
rlm@1
|
1062 }
|
rlm@1
|
1063 break;
|
rlm@1
|
1064 case 0x01:
|
rlm@1
|
1065 // EOR Rd, Rs
|
rlm@1
|
1066 {
|
rlm@1
|
1067 int dest = opcode & 7;
|
rlm@1
|
1068 reg[dest].I ^= reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1069 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1070 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1071 }
|
rlm@1
|
1072 break;
|
rlm@1
|
1073 case 0x02:
|
rlm@1
|
1074 // LSL Rd, Rs
|
rlm@1
|
1075 {
|
rlm@1
|
1076 int dest = opcode & 7;
|
rlm@1
|
1077 u32 value = reg[(opcode >> 3) & 7].B.B0;
|
rlm@1
|
1078 if (value)
|
rlm@1
|
1079 {
|
rlm@1
|
1080 if (value == 32)
|
rlm@1
|
1081 {
|
rlm@1
|
1082 value = 0;
|
rlm@1
|
1083 C_FLAG = (reg[dest].I & 1 ? true : false);
|
rlm@1
|
1084 }
|
rlm@1
|
1085 else if (value < 32)
|
rlm@1
|
1086 {
|
rlm@1
|
1087 LSL_RD_RS;
|
rlm@1
|
1088 }
|
rlm@1
|
1089 else
|
rlm@1
|
1090 {
|
rlm@1
|
1091 value = 0;
|
rlm@1
|
1092 C_FLAG = false;
|
rlm@1
|
1093 }
|
rlm@1
|
1094 reg[dest].I = value;
|
rlm@1
|
1095 }
|
rlm@1
|
1096 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1097 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1098 clockTicks++;
|
rlm@1
|
1099 }
|
rlm@1
|
1100 break;
|
rlm@1
|
1101 case 0x03:
|
rlm@1
|
1102 {
|
rlm@1
|
1103 // LSR Rd, Rs
|
rlm@1
|
1104 int dest = opcode & 7;
|
rlm@1
|
1105 u32 value = reg[(opcode >> 3) & 7].B.B0;
|
rlm@1
|
1106 if (value)
|
rlm@1
|
1107 {
|
rlm@1
|
1108 if (value == 32)
|
rlm@1
|
1109 {
|
rlm@1
|
1110 value = 0;
|
rlm@1
|
1111 C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
|
rlm@1
|
1112 }
|
rlm@1
|
1113 else if (value < 32)
|
rlm@1
|
1114 {
|
rlm@1
|
1115 LSR_RD_RS;
|
rlm@1
|
1116 }
|
rlm@1
|
1117 else
|
rlm@1
|
1118 {
|
rlm@1
|
1119 value = 0;
|
rlm@1
|
1120 C_FLAG = false;
|
rlm@1
|
1121 }
|
rlm@1
|
1122 reg[dest].I = value;
|
rlm@1
|
1123 }
|
rlm@1
|
1124 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1125 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1126 clockTicks++;
|
rlm@1
|
1127 }
|
rlm@1
|
1128 break;
|
rlm@1
|
1129 }
|
rlm@1
|
1130 break;
|
rlm@1
|
1131 case 0x41:
|
rlm@1
|
1132 switch ((opcode >> 6) & 3)
|
rlm@1
|
1133 {
|
rlm@1
|
1134 case 0x00:
|
rlm@1
|
1135 {
|
rlm@1
|
1136 // ASR Rd, Rs
|
rlm@1
|
1137 int dest = opcode & 7;
|
rlm@1
|
1138 u32 value = reg[(opcode >> 3) & 7].B.B0;
|
rlm@1
|
1139 // ASR
|
rlm@1
|
1140 if (value)
|
rlm@1
|
1141 {
|
rlm@1
|
1142 if (value < 32)
|
rlm@1
|
1143 {
|
rlm@1
|
1144 ASR_RD_RS;
|
rlm@1
|
1145 reg[dest].I = value;
|
rlm@1
|
1146 }
|
rlm@1
|
1147 else
|
rlm@1
|
1148 {
|
rlm@1
|
1149 if (reg[dest].I & 0x80000000)
|
rlm@1
|
1150 {
|
rlm@1
|
1151 reg[dest].I = 0xFFFFFFFF;
|
rlm@1
|
1152 C_FLAG = true;
|
rlm@1
|
1153 }
|
rlm@1
|
1154 else
|
rlm@1
|
1155 {
|
rlm@1
|
1156 reg[dest].I = 0x00000000;
|
rlm@1
|
1157 C_FLAG = false;
|
rlm@1
|
1158 }
|
rlm@1
|
1159 }
|
rlm@1
|
1160 }
|
rlm@1
|
1161 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1162 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1163 clockTicks++;
|
rlm@1
|
1164 }
|
rlm@1
|
1165 break;
|
rlm@1
|
1166 case 0x01:
|
rlm@1
|
1167 {
|
rlm@1
|
1168 // ADC Rd, Rs
|
rlm@1
|
1169 int dest = opcode & 0x07;
|
rlm@1
|
1170 u32 value = reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1171 // ADC
|
rlm@1
|
1172 ADC_RD_RS;
|
rlm@1
|
1173 }
|
rlm@1
|
1174 break;
|
rlm@1
|
1175 case 0x02:
|
rlm@1
|
1176 {
|
rlm@1
|
1177 // SBC Rd, Rs
|
rlm@1
|
1178 int dest = opcode & 0x07;
|
rlm@1
|
1179 u32 value = reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1180
|
rlm@1
|
1181 // SBC
|
rlm@1
|
1182 SBC_RD_RS;
|
rlm@1
|
1183 }
|
rlm@1
|
1184 break;
|
rlm@1
|
1185 case 0x03:
|
rlm@1
|
1186 // ROR Rd, Rs
|
rlm@1
|
1187 {
|
rlm@1
|
1188 int dest = opcode & 7;
|
rlm@1
|
1189 u32 value = reg[(opcode >> 3) & 7].B.B0;
|
rlm@1
|
1190
|
rlm@1
|
1191 if (value)
|
rlm@1
|
1192 {
|
rlm@1
|
1193 value = value & 0x1f;
|
rlm@1
|
1194 if (value == 0)
|
rlm@1
|
1195 {
|
rlm@1
|
1196 C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
|
rlm@1
|
1197 }
|
rlm@1
|
1198 else
|
rlm@1
|
1199 {
|
rlm@1
|
1200 ROR_RD_RS;
|
rlm@1
|
1201 reg[dest].I = value;
|
rlm@1
|
1202 }
|
rlm@1
|
1203 }
|
rlm@1
|
1204 clockTicks++;
|
rlm@1
|
1205 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1206 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1207 }
|
rlm@1
|
1208 break;
|
rlm@1
|
1209 }
|
rlm@1
|
1210 break;
|
rlm@1
|
1211 case 0x42:
|
rlm@1
|
1212 switch ((opcode >> 6) & 3)
|
rlm@1
|
1213 {
|
rlm@1
|
1214 case 0x00:
|
rlm@1
|
1215 {
|
rlm@1
|
1216 // TST Rd, Rs
|
rlm@1
|
1217 u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1218 N_FLAG = value & 0x80000000 ? true : false;
|
rlm@1
|
1219 Z_FLAG = value ? false : true;
|
rlm@1
|
1220 }
|
rlm@1
|
1221 break;
|
rlm@1
|
1222 case 0x01:
|
rlm@1
|
1223 {
|
rlm@1
|
1224 // NEG Rd, Rs
|
rlm@1
|
1225 int dest = opcode & 7;
|
rlm@1
|
1226 int source = (opcode >> 3) & 7;
|
rlm@1
|
1227 NEG_RD_RS;
|
rlm@1
|
1228 }
|
rlm@1
|
1229 break;
|
rlm@1
|
1230 case 0x02:
|
rlm@1
|
1231 {
|
rlm@1
|
1232 // CMP Rd, Rs
|
rlm@1
|
1233 int dest = opcode & 7;
|
rlm@1
|
1234 u32 value = reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1235 CMP_RD_RS;
|
rlm@1
|
1236 }
|
rlm@1
|
1237 break;
|
rlm@1
|
1238 case 0x03:
|
rlm@1
|
1239 {
|
rlm@1
|
1240 // CMN Rd, Rs
|
rlm@1
|
1241 int dest = opcode & 7;
|
rlm@1
|
1242 u32 value = reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1243 // CMN
|
rlm@1
|
1244 CMN_RD_RS;
|
rlm@1
|
1245 }
|
rlm@1
|
1246 break;
|
rlm@1
|
1247 }
|
rlm@1
|
1248 break;
|
rlm@1
|
1249 case 0x43:
|
rlm@1
|
1250 switch ((opcode >> 6) & 3)
|
rlm@1
|
1251 {
|
rlm@1
|
1252 case 0x00:
|
rlm@1
|
1253 {
|
rlm@1
|
1254 // ORR Rd, Rs
|
rlm@1
|
1255 int dest = opcode & 7;
|
rlm@1
|
1256 reg[dest].I |= reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1257 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1258 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1259 }
|
rlm@1
|
1260 break;
|
rlm@1
|
1261 case 0x01:
|
rlm@1
|
1262 {
|
rlm@1
|
1263 // MUL Rd, Rs
|
rlm@1
|
1264 int dest = opcode & 7;
|
rlm@1
|
1265 u32 rm = reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1266 reg[dest].I = reg[dest].I * rm;
|
rlm@1
|
1267 if (((s32)rm) < 0)
|
rlm@1
|
1268 rm = ~rm;
|
rlm@1
|
1269 if ((rm & 0xFFFFFF00) == 0)
|
rlm@1
|
1270 clockTicks += 1;
|
rlm@1
|
1271 else if ((rm & 0xFFFF0000) == 0)
|
rlm@1
|
1272 clockTicks += 2;
|
rlm@1
|
1273 else if ((rm & 0xFF000000) == 0)
|
rlm@1
|
1274 clockTicks += 3;
|
rlm@1
|
1275 else
|
rlm@1
|
1276 clockTicks += 4;
|
rlm@1
|
1277 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1278 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1279 }
|
rlm@1
|
1280 break;
|
rlm@1
|
1281 case 0x02:
|
rlm@1
|
1282 {
|
rlm@1
|
1283 // BIC Rd, Rs
|
rlm@1
|
1284 int dest = opcode & 7;
|
rlm@1
|
1285 reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
|
rlm@1
|
1286 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1287 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1288 }
|
rlm@1
|
1289 break;
|
rlm@1
|
1290 case 0x03:
|
rlm@1
|
1291 {
|
rlm@1
|
1292 // MVN Rd, Rs
|
rlm@1
|
1293 int dest = opcode & 7;
|
rlm@1
|
1294 reg[dest].I = ~reg[(opcode >> 3) & 7].I;
|
rlm@1
|
1295 Z_FLAG = reg[dest].I ? false : true;
|
rlm@1
|
1296 N_FLAG = reg[dest].I & 0x80000000 ? true : false;
|
rlm@1
|
1297 }
|
rlm@1
|
1298 break;
|
rlm@1
|
1299 }
|
rlm@1
|
1300 break;
|
rlm@1
|
1301 case 0x44:
|
rlm@1
|
1302 {
|
rlm@1
|
1303 int dest = opcode & 7;
|
rlm@1
|
1304 int base = (opcode >> 3) & 7;
|
rlm@1
|
1305 switch ((opcode >> 6) & 3)
|
rlm@1
|
1306 {
|
rlm@1
|
1307 default:
|
rlm@1
|
1308 goto unknown_thumb;
|
rlm@1
|
1309 case 1:
|
rlm@1
|
1310 // ADD Rd, Hs
|
rlm@1
|
1311 reg[dest].I += reg[base + 8].I;
|
rlm@1
|
1312 break;
|
rlm@1
|
1313 case 2:
|
rlm@1
|
1314 // ADD Hd, Rs
|
rlm@1
|
1315 reg[dest + 8].I += reg[base].I;
|
rlm@1
|
1316 if (dest == 7)
|
rlm@1
|
1317 {
|
rlm@1
|
1318 reg[15].I &= 0xFFFFFFFE;
|
rlm@1
|
1319 armNextPC = reg[15].I;
|
rlm@1
|
1320 reg[15].I += 2;
|
rlm@1
|
1321 clockTicks++;
|
rlm@1
|
1322 }
|
rlm@1
|
1323 break;
|
rlm@1
|
1324 case 3:
|
rlm@1
|
1325 // ADD Hd, Hs
|
rlm@1
|
1326 reg[dest + 8].I += reg[base + 8].I;
|
rlm@1
|
1327 if (dest == 7)
|
rlm@1
|
1328 {
|
rlm@1
|
1329 reg[15].I &= 0xFFFFFFFE;
|
rlm@1
|
1330 armNextPC = reg[15].I;
|
rlm@1
|
1331 reg[15].I += 2;
|
rlm@1
|
1332 clockTicks++;
|
rlm@1
|
1333 }
|
rlm@1
|
1334 break;
|
rlm@1
|
1335 }
|
rlm@1
|
1336 }
|
rlm@1
|
1337 break;
|
rlm@1
|
1338 case 0x45:
|
rlm@1
|
1339 {
|
rlm@1
|
1340 int dest = opcode & 7;
|
rlm@1
|
1341 int base = (opcode >> 3) & 7;
|
rlm@1
|
1342 u32 value;
|
rlm@1
|
1343 switch ((opcode >> 6) & 3)
|
rlm@1
|
1344 {
|
rlm@1
|
1345 case 0:
|
rlm@1
|
1346 // CMP Rd, Hs
|
rlm@1
|
1347 value = reg[base].I;
|
rlm@1
|
1348 CMP_RD_RS;
|
rlm@1
|
1349 break;
|
rlm@1
|
1350 case 1:
|
rlm@1
|
1351 // CMP Rd, Hs
|
rlm@1
|
1352 value = reg[base + 8].I;
|
rlm@1
|
1353 CMP_RD_RS;
|
rlm@1
|
1354 break;
|
rlm@1
|
1355 case 2:
|
rlm@1
|
1356 // CMP Hd, Rs
|
rlm@1
|
1357 value = reg[base].I;
|
rlm@1
|
1358 dest += 8;
|
rlm@1
|
1359 CMP_RD_RS;
|
rlm@1
|
1360 break;
|
rlm@1
|
1361 case 3:
|
rlm@1
|
1362 // CMP Hd, Hs
|
rlm@1
|
1363 value = reg[base + 8].I;
|
rlm@1
|
1364 dest += 8;
|
rlm@1
|
1365 CMP_RD_RS;
|
rlm@1
|
1366 break;
|
rlm@1
|
1367 }
|
rlm@1
|
1368 }
|
rlm@1
|
1369 break;
|
rlm@1
|
1370 case 0x46:
|
rlm@1
|
1371 {
|
rlm@1
|
1372 int dest = opcode & 7;
|
rlm@1
|
1373 int base = (opcode >> 3) & 7;
|
rlm@1
|
1374 switch ((opcode >> 6) & 3)
|
rlm@1
|
1375 {
|
rlm@1
|
1376 case 0:
|
rlm@1
|
1377 // this form should not be used...
|
rlm@1
|
1378 // MOV Rd, Rs
|
rlm@1
|
1379 reg[dest].I = reg[base].I;
|
rlm@1
|
1380 break;
|
rlm@1
|
1381 case 1:
|
rlm@1
|
1382 // MOV Rd, Hs
|
rlm@1
|
1383 reg[dest].I = reg[base + 8].I;
|
rlm@1
|
1384 break;
|
rlm@1
|
1385 case 2:
|
rlm@1
|
1386 // MOV Hd, Rs
|
rlm@1
|
1387 reg[dest + 8].I = reg[base].I;
|
rlm@1
|
1388 if (dest == 7)
|
rlm@1
|
1389 {
|
rlm@1
|
1390 reg[15].I &= 0xFFFFFFFE;
|
rlm@1
|
1391 armNextPC = reg[15].I;
|
rlm@1
|
1392 reg[15].I += 2;
|
rlm@1
|
1393 clockTicks++;
|
rlm@1
|
1394 }
|
rlm@1
|
1395 break;
|
rlm@1
|
1396 case 3:
|
rlm@1
|
1397 // MOV Hd, Hs
|
rlm@1
|
1398 reg[dest + 8].I = reg[base + 8].I;
|
rlm@1
|
1399 if (dest == 7)
|
rlm@1
|
1400 {
|
rlm@1
|
1401 reg[15].I &= 0xFFFFFFFE;
|
rlm@1
|
1402 armNextPC = reg[15].I;
|
rlm@1
|
1403 reg[15].I += 2;
|
rlm@1
|
1404 clockTicks++;
|
rlm@1
|
1405 }
|
rlm@1
|
1406 break;
|
rlm@1
|
1407 }
|
rlm@1
|
1408 }
|
rlm@1
|
1409 break;
|
rlm@1
|
1410 case 0x47:
|
rlm@1
|
1411 {
|
rlm@1
|
1412 int base = (opcode >> 3) & 7;
|
rlm@1
|
1413 switch ((opcode >> 6) & 3)
|
rlm@1
|
1414 {
|
rlm@1
|
1415 case 0:
|
rlm@1
|
1416 // BX Rs
|
rlm@1
|
1417 reg[15].I = (reg[base].I) & 0xFFFFFFFE;
|
rlm@1
|
1418 if (reg[base].I & 1)
|
rlm@1
|
1419 {
|
rlm@1
|
1420 armState = false;
|
rlm@1
|
1421 armNextPC = reg[15].I;
|
rlm@1
|
1422 reg[15].I += 2;
|
rlm@1
|
1423 }
|
rlm@1
|
1424 else
|
rlm@1
|
1425 {
|
rlm@1
|
1426 armState = true;
|
rlm@1
|
1427 reg[15].I &= 0xFFFFFFFC;
|
rlm@1
|
1428 armNextPC = reg[15].I;
|
rlm@1
|
1429 reg[15].I += 4;
|
rlm@1
|
1430 }
|
rlm@1
|
1431 break;
|
rlm@1
|
1432 case 1:
|
rlm@1
|
1433 // BX Hs
|
rlm@1
|
1434 reg[15].I = (reg[8 + base].I) & 0xFFFFFFFE;
|
rlm@1
|
1435 if (reg[8 + base].I & 1)
|
rlm@1
|
1436 {
|
rlm@1
|
1437 armState = false;
|
rlm@1
|
1438 armNextPC = reg[15].I;
|
rlm@1
|
1439 reg[15].I += 2;
|
rlm@1
|
1440 }
|
rlm@1
|
1441 else
|
rlm@1
|
1442 {
|
rlm@1
|
1443 armState = true;
|
rlm@1
|
1444 reg[15].I &= 0xFFFFFFFC;
|
rlm@1
|
1445 armNextPC = reg[15].I;
|
rlm@1
|
1446 reg[15].I += 4;
|
rlm@1
|
1447 }
|
rlm@1
|
1448 break;
|
rlm@1
|
1449 default:
|
rlm@1
|
1450 goto unknown_thumb;
|
rlm@1
|
1451 }
|
rlm@1
|
1452 }
|
rlm@1
|
1453 break;
|
rlm@1
|
1454 case 0x48:
|
rlm@1
|
1455 // LDR R0,[PC, #Imm]
|
rlm@1
|
1456 {
|
rlm@1
|
1457 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1458 reg[0].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1459 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1460 }
|
rlm@1
|
1461 break;
|
rlm@1
|
1462 case 0x49:
|
rlm@1
|
1463 // LDR R1,[PC, #Imm]
|
rlm@1
|
1464 {
|
rlm@1
|
1465 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1466 reg[1].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1467 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1468 }
|
rlm@1
|
1469 break;
|
rlm@1
|
1470 case 0x4a:
|
rlm@1
|
1471 // LDR R2,[PC, #Imm]
|
rlm@1
|
1472 {
|
rlm@1
|
1473 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1474 reg[2].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1475 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1476 }
|
rlm@1
|
1477 break;
|
rlm@1
|
1478 case 0x4b:
|
rlm@1
|
1479 // LDR R3,[PC, #Imm]
|
rlm@1
|
1480 {
|
rlm@1
|
1481 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1482 reg[3].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1483 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1484 }
|
rlm@1
|
1485 break;
|
rlm@1
|
1486 case 0x4c:
|
rlm@1
|
1487 // LDR R4,[PC, #Imm]
|
rlm@1
|
1488 {
|
rlm@1
|
1489 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1490 reg[4].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1491 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1492 }
|
rlm@1
|
1493 break;
|
rlm@1
|
1494 case 0x4d:
|
rlm@1
|
1495 // LDR R5,[PC, #Imm]
|
rlm@1
|
1496 {
|
rlm@1
|
1497 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1498 reg[5].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1499 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1500 }
|
rlm@1
|
1501 break;
|
rlm@1
|
1502 case 0x4e:
|
rlm@1
|
1503 // LDR R6,[PC, #Imm]
|
rlm@1
|
1504 {
|
rlm@1
|
1505 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1506 reg[6].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1507 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1508 }
|
rlm@1
|
1509 break;
|
rlm@1
|
1510 case 0x4f:
|
rlm@1
|
1511 // LDR R7,[PC, #Imm]
|
rlm@1
|
1512 {
|
rlm@1
|
1513 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
|
rlm@1
|
1514 reg[7].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1515 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1516 }
|
rlm@1
|
1517 break;
|
rlm@1
|
1518 case 0x50:
|
rlm@1
|
1519 case 0x51:
|
rlm@1
|
1520 // STR Rd, [Rs, Rn]
|
rlm@1
|
1521 {
|
rlm@1
|
1522 u32
|
rlm@1
|
1523 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1524 CPUWriteMemory(address,
|
rlm@1
|
1525 reg[opcode & 7].I);
|
rlm@1
|
1526 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1527 }
|
rlm@1
|
1528 break;
|
rlm@1
|
1529 case 0x52:
|
rlm@1
|
1530 case 0x53:
|
rlm@1
|
1531 // STRH Rd, [Rs, Rn]
|
rlm@1
|
1532 {
|
rlm@1
|
1533 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1534 CPUWriteHalfWord(address,
|
rlm@1
|
1535 reg[opcode & 7].W.W0);
|
rlm@1
|
1536 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1537 }
|
rlm@1
|
1538 break;
|
rlm@1
|
1539 case 0x54:
|
rlm@1
|
1540 case 0x55:
|
rlm@1
|
1541 // STRB Rd, [Rs, Rn]
|
rlm@1
|
1542 {
|
rlm@1
|
1543 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1544 CPUWriteByte(address,
|
rlm@1
|
1545 reg[opcode & 7].B.B0);
|
rlm@1
|
1546 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1547 }
|
rlm@1
|
1548 break;
|
rlm@1
|
1549 case 0x56:
|
rlm@1
|
1550 case 0x57:
|
rlm@1
|
1551 // LDSB Rd, [Rs, Rn]
|
rlm@1
|
1552 {
|
rlm@1
|
1553 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1554 reg[opcode & 7].I = (s8)CPUReadByte(address);
|
rlm@1
|
1555 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1556 }
|
rlm@1
|
1557 break;
|
rlm@1
|
1558 case 0x58:
|
rlm@1
|
1559 case 0x59:
|
rlm@1
|
1560 // LDR Rd, [Rs, Rn]
|
rlm@1
|
1561 {
|
rlm@1
|
1562 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1563 reg[opcode & 7].I = CPUReadMemory(address);
|
rlm@1
|
1564 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1565 }
|
rlm@1
|
1566 break;
|
rlm@1
|
1567 case 0x5a:
|
rlm@1
|
1568 case 0x5b:
|
rlm@1
|
1569 // LDRH Rd, [Rs, Rn]
|
rlm@1
|
1570 {
|
rlm@1
|
1571 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1572 reg[opcode & 7].I = CPUReadHalfWord(address);
|
rlm@1
|
1573 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1574 }
|
rlm@1
|
1575 break;
|
rlm@1
|
1576 case 0x5c:
|
rlm@1
|
1577 case 0x5d:
|
rlm@1
|
1578 // LDRB Rd, [Rs, Rn]
|
rlm@1
|
1579 {
|
rlm@1
|
1580 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1581 reg[opcode & 7].I = CPUReadByte(address);
|
rlm@1
|
1582 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1583 }
|
rlm@1
|
1584 break;
|
rlm@1
|
1585 case 0x5e:
|
rlm@1
|
1586 case 0x5f:
|
rlm@1
|
1587 // LDSH Rd, [Rs, Rn]
|
rlm@1
|
1588 {
|
rlm@1
|
1589 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
|
rlm@1
|
1590 reg[opcode & 7].I = (s16)CPUReadHalfWordSigned(address);
|
rlm@1
|
1591 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1592 }
|
rlm@1
|
1593 break;
|
rlm@1
|
1594 case 0x60:
|
rlm@1
|
1595 case 0x61:
|
rlm@1
|
1596 case 0x62:
|
rlm@1
|
1597 case 0x63:
|
rlm@1
|
1598 case 0x64:
|
rlm@1
|
1599 case 0x65:
|
rlm@1
|
1600 case 0x66:
|
rlm@1
|
1601 case 0x67:
|
rlm@1
|
1602 // STR Rd, [Rs, #Imm]
|
rlm@1
|
1603 {
|
rlm@1
|
1604 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
|
rlm@1
|
1605 CPUWriteMemory(address,
|
rlm@1
|
1606 reg[opcode & 7].I);
|
rlm@1
|
1607 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1608 }
|
rlm@1
|
1609 break;
|
rlm@1
|
1610 case 0x68:
|
rlm@1
|
1611 case 0x69:
|
rlm@1
|
1612 case 0x6a:
|
rlm@1
|
1613 case 0x6b:
|
rlm@1
|
1614 case 0x6c:
|
rlm@1
|
1615 case 0x6d:
|
rlm@1
|
1616 case 0x6e:
|
rlm@1
|
1617 case 0x6f:
|
rlm@1
|
1618 // LDR Rd, [Rs, #Imm]
|
rlm@1
|
1619 {
|
rlm@1
|
1620 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
|
rlm@1
|
1621 reg[opcode & 7].I = CPUReadMemory(address);
|
rlm@1
|
1622 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1623 }
|
rlm@1
|
1624 break;
|
rlm@1
|
1625 case 0x70:
|
rlm@1
|
1626 case 0x71:
|
rlm@1
|
1627 case 0x72:
|
rlm@1
|
1628 case 0x73:
|
rlm@1
|
1629 case 0x74:
|
rlm@1
|
1630 case 0x75:
|
rlm@1
|
1631 case 0x76:
|
rlm@1
|
1632 case 0x77:
|
rlm@1
|
1633 // STRB Rd, [Rs, #Imm]
|
rlm@1
|
1634 {
|
rlm@1
|
1635 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31));
|
rlm@1
|
1636 CPUWriteByte(address,
|
rlm@1
|
1637 reg[opcode & 7].B.B0);
|
rlm@1
|
1638 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1639 }
|
rlm@1
|
1640 break;
|
rlm@1
|
1641 case 0x78:
|
rlm@1
|
1642 case 0x79:
|
rlm@1
|
1643 case 0x7a:
|
rlm@1
|
1644 case 0x7b:
|
rlm@1
|
1645 case 0x7c:
|
rlm@1
|
1646 case 0x7d:
|
rlm@1
|
1647 case 0x7e:
|
rlm@1
|
1648 case 0x7f:
|
rlm@1
|
1649 // LDRB Rd, [Rs, #Imm]
|
rlm@1
|
1650 {
|
rlm@1
|
1651 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31));
|
rlm@1
|
1652 reg[opcode & 7].I = CPUReadByte(address);
|
rlm@1
|
1653 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1654 }
|
rlm@1
|
1655 break;
|
rlm@1
|
1656 case 0x80:
|
rlm@1
|
1657 case 0x81:
|
rlm@1
|
1658 case 0x82:
|
rlm@1
|
1659 case 0x83:
|
rlm@1
|
1660 case 0x84:
|
rlm@1
|
1661 case 0x85:
|
rlm@1
|
1662 case 0x86:
|
rlm@1
|
1663 case 0x87:
|
rlm@1
|
1664 // STRH Rd, [Rs, #Imm]
|
rlm@1
|
1665 {
|
rlm@1
|
1666 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
|
rlm@1
|
1667 CPUWriteHalfWord(address,
|
rlm@1
|
1668 reg[opcode & 7].W.W0);
|
rlm@1
|
1669 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1670 }
|
rlm@1
|
1671 break;
|
rlm@1
|
1672 case 0x88:
|
rlm@1
|
1673 case 0x89:
|
rlm@1
|
1674 case 0x8a:
|
rlm@1
|
1675 case 0x8b:
|
rlm@1
|
1676 case 0x8c:
|
rlm@1
|
1677 case 0x8d:
|
rlm@1
|
1678 case 0x8e:
|
rlm@1
|
1679 case 0x8f:
|
rlm@1
|
1680 // LDRH Rd, [Rs, #Imm]
|
rlm@1
|
1681 {
|
rlm@1
|
1682 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
|
rlm@1
|
1683 reg[opcode & 7].I = CPUReadHalfWord(address);
|
rlm@1
|
1684 clockTicks += CPUUpdateTicksAccess16(address);
|
rlm@1
|
1685 }
|
rlm@1
|
1686 break;
|
rlm@1
|
1687 case 0x90:
|
rlm@1
|
1688 // STR R0, [SP, #Imm]
|
rlm@1
|
1689 {
|
rlm@1
|
1690 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1691 CPUWriteMemory(address, reg[0].I);
|
rlm@1
|
1692 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1693 }
|
rlm@1
|
1694 break;
|
rlm@1
|
1695 case 0x91:
|
rlm@1
|
1696 // STR R1, [SP, #Imm]
|
rlm@1
|
1697 {
|
rlm@1
|
1698 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1699 CPUWriteMemory(address, reg[1].I);
|
rlm@1
|
1700 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1701 }
|
rlm@1
|
1702 break;
|
rlm@1
|
1703 case 0x92:
|
rlm@1
|
1704 // STR R2, [SP, #Imm]
|
rlm@1
|
1705 {
|
rlm@1
|
1706 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1707 CPUWriteMemory(address, reg[2].I);
|
rlm@1
|
1708 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1709 }
|
rlm@1
|
1710 break;
|
rlm@1
|
1711 case 0x93:
|
rlm@1
|
1712 // STR R3, [SP, #Imm]
|
rlm@1
|
1713 {
|
rlm@1
|
1714 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1715 CPUWriteMemory(address, reg[3].I);
|
rlm@1
|
1716 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1717 }
|
rlm@1
|
1718 break;
|
rlm@1
|
1719 case 0x94:
|
rlm@1
|
1720 // STR R4, [SP, #Imm]
|
rlm@1
|
1721 {
|
rlm@1
|
1722 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1723 CPUWriteMemory(address, reg[4].I);
|
rlm@1
|
1724 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1725 }
|
rlm@1
|
1726 break;
|
rlm@1
|
1727 case 0x95:
|
rlm@1
|
1728 // STR R5, [SP, #Imm]
|
rlm@1
|
1729 {
|
rlm@1
|
1730 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1731 CPUWriteMemory(address, reg[5].I);
|
rlm@1
|
1732 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1733 }
|
rlm@1
|
1734 break;
|
rlm@1
|
1735 case 0x96:
|
rlm@1
|
1736 // STR R6, [SP, #Imm]
|
rlm@1
|
1737 {
|
rlm@1
|
1738 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1739 CPUWriteMemory(address, reg[6].I);
|
rlm@1
|
1740 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1741 }
|
rlm@1
|
1742 break;
|
rlm@1
|
1743 case 0x97:
|
rlm@1
|
1744 // STR R7, [SP, #Imm]
|
rlm@1
|
1745 {
|
rlm@1
|
1746 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1747 CPUWriteMemory(address, reg[7].I);
|
rlm@1
|
1748 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1749 }
|
rlm@1
|
1750 break;
|
rlm@1
|
1751 case 0x98:
|
rlm@1
|
1752 // LDR R0, [SP, #Imm]
|
rlm@1
|
1753 {
|
rlm@1
|
1754 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1755 reg[0].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1756 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1757 }
|
rlm@1
|
1758 break;
|
rlm@1
|
1759 case 0x99:
|
rlm@1
|
1760 // LDR R1, [SP, #Imm]
|
rlm@1
|
1761 {
|
rlm@1
|
1762 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1763 reg[1].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1764 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1765 }
|
rlm@1
|
1766 break;
|
rlm@1
|
1767 case 0x9a:
|
rlm@1
|
1768 // LDR R2, [SP, #Imm]
|
rlm@1
|
1769 {
|
rlm@1
|
1770 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1771 reg[2].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1772 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1773 }
|
rlm@1
|
1774 break;
|
rlm@1
|
1775 case 0x9b:
|
rlm@1
|
1776 // LDR R3, [SP, #Imm]
|
rlm@1
|
1777 {
|
rlm@1
|
1778 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1779 reg[3].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1780 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1781 }
|
rlm@1
|
1782 break;
|
rlm@1
|
1783 case 0x9c:
|
rlm@1
|
1784 // LDR R4, [SP, #Imm]
|
rlm@1
|
1785 {
|
rlm@1
|
1786 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1787 reg[4].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1788 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1789 }
|
rlm@1
|
1790 break;
|
rlm@1
|
1791 case 0x9d:
|
rlm@1
|
1792 // LDR R5, [SP, #Imm]
|
rlm@1
|
1793 {
|
rlm@1
|
1794 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1795 reg[5].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1796 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1797 }
|
rlm@1
|
1798 break;
|
rlm@1
|
1799 case 0x9e:
|
rlm@1
|
1800 // LDR R6, [SP, #Imm]
|
rlm@1
|
1801 {
|
rlm@1
|
1802 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1803 reg[6].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1804 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1805 }
|
rlm@1
|
1806 break;
|
rlm@1
|
1807 case 0x9f:
|
rlm@1
|
1808 // LDR R7, [SP, #Imm]
|
rlm@1
|
1809 {
|
rlm@1
|
1810 u32 address = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1811 reg[7].I = CPUReadMemoryQuick(address);
|
rlm@1
|
1812 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1813 }
|
rlm@1
|
1814 break;
|
rlm@1
|
1815 case 0xa0:
|
rlm@1
|
1816 // ADD R0, PC, Imm
|
rlm@1
|
1817 reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1818 break;
|
rlm@1
|
1819 case 0xa1:
|
rlm@1
|
1820 // ADD R1, PC, Imm
|
rlm@1
|
1821 reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1822 break;
|
rlm@1
|
1823 case 0xa2:
|
rlm@1
|
1824 // ADD R2, PC, Imm
|
rlm@1
|
1825 reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1826 break;
|
rlm@1
|
1827 case 0xa3:
|
rlm@1
|
1828 // ADD R3, PC, Imm
|
rlm@1
|
1829 reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1830 break;
|
rlm@1
|
1831 case 0xa4:
|
rlm@1
|
1832 // ADD R4, PC, Imm
|
rlm@1
|
1833 reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1834 break;
|
rlm@1
|
1835 case 0xa5:
|
rlm@1
|
1836 // ADD R5, PC, Imm
|
rlm@1
|
1837 reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1838 break;
|
rlm@1
|
1839 case 0xa6:
|
rlm@1
|
1840 // ADD R6, PC, Imm
|
rlm@1
|
1841 reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1842 break;
|
rlm@1
|
1843 case 0xa7:
|
rlm@1
|
1844 // ADD R7, PC, Imm
|
rlm@1
|
1845 reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
|
rlm@1
|
1846 break;
|
rlm@1
|
1847 case 0xa8:
|
rlm@1
|
1848 // ADD R0, SP, Imm
|
rlm@1
|
1849 reg[0].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1850 break;
|
rlm@1
|
1851 case 0xa9:
|
rlm@1
|
1852 // ADD R1, SP, Imm
|
rlm@1
|
1853 reg[1].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1854 break;
|
rlm@1
|
1855 case 0xaa:
|
rlm@1
|
1856 // ADD R2, SP, Imm
|
rlm@1
|
1857 reg[2].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1858 break;
|
rlm@1
|
1859 case 0xab:
|
rlm@1
|
1860 // ADD R3, SP, Imm
|
rlm@1
|
1861 reg[3].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1862 break;
|
rlm@1
|
1863 case 0xac:
|
rlm@1
|
1864 // ADD R4, SP, Imm
|
rlm@1
|
1865 reg[4].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1866 break;
|
rlm@1
|
1867 case 0xad:
|
rlm@1
|
1868 // ADD R5, SP, Imm
|
rlm@1
|
1869 reg[5].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1870 break;
|
rlm@1
|
1871 case 0xae:
|
rlm@1
|
1872 // ADD R6, SP, Imm
|
rlm@1
|
1873 reg[6].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1874 break;
|
rlm@1
|
1875 case 0xaf:
|
rlm@1
|
1876 // ADD R7, SP, Imm
|
rlm@1
|
1877 reg[7].I = reg[13].I + ((opcode & 255) << 2);
|
rlm@1
|
1878 break;
|
rlm@1
|
1879 case 0xb0:
|
rlm@1
|
1880 {
|
rlm@1
|
1881 // ADD SP, Imm
|
rlm@1
|
1882 int offset = (opcode & 127) << 2;
|
rlm@1
|
1883 if (opcode & 0x80)
|
rlm@1
|
1884 offset = -offset;
|
rlm@1
|
1885 reg[13].I += offset;
|
rlm@1
|
1886 }
|
rlm@1
|
1887 break;
|
rlm@1
|
1888 #define PUSH_REG(val, r) \
|
rlm@1
|
1889 if (opcode & (val)) { \
|
rlm@1
|
1890 CPUWriteMemory(address, reg[(r)].I); \
|
rlm@1
|
1891 if (offset) \
|
rlm@1
|
1892 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
|
rlm@1
|
1893 else \
|
rlm@1
|
1894 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
|
rlm@1
|
1895 offset = 1; \
|
rlm@1
|
1896 address += 4; \
|
rlm@1
|
1897 }
|
rlm@1
|
1898 case 0xb4:
|
rlm@1
|
1899 // PUSH {Rlist}
|
rlm@1
|
1900 {
|
rlm@1
|
1901 int offset = 0;
|
rlm@1
|
1902 u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
1903 u32 address = temp & 0xFFFFFFFC;
|
rlm@1
|
1904 PUSH_REG(1, 0);
|
rlm@1
|
1905 PUSH_REG(2, 1);
|
rlm@1
|
1906 PUSH_REG(4, 2);
|
rlm@1
|
1907 PUSH_REG(8, 3);
|
rlm@1
|
1908 PUSH_REG(16, 4);
|
rlm@1
|
1909 PUSH_REG(32, 5);
|
rlm@1
|
1910 PUSH_REG(64, 6);
|
rlm@1
|
1911 PUSH_REG(128, 7);
|
rlm@1
|
1912 reg[13].I = temp;
|
rlm@1
|
1913 }
|
rlm@1
|
1914 break;
|
rlm@1
|
1915 case 0xb5:
|
rlm@1
|
1916 // PUSH {Rlist, LR}
|
rlm@1
|
1917 {
|
rlm@1
|
1918 int offset = 0;
|
rlm@1
|
1919 u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
1920 u32 address = temp & 0xFFFFFFFC;
|
rlm@1
|
1921 PUSH_REG(1, 0);
|
rlm@1
|
1922 PUSH_REG(2, 1);
|
rlm@1
|
1923 PUSH_REG(4, 2);
|
rlm@1
|
1924 PUSH_REG(8, 3);
|
rlm@1
|
1925 PUSH_REG(16, 4);
|
rlm@1
|
1926 PUSH_REG(32, 5);
|
rlm@1
|
1927 PUSH_REG(64, 6);
|
rlm@1
|
1928 PUSH_REG(128, 7);
|
rlm@1
|
1929 PUSH_REG(256, 14);
|
rlm@1
|
1930 reg[13].I = temp;
|
rlm@1
|
1931 }
|
rlm@1
|
1932 break;
|
rlm@1
|
1933 #define POP_REG(val, r) \
|
rlm@1
|
1934 if (opcode & (val)) { \
|
rlm@1
|
1935 reg[(r)].I = CPUReadMemory(address); \
|
rlm@1
|
1936 if (offset) \
|
rlm@1
|
1937 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \
|
rlm@1
|
1938 else \
|
rlm@1
|
1939 clockTicks += 2 + CPUUpdateTicksAccess32(address); \
|
rlm@1
|
1940 offset = 1; \
|
rlm@1
|
1941 address += 4; \
|
rlm@1
|
1942 }
|
rlm@1
|
1943 case 0xbc:
|
rlm@1
|
1944 // POP {Rlist}
|
rlm@1
|
1945 {
|
rlm@1
|
1946 int offset = 0;
|
rlm@1
|
1947 u32 address = reg[13].I & 0xFFFFFFFC;
|
rlm@1
|
1948 u32 temp = reg[13].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
1949 POP_REG(1, 0);
|
rlm@1
|
1950 POP_REG(2, 1);
|
rlm@1
|
1951 POP_REG(4, 2);
|
rlm@1
|
1952 POP_REG(8, 3);
|
rlm@1
|
1953 POP_REG(16, 4);
|
rlm@1
|
1954 POP_REG(32, 5);
|
rlm@1
|
1955 POP_REG(64, 6);
|
rlm@1
|
1956 POP_REG(128, 7);
|
rlm@1
|
1957 reg[13].I = temp;
|
rlm@1
|
1958 }
|
rlm@1
|
1959 break;
|
rlm@1
|
1960 case 0xbd:
|
rlm@1
|
1961 // POP {Rlist, PC}
|
rlm@1
|
1962 {
|
rlm@1
|
1963 int offset = 0;
|
rlm@1
|
1964 u32 address = reg[13].I & 0xFFFFFFFC;
|
rlm@1
|
1965 u32 temp = reg[13].I + 4 + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
1966 POP_REG(1, 0);
|
rlm@1
|
1967 POP_REG(2, 1);
|
rlm@1
|
1968 POP_REG(4, 2);
|
rlm@1
|
1969 POP_REG(8, 3);
|
rlm@1
|
1970 POP_REG(16, 4);
|
rlm@1
|
1971 POP_REG(32, 5);
|
rlm@1
|
1972 POP_REG(64, 6);
|
rlm@1
|
1973 POP_REG(128, 7);
|
rlm@1
|
1974 reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
|
rlm@1
|
1975 if (offset)
|
rlm@1
|
1976 clockTicks += CPUUpdateTicksAccessSeq32(address);
|
rlm@1
|
1977 else
|
rlm@1
|
1978 clockTicks += CPUUpdateTicksAccess32(address);
|
rlm@1
|
1979 armNextPC = reg[15].I;
|
rlm@1
|
1980 reg[15].I += 2;
|
rlm@1
|
1981 reg[13].I = temp;
|
rlm@1
|
1982 }
|
rlm@1
|
1983 break;
|
rlm@1
|
1984 #define THUMB_STM_REG(val, r, b) \
|
rlm@1
|
1985 if (opcode & (val)) { \
|
rlm@1
|
1986 CPUWriteMemory(address, reg[(r)].I); \
|
rlm@1
|
1987 if (!offset) { \
|
rlm@1
|
1988 reg[(b)].I = temp; \
|
rlm@1
|
1989 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
|
rlm@1
|
1990 } else \
|
rlm@1
|
1991 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
|
rlm@1
|
1992 offset = 1; \
|
rlm@1
|
1993 address += 4; \
|
rlm@1
|
1994 }
|
rlm@1
|
1995 case 0xc0:
|
rlm@1
|
1996 {
|
rlm@1
|
1997 // STM R0!, {Rlist}
|
rlm@1
|
1998 u32 address = reg[0].I & 0xFFFFFFFC;
|
rlm@1
|
1999 u32 temp = reg[0].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2000 int offset = 0;
|
rlm@1
|
2001 // store
|
rlm@1
|
2002 THUMB_STM_REG(1, 0, 0);
|
rlm@1
|
2003 THUMB_STM_REG(2, 1, 0);
|
rlm@1
|
2004 THUMB_STM_REG(4, 2, 0);
|
rlm@1
|
2005 THUMB_STM_REG(8, 3, 0);
|
rlm@1
|
2006 THUMB_STM_REG(16, 4, 0);
|
rlm@1
|
2007 THUMB_STM_REG(32, 5, 0);
|
rlm@1
|
2008 THUMB_STM_REG(64, 6, 0);
|
rlm@1
|
2009 THUMB_STM_REG(128, 7, 0);
|
rlm@1
|
2010 }
|
rlm@1
|
2011 break;
|
rlm@1
|
2012 case 0xc1:
|
rlm@1
|
2013 {
|
rlm@1
|
2014 // STM R1!, {Rlist}
|
rlm@1
|
2015 u32 address = reg[1].I & 0xFFFFFFFC;
|
rlm@1
|
2016 u32 temp = reg[1].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2017 int offset = 0;
|
rlm@1
|
2018 // store
|
rlm@1
|
2019 THUMB_STM_REG(1, 0, 1);
|
rlm@1
|
2020 THUMB_STM_REG(2, 1, 1);
|
rlm@1
|
2021 THUMB_STM_REG(4, 2, 1);
|
rlm@1
|
2022 THUMB_STM_REG(8, 3, 1);
|
rlm@1
|
2023 THUMB_STM_REG(16, 4, 1);
|
rlm@1
|
2024 THUMB_STM_REG(32, 5, 1);
|
rlm@1
|
2025 THUMB_STM_REG(64, 6, 1);
|
rlm@1
|
2026 THUMB_STM_REG(128, 7, 1);
|
rlm@1
|
2027 }
|
rlm@1
|
2028 break;
|
rlm@1
|
2029 case 0xc2:
|
rlm@1
|
2030 {
|
rlm@1
|
2031 // STM R2!, {Rlist}
|
rlm@1
|
2032 u32 address = reg[2].I & 0xFFFFFFFC;
|
rlm@1
|
2033 u32 temp = reg[2].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2034 int offset = 0;
|
rlm@1
|
2035 // store
|
rlm@1
|
2036 THUMB_STM_REG(1, 0, 2);
|
rlm@1
|
2037 THUMB_STM_REG(2, 1, 2);
|
rlm@1
|
2038 THUMB_STM_REG(4, 2, 2);
|
rlm@1
|
2039 THUMB_STM_REG(8, 3, 2);
|
rlm@1
|
2040 THUMB_STM_REG(16, 4, 2);
|
rlm@1
|
2041 THUMB_STM_REG(32, 5, 2);
|
rlm@1
|
2042 THUMB_STM_REG(64, 6, 2);
|
rlm@1
|
2043 THUMB_STM_REG(128, 7, 2);
|
rlm@1
|
2044 }
|
rlm@1
|
2045 break;
|
rlm@1
|
2046 case 0xc3:
|
rlm@1
|
2047 {
|
rlm@1
|
2048 // STM R3!, {Rlist}
|
rlm@1
|
2049 u32 address = reg[3].I & 0xFFFFFFFC;
|
rlm@1
|
2050 u32 temp = reg[3].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2051 int offset = 0;
|
rlm@1
|
2052 // store
|
rlm@1
|
2053 THUMB_STM_REG(1, 0, 3);
|
rlm@1
|
2054 THUMB_STM_REG(2, 1, 3);
|
rlm@1
|
2055 THUMB_STM_REG(4, 2, 3);
|
rlm@1
|
2056 THUMB_STM_REG(8, 3, 3);
|
rlm@1
|
2057 THUMB_STM_REG(16, 4, 3);
|
rlm@1
|
2058 THUMB_STM_REG(32, 5, 3);
|
rlm@1
|
2059 THUMB_STM_REG(64, 6, 3);
|
rlm@1
|
2060 THUMB_STM_REG(128, 7, 3);
|
rlm@1
|
2061 }
|
rlm@1
|
2062 break;
|
rlm@1
|
2063 case 0xc4:
|
rlm@1
|
2064 {
|
rlm@1
|
2065 // STM R4!, {Rlist}
|
rlm@1
|
2066 u32 address = reg[4].I & 0xFFFFFFFC;
|
rlm@1
|
2067 u32 temp = reg[4].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2068 int offset = 0;
|
rlm@1
|
2069 // store
|
rlm@1
|
2070 THUMB_STM_REG(1, 0, 4);
|
rlm@1
|
2071 THUMB_STM_REG(2, 1, 4);
|
rlm@1
|
2072 THUMB_STM_REG(4, 2, 4);
|
rlm@1
|
2073 THUMB_STM_REG(8, 3, 4);
|
rlm@1
|
2074 THUMB_STM_REG(16, 4, 4);
|
rlm@1
|
2075 THUMB_STM_REG(32, 5, 4);
|
rlm@1
|
2076 THUMB_STM_REG(64, 6, 4);
|
rlm@1
|
2077 THUMB_STM_REG(128, 7, 4);
|
rlm@1
|
2078 }
|
rlm@1
|
2079 break;
|
rlm@1
|
2080 case 0xc5:
|
rlm@1
|
2081 {
|
rlm@1
|
2082 // STM R5!, {Rlist}
|
rlm@1
|
2083 u32 address = reg[5].I & 0xFFFFFFFC;
|
rlm@1
|
2084 u32 temp = reg[5].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2085 int offset = 0;
|
rlm@1
|
2086 // store
|
rlm@1
|
2087 THUMB_STM_REG(1, 0, 5);
|
rlm@1
|
2088 THUMB_STM_REG(2, 1, 5);
|
rlm@1
|
2089 THUMB_STM_REG(4, 2, 5);
|
rlm@1
|
2090 THUMB_STM_REG(8, 3, 5);
|
rlm@1
|
2091 THUMB_STM_REG(16, 4, 5);
|
rlm@1
|
2092 THUMB_STM_REG(32, 5, 5);
|
rlm@1
|
2093 THUMB_STM_REG(64, 6, 5);
|
rlm@1
|
2094 THUMB_STM_REG(128, 7, 5);
|
rlm@1
|
2095 }
|
rlm@1
|
2096 break;
|
rlm@1
|
2097 case 0xc6:
|
rlm@1
|
2098 {
|
rlm@1
|
2099 // STM R6!, {Rlist}
|
rlm@1
|
2100 u32 address = reg[6].I & 0xFFFFFFFC;
|
rlm@1
|
2101 u32 temp = reg[6].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2102 int offset = 0;
|
rlm@1
|
2103 // store
|
rlm@1
|
2104 THUMB_STM_REG(1, 0, 6);
|
rlm@1
|
2105 THUMB_STM_REG(2, 1, 6);
|
rlm@1
|
2106 THUMB_STM_REG(4, 2, 6);
|
rlm@1
|
2107 THUMB_STM_REG(8, 3, 6);
|
rlm@1
|
2108 THUMB_STM_REG(16, 4, 6);
|
rlm@1
|
2109 THUMB_STM_REG(32, 5, 6);
|
rlm@1
|
2110 THUMB_STM_REG(64, 6, 6);
|
rlm@1
|
2111 THUMB_STM_REG(128, 7, 6);
|
rlm@1
|
2112 }
|
rlm@1
|
2113 break;
|
rlm@1
|
2114 case 0xc7:
|
rlm@1
|
2115 {
|
rlm@1
|
2116 // STM R7!, {Rlist}
|
rlm@1
|
2117 u32 address = reg[7].I & 0xFFFFFFFC;
|
rlm@1
|
2118 u32 temp = reg[7].I + 4 * cpuBitsSet[opcode & 0xff];
|
rlm@1
|
2119 int offset = 0;
|
rlm@1
|
2120 // store
|
rlm@1
|
2121 THUMB_STM_REG(1, 0, 7);
|
rlm@1
|
2122 THUMB_STM_REG(2, 1, 7);
|
rlm@1
|
2123 THUMB_STM_REG(4, 2, 7);
|
rlm@1
|
2124 THUMB_STM_REG(8, 3, 7);
|
rlm@1
|
2125 THUMB_STM_REG(16, 4, 7);
|
rlm@1
|
2126 THUMB_STM_REG(32, 5, 7);
|
rlm@1
|
2127 THUMB_STM_REG(64, 6, 7);
|
rlm@1
|
2128 THUMB_STM_REG(128, 7, 7);
|
rlm@1
|
2129 }
|
rlm@1
|
2130 break;
|
rlm@1
|
2131 #define THUMB_LDM_REG(val, r) \
|
rlm@1
|
2132 if (opcode & (val)) { \
|
rlm@1
|
2133 reg[(r)].I = CPUReadMemory(address); \
|
rlm@1
|
2134 if (offset) \
|
rlm@1
|
2135 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \
|
rlm@1
|
2136 else \
|
rlm@1
|
2137 clockTicks += 2 + CPUUpdateTicksAccess32(address); \
|
rlm@1
|
2138 offset = 1; \
|
rlm@1
|
2139 address += 4; \
|
rlm@1
|
2140 }
|
rlm@1
|
2141 case 0xc8:
|
rlm@1
|
2142 {
|
rlm@1
|
2143 // LDM R0!, {Rlist}
|
rlm@1
|
2144 u32 address = reg[0].I & 0xFFFFFFFC;
|
rlm@1
|
2145 u32 temp = reg[0].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2146 int offset = 0;
|
rlm@1
|
2147 // load
|
rlm@1
|
2148 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2149 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2150 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2151 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2152 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2153 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2154 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2155 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2156 if (!(opcode & 1))
|
rlm@1
|
2157 reg[0].I = temp;
|
rlm@1
|
2158 }
|
rlm@1
|
2159 break;
|
rlm@1
|
2160 case 0xc9:
|
rlm@1
|
2161 {
|
rlm@1
|
2162 // LDM R1!, {Rlist}
|
rlm@1
|
2163 u32 address = reg[1].I & 0xFFFFFFFC;
|
rlm@1
|
2164 u32 temp = reg[1].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2165 int offset = 0;
|
rlm@1
|
2166 // load
|
rlm@1
|
2167 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2168 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2169 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2170 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2171 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2172 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2173 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2174 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2175 if (!(opcode & 2))
|
rlm@1
|
2176 reg[1].I = temp;
|
rlm@1
|
2177 }
|
rlm@1
|
2178 break;
|
rlm@1
|
2179 case 0xca:
|
rlm@1
|
2180 {
|
rlm@1
|
2181 // LDM R2!, {Rlist}
|
rlm@1
|
2182 u32 address = reg[2].I & 0xFFFFFFFC;
|
rlm@1
|
2183 u32 temp = reg[2].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2184 int offset = 0;
|
rlm@1
|
2185 // load
|
rlm@1
|
2186 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2187 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2188 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2189 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2190 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2191 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2192 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2193 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2194 if (!(opcode & 4))
|
rlm@1
|
2195 reg[2].I = temp;
|
rlm@1
|
2196 }
|
rlm@1
|
2197 break;
|
rlm@1
|
2198 case 0xcb:
|
rlm@1
|
2199 {
|
rlm@1
|
2200 // LDM R3!, {Rlist}
|
rlm@1
|
2201 u32 address = reg[3].I & 0xFFFFFFFC;
|
rlm@1
|
2202 u32 temp = reg[3].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2203 int offset = 0;
|
rlm@1
|
2204 // load
|
rlm@1
|
2205 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2206 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2207 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2208 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2209 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2210 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2211 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2212 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2213 if (!(opcode & 8))
|
rlm@1
|
2214 reg[3].I = temp;
|
rlm@1
|
2215 }
|
rlm@1
|
2216 break;
|
rlm@1
|
2217 case 0xcc:
|
rlm@1
|
2218 {
|
rlm@1
|
2219 // LDM R4!, {Rlist}
|
rlm@1
|
2220 u32 address = reg[4].I & 0xFFFFFFFC;
|
rlm@1
|
2221 u32 temp = reg[4].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2222 int offset = 0;
|
rlm@1
|
2223 // load
|
rlm@1
|
2224 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2225 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2226 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2227 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2228 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2229 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2230 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2231 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2232 if (!(opcode & 16))
|
rlm@1
|
2233 reg[4].I = temp;
|
rlm@1
|
2234 }
|
rlm@1
|
2235 break;
|
rlm@1
|
2236 case 0xcd:
|
rlm@1
|
2237 {
|
rlm@1
|
2238 // LDM R5!, {Rlist}
|
rlm@1
|
2239 u32 address = reg[5].I & 0xFFFFFFFC;
|
rlm@1
|
2240 u32 temp = reg[5].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2241 int offset = 0;
|
rlm@1
|
2242 // load
|
rlm@1
|
2243 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2244 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2245 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2246 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2247 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2248 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2249 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2250 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2251 if (!(opcode & 32))
|
rlm@1
|
2252 reg[5].I = temp;
|
rlm@1
|
2253 }
|
rlm@1
|
2254 break;
|
rlm@1
|
2255 case 0xce:
|
rlm@1
|
2256 {
|
rlm@1
|
2257 // LDM R6!, {Rlist}
|
rlm@1
|
2258 u32 address = reg[6].I & 0xFFFFFFFC;
|
rlm@1
|
2259 u32 temp = reg[6].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2260 int offset = 0;
|
rlm@1
|
2261 // load
|
rlm@1
|
2262 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2263 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2264 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2265 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2266 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2267 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2268 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2269 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2270 if (!(opcode & 64))
|
rlm@1
|
2271 reg[6].I = temp;
|
rlm@1
|
2272 }
|
rlm@1
|
2273 break;
|
rlm@1
|
2274 case 0xcf:
|
rlm@1
|
2275 {
|
rlm@1
|
2276 // LDM R7!, {Rlist}
|
rlm@1
|
2277 u32 address = reg[7].I & 0xFFFFFFFC;
|
rlm@1
|
2278 u32 temp = reg[7].I + 4 * cpuBitsSet[opcode & 0xFF];
|
rlm@1
|
2279 int offset = 0;
|
rlm@1
|
2280 // load
|
rlm@1
|
2281 THUMB_LDM_REG(1, 0);
|
rlm@1
|
2282 THUMB_LDM_REG(2, 1);
|
rlm@1
|
2283 THUMB_LDM_REG(4, 2);
|
rlm@1
|
2284 THUMB_LDM_REG(8, 3);
|
rlm@1
|
2285 THUMB_LDM_REG(16, 4);
|
rlm@1
|
2286 THUMB_LDM_REG(32, 5);
|
rlm@1
|
2287 THUMB_LDM_REG(64, 6);
|
rlm@1
|
2288 THUMB_LDM_REG(128, 7);
|
rlm@1
|
2289 if (!(opcode & 128))
|
rlm@1
|
2290 reg[7].I = temp;
|
rlm@1
|
2291 }
|
rlm@1
|
2292 break;
|
rlm@1
|
2293 case 0xd0:
|
rlm@1
|
2294 // BEQ offset
|
rlm@1
|
2295 if (Z_FLAG)
|
rlm@1
|
2296 {
|
rlm@1
|
2297 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2298 armNextPC = reg[15].I;
|
rlm@1
|
2299 reg[15].I += 2;
|
rlm@1
|
2300 clockTicks = 3;
|
rlm@1
|
2301 }
|
rlm@1
|
2302 break;
|
rlm@1
|
2303 case 0xd1:
|
rlm@1
|
2304 // BNE offset
|
rlm@1
|
2305 if (!Z_FLAG)
|
rlm@1
|
2306 {
|
rlm@1
|
2307 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2308 armNextPC = reg[15].I;
|
rlm@1
|
2309 reg[15].I += 2;
|
rlm@1
|
2310 clockTicks = 3;
|
rlm@1
|
2311 }
|
rlm@1
|
2312 break;
|
rlm@1
|
2313 case 0xd2:
|
rlm@1
|
2314 // BCS offset
|
rlm@1
|
2315 if (C_FLAG)
|
rlm@1
|
2316 {
|
rlm@1
|
2317 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2318 armNextPC = reg[15].I;
|
rlm@1
|
2319 reg[15].I += 2;
|
rlm@1
|
2320 clockTicks = 3;
|
rlm@1
|
2321 }
|
rlm@1
|
2322 break;
|
rlm@1
|
2323 case 0xd3:
|
rlm@1
|
2324 // BCC offset
|
rlm@1
|
2325 if (!C_FLAG)
|
rlm@1
|
2326 {
|
rlm@1
|
2327 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2328 armNextPC = reg[15].I;
|
rlm@1
|
2329 reg[15].I += 2;
|
rlm@1
|
2330 clockTicks = 3;
|
rlm@1
|
2331 }
|
rlm@1
|
2332 break;
|
rlm@1
|
2333 case 0xd4:
|
rlm@1
|
2334 // BMI offset
|
rlm@1
|
2335 if (N_FLAG)
|
rlm@1
|
2336 {
|
rlm@1
|
2337 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2338 armNextPC = reg[15].I;
|
rlm@1
|
2339 reg[15].I += 2;
|
rlm@1
|
2340 clockTicks = 3;
|
rlm@1
|
2341 }
|
rlm@1
|
2342 break;
|
rlm@1
|
2343 case 0xd5:
|
rlm@1
|
2344 // BPL offset
|
rlm@1
|
2345 if (!N_FLAG)
|
rlm@1
|
2346 {
|
rlm@1
|
2347 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2348 armNextPC = reg[15].I;
|
rlm@1
|
2349 reg[15].I += 2;
|
rlm@1
|
2350 clockTicks = 3;
|
rlm@1
|
2351 }
|
rlm@1
|
2352 break;
|
rlm@1
|
2353 case 0xd6:
|
rlm@1
|
2354 // BVS offset
|
rlm@1
|
2355 if (V_FLAG)
|
rlm@1
|
2356 {
|
rlm@1
|
2357 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2358 armNextPC = reg[15].I;
|
rlm@1
|
2359 reg[15].I += 2;
|
rlm@1
|
2360 clockTicks = 3;
|
rlm@1
|
2361 }
|
rlm@1
|
2362 break;
|
rlm@1
|
2363 case 0xd7:
|
rlm@1
|
2364 // BVC offset
|
rlm@1
|
2365 if (!V_FLAG)
|
rlm@1
|
2366 {
|
rlm@1
|
2367 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2368 armNextPC = reg[15].I;
|
rlm@1
|
2369 reg[15].I += 2;
|
rlm@1
|
2370 clockTicks = 3;
|
rlm@1
|
2371 }
|
rlm@1
|
2372 break;
|
rlm@1
|
2373 case 0xd8:
|
rlm@1
|
2374 // BHI offset
|
rlm@1
|
2375 if (C_FLAG && !Z_FLAG)
|
rlm@1
|
2376 {
|
rlm@1
|
2377 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2378 armNextPC = reg[15].I;
|
rlm@1
|
2379 reg[15].I += 2;
|
rlm@1
|
2380 clockTicks = 3;
|
rlm@1
|
2381 }
|
rlm@1
|
2382 break;
|
rlm@1
|
2383 case 0xd9:
|
rlm@1
|
2384 // BLS offset
|
rlm@1
|
2385 if (!C_FLAG || Z_FLAG)
|
rlm@1
|
2386 {
|
rlm@1
|
2387 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2388 armNextPC = reg[15].I;
|
rlm@1
|
2389 reg[15].I += 2;
|
rlm@1
|
2390 clockTicks = 3;
|
rlm@1
|
2391 }
|
rlm@1
|
2392 break;
|
rlm@1
|
2393 case 0xda:
|
rlm@1
|
2394 // BGE offset
|
rlm@1
|
2395 if (N_FLAG == V_FLAG)
|
rlm@1
|
2396 {
|
rlm@1
|
2397 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2398 armNextPC = reg[15].I;
|
rlm@1
|
2399 reg[15].I += 2;
|
rlm@1
|
2400 clockTicks = 3;
|
rlm@1
|
2401 }
|
rlm@1
|
2402 break;
|
rlm@1
|
2403 case 0xdb:
|
rlm@1
|
2404 // BLT offset
|
rlm@1
|
2405 if (N_FLAG != V_FLAG)
|
rlm@1
|
2406 {
|
rlm@1
|
2407 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2408 armNextPC = reg[15].I;
|
rlm@1
|
2409 reg[15].I += 2;
|
rlm@1
|
2410 clockTicks = 3;
|
rlm@1
|
2411 }
|
rlm@1
|
2412 break;
|
rlm@1
|
2413 case 0xdc:
|
rlm@1
|
2414 // BGT offset
|
rlm@1
|
2415 if (!Z_FLAG && (N_FLAG == V_FLAG))
|
rlm@1
|
2416 {
|
rlm@1
|
2417 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2418 armNextPC = reg[15].I;
|
rlm@1
|
2419 reg[15].I += 2;
|
rlm@1
|
2420 clockTicks = 3;
|
rlm@1
|
2421 }
|
rlm@1
|
2422 break;
|
rlm@1
|
2423 case 0xdd:
|
rlm@1
|
2424 // BLE offset
|
rlm@1
|
2425 if (Z_FLAG || (N_FLAG != V_FLAG))
|
rlm@1
|
2426 {
|
rlm@1
|
2427 reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
rlm@1
|
2428 armNextPC = reg[15].I;
|
rlm@1
|
2429 reg[15].I += 2;
|
rlm@1
|
2430 clockTicks = 3;
|
rlm@1
|
2431 }
|
rlm@1
|
2432 break;
|
rlm@1
|
2433 case 0xdf:
|
rlm@1
|
2434 // SWI #comment
|
rlm@1
|
2435 CPUSoftwareInterrupt(opcode & 0xFF);
|
rlm@1
|
2436 break;
|
rlm@1
|
2437 case 0xe0:
|
rlm@1
|
2438 case 0xe1:
|
rlm@1
|
2439 case 0xe2:
|
rlm@1
|
2440 case 0xe3:
|
rlm@1
|
2441 case 0xe4:
|
rlm@1
|
2442 case 0xe5:
|
rlm@1
|
2443 case 0xe6:
|
rlm@1
|
2444 case 0xe7:
|
rlm@1
|
2445 {
|
rlm@1
|
2446 // B offset
|
rlm@1
|
2447 int offset = (opcode & 0x3FF) << 1;
|
rlm@1
|
2448 if (opcode & 0x0400)
|
rlm@1
|
2449 offset |= 0xFFFFF800;
|
rlm@1
|
2450 reg[15].I += offset;
|
rlm@1
|
2451 armNextPC = reg[15].I;
|
rlm@1
|
2452 reg[15].I += 2;
|
rlm@1
|
2453 }
|
rlm@1
|
2454 break;
|
rlm@1
|
2455 case 0xf0:
|
rlm@1
|
2456 case 0xf1:
|
rlm@1
|
2457 case 0xf2:
|
rlm@1
|
2458 case 0xf3:
|
rlm@1
|
2459 {
|
rlm@1
|
2460 // BLL #offset
|
rlm@1
|
2461 int offset = (opcode & 0x7FF);
|
rlm@1
|
2462 reg[14].I = reg[15].I + (offset << 12);
|
rlm@1
|
2463 }
|
rlm@1
|
2464 break;
|
rlm@1
|
2465 case 0xf4:
|
rlm@1
|
2466 case 0xf5:
|
rlm@1
|
2467 case 0xf6:
|
rlm@1
|
2468 case 0xf7:
|
rlm@1
|
2469 {
|
rlm@1
|
2470 // BLL #offset
|
rlm@1
|
2471 int offset = (opcode & 0x7FF);
|
rlm@1
|
2472 reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
|
rlm@1
|
2473 }
|
rlm@1
|
2474 break;
|
rlm@1
|
2475 case 0xf8:
|
rlm@1
|
2476 case 0xf9:
|
rlm@1
|
2477 case 0xfa:
|
rlm@1
|
2478 case 0xfb:
|
rlm@1
|
2479 case 0xfc:
|
rlm@1
|
2480 case 0xfd:
|
rlm@1
|
2481 case 0xfe:
|
rlm@1
|
2482 case 0xff:
|
rlm@1
|
2483 {
|
rlm@1
|
2484 // BLH #offset
|
rlm@1
|
2485 int offset = (opcode & 0x7FF);
|
rlm@1
|
2486 u32 temp = reg[15].I - 2;
|
rlm@1
|
2487 reg[15].I = (reg[14].I + (offset << 1)) & 0xFFFFFFFE;
|
rlm@1
|
2488 armNextPC = reg[15].I;
|
rlm@1
|
2489 reg[15].I += 2;
|
rlm@1
|
2490 reg[14].I = temp | 1;
|
rlm@1
|
2491 }
|
rlm@1
|
2492 break;
|
rlm@1
|
2493 #ifdef BKPT_SUPPORT
|
rlm@1
|
2494 case 0xbe:
|
rlm@1
|
2495 // BKPT #comment
|
rlm@1
|
2496 extern void (*dbgSignal)(int, int);
|
rlm@1
|
2497 reg[15].I -= 2;
|
rlm@1
|
2498 armNextPC -= 2;
|
rlm@1
|
2499 dbgSignal(5, opcode & 255);
|
rlm@1
|
2500 return;
|
rlm@1
|
2501 #endif
|
rlm@1
|
2502 case 0xb1:
|
rlm@1
|
2503 case 0xb2:
|
rlm@1
|
2504 case 0xb3:
|
rlm@1
|
2505 case 0xb6:
|
rlm@1
|
2506 case 0xb7:
|
rlm@1
|
2507 case 0xb8:
|
rlm@1
|
2508 case 0xb9:
|
rlm@1
|
2509 case 0xba:
|
rlm@1
|
2510 case 0xbb:
|
rlm@1
|
2511 #ifndef BKPT_SUPPORT
|
rlm@1
|
2512 case 0xbe:
|
rlm@1
|
2513 #endif
|
rlm@1
|
2514 case 0xbf:
|
rlm@1
|
2515 case 0xde:
|
rlm@1
|
2516 default:
|
rlm@1
|
2517 unknown_thumb:
|
rlm@1
|
2518 #ifdef GBA_LOGGING
|
rlm@1
|
2519 if (systemVerbose & VERBOSE_UNDEFINED)
|
rlm@1
|
2520 log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC - 2);
|
rlm@1
|
2521 #endif
|
rlm@1
|
2522 CPUUndefinedException();
|
rlm@1
|
2523 break;
|
rlm@1
|
2524 }
|