view src/gba/thumb.h @ 328:35960b03693f

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