view src/gba/arm-new.h @ 304:fefe5ce49b21

improve testing program
author Robert McIntyre <rlm@mit.edu>
date Sat, 31 Mar 2012 00:41:14 -0500
parents f9f4f1b99eed
children
line wrap: on
line source
1 #ifdef BKPT_SUPPORT
2 #define CONSOLE_OUTPUT(a, b) \
3 extern void (*dbgOutput)(char *, u32); \
4 if ((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) { \
5 dbgOutput((a), (b)); \
6 }
7 #else
8 #define CONSOLE_OUTPUT(a, b)
9 #endif
11 #define OP_AND \
12 reg[dest].I = reg[(opcode >> 16) & 15].I & value; \
13 CONSOLE_OUTPUT(NULL, reg[2].I);
15 #define OP_ANDS \
16 reg[dest].I = reg[(opcode >> 16) & 15].I & value; \
17 \
18 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
19 Z_FLAG = (reg[dest].I) ? false : true; \
20 C_FLAG = C_OUT;
22 #define OP_EOR \
23 reg[dest].I = reg[(opcode >> 16) & 15].I ^ value;
25 #define OP_EORS \
26 reg[dest].I = reg[(opcode >> 16) & 15].I ^ value; \
27 \
28 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
29 Z_FLAG = (reg[dest].I) ? false : true; \
30 C_FLAG = C_OUT;
31 #ifdef C_CORE
32 #define NEG(i) ((i) >> 31)
33 #define POS(i) ((~(i)) >> 31)
34 #define ADDCARRY(a, b, c) \
35 C_FLAG = ((NEG(a) & NEG(b)) | \
36 (NEG(a) & POS(c)) | \
37 (NEG(b) & POS(c))) ? true : false;
38 #define ADDOVERFLOW(a, b, c) \
39 V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \
40 (POS(a) & POS(b) & NEG(c))) ? true : false;
41 #define SUBCARRY(a, b, c) \
42 C_FLAG = ((NEG(a) & POS(b)) | \
43 (NEG(a) & POS(c)) | \
44 (POS(b) & POS(c))) ? true : false;
45 #define SUBOVERFLOW(a, b, c) \
46 V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \
47 (POS(a) & NEG(b) & NEG(c))) ? true : false;
48 #define OP_SUB \
49 { \
50 reg[dest].I = reg[base].I - value; \
51 }
52 #define OP_SUBS \
53 { \
54 u32 lhs = reg[base].I; \
55 u32 rhs = value; \
56 u32 res = lhs - rhs; \
57 reg[dest].I = res; \
58 Z_FLAG = (res == 0) ? true : false; \
59 N_FLAG = NEG(res) ? true : false; \
60 SUBCARRY(lhs, rhs, res); \
61 SUBOVERFLOW(lhs, rhs, res); \
62 }
63 #define OP_RSB \
64 { \
65 reg[dest].I = value - reg[base].I; \
66 }
67 #define OP_RSBS \
68 { \
69 u32 lhs = reg[base].I; \
70 u32 rhs = value; \
71 u32 res = rhs - lhs; \
72 reg[dest].I = res; \
73 Z_FLAG = (res == 0) ? true : false; \
74 N_FLAG = NEG(res) ? true : false; \
75 SUBCARRY(rhs, lhs, res); \
76 SUBOVERFLOW(rhs, lhs, res); \
77 }
78 #define OP_ADD \
79 { \
80 reg[dest].I = reg[base].I + value; \
81 }
82 #define OP_ADDS \
83 { \
84 u32 lhs = reg[base].I; \
85 u32 rhs = value; \
86 u32 res = lhs + rhs; \
87 reg[dest].I = res; \
88 Z_FLAG = (res == 0) ? true : false; \
89 N_FLAG = NEG(res) ? true : false; \
90 ADDCARRY(lhs, rhs, res); \
91 ADDOVERFLOW(lhs, rhs, res); \
92 }
93 #define OP_ADC \
94 { \
95 reg[dest].I = reg[base].I + value + (u32)C_FLAG; \
96 }
97 #define OP_ADCS \
98 { \
99 u32 lhs = reg[base].I; \
100 u32 rhs = value; \
101 u32 res = lhs + rhs + (u32)C_FLAG; \
102 reg[dest].I = res; \
103 Z_FLAG = (res == 0) ? true : false; \
104 N_FLAG = NEG(res) ? true : false; \
105 ADDCARRY(lhs, rhs, res); \
106 ADDOVERFLOW(lhs, rhs, res); \
107 }
108 #define OP_SBC \
109 { \
110 reg[dest].I = reg[base].I - value - !((u32)C_FLAG); \
111 }
112 #define OP_SBCS \
113 { \
114 u32 lhs = reg[base].I; \
115 u32 rhs = value; \
116 u32 res = lhs - rhs - !((u32)C_FLAG); \
117 reg[dest].I = res; \
118 Z_FLAG = (res == 0) ? true : false; \
119 N_FLAG = NEG(res) ? true : false; \
120 SUBCARRY(lhs, rhs, res); \
121 SUBOVERFLOW(lhs, rhs, res); \
122 }
123 #define OP_RSC \
124 { \
125 reg[dest].I = value - reg[base].I - !((u32)C_FLAG); \
126 }
127 #define OP_RSCS \
128 { \
129 u32 lhs = reg[base].I; \
130 u32 rhs = value; \
131 u32 res = rhs - lhs - !((u32)C_FLAG); \
132 reg[dest].I = res; \
133 Z_FLAG = (res == 0) ? true : false; \
134 N_FLAG = NEG(res) ? true : false; \
135 SUBCARRY(rhs, lhs, res); \
136 SUBOVERFLOW(rhs, lhs, res); \
137 }
138 #define OP_CMP \
139 { \
140 u32 lhs = reg[base].I; \
141 u32 rhs = value; \
142 u32 res = lhs - rhs; \
143 Z_FLAG = (res == 0) ? true : false; \
144 N_FLAG = NEG(res) ? true : false; \
145 SUBCARRY(lhs, rhs, res); \
146 SUBOVERFLOW(lhs, rhs, res); \
147 }
148 #define OP_CMN \
149 { \
150 u32 lhs = reg[base].I; \
151 u32 rhs = value; \
152 u32 res = lhs + rhs; \
153 Z_FLAG = (res == 0) ? true : false; \
154 N_FLAG = NEG(res) ? true : false; \
155 ADDCARRY(lhs, rhs, res); \
156 ADDOVERFLOW(lhs, rhs, res); \
157 }
159 #define LOGICAL_LSL_REG \
160 { \
161 u32 v = reg[opcode & 0x0f].I; \
162 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
163 value = v << shift; \
164 }
165 #define LOGICAL_LSR_REG \
166 { \
167 u32 v = reg[opcode & 0x0f].I; \
168 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
169 value = v >> shift; \
170 }
171 #define LOGICAL_ASR_REG \
172 { \
173 u32 v = reg[opcode & 0x0f].I; \
174 C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \
175 value = (s32)v >> (int)shift; \
176 }
177 #define LOGICAL_ROR_REG \
178 { \
179 u32 v = reg[opcode & 0x0f].I; \
180 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
181 value = ((v << (32 - shift)) | \
182 (v >> shift)); \
183 }
184 #define LOGICAL_RRX_REG \
185 { \
186 u32 v = reg[opcode & 0x0f].I; \
187 shift = (int)C_FLAG; \
188 C_OUT = (v & 1) ? true : false; \
189 value = ((v >> 1) | \
190 (shift << 31)); \
191 }
192 #define LOGICAL_ROR_IMM \
193 { \
194 u32 v = opcode & 0xff; \
195 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
196 value = ((v << (32 - shift)) | \
197 (v >> shift)); \
198 }
199 #define ARITHMETIC_LSL_REG \
200 { \
201 u32 v = reg[opcode & 0x0f].I; \
202 value = v << shift; \
203 }
204 #define ARITHMETIC_LSR_REG \
205 { \
206 u32 v = reg[opcode & 0x0f].I; \
207 value = v >> shift; \
208 }
209 #define ARITHMETIC_ASR_REG \
210 { \
211 u32 v = reg[opcode & 0x0f].I; \
212 value = (s32)v >> (int)shift; \
213 }
214 #define ARITHMETIC_ROR_REG \
215 { \
216 u32 v = reg[opcode & 0x0f].I; \
217 value = ((v << (32 - shift)) | \
218 (v >> shift)); \
219 }
220 #define ARITHMETIC_RRX_REG \
221 { \
222 u32 v = reg[opcode & 0x0f].I; \
223 shift = (int)C_FLAG; \
224 value = ((v >> 1) | \
225 (shift << 31)); \
226 }
227 #define ARITHMETIC_ROR_IMM \
228 { \
229 u32 v = opcode & 0xff; \
230 value = ((v << (32 - shift)) | \
231 (v >> shift)); \
232 }
233 #define ROR_IMM_MSR \
234 { \
235 u32 v = opcode & 0xff; \
236 value = ((v << (32 - shift)) | \
237 (v >> shift)); \
238 }
239 #define ROR_VALUE \
240 { \
241 value = ((value << (32 - shift)) | \
242 (value >> shift)); \
243 }
244 #define RCR_VALUE \
245 { \
246 shift = (int)C_FLAG; \
247 value = ((value >> 1) | \
248 (shift << 31)); \
249 }
250 #else
251 #ifdef __GNUC__
252 #ifdef __POWERPC__
253 #define OP_SUB \
254 { \
255 reg[dest].I = reg[base].I - value; \
256 }
257 #define OP_SUBS \
258 { \
259 register int Flags; \
260 register int Result; \
261 asm volatile ("subco. %0, %2, %3\n" \
262 "mcrxr cr1\n" \
263 "mfcr %1\n" \
264 : "=r" (Result), \
265 "=r" (Flags) \
266 : "r" (reg[base].I), \
267 "r" (value) \
268 ); \
269 reg[dest].I = Result; \
270 Z_FLAG = (Flags >> 29) & 1; \
271 N_FLAG = (Flags >> 31) & 1; \
272 C_FLAG = (Flags >> 25) & 1; \
273 V_FLAG = (Flags >> 26) & 1; \
274 }
275 #define OP_RSB \
276 { \
277 reg[dest].I = value - reg[base].I; \
278 }
279 #define OP_RSBS \
280 { \
281 register int Flags; \
282 register int Result; \
283 asm volatile ("subfco. %0, %2, %3\n" \
284 "mcrxr cr1\n" \
285 "mfcr %1\n" \
286 : "=r" (Result), \
287 "=r" (Flags) \
288 : "r" (reg[base].I), \
289 "r" (value) \
290 ); \
291 reg[dest].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 OP_ADD \
298 { \
299 reg[dest].I = reg[base].I + value; \
300 }
302 #define OP_ADDS \
303 { \
304 register int Flags; \
305 register int Result; \
306 asm volatile ("addco. %0, %2, %3\n" \
307 "mcrxr cr1\n" \
308 "mfcr %1\n" \
309 : "=r" (Result), \
310 "=r" (Flags) \
311 : "r" (reg[base].I), \
312 "r" (value) \
313 ); \
314 reg[dest].I = Result; \
315 Z_FLAG = (Flags >> 29) & 1; \
316 N_FLAG = (Flags >> 31) & 1; \
317 C_FLAG = (Flags >> 25) & 1; \
318 V_FLAG = (Flags >> 26) & 1; \
319 }
320 #define OP_ADC \
321 { \
322 reg[dest].I = reg[base].I + value + (u32)C_FLAG; \
323 }
324 #define OP_ADCS \
325 { \
326 register int Flags; \
327 register int Result; \
328 asm volatile ("mtspr xer, %4\n" \
329 "addeo. %0, %2, %3\n" \
330 "mcrxr cr1\n" \
331 "mfcr %1\n" \
332 : "=r" (Result), \
333 "=r" (Flags) \
334 : "r" (reg[base].I), \
335 "r" (value), \
336 "r" (C_FLAG << 29) \
337 ); \
338 reg[dest].I = Result; \
339 Z_FLAG = (Flags >> 29) & 1; \
340 N_FLAG = (Flags >> 31) & 1; \
341 C_FLAG = (Flags >> 25) & 1; \
342 V_FLAG = (Flags >> 26) & 1; \
343 }
344 #define OP_SBC \
345 { \
346 reg[dest].I = reg[base].I - value - (C_FLAG ^ 1); \
347 }
348 #define OP_SBCS \
349 { \
350 register int Flags; \
351 register int Result; \
352 asm volatile ("mtspr xer, %4\n" \
353 "subfeo. %0, %3, %2\n" \
354 "mcrxr cr1\n" \
355 "mfcr %1\n" \
356 : "=r" (Result), \
357 "=r" (Flags) \
358 : "r" (reg[base].I), \
359 "r" (value), \
360 "r" (C_FLAG << 29) \
361 ); \
362 reg[dest].I = Result; \
363 Z_FLAG = (Flags >> 29) & 1; \
364 N_FLAG = (Flags >> 31) & 1; \
365 C_FLAG = (Flags >> 25) & 1; \
366 V_FLAG = (Flags >> 26) & 1; \
367 }
368 #define OP_RSC \
369 { \
370 reg[dest].I = value - reg[base].I - (C_FLAG ^ 1); \
371 }
372 #define OP_RSCS \
373 { \
374 register int Flags; \
375 register int Result; \
376 asm volatile ("mtspr xer, %4\n" \
377 "subfeo. %0, %2, %3\n" \
378 "mcrxr cr1\n" \
379 "mfcr %1\n" \
380 : "=r" (Result), \
381 "=r" (Flags) \
382 : "r" (reg[base].I), \
383 "r" (value), \
384 "r" (C_FLAG << 29) \
385 ); \
386 reg[dest].I = Result; \
387 Z_FLAG = (Flags >> 29) & 1; \
388 N_FLAG = (Flags >> 31) & 1; \
389 C_FLAG = (Flags >> 25) & 1; \
390 V_FLAG = (Flags >> 26) & 1; \
391 }
392 #define OP_CMP \
393 { \
394 register int Flags; \
395 register int Result; \
396 asm volatile ("subco. %0, %2, %3\n" \
397 "mcrxr cr1\n" \
398 "mfcr %1\n" \
399 : "=r" (Result), \
400 "=r" (Flags) \
401 : "r" (reg[base].I), \
402 "r" (value) \
403 ); \
404 Z_FLAG = (Flags >> 29) & 1; \
405 N_FLAG = (Flags >> 31) & 1; \
406 C_FLAG = (Flags >> 25) & 1; \
407 V_FLAG = (Flags >> 26) & 1; \
408 }
409 #define OP_CMN \
410 { \
411 register int Flags; \
412 register int Result; \
413 asm volatile ("addco. %0, %2, %3\n" \
414 "mcrxr cr1\n" \
415 "mfcr %1\n" \
416 : "=r" (Result), \
417 "=r" (Flags) \
418 : "r" (reg[base].I), \
419 "r" (value) \
420 ); \
421 Z_FLAG = (Flags >> 29) & 1; \
422 N_FLAG = (Flags >> 31) & 1; \
423 C_FLAG = (Flags >> 25) & 1; \
424 V_FLAG = (Flags >> 26) & 1; \
425 }
427 #define LOGICAL_LSL_REG \
428 { \
429 u32 v = reg[opcode & 0x0f].I; \
430 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
431 value = v << shift; \
432 }
433 #define LOGICAL_LSR_REG \
434 { \
435 u32 v = reg[opcode & 0x0f].I; \
436 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
437 value = v >> shift; \
438 }
439 #define LOGICAL_ASR_REG \
440 { \
441 u32 v = reg[opcode & 0x0f].I; \
442 C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \
443 value = (s32)v >> (int)shift; \
444 }
445 #define LOGICAL_ROR_REG \
446 { \
447 u32 v = reg[opcode & 0x0f].I; \
448 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
449 value = ((v << (32 - shift)) | \
450 (v >> shift)); \
451 }
452 #define LOGICAL_RRX_REG \
453 { \
454 u32 v = reg[opcode & 0x0f].I; \
455 shift = (int)C_FLAG; \
456 C_OUT = (v & 1) ? true : false; \
457 value = ((v >> 1) | \
458 (shift << 31)); \
459 }
460 #define LOGICAL_ROR_IMM \
461 { \
462 u32 v = opcode & 0xff; \
463 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
464 value = ((v << (32 - shift)) | \
465 (v >> shift)); \
466 }
467 #define ARITHMETIC_LSL_REG \
468 { \
469 u32 v = reg[opcode & 0x0f].I; \
470 value = v << shift; \
471 }
472 #define ARITHMETIC_LSR_REG \
473 { \
474 u32 v = reg[opcode & 0x0f].I; \
475 value = v >> shift; \
476 }
477 #define ARITHMETIC_ASR_REG \
478 { \
479 u32 v = reg[opcode & 0x0f].I; \
480 value = (s32)v >> (int)shift; \
481 }
482 #define ARITHMETIC_ROR_REG \
483 { \
484 u32 v = reg[opcode & 0x0f].I; \
485 value = ((v << (32 - shift)) | \
486 (v >> shift)); \
487 }
488 #define ARITHMETIC_RRX_REG \
489 { \
490 u32 v = reg[opcode & 0x0f].I; \
491 shift = (int)C_FLAG; \
492 value = ((v >> 1) | \
493 (shift << 31)); \
494 }
495 #define ARITHMETIC_ROR_IMM \
496 { \
497 u32 v = opcode & 0xff; \
498 value = ((v << (32 - shift)) | \
499 (v >> shift)); \
500 }
501 #define ROR_IMM_MSR \
502 { \
503 u32 v = opcode & 0xff; \
504 value = ((v << (32 - shift)) | \
505 (v >> shift)); \
506 }
507 #define ROR_VALUE \
508 { \
509 value = ((value << (32 - shift)) | \
510 (value >> shift)); \
511 }
512 #define RCR_VALUE \
513 { \
514 shift = (int)C_FLAG; \
515 value = ((value >> 1) | \
516 (shift << 31)); \
517 }
518 #else
519 #define OP_SUB \
520 asm ("sub %1, %%ebx;" \
521 : "=b" (reg[dest].I) \
522 : "r" (value), "b" (reg[base].I));
524 #define OP_SUBS \
525 asm ("sub %1, %%ebx;" \
526 "setsb N_FLAG;" \
527 "setzb Z_FLAG;" \
528 "setncb C_FLAG;" \
529 "setob V_FLAG;" \
530 : "=b" (reg[dest].I) \
531 : "r" (value), "b" (reg[base].I));
533 #define OP_RSB \
534 asm ("sub %1, %%ebx;" \
535 : "=b" (reg[dest].I) \
536 : "r" (reg[base].I), "b" (value));
538 #define OP_RSBS \
539 asm ("sub %1, %%ebx;" \
540 "setsb N_FLAG;" \
541 "setzb Z_FLAG;" \
542 "setncb C_FLAG;" \
543 "setob V_FLAG;" \
544 : "=b" (reg[dest].I) \
545 : "r" (reg[base].I), "b" (value));
547 #define OP_ADD \
548 asm ("add %1, %%ebx;" \
549 : "=b" (reg[dest].I) \
550 : "r" (value), "b" (reg[base].I));
552 #define OP_ADDS \
553 asm ("add %1, %%ebx;" \
554 "setsb N_FLAG;" \
555 "setzb Z_FLAG;" \
556 "setcb C_FLAG;" \
557 "setob V_FLAG;" \
558 : "=b" (reg[dest].I) \
559 : "r" (value), "b" (reg[base].I));
561 #define OP_ADC \
562 asm ("bt $0, C_FLAG;" \
563 "adc %1, %%ebx;" \
564 : "=b" (reg[dest].I) \
565 : "r" (value), "b" (reg[base].I));
567 #define OP_ADCS \
568 asm ("bt $0, C_FLAG;" \
569 "adc %1, %%ebx;" \
570 "setsb N_FLAG;" \
571 "setzb Z_FLAG;" \
572 "setcb C_FLAG;" \
573 "setob V_FLAG;" \
574 : "=b" (reg[dest].I) \
575 : "r" (value), "b" (reg[base].I));
577 #define OP_SBC \
578 asm ("bt $0, C_FLAG;" \
579 "cmc;" \
580 "sbb %1, %%ebx;" \
581 : "=b" (reg[dest].I) \
582 : "r" (value), "b" (reg[base].I));
584 #define OP_SBCS \
585 asm ("bt $0, C_FLAG;" \
586 "cmc;" \
587 "sbb %1, %%ebx;" \
588 "setsb N_FLAG;" \
589 "setzb Z_FLAG;" \
590 "setncb C_FLAG;" \
591 "setob V_FLAG;" \
592 : "=b" (reg[dest].I) \
593 : "r" (value), "b" (reg[base].I));
594 #define OP_RSC \
595 asm ("bt $0, C_FLAG;" \
596 "cmc;" \
597 "sbb %1, %%ebx;" \
598 : "=b" (reg[dest].I) \
599 : "r" (reg[base].I), "b" (value));
601 #define OP_RSCS \
602 asm ("bt $0, C_FLAG;" \
603 "cmc;" \
604 "sbb %1, %%ebx;" \
605 "setsb N_FLAG;" \
606 "setzb Z_FLAG;" \
607 "setncb C_FLAG;" \
608 "setob V_FLAG;" \
609 : "=b" (reg[dest].I) \
610 : "r" (reg[base].I), "b" (value));
611 #define OP_CMP \
612 asm ("sub %0, %1;" \
613 "setsb N_FLAG;" \
614 "setzb Z_FLAG;" \
615 "setncb C_FLAG;" \
616 "setob V_FLAG;" \
617 : \
618 : "r" (value), "r" (reg[base].I));
620 #define OP_CMN \
621 asm ("add %0, %1;" \
622 "setsb N_FLAG;" \
623 "setzb Z_FLAG;" \
624 "setcb C_FLAG;" \
625 "setob V_FLAG;" \
626 : \
627 : "r" (value), "r" (reg[base].I));
628 #define LOGICAL_LSL_REG \
629 asm ("shl %%cl, %%eax;" \
630 "setcb %%cl;" \
631 : "=a" (value), "=c" (C_OUT) \
632 : "a" (reg[opcode & 0x0f].I), "c" (shift));
634 #define LOGICAL_LSR_REG \
635 asm ("shr %%cl, %%eax;" \
636 "setcb %%cl;" \
637 : "=a" (value), "=c" (C_OUT) \
638 : "a" (reg[opcode & 0x0f].I), "c" (shift));
640 #define LOGICAL_ASR_REG \
641 asm ("sar %%cl, %%eax;" \
642 "setcb %%cl;" \
643 : "=a" (value), "=c" (C_OUT) \
644 : "a" (reg[opcode & 0x0f].I), "c" (shift));
646 #define LOGICAL_ROR_REG \
647 asm ("ror %%cl, %%eax;" \
648 "setcb %%cl;" \
649 : "=a" (value), "=c" (C_OUT) \
650 : "a" (reg[opcode & 0x0f].I), "c" (shift));
652 #define LOGICAL_RRX_REG \
653 asm ("bt $0, C_FLAG;" \
654 "rcr $1, %%eax;" \
655 "setcb %%cl;" \
656 : "=a" (value), "=c" (C_OUT) \
657 : "a" (reg[opcode & 0x0f].I));
659 #define LOGICAL_ROR_IMM \
660 asm ("ror %%cl, %%eax;" \
661 "setcb %%cl;" \
662 : "=a" (value), "=c" (C_OUT) \
663 : "a" (opcode & 0xff), "c" (shift));
664 #define ARITHMETIC_LSL_REG \
665 asm ("\
666 shl %%cl, %%eax;" \
667 : "=a" (value) \
668 : "a" (reg[opcode & 0x0f].I), "c" (shift));
670 #define ARITHMETIC_LSR_REG \
671 asm ("\
672 shr %%cl, %%eax;" \
673 : "=a" (value) \
674 : "a" (reg[opcode & 0x0f].I), "c" (shift));
676 #define ARITHMETIC_ASR_REG \
677 asm ("\
678 sar %%cl, %%eax;" \
679 : "=a" (value) \
680 : "a" (reg[opcode & 0x0f].I), "c" (shift));
682 #define ARITHMETIC_ROR_REG \
683 asm ("\
684 ror %%cl, %%eax;" \
685 : "=a" (value) \
686 : "a" (reg[opcode & 0x0f].I), "c" (shift));
688 #define ARITHMETIC_RRX_REG \
689 asm ("\
690 bt $0, C_FLAG;\
691 rcr $1, %%eax;" \
692 : "=a" (value) \
693 : "a" (reg[opcode & 0x0f].I));
695 #define ARITHMETIC_ROR_IMM \
696 asm ("\
697 ror %%cl, %%eax;" \
698 : "=a" (value) \
699 : "a" (opcode & 0xff), "c" (shift));
700 #define ROR_IMM_MSR \
701 asm ("ror %%cl, %%eax;" \
702 : "=a" (value) \
703 : "a" (opcode & 0xFF), "c" (shift));
704 #define ROR_VALUE \
705 asm ("ror %%cl, %0" \
706 : "=r" (value) \
707 : "r" (value), "c" (shift));
708 #define RCR_VALUE \
709 asm ("bt $0, C_FLAG;" \
710 "rcr $1, %0" \
711 : "=r" (value) \
712 : "r" (value));
713 #endif
714 #else
715 #define OP_SUB \
716 { \
717 __asm mov ebx, base \
718 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
719 __asm sub ebx, value \
720 __asm mov eax, dest \
721 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
722 }
724 #define OP_SUBS \
725 { \
726 __asm mov ebx, base \
727 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
728 __asm sub ebx, value \
729 __asm mov eax, dest \
730 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
731 __asm sets byte ptr N_FLAG \
732 __asm setz byte ptr Z_FLAG \
733 __asm setnc byte ptr C_FLAG \
734 __asm seto byte ptr V_FLAG \
735 }
737 #define OP_RSB \
738 { \
739 __asm mov ebx, base \
740 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
741 __asm mov eax, value \
742 __asm sub eax, ebx \
743 __asm mov ebx, dest \
744 __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \
745 }
747 #define OP_RSBS \
748 { \
749 __asm mov ebx, base \
750 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
751 __asm mov eax, value \
752 __asm sub eax, ebx \
753 __asm mov ebx, dest \
754 __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \
755 __asm sets byte ptr N_FLAG \
756 __asm setz byte ptr Z_FLAG \
757 __asm setnc byte ptr C_FLAG \
758 __asm seto byte ptr V_FLAG \
759 }
761 #define OP_ADD \
762 { \
763 __asm mov ebx, base \
764 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
765 __asm add ebx, value \
766 __asm mov eax, dest \
767 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
768 }
770 #define OP_ADDS \
771 { \
772 __asm mov ebx, base \
773 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
774 __asm add ebx, value \
775 __asm mov eax, dest \
776 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
777 __asm sets byte ptr N_FLAG \
778 __asm setz byte ptr Z_FLAG \
779 __asm setc byte ptr C_FLAG \
780 __asm seto byte ptr V_FLAG \
781 }
783 #define OP_ADC \
784 { \
785 __asm mov ebx, base \
786 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
787 __asm bt word ptr C_FLAG, 0 \
788 __asm adc ebx, value \
789 __asm mov eax, dest \
790 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
791 }
793 #define OP_ADCS \
794 { \
795 __asm mov ebx, base \
796 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
797 __asm bt word ptr C_FLAG, 0 \
798 __asm adc ebx, value \
799 __asm mov eax, dest \
800 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
801 __asm sets byte ptr N_FLAG \
802 __asm setz byte ptr Z_FLAG \
803 __asm setc byte ptr C_FLAG \
804 __asm seto byte ptr V_FLAG \
805 }
807 #define OP_SBC \
808 { \
809 __asm mov ebx, base \
810 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
811 __asm mov eax, value \
812 __asm bt word ptr C_FLAG, 0 \
813 __asm cmc \
814 __asm sbb ebx, eax \
815 __asm mov eax, dest \
816 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
817 }
819 #define OP_SBCS \
820 { \
821 __asm mov ebx, base \
822 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
823 __asm mov eax, value \
824 __asm bt word ptr C_FLAG, 0 \
825 __asm cmc \
826 __asm sbb ebx, eax \
827 __asm mov eax, dest \
828 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
829 __asm sets byte ptr N_FLAG \
830 __asm setz byte ptr Z_FLAG \
831 __asm setnc byte ptr C_FLAG \
832 __asm seto byte ptr V_FLAG \
833 }
834 #define OP_RSC \
835 { \
836 __asm mov ebx, value \
837 __asm mov eax, base \
838 __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \
839 __asm bt word ptr C_FLAG, 0 \
840 __asm cmc \
841 __asm sbb ebx, eax \
842 __asm mov eax, dest \
843 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
844 }
846 #define OP_RSCS \
847 { \
848 __asm mov ebx, value \
849 __asm mov eax, base \
850 __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \
851 __asm bt word ptr C_FLAG, 0 \
852 __asm cmc \
853 __asm sbb ebx, eax \
854 __asm mov eax, dest \
855 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
856 __asm sets byte ptr N_FLAG \
857 __asm setz byte ptr Z_FLAG \
858 __asm setnc byte ptr C_FLAG \
859 __asm seto byte ptr V_FLAG \
860 }
861 #define OP_CMP \
862 { \
863 __asm mov eax, base \
864 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
865 __asm sub ebx, value \
866 __asm sets byte ptr N_FLAG \
867 __asm setz byte ptr Z_FLAG \
868 __asm setnc byte ptr C_FLAG \
869 __asm seto byte ptr V_FLAG \
870 }
872 #define OP_CMN \
873 { \
874 __asm mov eax, base \
875 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
876 __asm add ebx, value \
877 __asm sets byte ptr N_FLAG \
878 __asm setz byte ptr Z_FLAG \
879 __asm setc byte ptr C_FLAG \
880 __asm seto byte ptr V_FLAG \
881 }
882 #define LOGICAL_LSL_REG \
883 __asm mov eax, opcode \
884 __asm and eax, 0x0f \
885 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
886 __asm mov cl, byte ptr shift \
887 __asm shl eax, cl \
888 __asm mov value, eax \
889 __asm setc byte ptr C_OUT
891 #define LOGICAL_LSR_REG \
892 __asm mov eax, opcode \
893 __asm and eax, 0x0f \
894 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
895 __asm mov cl, byte ptr shift \
896 __asm shr eax, cl \
897 __asm mov value, eax \
898 __asm setc byte ptr C_OUT
900 #define LOGICAL_ASR_REG \
901 __asm mov eax, opcode \
902 __asm and eax, 0x0f \
903 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
904 __asm mov cl, byte ptr shift \
905 __asm sar eax, cl \
906 __asm mov value, eax \
907 __asm setc byte ptr C_OUT
909 #define LOGICAL_ROR_REG \
910 __asm mov eax, opcode \
911 __asm and eax, 0x0F \
912 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
913 __asm mov cl, byte ptr shift \
914 __asm ror eax, cl \
915 __asm mov value, eax \
916 __asm setc byte ptr C_OUT
918 #define LOGICAL_RRX_REG \
919 __asm mov eax, opcode \
920 __asm and eax, 0x0F \
921 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
922 __asm bt word ptr C_OUT, 0 \
923 __asm rcr eax, 1 \
924 __asm mov value, eax \
925 __asm setc byte ptr C_OUT
927 #define LOGICAL_ROR_IMM \
928 __asm mov eax, opcode \
929 __asm and eax, 0xff \
930 __asm mov cl, byte ptr shift \
931 __asm ror eax, cl \
932 __asm mov value, eax \
933 __asm setc byte ptr C_OUT
934 #define ARITHMETIC_LSL_REG \
935 __asm mov eax, opcode \
936 __asm and eax, 0x0f \
937 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
938 __asm mov cl, byte ptr shift \
939 __asm shl eax, cl \
940 __asm mov value, eax
942 #define ARITHMETIC_LSR_REG \
943 __asm mov eax, opcode \
944 __asm and eax, 0x0f \
945 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
946 __asm mov cl, byte ptr shift \
947 __asm shr eax, cl \
948 __asm mov value, eax
950 #define ARITHMETIC_ASR_REG \
951 __asm mov eax, opcode \
952 __asm and eax, 0x0f \
953 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
954 __asm mov cl, byte ptr shift \
955 __asm sar eax, cl \
956 __asm mov value, eax
958 #define ARITHMETIC_ROR_REG \
959 __asm mov eax, opcode \
960 __asm and eax, 0x0F \
961 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
962 __asm mov cl, byte ptr shift \
963 __asm ror eax, cl \
964 __asm mov value, eax
966 #define ARITHMETIC_RRX_REG \
967 __asm mov eax, opcode \
968 __asm and eax, 0x0F \
969 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
970 __asm bt word ptr C_FLAG, 0 \
971 __asm rcr eax, 1 \
972 __asm mov value, eax
974 #define ARITHMETIC_ROR_IMM \
975 __asm mov eax, opcode \
976 __asm and eax, 0xff \
977 __asm mov cl, byte ptr shift \
978 __asm ror eax, cl \
979 __asm mov value, eax
980 #define ROR_IMM_MSR \
981 { \
982 __asm mov eax, opcode \
983 __asm and eax, 0xff \
984 __asm mov cl, byte ptr shift \
985 __asm ror eax, CL \
986 __asm mov value, eax \
987 }
988 #define ROR_VALUE \
989 { \
990 __asm mov cl, byte ptr shift \
991 __asm ror dword ptr value, cl \
992 }
993 #define RCR_VALUE \
994 { \
995 __asm mov cl, byte ptr shift \
996 __asm bt word ptr C_FLAG, 0 \
997 __asm rcr dword ptr value, 1 \
998 }
999 #endif
1000 #endif
1002 #define OP_TST \
1003 u32 res = reg[base].I & value; \
1004 N_FLAG = (res & 0x80000000) ? true : false; \
1005 Z_FLAG = (res) ? false : true; \
1006 C_FLAG = C_OUT;
1008 #define OP_TEQ \
1009 u32 res = reg[base].I ^ value; \
1010 N_FLAG = (res & 0x80000000) ? true : false; \
1011 Z_FLAG = (res) ? false : true; \
1012 C_FLAG = C_OUT;
1014 #define OP_ORR \
1015 reg[dest].I = reg[base].I | value;
1017 #define OP_ORRS \
1018 reg[dest].I = reg[base].I | value; \
1019 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
1020 Z_FLAG = (reg[dest].I) ? false : true; \
1021 C_FLAG = C_OUT;
1023 #define OP_MOV \
1024 reg[dest].I = value;
1026 #define OP_MOVS \
1027 reg[dest].I = value; \
1028 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
1029 Z_FLAG = (reg[dest].I) ? false : true; \
1030 C_FLAG = C_OUT;
1032 #define OP_BIC \
1033 reg[dest].I = reg[base].I & (~value);
1035 #define OP_BICS \
1036 reg[dest].I = reg[base].I & (~value); \
1037 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
1038 Z_FLAG = (reg[dest].I) ? false : true; \
1039 C_FLAG = C_OUT;
1041 #define OP_MVN \
1042 reg[dest].I = ~value;
1044 #define OP_MVNS \
1045 reg[dest].I = ~value; \
1046 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
1047 Z_FLAG = (reg[dest].I) ? false : true; \
1048 C_FLAG = C_OUT;
1050 #define CASE_16(BASE) \
1051 case BASE: \
1052 case BASE + 1: \
1053 case BASE + 2: \
1054 case BASE + 3: \
1055 case BASE + 4: \
1056 case BASE + 5: \
1057 case BASE + 6: \
1058 case BASE + 7: \
1059 case BASE + 8: \
1060 case BASE + 9: \
1061 case BASE + 10: \
1062 case BASE + 11: \
1063 case BASE + 12: \
1064 case BASE + 13: \
1065 case BASE + 14: \
1066 case BASE + 15:
1068 #define CASE_256(BASE) \
1069 CASE_16(BASE) \
1070 CASE_16(BASE + 0x10) \
1071 CASE_16(BASE + 0x20) \
1072 CASE_16(BASE + 0x30) \
1073 CASE_16(BASE + 0x40) \
1074 CASE_16(BASE + 0x50) \
1075 CASE_16(BASE + 0x60) \
1076 CASE_16(BASE + 0x70) \
1077 CASE_16(BASE + 0x80) \
1078 CASE_16(BASE + 0x90) \
1079 CASE_16(BASE + 0xa0) \
1080 CASE_16(BASE + 0xb0) \
1081 CASE_16(BASE + 0xc0) \
1082 CASE_16(BASE + 0xd0) \
1083 CASE_16(BASE + 0xe0) \
1084 CASE_16(BASE + 0xf0)
1086 #define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
1087 case BASE: \
1088 case BASE + 8: \
1089 { \
1090 /* OP Rd,Rb,Rm LSL # */ \
1091 int base = (opcode >> 16) & 0x0F; \
1092 int shift = (opcode >> 7) & 0x1F; \
1093 int dest = (opcode >> 12) & 15; \
1094 bool C_OUT = C_FLAG; \
1095 u32 value; \
1097 if (shift) { \
1098 LOGICAL_LSL_REG \
1099 } else { \
1100 value = reg[opcode & 0x0F].I; \
1101 } \
1102 if (dest == 15) { \
1103 OPCODE2 \
1104 /* todo */ \
1105 if (opcode & 0x00100000) { \
1106 clockTicks++; \
1107 CPUSwitchMode(reg[17].I & 0x1f, false); \
1108 } \
1109 if (armState) { \
1110 reg[15].I &= 0xFFFFFFFC; \
1111 armNextPC = reg[15].I; \
1112 reg[15].I += 4; \
1113 } else { \
1114 reg[15].I &= 0xFFFFFFFE; \
1115 armNextPC = reg[15].I; \
1116 reg[15].I += 2; \
1117 } \
1118 } else { \
1119 OPCODE \
1120 } \
1121 } \
1122 break; \
1123 case BASE + 2: \
1124 case BASE + 10: \
1125 { \
1126 /* OP Rd,Rb,Rm LSR # */ \
1127 int base = (opcode >> 16) & 0x0F; \
1128 int shift = (opcode >> 7) & 0x1F; \
1129 int dest = (opcode >> 12) & 15; \
1130 bool C_OUT = C_FLAG; \
1131 u32 value; \
1132 if (shift) { \
1133 LOGICAL_LSR_REG \
1134 } else { \
1135 value = 0; \
1136 C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \
1137 } \
1139 if (dest == 15) { \
1140 OPCODE2 \
1141 /* todo */ \
1142 if (opcode & 0x00100000) { \
1143 clockTicks++; \
1144 CPUSwitchMode(reg[17].I & 0x1f, false); \
1145 } \
1146 if (armState) { \
1147 reg[15].I &= 0xFFFFFFFC; \
1148 armNextPC = reg[15].I; \
1149 reg[15].I += 4; \
1150 } else { \
1151 reg[15].I &= 0xFFFFFFFE; \
1152 armNextPC = reg[15].I; \
1153 reg[15].I += 2; \
1154 } \
1155 } else { \
1156 OPCODE \
1157 } \
1158 } \
1159 break; \
1160 case BASE + 4: \
1161 case BASE + 12: \
1162 { \
1163 /* OP Rd,Rb,Rm ASR # */ \
1164 int base = (opcode >> 16) & 0x0F; \
1165 int shift = (opcode >> 7) & 0x1F; \
1166 int dest = (opcode >> 12) & 15; \
1167 bool C_OUT = C_FLAG; \
1168 u32 value; \
1169 if (shift) { \
1170 LOGICAL_ASR_REG \
1171 } else { \
1172 if (reg[opcode & 0x0F].I & 0x80000000) { \
1173 value = 0xFFFFFFFF; \
1174 C_OUT = true; \
1175 } else { \
1176 value = 0; \
1177 C_OUT = false; \
1178 } \
1179 } \
1181 if (dest == 15) { \
1182 OPCODE2 \
1183 /* todo */ \
1184 if (opcode & 0x00100000) { \
1185 clockTicks++; \
1186 CPUSwitchMode(reg[17].I & 0x1f, false); \
1187 } \
1188 if (armState) { \
1189 reg[15].I &= 0xFFFFFFFC; \
1190 armNextPC = reg[15].I; \
1191 reg[15].I += 4; \
1192 } else { \
1193 reg[15].I &= 0xFFFFFFFE; \
1194 armNextPC = reg[15].I; \
1195 reg[15].I += 2; \
1196 } \
1197 } else { \
1198 OPCODE \
1199 } \
1200 } \
1201 break; \
1202 case BASE + 6: \
1203 case BASE + 14: \
1204 { \
1205 /* OP Rd,Rb,Rm ROR # */ \
1206 int base = (opcode >> 16) & 0x0F; \
1207 int shift = (opcode >> 7) & 0x1F; \
1208 int dest = (opcode >> 12) & 15; \
1209 bool C_OUT = C_FLAG; \
1210 u32 value; \
1211 if (shift) { \
1212 LOGICAL_ROR_REG \
1213 } else { \
1214 LOGICAL_RRX_REG \
1215 } \
1216 if (dest == 15) { \
1217 OPCODE2 \
1218 /* todo */ \
1219 if (opcode & 0x00100000) { \
1220 clockTicks++; \
1221 CPUSwitchMode(reg[17].I & 0x1f, false); \
1222 } \
1223 if (armState) { \
1224 reg[15].I &= 0xFFFFFFFC; \
1225 armNextPC = reg[15].I; \
1226 reg[15].I += 4; \
1227 } else { \
1228 reg[15].I &= 0xFFFFFFFE; \
1229 armNextPC = reg[15].I; \
1230 reg[15].I += 2; \
1231 } \
1232 } else { \
1233 OPCODE \
1234 } \
1235 } \
1236 break; \
1237 case BASE + 1: \
1238 { \
1239 /* OP Rd,Rb,Rm LSL Rs */ \
1240 clockTicks++; \
1241 int base = (opcode >> 16) & 0x0F; \
1242 int shift = reg[(opcode >> 8) & 15].B.B0; \
1243 int dest = (opcode >> 12) & 15; \
1244 bool C_OUT = C_FLAG; \
1245 u32 value; \
1246 if (shift) { \
1247 if (shift == 32) { \
1248 value = 0; \
1249 C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \
1250 } else if (shift < 32) { \
1251 LOGICAL_LSL_REG \
1252 } else { \
1253 value = 0; \
1254 C_OUT = false; \
1255 } \
1256 } else { \
1257 value = reg[opcode & 0x0F].I; \
1258 } \
1259 if (dest == 15) { \
1260 OPCODE2 \
1261 /* todo */ \
1262 if (opcode & 0x00100000) { \
1263 clockTicks++; \
1264 CPUSwitchMode(reg[17].I & 0x1f, false); \
1265 } \
1266 if (armState) { \
1267 reg[15].I &= 0xFFFFFFFC; \
1268 armNextPC = reg[15].I; \
1269 reg[15].I += 4; \
1270 } else { \
1271 reg[15].I &= 0xFFFFFFFE; \
1272 armNextPC = reg[15].I; \
1273 reg[15].I += 2; \
1274 } \
1275 } else { \
1276 OPCODE \
1277 } \
1278 } \
1279 break; \
1280 case BASE + 3: \
1281 { \
1282 /* OP Rd,Rb,Rm LSR Rs */ \
1283 clockTicks++; \
1284 int base = (opcode >> 16) & 0x0F; \
1285 int shift = reg[(opcode >> 8) & 15].B.B0; \
1286 int dest = (opcode >> 12) & 15; \
1287 bool C_OUT = C_FLAG; \
1288 u32 value; \
1289 if (shift) { \
1290 if (shift == 32) { \
1291 value = 0; \
1292 C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \
1293 } else if (shift < 32) { \
1294 LOGICAL_LSR_REG \
1295 } else { \
1296 value = 0; \
1297 C_OUT = false; \
1298 } \
1299 } else { \
1300 value = reg[opcode & 0x0F].I; \
1301 } \
1302 if (dest == 15) { \
1303 OPCODE2 \
1304 /* todo */ \
1305 if (opcode & 0x00100000) { \
1306 clockTicks++; \
1307 CPUSwitchMode(reg[17].I & 0x1f, false); \
1308 } \
1309 if (armState) { \
1310 reg[15].I &= 0xFFFFFFFC; \
1311 armNextPC = reg[15].I; \
1312 reg[15].I += 4; \
1313 } else { \
1314 reg[15].I &= 0xFFFFFFFE; \
1315 armNextPC = reg[15].I; \
1316 reg[15].I += 2; \
1317 } \
1318 } else { \
1319 OPCODE \
1320 } \
1321 } \
1322 break; \
1323 case BASE + 5: \
1324 { \
1325 /* OP Rd,Rb,Rm ASR Rs */ \
1326 clockTicks++; \
1327 int base = (opcode >> 16) & 0x0F; \
1328 int shift = reg[(opcode >> 8) & 15].B.B0; \
1329 int dest = (opcode >> 12) & 15; \
1330 bool C_OUT = C_FLAG; \
1331 u32 value; \
1332 if (shift < 32) { \
1333 if (shift) { \
1334 LOGICAL_ASR_REG \
1335 } else { \
1336 value = reg[opcode & 0x0F].I; \
1337 } \
1338 } else { \
1339 if (reg[opcode & 0x0F].I & 0x80000000) { \
1340 value = 0xFFFFFFFF; \
1341 C_OUT = true; \
1342 } else { \
1343 value = 0; \
1344 C_OUT = false; \
1345 } \
1346 } \
1347 if (dest == 15) { \
1348 OPCODE2 \
1349 /* todo */ \
1350 if (opcode & 0x00100000) { \
1351 clockTicks++; \
1352 CPUSwitchMode(reg[17].I & 0x1f, false); \
1353 } \
1354 if (armState) { \
1355 reg[15].I &= 0xFFFFFFFC; \
1356 armNextPC = reg[15].I; \
1357 reg[15].I += 4; \
1358 } else { \
1359 reg[15].I &= 0xFFFFFFFE; \
1360 armNextPC = reg[15].I; \
1361 reg[15].I += 2; \
1362 } \
1363 } else { \
1364 OPCODE \
1365 } \
1366 } \
1367 break; \
1368 case BASE + 7: \
1369 { \
1370 /* OP Rd,Rb,Rm ROR Rs */ \
1371 clockTicks++; \
1372 int base = (opcode >> 16) & 0x0F; \
1373 int shift = reg[(opcode >> 8) & 15].B.B0; \
1374 int dest = (opcode >> 12) & 15; \
1375 bool C_OUT = C_FLAG; \
1376 u32 value; \
1377 if (shift) { \
1378 shift &= 0x1f; \
1379 if (shift) { \
1380 LOGICAL_ROR_REG \
1381 } else { \
1382 value = reg[opcode & 0x0F].I; \
1383 C_OUT = (value & 0x80000000 ? true : false); \
1384 } \
1385 } else { \
1386 value = reg[opcode & 0x0F].I; \
1387 C_OUT = (value & 0x80000000 ? true : false); \
1388 } \
1389 if (dest == 15) { \
1390 OPCODE2 \
1391 /* todo */ \
1392 if (opcode & 0x00100000) { \
1393 clockTicks++; \
1394 CPUSwitchMode(reg[17].I & 0x1f, false); \
1395 } \
1396 if (armState) { \
1397 reg[15].I &= 0xFFFFFFFC; \
1398 armNextPC = reg[15].I; \
1399 reg[15].I += 4; \
1400 } else { \
1401 reg[15].I &= 0xFFFFFFFE; \
1402 armNextPC = reg[15].I; \
1403 reg[15].I += 2; \
1404 } \
1405 } else { \
1406 OPCODE \
1407 } \
1408 } \
1409 break; \
1410 case BASE + 0x200: \
1411 case BASE + 0x201: \
1412 case BASE + 0x202: \
1413 case BASE + 0x203: \
1414 case BASE + 0x204: \
1415 case BASE + 0x205: \
1416 case BASE + 0x206: \
1417 case BASE + 0x207: \
1418 case BASE + 0x208: \
1419 case BASE + 0x209: \
1420 case BASE + 0x20a: \
1421 case BASE + 0x20b: \
1422 case BASE + 0x20c: \
1423 case BASE + 0x20d: \
1424 case BASE + 0x20e: \
1425 case BASE + 0x20f: \
1426 { \
1427 int shift = (opcode & 0xF00) >> 7; \
1428 int base = (opcode >> 16) & 0x0F; \
1429 int dest = (opcode >> 12) & 0x0F; \
1430 bool C_OUT = C_FLAG; \
1431 u32 value; \
1432 if (shift) { \
1433 LOGICAL_ROR_IMM \
1434 } else { \
1435 value = opcode & 0xff; \
1436 } \
1437 if (dest == 15) { \
1438 OPCODE2 \
1439 /* todo */ \
1440 if (opcode & 0x00100000) { \
1441 clockTicks++; \
1442 CPUSwitchMode(reg[17].I & 0x1f, false); \
1443 } \
1444 if (armState) { \
1445 reg[15].I &= 0xFFFFFFFC; \
1446 armNextPC = reg[15].I; \
1447 reg[15].I += 4; \
1448 } else { \
1449 reg[15].I &= 0xFFFFFFFE; \
1450 armNextPC = reg[15].I; \
1451 reg[15].I += 2; \
1452 } \
1453 } else { \
1454 OPCODE \
1455 } \
1456 } \
1457 break;
1459 #define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \
1460 case BASE: \
1461 case BASE + 8: \
1462 { \
1463 /* OP Rd,Rb,Rm LSL # */ \
1464 int shift = (opcode >> 7) & 0x1F; \
1465 int dest = (opcode >> 12) & 15; \
1466 bool C_OUT = C_FLAG; \
1467 u32 value; \
1469 if (shift) { \
1470 LOGICAL_LSL_REG \
1471 } else { \
1472 value = reg[opcode & 0x0F].I; \
1473 } \
1474 if (dest == 15) { \
1475 OPCODE2 \
1476 /* todo */ \
1477 if (opcode & 0x00100000) { \
1478 clockTicks++; \
1479 CPUSwitchMode(reg[17].I & 0x1f, false); \
1480 } \
1481 if (armState) { \
1482 reg[15].I &= 0xFFFFFFFC; \
1483 armNextPC = reg[15].I; \
1484 reg[15].I += 4; \
1485 } else { \
1486 reg[15].I &= 0xFFFFFFFE; \
1487 armNextPC = reg[15].I; \
1488 reg[15].I += 2; \
1489 } \
1490 } else { \
1491 OPCODE \
1492 } \
1493 } \
1494 break; \
1495 case BASE + 2: \
1496 case BASE + 10: \
1497 { \
1498 /* OP Rd,Rb,Rm LSR # */ \
1499 int shift = (opcode >> 7) & 0x1F; \
1500 int dest = (opcode >> 12) & 15; \
1501 bool C_OUT = C_FLAG; \
1502 u32 value; \
1503 if (shift) { \
1504 LOGICAL_LSR_REG \
1505 } else { \
1506 value = 0; \
1507 C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \
1508 } \
1510 if (dest == 15) { \
1511 OPCODE2 \
1512 /* todo */ \
1513 if (opcode & 0x00100000) { \
1514 clockTicks++; \
1515 CPUSwitchMode(reg[17].I & 0x1f, false); \
1516 } \
1517 if (armState) { \
1518 reg[15].I &= 0xFFFFFFFC; \
1519 armNextPC = reg[15].I; \
1520 reg[15].I += 4; \
1521 } else { \
1522 reg[15].I &= 0xFFFFFFFE; \
1523 armNextPC = reg[15].I; \
1524 reg[15].I += 2; \
1525 } \
1526 } else { \
1527 OPCODE \
1528 } \
1529 } \
1530 break; \
1531 case BASE + 4: \
1532 case BASE + 12: \
1533 { \
1534 /* OP Rd,Rb,Rm ASR # */ \
1535 int shift = (opcode >> 7) & 0x1F; \
1536 int dest = (opcode >> 12) & 15; \
1537 bool C_OUT = C_FLAG; \
1538 u32 value; \
1539 if (shift) { \
1540 LOGICAL_ASR_REG \
1541 } else { \
1542 if (reg[opcode & 0x0F].I & 0x80000000) { \
1543 value = 0xFFFFFFFF; \
1544 C_OUT = true; \
1545 } else { \
1546 value = 0; \
1547 C_OUT = false; \
1548 } \
1549 } \
1551 if (dest == 15) { \
1552 OPCODE2 \
1553 /* todo */ \
1554 if (opcode & 0x00100000) { \
1555 clockTicks++; \
1556 CPUSwitchMode(reg[17].I & 0x1f, false); \
1557 } \
1558 if (armState) { \
1559 reg[15].I &= 0xFFFFFFFC; \
1560 armNextPC = reg[15].I; \
1561 reg[15].I += 4; \
1562 } else { \
1563 reg[15].I &= 0xFFFFFFFE; \
1564 armNextPC = reg[15].I; \
1565 reg[15].I += 2; \
1566 } \
1567 } else { \
1568 OPCODE \
1569 } \
1570 } \
1571 break; \
1572 case BASE + 6: \
1573 case BASE + 14: \
1574 { \
1575 /* OP Rd,Rb,Rm ROR # */ \
1576 int shift = (opcode >> 7) & 0x1F; \
1577 int dest = (opcode >> 12) & 15; \
1578 bool C_OUT = C_FLAG; \
1579 u32 value; \
1580 if (shift) { \
1581 LOGICAL_ROR_REG \
1582 } else { \
1583 LOGICAL_RRX_REG \
1584 } \
1585 if (dest == 15) { \
1586 OPCODE2 \
1587 /* todo */ \
1588 if (opcode & 0x00100000) { \
1589 clockTicks++; \
1590 CPUSwitchMode(reg[17].I & 0x1f, false); \
1591 } \
1592 if (armState) { \
1593 reg[15].I &= 0xFFFFFFFC; \
1594 armNextPC = reg[15].I; \
1595 reg[15].I += 4; \
1596 } else { \
1597 reg[15].I &= 0xFFFFFFFE; \
1598 armNextPC = reg[15].I; \
1599 reg[15].I += 2; \
1600 } \
1601 } else { \
1602 OPCODE \
1603 } \
1604 } \
1605 break; \
1606 case BASE + 1: \
1607 { \
1608 /* OP Rd,Rb,Rm LSL Rs */ \
1609 clockTicks++; \
1610 int shift = reg[(opcode >> 8) & 15].B.B0; \
1611 int dest = (opcode >> 12) & 15; \
1612 bool C_OUT = C_FLAG; \
1613 u32 value; \
1614 if (shift) { \
1615 if (shift == 32) { \
1616 value = 0; \
1617 C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \
1618 } else if (shift < 32) { \
1619 LOGICAL_LSL_REG \
1620 } else { \
1621 value = 0; \
1622 C_OUT = false; \
1623 } \
1624 } else { \
1625 value = reg[opcode & 0x0F].I; \
1626 } \
1627 if (dest == 15) { \
1628 OPCODE2 \
1629 /* todo */ \
1630 if (opcode & 0x00100000) { \
1631 clockTicks++; \
1632 CPUSwitchMode(reg[17].I & 0x1f, false); \
1633 } \
1634 if (armState) { \
1635 reg[15].I &= 0xFFFFFFFC; \
1636 armNextPC = reg[15].I; \
1637 reg[15].I += 4; \
1638 } else { \
1639 reg[15].I &= 0xFFFFFFFE; \
1640 armNextPC = reg[15].I; \
1641 reg[15].I += 2; \
1642 } \
1643 } else { \
1644 OPCODE \
1645 } \
1646 } \
1647 break; \
1648 case BASE + 3: \
1649 { \
1650 /* OP Rd,Rb,Rm LSR Rs */ \
1651 clockTicks++; \
1652 int shift = reg[(opcode >> 8) & 15].B.B0; \
1653 int dest = (opcode >> 12) & 15; \
1654 bool C_OUT = C_FLAG; \
1655 u32 value; \
1656 if (shift) { \
1657 if (shift == 32) { \
1658 value = 0; \
1659 C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \
1660 } else if (shift < 32) { \
1661 LOGICAL_LSR_REG \
1662 } else { \
1663 value = 0; \
1664 C_OUT = false; \
1665 } \
1666 } else { \
1667 value = reg[opcode & 0x0F].I; \
1668 } \
1669 if (dest == 15) { \
1670 OPCODE2 \
1671 /* todo */ \
1672 if (opcode & 0x00100000) { \
1673 clockTicks++; \
1674 CPUSwitchMode(reg[17].I & 0x1f, false); \
1675 } \
1676 if (armState) { \
1677 reg[15].I &= 0xFFFFFFFC; \
1678 armNextPC = reg[15].I; \
1679 reg[15].I += 4; \
1680 } else { \
1681 reg[15].I &= 0xFFFFFFFE; \
1682 armNextPC = reg[15].I; \
1683 reg[15].I += 2; \
1684 } \
1685 } else { \
1686 OPCODE \
1687 } \
1688 } \
1689 break; \
1690 case BASE + 5: \
1691 { \
1692 /* OP Rd,Rb,Rm ASR Rs */ \
1693 clockTicks++; \
1694 int shift = reg[(opcode >> 8) & 15].B.B0; \
1695 int dest = (opcode >> 12) & 15; \
1696 bool C_OUT = C_FLAG; \
1697 u32 value; \
1698 if (shift < 32) { \
1699 if (shift) { \
1700 LOGICAL_ASR_REG \
1701 } else { \
1702 value = reg[opcode & 0x0F].I; \
1703 } \
1704 } else { \
1705 if (reg[opcode & 0x0F].I & 0x80000000) { \
1706 value = 0xFFFFFFFF; \
1707 C_OUT = true; \
1708 } else { \
1709 value = 0; \
1710 C_OUT = false; \
1711 } \
1712 } \
1713 if (dest == 15) { \
1714 OPCODE2 \
1715 /* todo */ \
1716 if (opcode & 0x00100000) { \
1717 clockTicks++; \
1718 CPUSwitchMode(reg[17].I & 0x1f, false); \
1719 } \
1720 if (armState) { \
1721 reg[15].I &= 0xFFFFFFFC; \
1722 armNextPC = reg[15].I; \
1723 reg[15].I += 4; \
1724 } else { \
1725 reg[15].I &= 0xFFFFFFFE; \
1726 armNextPC = reg[15].I; \
1727 reg[15].I += 2; \
1728 } \
1729 } else { \
1730 OPCODE \
1731 } \
1732 } \
1733 break; \
1734 case BASE + 7: \
1735 { \
1736 /* OP Rd,Rb,Rm ROR Rs */ \
1737 clockTicks++; \
1738 int shift = reg[(opcode >> 8) & 15].B.B0; \
1739 int dest = (opcode >> 12) & 15; \
1740 bool C_OUT = C_FLAG; \
1741 u32 value; \
1742 if (shift) { \
1743 shift &= 0x1f; \
1744 if (shift) { \
1745 LOGICAL_ROR_REG \
1746 } else { \
1747 value = reg[opcode & 0x0F].I; \
1748 C_OUT = (value & 0x80000000 ? true : false); \
1749 } \
1750 } else { \
1751 value = reg[opcode & 0x0F].I; \
1752 C_OUT = (value & 0x80000000 ? true : false); \
1753 } \
1754 if (dest == 15) { \
1755 OPCODE2 \
1756 /* todo */ \
1757 if (opcode & 0x00100000) { \
1758 clockTicks++; \
1759 CPUSwitchMode(reg[17].I & 0x1f, false); \
1760 } \
1761 if (armState) { \
1762 reg[15].I &= 0xFFFFFFFC; \
1763 armNextPC = reg[15].I; \
1764 reg[15].I += 4; \
1765 } else { \
1766 reg[15].I &= 0xFFFFFFFE; \
1767 armNextPC = reg[15].I; \
1768 reg[15].I += 2; \
1769 } \
1770 } else { \
1771 OPCODE \
1772 } \
1773 } \
1774 break; \
1775 case BASE + 0x200: \
1776 case BASE + 0x201: \
1777 case BASE + 0x202: \
1778 case BASE + 0x203: \
1779 case BASE + 0x204: \
1780 case BASE + 0x205: \
1781 case BASE + 0x206: \
1782 case BASE + 0x207: \
1783 case BASE + 0x208: \
1784 case BASE + 0x209: \
1785 case BASE + 0x20a: \
1786 case BASE + 0x20b: \
1787 case BASE + 0x20c: \
1788 case BASE + 0x20d: \
1789 case BASE + 0x20e: \
1790 case BASE + 0x20f: \
1791 { \
1792 int shift = (opcode & 0xF00) >> 7; \
1793 int dest = (opcode >> 12) & 0x0F; \
1794 bool C_OUT = C_FLAG; \
1795 u32 value; \
1796 if (shift) { \
1797 LOGICAL_ROR_IMM \
1798 } else { \
1799 value = opcode & 0xff; \
1800 } \
1801 if (dest == 15) { \
1802 OPCODE2 \
1803 /* todo */ \
1804 if (opcode & 0x00100000) { \
1805 clockTicks++; \
1806 CPUSwitchMode(reg[17].I & 0x1f, false); \
1807 } \
1808 if (armState) { \
1809 reg[15].I &= 0xFFFFFFFC; \
1810 armNextPC = reg[15].I; \
1811 reg[15].I += 4; \
1812 } else { \
1813 reg[15].I &= 0xFFFFFFFE; \
1814 armNextPC = reg[15].I; \
1815 reg[15].I += 2; \
1816 } \
1817 } else { \
1818 OPCODE \
1819 } \
1820 } \
1821 break;
1823 #define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
1824 case BASE: \
1825 case BASE + 8: \
1826 { \
1827 /* OP Rd,Rb,Rm LSL # */ \
1828 int base = (opcode >> 16) & 0x0F; \
1829 int shift = (opcode >> 7) & 0x1F; \
1830 int dest = (opcode >> 12) & 15; \
1831 u32 value; \
1832 if (shift) { \
1833 ARITHMETIC_LSL_REG \
1834 } else { \
1835 value = reg[opcode & 0x0F].I; \
1836 } \
1837 if (dest == 15) { \
1838 OPCODE2 \
1839 /* todo */ \
1840 if (opcode & 0x00100000) { \
1841 clockTicks++; \
1842 CPUSwitchMode(reg[17].I & 0x1f, false); \
1843 } \
1844 if (armState) { \
1845 reg[15].I &= 0xFFFFFFFC; \
1846 armNextPC = reg[15].I; \
1847 reg[15].I += 4; \
1848 } else { \
1849 reg[15].I &= 0xFFFFFFFE; \
1850 armNextPC = reg[15].I; \
1851 reg[15].I += 2; \
1852 } \
1853 } else { \
1854 OPCODE \
1855 } \
1856 } \
1857 break; \
1858 case BASE + 2: \
1859 case BASE + 10: \
1860 { \
1861 /* OP Rd,Rb,Rm LSR # */ \
1862 int base = (opcode >> 16) & 0x0F; \
1863 int shift = (opcode >> 7) & 0x1F; \
1864 int dest = (opcode >> 12) & 15; \
1865 u32 value; \
1866 if (shift) { \
1867 ARITHMETIC_LSR_REG \
1868 } else { \
1869 value = 0; \
1870 } \
1871 if (dest == 15) { \
1872 OPCODE2 \
1873 /* todo */ \
1874 if (opcode & 0x00100000) { \
1875 clockTicks++; \
1876 CPUSwitchMode(reg[17].I & 0x1f, false); \
1877 } \
1878 if (armState) { \
1879 reg[15].I &= 0xFFFFFFFC; \
1880 armNextPC = reg[15].I; \
1881 reg[15].I += 4; \
1882 } else { \
1883 reg[15].I &= 0xFFFFFFFE; \
1884 armNextPC = reg[15].I; \
1885 reg[15].I += 2; \
1886 } \
1887 } else { \
1888 OPCODE \
1889 } \
1890 } \
1891 break; \
1892 case BASE + 4: \
1893 case BASE + 12: \
1894 { \
1895 /* OP Rd,Rb,Rm ASR # */ \
1896 int base = (opcode >> 16) & 0x0F; \
1897 int shift = (opcode >> 7) & 0x1F; \
1898 int dest = (opcode >> 12) & 15; \
1899 u32 value; \
1900 if (shift) { \
1901 ARITHMETIC_ASR_REG \
1902 } else { \
1903 if (reg[opcode & 0x0F].I & 0x80000000) { \
1904 value = 0xFFFFFFFF; \
1905 } else value = 0; \
1906 } \
1907 if (dest == 15) { \
1908 OPCODE2 \
1909 /* todo */ \
1910 if (opcode & 0x00100000) { \
1911 clockTicks++; \
1912 CPUSwitchMode(reg[17].I & 0x1f, false); \
1913 } \
1914 if (armState) { \
1915 reg[15].I &= 0xFFFFFFFC; \
1916 armNextPC = reg[15].I; \
1917 reg[15].I += 4; \
1918 } else { \
1919 reg[15].I &= 0xFFFFFFFE; \
1920 armNextPC = reg[15].I; \
1921 reg[15].I += 2; \
1922 } \
1923 } else { \
1924 OPCODE \
1925 } \
1926 } \
1927 break; \
1928 case BASE + 6: \
1929 case BASE + 14: \
1930 { \
1931 /* OP Rd,Rb,Rm ROR # */ \
1932 int base = (opcode >> 16) & 0x0F; \
1933 int shift = (opcode >> 7) & 0x1F; \
1934 int dest = (opcode >> 12) & 15; \
1935 u32 value; \
1936 if (shift) { \
1937 ARITHMETIC_ROR_REG \
1938 } else { \
1939 ARITHMETIC_RRX_REG \
1940 } \
1941 if (dest == 15) { \
1942 OPCODE2 \
1943 /* todo */ \
1944 if (opcode & 0x00100000) { \
1945 clockTicks++; \
1946 CPUSwitchMode(reg[17].I & 0x1f, false); \
1947 } \
1948 if (armState) { \
1949 reg[15].I &= 0xFFFFFFFC; \
1950 armNextPC = reg[15].I; \
1951 reg[15].I += 4; \
1952 } else { \
1953 reg[15].I &= 0xFFFFFFFE; \
1954 armNextPC = reg[15].I; \
1955 reg[15].I += 2; \
1956 } \
1957 } else { \
1958 OPCODE \
1959 } \
1960 } \
1961 break; \
1962 case BASE + 1: \
1963 { \
1964 /* OP Rd,Rb,Rm LSL Rs */ \
1965 clockTicks++; \
1966 int base = (opcode >> 16) & 0x0F; \
1967 int shift = reg[(opcode >> 8) & 15].B.B0; \
1968 int dest = (opcode >> 12) & 15; \
1969 u32 value; \
1970 if (shift) { \
1971 if (shift == 32) { \
1972 value = 0; \
1973 } else if (shift < 32) { \
1974 ARITHMETIC_LSL_REG \
1975 } else value = 0; \
1976 } else { \
1977 value = reg[opcode & 0x0F].I; \
1978 } \
1979 if (dest == 15) { \
1980 OPCODE2 \
1981 /* todo */ \
1982 if (opcode & 0x00100000) { \
1983 clockTicks++; \
1984 CPUSwitchMode(reg[17].I & 0x1f, false); \
1985 } \
1986 if (armState) { \
1987 reg[15].I &= 0xFFFFFFFC; \
1988 armNextPC = reg[15].I; \
1989 reg[15].I += 4; \
1990 } else { \
1991 reg[15].I &= 0xFFFFFFFE; \
1992 armNextPC = reg[15].I; \
1993 reg[15].I += 2; \
1994 } \
1995 } else { \
1996 OPCODE \
1997 } \
1998 } \
1999 break; \
2000 case BASE + 3: \
2001 { \
2002 /* OP Rd,Rb,Rm LSR Rs */ \
2003 clockTicks++; \
2004 int base = (opcode >> 16) & 0x0F; \
2005 int shift = reg[(opcode >> 8) & 15].B.B0; \
2006 int dest = (opcode >> 12) & 15; \
2007 u32 value; \
2008 if (shift) { \
2009 if (shift == 32) { \
2010 value = 0; \
2011 } else if (shift < 32) { \
2012 ARITHMETIC_LSR_REG \
2013 } else value = 0; \
2014 } else { \
2015 value = reg[opcode & 0x0F].I; \
2016 } \
2017 if (dest == 15) { \
2018 OPCODE2 \
2019 /* todo */ \
2020 if (opcode & 0x00100000) { \
2021 clockTicks++; \
2022 CPUSwitchMode(reg[17].I & 0x1f, false); \
2023 } \
2024 if (armState) { \
2025 reg[15].I &= 0xFFFFFFFC; \
2026 armNextPC = reg[15].I; \
2027 reg[15].I += 4; \
2028 } else { \
2029 reg[15].I &= 0xFFFFFFFE; \
2030 armNextPC = reg[15].I; \
2031 reg[15].I += 2; \
2032 } \
2033 } else { \
2034 OPCODE \
2035 } \
2036 } \
2037 break; \
2038 case BASE + 5: \
2039 { \
2040 /* OP Rd,Rb,Rm ASR Rs */ \
2041 clockTicks++; \
2042 int base = (opcode >> 16) & 0x0F; \
2043 int shift = reg[(opcode >> 8) & 15].B.B0; \
2044 int dest = (opcode >> 12) & 15; \
2045 u32 value; \
2046 if (shift < 32) { \
2047 if (shift) { \
2048 ARITHMETIC_ASR_REG \
2049 } else { \
2050 value = reg[opcode & 0x0F].I; \
2051 } \
2052 } else { \
2053 if (reg[opcode & 0x0F].I & 0x80000000) { \
2054 value = 0xFFFFFFFF; \
2055 } else value = 0; \
2056 } \
2057 if (dest == 15) { \
2058 OPCODE2 \
2059 /* todo */ \
2060 if (opcode & 0x00100000) { \
2061 clockTicks++; \
2062 CPUSwitchMode(reg[17].I & 0x1f, false); \
2063 } \
2064 if (armState) { \
2065 reg[15].I &= 0xFFFFFFFC; \
2066 armNextPC = reg[15].I; \
2067 reg[15].I += 4; \
2068 } else { \
2069 reg[15].I &= 0xFFFFFFFE; \
2070 armNextPC = reg[15].I; \
2071 reg[15].I += 2; \
2072 } \
2073 } else { \
2074 OPCODE \
2075 } \
2076 } \
2077 break; \
2078 case BASE + 7: \
2079 { \
2080 /* OP Rd,Rb,Rm ROR Rs */ \
2081 clockTicks++; \
2082 int base = (opcode >> 16) & 0x0F; \
2083 int shift = reg[(opcode >> 8) & 15].B.B0; \
2084 int dest = (opcode >> 12) & 15; \
2085 u32 value; \
2086 if (shift) { \
2087 shift &= 0x1f; \
2088 if (shift) { \
2089 ARITHMETIC_ROR_REG \
2090 } else { \
2091 value = reg[opcode & 0x0F].I; \
2092 } \
2093 } else { \
2094 value = reg[opcode & 0x0F].I; \
2095 } \
2096 if (dest == 15) { \
2097 OPCODE2 \
2098 /* todo */ \
2099 if (opcode & 0x00100000) { \
2100 clockTicks++; \
2101 CPUSwitchMode(reg[17].I & 0x1f, false); \
2102 } \
2103 if (armState) { \
2104 reg[15].I &= 0xFFFFFFFC; \
2105 armNextPC = reg[15].I; \
2106 reg[15].I += 4; \
2107 } else { \
2108 reg[15].I &= 0xFFFFFFFE; \
2109 armNextPC = reg[15].I; \
2110 reg[15].I += 2; \
2111 } \
2112 } else { \
2113 OPCODE \
2114 } \
2115 } \
2116 break; \
2117 case BASE + 0x200: \
2118 case BASE + 0x201: \
2119 case BASE + 0x202: \
2120 case BASE + 0x203: \
2121 case BASE + 0x204: \
2122 case BASE + 0x205: \
2123 case BASE + 0x206: \
2124 case BASE + 0x207: \
2125 case BASE + 0x208: \
2126 case BASE + 0x209: \
2127 case BASE + 0x20a: \
2128 case BASE + 0x20b: \
2129 case BASE + 0x20c: \
2130 case BASE + 0x20d: \
2131 case BASE + 0x20e: \
2132 case BASE + 0x20f: \
2133 { \
2134 int shift = (opcode & 0xF00) >> 7; \
2135 int base = (opcode >> 16) & 0x0F; \
2136 int dest = (opcode >> 12) & 0x0F; \
2137 u32 value; \
2138 { \
2139 ARITHMETIC_ROR_IMM \
2140 } \
2141 if (dest == 15) { \
2142 OPCODE2 \
2143 /* todo */ \
2144 if (opcode & 0x00100000) { \
2145 clockTicks++; \
2146 CPUSwitchMode(reg[17].I & 0x1f, false); \
2147 } \
2148 if (armState) { \
2149 reg[15].I &= 0xFFFFFFFC; \
2150 armNextPC = reg[15].I; \
2151 reg[15].I += 4; \
2152 } else { \
2153 reg[15].I &= 0xFFFFFFFE; \
2154 armNextPC = reg[15].I; \
2155 reg[15].I += 2; \
2156 } \
2157 } else { \
2158 OPCODE \
2159 } \
2160 } \
2161 break;
2163 u32 opcode = CPUReadMemoryQuick(armNextPC);
2165 clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15];
2167 #ifndef FINAL_VERSION
2168 if (armNextPC == stop)
2170 armNextPC++;
2172 #endif
2174 armNextPC = reg[15].I;
2175 reg[15].I += 4;
2176 int cond = opcode >> 28;
2177 // suggested optimization for frequent cases
2178 bool cond_res;
2179 if (cond == 0x0e)
2181 cond_res = true;
2183 else
2185 switch (cond)
2187 case 0x00: // EQ
2188 cond_res = Z_FLAG;
2189 break;
2190 case 0x01: // NE
2191 cond_res = !Z_FLAG;
2192 break;
2193 case 0x02: // CS
2194 cond_res = C_FLAG;
2195 break;
2196 case 0x03: // CC
2197 cond_res = !C_FLAG;
2198 break;
2199 case 0x04: // MI
2200 cond_res = N_FLAG;
2201 break;
2202 case 0x05: // PL
2203 cond_res = !N_FLAG;
2204 break;
2205 case 0x06: // VS
2206 cond_res = V_FLAG;
2207 break;
2208 case 0x07: // VC
2209 cond_res = !V_FLAG;
2210 break;
2211 case 0x08: // HI
2212 cond_res = C_FLAG && !Z_FLAG;
2213 break;
2214 case 0x09: // LS
2215 cond_res = !C_FLAG || Z_FLAG;
2216 break;
2217 case 0x0A: // GE
2218 cond_res = N_FLAG == V_FLAG;
2219 break;
2220 case 0x0B: // LT
2221 cond_res = N_FLAG != V_FLAG;
2222 break;
2223 case 0x0C: // GT
2224 cond_res = !Z_FLAG && (N_FLAG == V_FLAG);
2225 break;
2226 case 0x0D: // LE
2227 cond_res = Z_FLAG || (N_FLAG != V_FLAG);
2228 break;
2229 case 0x0E:
2230 cond_res = true;
2231 break;
2232 case 0x0F:
2233 default:
2234 // ???
2235 cond_res = false;
2236 break;
2240 if (cond_res)
2242 switch (((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x0F))
2244 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND, OP_AND, 0x000);
2245 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010);
2246 case 0x009:
2248 // MUL Rd, Rm, Rs
2249 int dest = (opcode >> 16) & 0x0F;
2250 int mult = (opcode & 0x0F);
2251 u32 rs = reg[(opcode >> 8) & 0x0F].I;
2252 reg[dest].I = reg[mult].I * rs;
2253 if (((s32)rs) < 0)
2254 rs = ~rs;
2255 if ((rs & 0xFFFFFF00) == 0)
2256 clockTicks += 2;
2257 else if ((rs & 0xFFFF0000) == 0)
2258 clockTicks += 3;
2259 else if ((rs & 0xFF000000) == 0)
2260 clockTicks += 4;
2261 else
2262 clockTicks += 5;
2264 break;
2265 case 0x019:
2267 // MULS Rd, Rm, Rs
2268 int dest = (opcode >> 16) & 0x0F;
2269 int mult = (opcode & 0x0F);
2270 u32 rs = reg[(opcode >> 8) & 0x0F].I;
2271 reg[dest].I = reg[mult].I * rs;
2272 N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
2273 Z_FLAG = (reg[dest].I) ? false : true;
2274 if (((s32)rs) < 0)
2275 rs = ~rs;
2276 if ((rs & 0xFFFFFF00) == 0)
2277 clockTicks += 2;
2278 else if ((rs & 0xFFFF0000) == 0)
2279 clockTicks += 3;
2280 else if ((rs & 0xFF000000) == 0)
2281 clockTicks += 4;
2282 else
2283 clockTicks += 5;
2285 break;
2286 case 0x00b:
2287 case 0x02b:
2289 // STRH Rd, [Rn], -Rm
2290 int base = (opcode >> 16) & 0x0F;
2291 int dest = (opcode >> 12) & 0x0F;
2292 u32 address = reg[base].I;
2293 int offset = reg[opcode & 0x0F].I;
2294 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2295 CPUWriteHalfWord(address, reg[dest].W.W0);
2296 address -= offset;
2297 reg[base].I = address;
2299 break;
2300 case 0x04b:
2301 case 0x06b:
2303 // STRH Rd, [Rn], #-offset
2304 int base = (opcode >> 16) & 0x0F;
2305 int dest = (opcode >> 12) & 0x0F;
2306 u32 address = reg[base].I;
2307 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2308 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2309 CPUWriteHalfWord(address, reg[dest].W.W0);
2310 address -= offset;
2311 reg[base].I = address;
2313 break;
2314 case 0x08b:
2315 case 0x0ab:
2317 // STRH Rd, [Rn], Rm
2318 int base = (opcode >> 16) & 0x0F;
2319 int dest = (opcode >> 12) & 0x0F;
2320 u32 address = reg[base].I;
2321 int offset = reg[opcode & 0x0F].I;
2322 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2323 CPUWriteHalfWord(address, reg[dest].W.W0);
2324 address += offset;
2325 reg[base].I = address;
2327 break;
2328 case 0x0cb:
2329 case 0x0eb:
2331 // STRH Rd, [Rn], #offset
2332 int base = (opcode >> 16) & 0x0F;
2333 int dest = (opcode >> 12) & 0x0F;
2334 u32 address = reg[base].I;
2335 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2336 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2337 CPUWriteHalfWord(address, reg[dest].W.W0);
2338 address += offset;
2339 reg[base].I = address;
2341 break;
2342 case 0x10b:
2344 // STRH Rd, [Rn, -Rm]
2345 int base = (opcode >> 16) & 0x0F;
2346 int dest = (opcode >> 12) & 0x0F;
2347 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2348 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2349 CPUWriteHalfWord(address, reg[dest].W.W0);
2351 break;
2352 case 0x12b:
2354 // STRH Rd, [Rn, -Rm]!
2355 int base = (opcode >> 16) & 0x0F;
2356 int dest = (opcode >> 12) & 0x0F;
2357 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2358 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2359 CPUWriteHalfWord(address, reg[dest].W.W0);
2360 reg[base].I = address;
2362 break;
2363 case 0x14b:
2365 // STRH Rd, [Rn, -#offset]
2366 int base = (opcode >> 16) & 0x0F;
2367 int dest = (opcode >> 12) & 0x0F;
2368 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2369 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2370 CPUWriteHalfWord(address, reg[dest].W.W0);
2372 break;
2373 case 0x16b:
2375 // STRH Rd, [Rn, -#offset]!
2376 int base = (opcode >> 16) & 0x0F;
2377 int dest = (opcode >> 12) & 0x0F;
2378 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2379 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2380 CPUWriteHalfWord(address, reg[dest].W.W0);
2381 reg[base].I = address;
2383 break;
2384 case 0x18b:
2386 // STRH Rd, [Rn, Rm]
2387 int base = (opcode >> 16) & 0x0F;
2388 int dest = (opcode >> 12) & 0x0F;
2389 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2390 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2391 CPUWriteHalfWord(address, reg[dest].W.W0);
2393 break;
2394 case 0x1ab:
2396 // STRH Rd, [Rn, Rm]!
2397 int base = (opcode >> 16) & 0x0F;
2398 int dest = (opcode >> 12) & 0x0F;
2399 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2400 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2401 CPUWriteHalfWord(address, reg[dest].W.W0);
2402 reg[base].I = address;
2404 break;
2405 case 0x1cb:
2407 // STRH Rd, [Rn, #offset]
2408 int base = (opcode >> 16) & 0x0F;
2409 int dest = (opcode >> 12) & 0x0F;
2410 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2411 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2412 CPUWriteHalfWord(address, reg[dest].W.W0);
2414 break;
2415 case 0x1eb:
2417 // STRH Rd, [Rn, #offset]!
2418 int base = (opcode >> 16) & 0x0F;
2419 int dest = (opcode >> 12) & 0x0F;
2420 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2421 clockTicks += 4 + CPUUpdateTicksAccess16(address);
2422 CPUWriteHalfWord(address, reg[dest].W.W0);
2423 reg[base].I = address;
2425 break;
2426 case 0x01b:
2427 case 0x03b:
2429 // LDRH Rd, [Rn], -Rm
2430 int base = (opcode >> 16) & 0x0F;
2431 int dest = (opcode >> 12) & 0x0F;
2432 u32 address = reg[base].I;
2433 int offset = reg[opcode & 0x0F].I;
2434 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2435 reg[dest].I = CPUReadHalfWord(address);
2436 if (dest != base)
2438 address -= offset;
2439 reg[base].I = address;
2442 break;
2443 case 0x05b:
2444 case 0x07b:
2446 // LDRH Rd, [Rn], #-offset
2447 int base = (opcode >> 16) & 0x0F;
2448 int dest = (opcode >> 12) & 0x0F;
2449 u32 address = reg[base].I;
2450 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2451 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2452 reg[dest].I = CPUReadHalfWord(address);
2453 if (dest != base)
2455 address -= offset;
2456 reg[base].I = address;
2459 break;
2460 case 0x09b:
2461 case 0x0bb:
2463 // LDRH Rd, [Rn], Rm
2464 int base = (opcode >> 16) & 0x0F;
2465 int dest = (opcode >> 12) & 0x0F;
2466 u32 address = reg[base].I;
2467 int offset = reg[opcode & 0x0F].I;
2468 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2469 reg[dest].I = CPUReadHalfWord(address);
2470 if (dest != base)
2472 address += offset;
2473 reg[base].I = address;
2476 break;
2477 case 0x0db:
2478 case 0x0fb:
2480 // LDRH Rd, [Rn], #offset
2481 int base = (opcode >> 16) & 0x0F;
2482 int dest = (opcode >> 12) & 0x0F;
2483 u32 address = reg[base].I;
2484 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2485 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2486 reg[dest].I = CPUReadHalfWord(address);
2487 if (dest != base)
2489 address += offset;
2490 reg[base].I = address;
2493 break;
2494 case 0x11b:
2496 // LDRH Rd, [Rn, -Rm]
2497 int base = (opcode >> 16) & 0x0F;
2498 int dest = (opcode >> 12) & 0x0F;
2499 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2500 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2501 reg[dest].I = CPUReadHalfWord(address);
2503 break;
2504 case 0x13b:
2506 // LDRH Rd, [Rn, -Rm]!
2507 int base = (opcode >> 16) & 0x0F;
2508 int dest = (opcode >> 12) & 0x0F;
2509 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2510 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2511 reg[dest].I = CPUReadHalfWord(address);
2512 if (dest != base)
2513 reg[base].I = address;
2515 break;
2516 case 0x15b:
2518 // LDRH Rd, [Rn, -#offset]
2519 int base = (opcode >> 16) & 0x0F;
2520 int dest = (opcode >> 12) & 0x0F;
2521 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2522 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2523 reg[dest].I = CPUReadHalfWord(address);
2525 break;
2526 case 0x17b:
2528 // LDRH Rd, [Rn, -#offset]!
2529 int base = (opcode >> 16) & 0x0F;
2530 int dest = (opcode >> 12) & 0x0F;
2531 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2532 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2533 reg[dest].I = CPUReadHalfWord(address);
2534 if (dest != base)
2535 reg[base].I = address;
2537 break;
2538 case 0x19b:
2540 // LDRH Rd, [Rn, Rm]
2541 int base = (opcode >> 16) & 0x0F;
2542 int dest = (opcode >> 12) & 0x0F;
2543 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2544 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2545 reg[dest].I = CPUReadHalfWord(address);
2547 break;
2548 case 0x1bb:
2550 // LDRH Rd, [Rn, Rm]!
2551 int base = (opcode >> 16) & 0x0F;
2552 int dest = (opcode >> 12) & 0x0F;
2553 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2554 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2555 reg[dest].I = CPUReadHalfWord(address);
2556 if (dest != base)
2557 reg[base].I = address;
2559 break;
2560 case 0x1db:
2562 // LDRH Rd, [Rn, #offset]
2563 int base = (opcode >> 16) & 0x0F;
2564 int dest = (opcode >> 12) & 0x0F;
2565 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2566 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2567 reg[dest].I = CPUReadHalfWord(address);
2569 break;
2570 case 0x1fb:
2572 // LDRH Rd, [Rn, #offset]!
2573 int base = (opcode >> 16) & 0x0F;
2574 int dest = (opcode >> 12) & 0x0F;
2575 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2576 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2577 reg[dest].I = CPUReadHalfWord(address);
2578 if (dest != base)
2579 reg[base].I = address;
2581 break;
2582 case 0x01d:
2583 case 0x03d:
2585 // LDRSB Rd, [Rn], -Rm
2586 int base = (opcode >> 16) & 0x0F;
2587 int dest = (opcode >> 12) & 0x0F;
2588 u32 address = reg[base].I;
2589 int offset = reg[opcode & 0x0F].I;
2590 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2591 reg[dest].I = (s8)CPUReadByte(address);
2592 if (dest != base)
2594 address -= offset;
2595 reg[base].I = address;
2598 break;
2599 case 0x05d:
2600 case 0x07d:
2602 // LDRSB Rd, [Rn], #-offset
2603 int base = (opcode >> 16) & 0x0F;
2604 int dest = (opcode >> 12) & 0x0F;
2605 u32 address = reg[base].I;
2606 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2607 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2608 reg[dest].I = (s8)CPUReadByte(address);
2609 if (dest != base)
2611 address -= offset;
2612 reg[base].I = address;
2615 break;
2616 case 0x09d:
2617 case 0x0bd:
2619 // LDRSB Rd, [Rn], Rm
2620 int base = (opcode >> 16) & 0x0F;
2621 int dest = (opcode >> 12) & 0x0F;
2622 u32 address = reg[base].I;
2623 int offset = reg[opcode & 0x0F].I;
2624 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2625 reg[dest].I = (s8)CPUReadByte(address);
2626 if (dest != base)
2628 address += offset;
2629 reg[base].I = address;
2632 break;
2633 case 0x0dd:
2634 case 0x0fd:
2636 // LDRSB Rd, [Rn], #offset
2637 int base = (opcode >> 16) & 0x0F;
2638 int dest = (opcode >> 12) & 0x0F;
2639 u32 address = reg[base].I;
2640 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2641 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2642 reg[dest].I = (s8)CPUReadByte(address);
2643 if (dest != base)
2645 address += offset;
2646 reg[base].I = address;
2649 break;
2650 case 0x11d:
2652 // LDRSB Rd, [Rn, -Rm]
2653 int base = (opcode >> 16) & 0x0F;
2654 int dest = (opcode >> 12) & 0x0F;
2655 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2656 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2657 reg[dest].I = (s8)CPUReadByte(address);
2659 break;
2660 case 0x13d:
2662 // LDRSB Rd, [Rn, -Rm]!
2663 int base = (opcode >> 16) & 0x0F;
2664 int dest = (opcode >> 12) & 0x0F;
2665 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2666 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2667 reg[dest].I = (s8)CPUReadByte(address);
2668 if (dest != base)
2669 reg[base].I = address;
2671 break;
2672 case 0x15d:
2674 // LDRSB Rd, [Rn, -#offset]
2675 int base = (opcode >> 16) & 0x0F;
2676 int dest = (opcode >> 12) & 0x0F;
2677 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2678 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2679 reg[dest].I = (s8)CPUReadByte(address);
2681 break;
2682 case 0x17d:
2684 // LDRSB Rd, [Rn, -#offset]!
2685 int base = (opcode >> 16) & 0x0F;
2686 int dest = (opcode >> 12) & 0x0F;
2687 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2688 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2689 reg[dest].I = (s8)CPUReadByte(address);
2690 if (dest != base)
2691 reg[base].I = address;
2693 break;
2694 case 0x19d:
2696 // LDRSB Rd, [Rn, Rm]
2697 int base = (opcode >> 16) & 0x0F;
2698 int dest = (opcode >> 12) & 0x0F;
2699 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2700 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2701 reg[dest].I = (s8)CPUReadByte(address);
2703 break;
2704 case 0x1bd:
2706 // LDRSB Rd, [Rn, Rm]!
2707 int base = (opcode >> 16) & 0x0F;
2708 int dest = (opcode >> 12) & 0x0F;
2709 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2710 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2711 reg[dest].I = (s8)CPUReadByte(address);
2712 if (dest != base)
2713 reg[base].I = address;
2715 break;
2716 case 0x1dd:
2718 // LDRSB Rd, [Rn, #offset]
2719 int base = (opcode >> 16) & 0x0F;
2720 int dest = (opcode >> 12) & 0x0F;
2721 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2722 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2723 reg[dest].I = (s8)CPUReadByte(address);
2725 break;
2726 case 0x1fd:
2728 // LDRSB Rd, [Rn, #offset]!
2729 int base = (opcode >> 16) & 0x0F;
2730 int dest = (opcode >> 12) & 0x0F;
2731 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2732 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2733 reg[dest].I = (s8)CPUReadByte(address);
2734 if (dest != base)
2735 reg[base].I = address;
2737 break;
2738 case 0x01f:
2739 case 0x03f:
2741 // LDRSH Rd, [Rn], -Rm
2742 int base = (opcode >> 16) & 0x0F;
2743 int dest = (opcode >> 12) & 0x0F;
2744 u32 address = reg[base].I;
2745 int offset = reg[opcode & 0x0F].I;
2746 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2747 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2748 if (dest != base)
2750 address -= offset;
2751 reg[base].I = address;
2754 break;
2755 case 0x05f:
2756 case 0x07f:
2758 // LDRSH Rd, [Rn], #-offset
2759 int base = (opcode >> 16) & 0x0F;
2760 int dest = (opcode >> 12) & 0x0F;
2761 u32 address = reg[base].I;
2762 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2763 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2764 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2765 if (dest != base)
2767 address -= offset;
2768 reg[base].I = address;
2771 break;
2772 case 0x09f:
2773 case 0x0bf:
2775 // LDRSH Rd, [Rn], Rm
2776 int base = (opcode >> 16) & 0x0F;
2777 int dest = (opcode >> 12) & 0x0F;
2778 u32 address = reg[base].I;
2779 int offset = reg[opcode & 0x0F].I;
2780 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2781 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2782 if (dest != base)
2784 address += offset;
2785 reg[base].I = address;
2788 break;
2789 case 0x0df:
2790 case 0x0ff:
2792 // LDRSH Rd, [Rn], #offset
2793 int base = (opcode >> 16) & 0x0F;
2794 int dest = (opcode >> 12) & 0x0F;
2795 u32 address = reg[base].I;
2796 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2797 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2798 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2799 if (dest != base)
2801 address += offset;
2802 reg[base].I = address;
2805 break;
2806 case 0x11f:
2808 // LDRSH Rd, [Rn, -Rm]
2809 int base = (opcode >> 16) & 0x0F;
2810 int dest = (opcode >> 12) & 0x0F;
2811 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2812 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2813 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2815 break;
2816 case 0x13f:
2818 // LDRSH Rd, [Rn, -Rm]!
2819 int base = (opcode >> 16) & 0x0F;
2820 int dest = (opcode >> 12) & 0x0F;
2821 u32 address = reg[base].I - reg[opcode & 0x0F].I;
2822 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2823 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2824 if (dest != base)
2825 reg[base].I = address;
2827 break;
2828 case 0x15f:
2830 // LDRSH Rd, [Rn, -#offset]
2831 int base = (opcode >> 16) & 0x0F;
2832 int dest = (opcode >> 12) & 0x0F;
2833 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2834 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2835 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2837 break;
2838 case 0x17f:
2840 // LDRSH Rd, [Rn, -#offset]!
2841 int base = (opcode >> 16) & 0x0F;
2842 int dest = (opcode >> 12) & 0x0F;
2843 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2844 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2845 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2846 if (dest != base)
2847 reg[base].I = address;
2849 break;
2850 case 0x19f:
2852 // LDRSH Rd, [Rn, Rm]
2853 int base = (opcode >> 16) & 0x0F;
2854 int dest = (opcode >> 12) & 0x0F;
2855 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2856 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2857 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2859 break;
2860 case 0x1bf:
2862 // LDRSH Rd, [Rn, Rm]!
2863 int base = (opcode >> 16) & 0x0F;
2864 int dest = (opcode >> 12) & 0x0F;
2865 u32 address = reg[base].I + reg[opcode & 0x0F].I;
2866 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2867 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2868 if (dest != base)
2869 reg[base].I = address;
2871 break;
2872 case 0x1df:
2874 // LDRSH Rd, [Rn, #offset]
2875 int base = (opcode >> 16) & 0x0F;
2876 int dest = (opcode >> 12) & 0x0F;
2877 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2878 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2879 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2881 break;
2882 case 0x1ff:
2884 // LDRSH Rd, [Rn, #offset]!
2885 int base = (opcode >> 16) & 0x0F;
2886 int dest = (opcode >> 12) & 0x0F;
2887 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
2888 clockTicks += 3 + CPUUpdateTicksAccess16(address);
2889 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2890 if (dest != base)
2891 reg[base].I = address;
2893 break;
2894 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020);
2895 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030);
2896 case 0x029:
2898 // MLA Rd, Rm, Rs, Rn
2899 int dest = (opcode >> 16) & 0x0F;
2900 int mult = (opcode & 0x0F);
2901 u32 rs = reg[(opcode >> 8) & 0x0F].I;
2902 reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I;
2903 if (((s32)rs) < 0)
2904 rs = ~rs;
2905 if ((rs & 0xFFFFFF00) == 0)
2906 clockTicks += 3;
2907 else if ((rs & 0xFFFF0000) == 0)
2908 clockTicks += 4;
2909 else if ((rs & 0xFF000000) == 0)
2910 clockTicks += 5;
2911 else
2912 clockTicks += 6;
2914 break;
2915 case 0x039:
2917 // MLAS Rd, Rm, Rs, Rn
2918 int dest = (opcode >> 16) & 0x0F;
2919 int mult = (opcode & 0x0F);
2920 u32 rs = reg[(opcode >> 8) & 0x0F].I;
2921 reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I;
2922 N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
2923 Z_FLAG = (reg[dest].I) ? false : true;
2924 if (((s32)rs) < 0)
2925 rs = ~rs;
2926 if ((rs & 0xFFFFFF00) == 0)
2927 clockTicks += 3;
2928 else if ((rs & 0xFFFF0000) == 0)
2929 clockTicks += 4;
2930 else if ((rs & 0xFF000000) == 0)
2931 clockTicks += 5;
2932 else
2933 clockTicks += 6;
2935 break;
2936 ARITHMETIC_DATA_OPCODE(OP_SUB, OP_SUB, 0x040);
2937 ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050);
2938 ARITHMETIC_DATA_OPCODE(OP_RSB, OP_RSB, 0x060);
2939 ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070);
2940 ARITHMETIC_DATA_OPCODE(OP_ADD, OP_ADD, 0x080);
2941 ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090);
2942 case 0x089:
2944 // UMULL RdLo, RdHi, Rn, Rs
2945 u32 umult = reg[(opcode & 0x0F)].I;
2946 u32 usource = reg[(opcode >> 8) & 0x0F].I;
2947 int destLo = (opcode >> 12) & 0x0F;
2948 int destHi = (opcode >> 16) & 0x0F;
2949 u64 uTemp = ((u64)umult) * ((u64)usource);
2950 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
2951 reg[destHi].I = (u32)(uTemp >> 32);
2952 if ((usource & 0xFFFFFF00) == 0)
2953 clockTicks += 2;
2954 else if ((usource & 0xFFFF0000) == 0)
2955 clockTicks += 3;
2956 else if ((usource & 0xFF000000) == 0)
2957 clockTicks += 4;
2958 else
2959 clockTicks += 5;
2961 break;
2962 case 0x099:
2964 // UMULLS RdLo, RdHi, Rn, Rs
2965 u32 umult = reg[(opcode & 0x0F)].I;
2966 u32 usource = reg[(opcode >> 8) & 0x0F].I;
2967 int destLo = (opcode >> 12) & 0x0F;
2968 int destHi = (opcode >> 16) & 0x0F;
2969 u64 uTemp = ((u64)umult) * ((u64)usource);
2970 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
2971 reg[destHi].I = (u32)(uTemp >> 32);
2972 Z_FLAG = (uTemp) ? false : true;
2973 N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
2974 if ((usource & 0xFFFFFF00) == 0)
2975 clockTicks += 2;
2976 else if ((usource & 0xFFFF0000) == 0)
2977 clockTicks += 3;
2978 else if ((usource & 0xFF000000) == 0)
2979 clockTicks += 4;
2980 else
2981 clockTicks += 5;
2983 break;
2984 ARITHMETIC_DATA_OPCODE(OP_ADC, OP_ADC, 0x0a0);
2985 ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0);
2986 case 0x0a9:
2988 // UMLAL RdLo, RdHi, Rn, Rs
2989 u32 umult = reg[(opcode & 0x0F)].I;
2990 u32 usource = reg[(opcode >> 8) & 0x0F].I;
2991 int destLo = (opcode >> 12) & 0x0F;
2992 int destHi = (opcode >> 16) & 0x0F;
2993 u64 uTemp = (u64)reg[destHi].I;
2994 uTemp <<= 32;
2995 uTemp |= (u64)reg[destLo].I;
2996 uTemp += ((u64)umult) * ((u64)usource);
2997 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
2998 reg[destHi].I = (u32)(uTemp >> 32);
2999 if ((usource & 0xFFFFFF00) == 0)
3000 clockTicks += 3;
3001 else if ((usource & 0xFFFF0000) == 0)
3002 clockTicks += 4;
3003 else if ((usource & 0xFF000000) == 0)
3004 clockTicks += 5;
3005 else
3006 clockTicks += 6;
3008 break;
3009 case 0x0b9:
3011 // UMLALS RdLo, RdHi, Rn, Rs
3012 u32 umult = reg[(opcode & 0x0F)].I;
3013 u32 usource = reg[(opcode >> 8) & 0x0F].I;
3014 int destLo = (opcode >> 12) & 0x0F;
3015 int destHi = (opcode >> 16) & 0x0F;
3016 u64 uTemp = (u64)reg[destHi].I;
3017 uTemp <<= 32;
3018 uTemp |= (u64)reg[destLo].I;
3019 uTemp += ((u64)umult) * ((u64)usource);
3020 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
3021 reg[destHi].I = (u32)(uTemp >> 32);
3022 Z_FLAG = (uTemp) ? false : true;
3023 N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
3024 if ((usource & 0xFFFFFF00) == 0)
3025 clockTicks += 3;
3026 else if ((usource & 0xFFFF0000) == 0)
3027 clockTicks += 4;
3028 else if ((usource & 0xFF000000) == 0)
3029 clockTicks += 5;
3030 else
3031 clockTicks += 6;
3033 break;
3034 ARITHMETIC_DATA_OPCODE(OP_SBC, OP_SBC, 0x0c0);
3035 ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0);
3036 case 0x0c9:
3038 // SMULL RdLo, RdHi, Rm, Rs
3039 int destLo = (opcode >> 12) & 0x0F;
3040 int destHi = (opcode >> 16) & 0x0F;
3041 u32 rs = reg[(opcode >> 8) & 0x0F].I;
3042 s64 m = (s32)reg[(opcode & 0x0F)].I;
3043 s64 s = (s32)rs;
3044 s64 sTemp = m * s;
3045 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
3046 reg[destHi].I = (u32)(sTemp >> 32);
3047 if (((s32)rs) < 0)
3048 rs = ~rs;
3049 if ((rs & 0xFFFFFF00) == 0)
3050 clockTicks += 2;
3051 else if ((rs & 0xFFFF0000) == 0)
3052 clockTicks += 3;
3053 else if ((rs & 0xFF000000) == 0)
3054 clockTicks += 4;
3055 else
3056 clockTicks += 5;
3058 break;
3059 case 0x0d9:
3061 // SMULLS RdLo, RdHi, Rm, Rs
3062 int destLo = (opcode >> 12) & 0x0F;
3063 int destHi = (opcode >> 16) & 0x0F;
3064 u32 rs = reg[(opcode >> 8) & 0x0F].I;
3065 s64 m = (s32)reg[(opcode & 0x0F)].I;
3066 s64 s = (s32)rs;
3067 s64 sTemp = m * s;
3068 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
3069 reg[destHi].I = (u32)(sTemp >> 32);
3070 Z_FLAG = (sTemp) ? false : true;
3071 N_FLAG = (sTemp < 0) ? true : false;
3072 if (((s32)rs) < 0)
3073 rs = ~rs;
3074 if ((rs & 0xFFFFFF00) == 0)
3075 clockTicks += 2;
3076 else if ((rs & 0xFFFF0000) == 0)
3077 clockTicks += 3;
3078 else if ((rs & 0xFF000000) == 0)
3079 clockTicks += 4;
3080 else
3081 clockTicks += 5;
3083 break;
3084 ARITHMETIC_DATA_OPCODE(OP_RSC, OP_RSC, 0x0e0);
3085 ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0);
3086 case 0x0e9:
3088 // SMLAL RdLo, RdHi, Rm, Rs
3089 int destLo = (opcode >> 12) & 0x0F;
3090 int destHi = (opcode >> 16) & 0x0F;
3091 u32 rs = reg[(opcode >> 8) & 0x0F].I;
3092 s64 m = (s32)reg[(opcode & 0x0F)].I;
3093 s64 s = (s32)rs;
3094 s64 sTemp = (u64)reg[destHi].I;
3095 sTemp <<= 32;
3096 sTemp |= (u64)reg[destLo].I;
3097 sTemp += m * s;
3098 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
3099 reg[destHi].I = (u32)(sTemp >> 32);
3100 if (((s32)rs) < 0)
3101 rs = ~rs;
3102 if ((rs & 0xFFFFFF00) == 0)
3103 clockTicks += 3;
3104 else if ((rs & 0xFFFF0000) == 0)
3105 clockTicks += 4;
3106 else if ((rs & 0xFF000000) == 0)
3107 clockTicks += 5;
3108 else
3109 clockTicks += 6;
3111 break;
3112 case 0x0f9:
3114 // SMLALS RdLo, RdHi, Rm, Rs
3115 int destLo = (opcode >> 12) & 0x0F;
3116 int destHi = (opcode >> 16) & 0x0F;
3117 u32 rs = reg[(opcode >> 8) & 0x0F].I;
3118 s64 m = (s32)reg[(opcode & 0x0F)].I;
3119 s64 s = (s32)rs;
3120 s64 sTemp = (u64)reg[destHi].I;
3121 sTemp <<= 32;
3122 sTemp |= (u64)reg[destLo].I;
3123 sTemp += m * s;
3124 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
3125 reg[destHi].I = (u32)(sTemp >> 32);
3126 Z_FLAG = (sTemp) ? false : true;
3127 N_FLAG = (sTemp < 0) ? true : false;
3128 if (((s32)rs) < 0)
3129 rs = ~rs;
3130 if ((rs & 0xFFFFFF00) == 0)
3131 clockTicks += 3;
3132 else if ((rs & 0xFFFF0000) == 0)
3133 clockTicks += 4;
3134 else if ((rs & 0xFF000000) == 0)
3135 clockTicks += 5;
3136 else
3137 clockTicks += 6;
3139 break;
3140 LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110);
3141 case 0x100:
3142 // MRS Rd, CPSR
3143 // TODO: check if right instruction....
3144 CPUUpdateCPSR();
3145 reg[(opcode >> 12) & 0x0F].I = reg[16].I;
3146 break;
3147 case 0x109:
3149 // SWP Rd, Rm, [Rn]
3150 u32 address = reg[(opcode >> 16) & 15].I;
3151 u32 temp = CPUReadMemory(address);
3152 CPUWriteMemory(address, reg[opcode & 15].I);
3153 reg[(opcode >> 12) & 15].I = temp;
3155 break;
3156 LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130);
3157 case 0x120:
3159 // MSR CPSR_fields, Rm
3160 CPUUpdateCPSR();
3161 u32 value = reg[opcode & 15].I;
3162 u32 newValue = reg[16].I;
3163 if (armMode > 0x10)
3165 if (opcode & 0x00010000)
3166 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3167 if (opcode & 0x00020000)
3168 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3169 if (opcode & 0x00040000)
3170 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3172 if (opcode & 0x00080000)
3173 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3174 newValue |= 0x10;
3175 CPUSwitchMode(newValue & 0x1f, false);
3176 reg[16].I = newValue;
3177 CPUUpdateFlags();
3179 break;
3180 case 0x121:
3182 // BX Rm
3183 // TODO: check if right instruction...
3184 clockTicks += 3;
3185 int base = opcode & 0x0F;
3186 armState = reg[base].I & 1 ? false : true;
3187 if (armState)
3189 reg[15].I = reg[base].I & 0xFFFFFFFC;
3190 armNextPC = reg[15].I;
3191 reg[15].I += 4;
3193 else
3195 reg[15].I = reg[base].I & 0xFFFFFFFE;
3196 armNextPC = reg[15].I;
3197 reg[15].I += 2;
3200 break;
3201 ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150);
3202 case 0x140:
3203 // MRS Rd, SPSR
3204 // TODO: check if right instruction...
3205 reg[(opcode >> 12) & 0x0F].I = reg[17].I;
3206 break;
3207 case 0x149:
3209 // SWPB Rd, Rm, [Rn]
3210 u32 address = reg[(opcode >> 16) & 15].I;
3211 u32 temp = CPUReadByte(address);
3212 CPUWriteByte(address, reg[opcode & 15].B.B0);
3213 reg[(opcode >> 12) & 15].I = temp;
3215 break;
3216 ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170);
3217 case 0x160:
3219 // MSR SPSR_fields, Rm
3220 u32 value = reg[opcode & 15].I;
3221 if (armMode > 0x10 && armMode < 0x1f)
3223 if (opcode & 0x00010000)
3224 reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3225 if (opcode & 0x00020000)
3226 reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3227 if (opcode & 0x00040000)
3228 reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3229 if (opcode & 0x00080000)
3230 reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3233 break;
3234 LOGICAL_DATA_OPCODE(OP_ORR, OP_ORR, 0x180);
3235 LOGICAL_DATA_OPCODE(OP_ORRS, OP_ORR, 0x190);
3236 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV, OP_MOV, 0x1a0);
3237 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0);
3238 LOGICAL_DATA_OPCODE(OP_BIC, OP_BIC, 0x1c0);
3239 LOGICAL_DATA_OPCODE(OP_BICS, OP_BIC, 0x1d0);
3240 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN, OP_MVN, 0x1e0);
3241 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0);
3242 #ifdef BKPT_SUPPORT
3243 case 0x127:
3244 case 0x7ff: // for GDB support
3245 extern void (*dbgSignal)(int, int);
3246 reg[15].I -= 4;
3247 armNextPC -= 4;
3248 dbgSignal(5, (opcode & 0x0f) | ((opcode >> 4) & 0xfff0));
3249 return;
3250 #endif
3251 case 0x320:
3252 case 0x321:
3253 case 0x322:
3254 case 0x323:
3255 case 0x324:
3256 case 0x325:
3257 case 0x326:
3258 case 0x327:
3259 case 0x328:
3260 case 0x329:
3261 case 0x32a:
3262 case 0x32b:
3263 case 0x32c:
3264 case 0x32d:
3265 case 0x32e:
3266 case 0x32f:
3268 // MSR CPSR_fields, #
3269 CPUUpdateCPSR();
3270 u32 value = opcode & 0xFF;
3271 int shift = (opcode & 0xF00) >> 7;
3272 if (shift)
3274 ROR_IMM_MSR;
3276 u32 newValue = reg[16].I;
3277 if (armMode > 0x10)
3279 if (opcode & 0x00010000)
3280 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3281 if (opcode & 0x00020000)
3282 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3283 if (opcode & 0x00040000)
3284 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3286 if (opcode & 0x00080000)
3287 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3289 newValue |= 0x10;
3291 CPUSwitchMode(newValue & 0x1f, false);
3292 reg[16].I = newValue;
3293 CPUUpdateFlags();
3295 break;
3296 case 0x360:
3297 case 0x361:
3298 case 0x362:
3299 case 0x363:
3300 case 0x364:
3301 case 0x365:
3302 case 0x366:
3303 case 0x367:
3304 case 0x368:
3305 case 0x369:
3306 case 0x36a:
3307 case 0x36b:
3308 case 0x36c:
3309 case 0x36d:
3310 case 0x36e:
3311 case 0x36f:
3313 // MSR SPSR_fields, #
3314 if (armMode > 0x10 && armMode < 0x1f)
3316 u32 value = opcode & 0xFF;
3317 int shift = (opcode & 0xF00) >> 7;
3318 if (shift)
3320 ROR_IMM_MSR;
3322 if (opcode & 0x00010000)
3323 reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3324 if (opcode & 0x00020000)
3325 reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3326 if (opcode & 0x00040000)
3327 reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3328 if (opcode & 0x00080000)
3329 reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3332 break;
3333 CASE_16(0x400)
3334 // T versions shouldn't be different on GBA
3335 CASE_16(0x420)
3337 // STR Rd, [Rn], -#
3338 int offset = opcode & 0xFFF;
3339 int dest = (opcode >> 12) & 15;
3340 int base = (opcode >> 16) & 15;
3341 u32 address = reg[base].I;
3342 CPUWriteMemory(address, reg[dest].I);
3343 reg[base].I = address - offset;
3344 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3346 break;
3347 CASE_16(0x480)
3348 // T versions shouldn't be different on GBA
3349 CASE_16(0x4a0)
3351 // STR Rd, [Rn], #
3352 int offset = opcode & 0xFFF;
3353 int dest = (opcode >> 12) & 15;
3354 int base = (opcode >> 16) & 15;
3355 u32 address = reg[base].I;
3356 CPUWriteMemory(address, reg[dest].I);
3357 reg[base].I = address + offset;
3358 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3360 break;
3361 CASE_16(0x500)
3363 // STR Rd, [Rn, -#]
3364 int offset = opcode & 0xFFF;
3365 int dest = (opcode >> 12) & 15;
3366 int base = (opcode >> 16) & 15;
3367 u32 address = reg[base].I - offset;
3368 CPUWriteMemory(address, reg[dest].I);
3369 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3371 break;
3372 CASE_16(0x520)
3374 // STR Rd, [Rn, -#]!
3375 int offset = opcode & 0xFFF;
3376 int dest = (opcode >> 12) & 15;
3377 int base = (opcode >> 16) & 15;
3378 u32 address = reg[base].I - offset;
3379 reg[base].I = address;
3380 CPUWriteMemory(address, reg[dest].I);
3381 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3383 break;
3384 CASE_16(0x580)
3386 // STR Rd, [Rn, #]
3387 int offset = opcode & 0xFFF;
3388 int dest = (opcode >> 12) & 15;
3389 int base = (opcode >> 16) & 15;
3390 u32 address = reg[base].I + offset;
3391 CPUWriteMemory(address, reg[dest].I);
3392 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3394 break;
3395 CASE_16(0x5a0)
3397 // STR Rd, [Rn, #]!
3398 int offset = opcode & 0xFFF;
3399 int dest = (opcode >> 12) & 15;
3400 int base = (opcode >> 16) & 15;
3401 u32 address = reg[base].I + offset;
3402 reg[base].I = address;
3403 CPUWriteMemory(address, reg[dest].I);
3404 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3406 break;
3407 CASE_16(0x410)
3409 // LDR Rd, [Rn], -#
3410 int offset = opcode & 0xFFF;
3411 int dest = (opcode >> 12) & 15;
3412 int base = (opcode >> 16) & 15;
3413 u32 address = reg[base].I;
3414 reg[dest].I = CPUReadMemory(address);
3415 if (dest != base)
3416 reg[base].I -= offset;
3417 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3418 if (dest == 15)
3420 clockTicks += 2;
3421 reg[15].I &= 0xFFFFFFFC;
3422 armNextPC = reg[15].I;
3423 reg[15].I += 4;
3426 break;
3427 CASE_16(0x430)
3429 // LDRT Rd, [Rn], -#
3430 int offset = opcode & 0xFFF;
3431 int dest = (opcode >> 12) & 15;
3432 int base = (opcode >> 16) & 15;
3433 u32 address = reg[base].I;
3434 reg[dest].I = CPUReadMemory(address);
3435 if (dest != base)
3436 reg[base].I -= offset;
3437 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3439 break;
3440 CASE_16(0x490)
3442 // LDR Rd, [Rn], #
3443 int offset = opcode & 0xFFF;
3444 int dest = (opcode >> 12) & 15;
3445 int base = (opcode >> 16) & 15;
3446 u32 address = reg[base].I;
3447 reg[dest].I = CPUReadMemory(address);
3448 if (dest != base)
3449 reg[base].I += offset;
3450 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3451 if (dest == 15)
3453 clockTicks += 2;
3454 reg[15].I &= 0xFFFFFFFC;
3455 armNextPC = reg[15].I;
3456 reg[15].I += 4;
3459 break;
3460 CASE_16(0x4b0)
3462 // LDRT Rd, [Rn], #
3463 int offset = opcode & 0xFFF;
3464 int dest = (opcode >> 12) & 15;
3465 int base = (opcode >> 16) & 15;
3466 u32 address = reg[base].I;
3467 reg[dest].I = CPUReadMemory(address);
3468 if (dest != base)
3469 reg[base].I += offset;
3470 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3472 break;
3473 CASE_16(0x510)
3475 // LDR Rd, [Rn, -#]
3476 int offset = opcode & 0xFFF;
3477 int dest = (opcode >> 12) & 15;
3478 int base = (opcode >> 16) & 15;
3479 u32 address = reg[base].I - offset;
3480 reg[dest].I = CPUReadMemory(address);
3481 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3482 if (dest == 15)
3484 clockTicks += 2;
3485 reg[15].I &= 0xFFFFFFFC;
3486 armNextPC = reg[15].I;
3487 reg[15].I += 4;
3490 break;
3491 CASE_16(0x530)
3493 // LDR Rd, [Rn, -#]!
3494 int offset = opcode & 0xFFF;
3495 int dest = (opcode >> 12) & 15;
3496 int base = (opcode >> 16) & 15;
3497 u32 address = reg[base].I - offset;
3498 reg[dest].I = CPUReadMemory(address);
3499 if (dest != base)
3500 reg[base].I = address;
3501 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3502 if (dest == 15)
3504 clockTicks += 2;
3505 reg[15].I &= 0xFFFFFFFC;
3506 armNextPC = reg[15].I;
3507 reg[15].I += 4;
3510 break;
3511 CASE_16(0x590)
3513 // LDR Rd, [Rn, #]
3514 int offset = opcode & 0xFFF;
3515 int dest = (opcode >> 12) & 15;
3516 int base = (opcode >> 16) & 15;
3517 u32 address = reg[base].I + offset;
3518 reg[dest].I = CPUReadMemory(address);
3519 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3520 if (dest == 15)
3522 clockTicks += 2;
3523 reg[15].I &= 0xFFFFFFFC;
3524 armNextPC = reg[15].I;
3525 reg[15].I += 4;
3528 break;
3529 CASE_16(0x5b0)
3531 // LDR Rd, [Rn, #]!
3532 int offset = opcode & 0xFFF;
3533 int dest = (opcode >> 12) & 15;
3534 int base = (opcode >> 16) & 15;
3535 u32 address = reg[base].I + offset;
3536 reg[dest].I = CPUReadMemory(address);
3537 if (dest != base)
3538 reg[base].I = address;
3539 clockTicks += 3 + CPUUpdateTicksAccess32(address);
3540 if (dest == 15)
3542 clockTicks += 2;
3543 reg[15].I &= 0xFFFFFFFC;
3544 armNextPC = reg[15].I;
3545 reg[15].I += 4;
3548 break;
3549 CASE_16(0x440)
3550 // T versions shouldn't be different on GBA
3551 CASE_16(0x460)
3553 // STRB Rd, [Rn], -#
3554 int offset = opcode & 0xFFF;
3555 int dest = (opcode >> 12) & 15;
3556 int base = (opcode >> 16) & 15;
3557 u32 address = reg[base].I;
3558 CPUWriteByte(address, reg[dest].B.B0);
3559 reg[base].I = address - offset;
3560 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3562 break;
3563 CASE_16(0x4c0)
3564 // T versions shouldn't be different on GBA
3565 CASE_16(0x4e0)
3566 // STRB Rd, [Rn], #
3568 int offset = opcode & 0xFFF;
3569 int dest = (opcode >> 12) & 15;
3570 int base = (opcode >> 16) & 15;
3571 u32 address = reg[base].I;
3572 CPUWriteByte(address, reg[dest].B.B0);
3573 reg[base].I = address + offset;
3574 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3576 break;
3577 CASE_16(0x540)
3579 // STRB Rd, [Rn, -#]
3580 int offset = opcode & 0xFFF;
3581 int dest = (opcode >> 12) & 15;
3582 int base = (opcode >> 16) & 15;
3583 u32 address = reg[base].I - offset;
3584 CPUWriteByte(address, reg[dest].B.B0);
3585 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3587 break;
3588 CASE_16(0x560)
3590 // STRB Rd, [Rn, -#]!
3591 int offset = opcode & 0xFFF;
3592 int dest = (opcode >> 12) & 15;
3593 int base = (opcode >> 16) & 15;
3594 u32 address = reg[base].I - offset;
3595 reg[base].I = address;
3596 CPUWriteByte(address, reg[dest].B.B0);
3597 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3599 break;
3600 CASE_16(0x5c0)
3602 // STRB Rd, [Rn, #]
3603 int offset = opcode & 0xFFF;
3604 int dest = (opcode >> 12) & 15;
3605 int base = (opcode >> 16) & 15;
3606 u32 address = reg[base].I + offset;
3607 CPUWriteByte(address, reg[dest].B.B0);
3608 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3610 break;
3611 CASE_16(0x5e0)
3613 // STRB Rd, [Rn, #]!
3614 int offset = opcode & 0xFFF;
3615 int dest = (opcode >> 12) & 15;
3616 int base = (opcode >> 16) & 15;
3617 u32 address = reg[base].I + offset;
3618 reg[base].I = address;
3619 CPUWriteByte(address, reg[dest].I);
3620 clockTicks += 2 + CPUUpdateTicksAccess16(address);
3622 break;
3623 CASE_16(0x450)
3624 // T versions shouldn't be different
3625 CASE_16(0x470)
3627 // LDRB Rd, [Rn], -#
3628 int offset = opcode & 0xFFF;
3629 int dest = (opcode >> 12) & 15;
3630 int base = (opcode >> 16) & 15;
3631 u32 address = reg[base].I;
3632 reg[dest].I = CPUReadByte(address);
3633 if (dest != base)
3634 reg[base].I -= offset;
3635 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3637 break;
3638 CASE_16(0x4d0)
3639 CASE_16(0x4f0) // T versions should not be different
3641 // LDRB Rd, [Rn], #
3642 int offset = opcode & 0xFFF;
3643 int dest = (opcode >> 12) & 15;
3644 int base = (opcode >> 16) & 15;
3645 u32 address = reg[base].I;
3646 reg[dest].I = CPUReadByte(address);
3647 if (dest != base)
3648 reg[base].I += offset;
3649 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3651 break;
3652 CASE_16(0x550)
3654 // LDRB Rd, [Rn, -#]
3655 int offset = opcode & 0xFFF;
3656 int dest = (opcode >> 12) & 15;
3657 int base = (opcode >> 16) & 15;
3658 u32 address = reg[base].I - offset;
3659 reg[dest].I = CPUReadByte(address);
3660 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3662 break;
3663 CASE_16(0x570)
3665 // LDRB Rd, [Rn, -#]!
3666 int offset = opcode & 0xFFF;
3667 int dest = (opcode >> 12) & 15;
3668 int base = (opcode >> 16) & 15;
3669 u32 address = reg[base].I - offset;
3670 reg[dest].I = CPUReadByte(address);
3671 if (dest != base)
3672 reg[base].I = address;
3673 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3675 break;
3676 CASE_16(0x5d0)
3678 // LDRB Rd, [Rn, #]
3679 int offset = opcode & 0xFFF;
3680 int dest = (opcode >> 12) & 15;
3681 int base = (opcode >> 16) & 15;
3682 u32 address = reg[base].I + offset;
3683 reg[dest].I = CPUReadByte(address);
3684 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3686 break;
3687 CASE_16(0x5f0)
3689 // LDRB Rd, [Rn, #]!
3690 int offset = opcode & 0xFFF;
3691 int dest = (opcode >> 12) & 15;
3692 int base = (opcode >> 16) & 15;
3693 u32 address = reg[base].I + offset;
3694 reg[dest].I = CPUReadByte(address);
3695 if (dest != base)
3696 reg[base].I = address;
3697 clockTicks += 3 + CPUUpdateTicksAccess16(address);
3699 break;
3700 case 0x600:
3701 case 0x608:
3702 // T versions are the same
3703 case 0x620:
3704 case 0x628:
3706 // STR Rd, [Rn], -Rm, LSL #
3707 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
3708 int dest = (opcode >> 12) & 15;
3709 int base = (opcode >> 16) & 15;
3710 u32 address = reg[base].I;
3711 CPUWriteMemory(address, reg[dest].I);
3712 reg[base].I = address - offset;
3713 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3715 break;
3716 case 0x602:
3717 case 0x60a:
3718 // T versions are the same
3719 case 0x622:
3720 case 0x62a:
3722 // STR Rd, [Rn], -Rm, LSR #
3723 int shift = (opcode >> 7) & 31;
3724 int offset = shift ? reg[opcode & 15].I >> shift : 0;
3725 int dest = (opcode >> 12) & 15;
3726 int base = (opcode >> 16) & 15;
3727 u32 address = reg[base].I;
3728 CPUWriteMemory(address, reg[dest].I);
3729 reg[base].I = address - offset;
3730 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3732 break;
3733 case 0x604:
3734 case 0x60c:
3735 // T versions are the same
3736 case 0x624:
3737 case 0x62c:
3739 // STR Rd, [Rn], -Rm, ASR #
3740 int shift = (opcode >> 7) & 31;
3741 int offset;
3742 if (shift)
3743 offset = (int)((s32)reg[opcode & 15].I >> shift);
3744 else if (reg[opcode & 15].I & 0x80000000)
3745 offset = 0xFFFFFFFF;
3746 else
3747 offset = 0;
3748 int dest = (opcode >> 12) & 15;
3749 int base = (opcode >> 16) & 15;
3750 u32 address = reg[base].I;
3751 CPUWriteMemory(address, reg[dest].I);
3752 reg[base].I = address - offset;
3753 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3755 break;
3756 case 0x606:
3757 case 0x60e:
3758 // T versions are the same
3759 case 0x626:
3760 case 0x62e:
3762 // STR Rd, [Rn], -Rm, ROR #
3763 int shift = (opcode >> 7) & 31;
3764 u32 value = reg[opcode & 15].I;
3765 if (shift)
3767 ROR_VALUE;
3769 else
3771 RCR_VALUE;
3773 int dest = (opcode >> 12) & 15;
3774 int base = (opcode >> 16) & 15;
3775 u32 address = reg[base].I;
3776 CPUWriteMemory(address, reg[dest].I);
3777 reg[base].I = address - value;
3778 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3780 break;
3781 case 0x680:
3782 case 0x688:
3783 // T versions are the same
3784 case 0x6a0:
3785 case 0x6a8:
3787 // STR Rd, [Rn], Rm, LSL #
3788 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
3789 int dest = (opcode >> 12) & 15;
3790 int base = (opcode >> 16) & 15;
3791 u32 address = reg[base].I;
3792 CPUWriteMemory(address, reg[dest].I);
3793 reg[base].I = address + offset;
3794 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3796 break;
3797 case 0x682:
3798 case 0x68a:
3799 // T versions are the same
3800 case 0x6a2:
3801 case 0x6aa:
3803 // STR Rd, [Rn], Rm, LSR #
3804 int shift = (opcode >> 7) & 31;
3805 int offset = shift ? reg[opcode & 15].I >> shift : 0;
3806 int dest = (opcode >> 12) & 15;
3807 int base = (opcode >> 16) & 15;
3808 u32 address = reg[base].I;
3809 CPUWriteMemory(address, reg[dest].I);
3810 reg[base].I = address + offset;
3811 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3813 break;
3814 case 0x684:
3815 case 0x68c:
3816 // T versions are the same
3817 case 0x6a4:
3818 case 0x6ac:
3820 // STR Rd, [Rn], Rm, ASR #
3821 int shift = (opcode >> 7) & 31;
3822 int offset;
3823 if (shift)
3824 offset = (int)((s32)reg[opcode & 15].I >> shift);
3825 else if (reg[opcode & 15].I & 0x80000000)
3826 offset = 0xFFFFFFFF;
3827 else
3828 offset = 0;
3829 int dest = (opcode >> 12) & 15;
3830 int base = (opcode >> 16) & 15;
3831 u32 address = reg[base].I;
3832 CPUWriteMemory(address, reg[dest].I);
3833 reg[base].I = address + offset;
3834 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3836 break;
3837 case 0x686:
3838 case 0x68e:
3839 // T versions are the same
3840 case 0x6a6:
3841 case 0x6ae:
3843 // STR Rd, [Rn], Rm, ROR #
3844 int shift = (opcode >> 7) & 31;
3845 u32 value = reg[opcode & 15].I;
3846 if (shift)
3848 ROR_VALUE;
3850 else
3852 RCR_VALUE;
3854 int dest = (opcode >> 12) & 15;
3855 int base = (opcode >> 16) & 15;
3856 u32 address = reg[base].I;
3857 CPUWriteMemory(address, reg[dest].I);
3858 reg[base].I = address + value;
3859 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3861 break;
3862 case 0x700:
3863 case 0x708:
3865 // STR Rd, [Rn, -Rm, LSL #]
3866 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
3867 int dest = (opcode >> 12) & 15;
3868 int base = (opcode >> 16) & 15;
3869 u32 address = reg[base].I - offset;
3870 CPUWriteMemory(address, reg[dest].I);
3871 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3873 break;
3874 case 0x702:
3875 case 0x70a:
3877 // STR Rd, [Rn, -Rm, LSR #]
3878 int shift = (opcode >> 7) & 31;
3879 int offset = shift ? reg[opcode & 15].I >> shift : 0;
3880 int dest = (opcode >> 12) & 15;
3881 int base = (opcode >> 16) & 15;
3882 u32 address = reg[base].I - offset;
3883 CPUWriteMemory(address, reg[dest].I);
3884 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3886 break;
3887 case 0x704:
3888 case 0x70c:
3890 // STR Rd, [Rn, -Rm, ASR #]
3891 int shift = (opcode >> 7) & 31;
3892 int offset;
3893 if (shift)
3894 offset = (int)((s32)reg[opcode & 15].I >> shift);
3895 else if (reg[opcode & 15].I & 0x80000000)
3896 offset = 0xFFFFFFFF;
3897 else
3898 offset = 0;
3899 int dest = (opcode >> 12) & 15;
3900 int base = (opcode >> 16) & 15;
3901 u32 address = reg[base].I - offset;
3902 CPUWriteMemory(address, reg[dest].I);
3903 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3905 break;
3906 case 0x706:
3907 case 0x70e:
3909 // STR Rd, [Rn, -Rm, ROR #]
3910 int shift = (opcode >> 7) & 31;
3911 u32 value = reg[opcode & 15].I;
3912 if (shift)
3914 ROR_VALUE;
3916 else
3918 RCR_VALUE;
3920 int dest = (opcode >> 12) & 15;
3921 int base = (opcode >> 16) & 15;
3922 u32 address = reg[base].I - value;
3923 CPUWriteMemory(address, reg[dest].I);
3924 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3926 break;
3927 case 0x720:
3928 case 0x728:
3930 // STR Rd, [Rn, -Rm, LSL #]!
3931 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
3932 int dest = (opcode >> 12) & 15;
3933 int base = (opcode >> 16) & 15;
3934 u32 address = reg[base].I - offset;
3935 reg[base].I = address;
3936 CPUWriteMemory(address, reg[dest].I);
3937 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3939 break;
3940 case 0x722:
3941 case 0x72a:
3943 // STR Rd, [Rn, -Rm, LSR #]!
3944 int shift = (opcode >> 7) & 31;
3945 int offset = shift ? reg[opcode & 15].I >> shift : 0;
3946 int dest = (opcode >> 12) & 15;
3947 int base = (opcode >> 16) & 15;
3948 u32 address = reg[base].I - offset;
3949 reg[base].I = address;
3950 CPUWriteMemory(address, reg[dest].I);
3951 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3953 break;
3954 case 0x724:
3955 case 0x72c:
3957 // STR Rd, [Rn, -Rm, ASR #]!
3958 int shift = (opcode >> 7) & 31;
3959 int offset;
3960 if (shift)
3961 offset = (int)((s32)reg[opcode & 15].I >> shift);
3962 else if (reg[opcode & 15].I & 0x80000000)
3963 offset = 0xFFFFFFFF;
3964 else
3965 offset = 0;
3966 int dest = (opcode >> 12) & 15;
3967 int base = (opcode >> 16) & 15;
3968 u32 address = reg[base].I - offset;
3969 reg[base].I = address;
3970 CPUWriteMemory(address, reg[dest].I);
3971 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3973 break;
3974 case 0x726:
3975 case 0x72e:
3977 // STR Rd, [Rn, -Rm, ROR #]!
3978 int shift = (opcode >> 7) & 31;
3979 u32 value = reg[opcode & 15].I;
3980 if (shift)
3982 ROR_VALUE;
3984 else
3986 RCR_VALUE;
3988 int dest = (opcode >> 12) & 15;
3989 int base = (opcode >> 16) & 15;
3990 u32 address = reg[base].I - value;
3991 reg[base].I = address;
3992 CPUWriteMemory(address, reg[dest].I);
3993 clockTicks += 2 + CPUUpdateTicksAccess32(address);
3995 break;
3996 case 0x780:
3997 case 0x788:
3999 // STR Rd, [Rn, Rm, LSL #]
4000 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4001 int dest = (opcode >> 12) & 15;
4002 int base = (opcode >> 16) & 15;
4003 u32 address = reg[base].I + offset;
4004 CPUWriteMemory(address, reg[dest].I);
4005 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4007 break;
4008 case 0x782:
4009 case 0x78a:
4011 // STR Rd, [Rn, Rm, LSR #]
4012 int shift = (opcode >> 7) & 31;
4013 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4014 int dest = (opcode >> 12) & 15;
4015 int base = (opcode >> 16) & 15;
4016 u32 address = reg[base].I + offset;
4017 CPUWriteMemory(address, reg[dest].I);
4018 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4020 break;
4021 case 0x784:
4022 case 0x78c:
4024 // STR Rd, [Rn, Rm, ASR #]
4025 int shift = (opcode >> 7) & 31;
4026 int offset;
4027 if (shift)
4028 offset = (int)((s32)reg[opcode & 15].I >> shift);
4029 else if (reg[opcode & 15].I & 0x80000000)
4030 offset = 0xFFFFFFFF;
4031 else
4032 offset = 0;
4033 int dest = (opcode >> 12) & 15;
4034 int base = (opcode >> 16) & 15;
4035 u32 address = reg[base].I + offset;
4036 CPUWriteMemory(address, reg[dest].I);
4037 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4039 break;
4040 case 0x786:
4041 case 0x78e:
4043 // STR Rd, [Rn, Rm, ROR #]
4044 int shift = (opcode >> 7) & 31;
4045 u32 value = reg[opcode & 15].I;
4046 if (shift)
4048 ROR_VALUE;
4050 else
4052 RCR_VALUE;
4054 int dest = (opcode >> 12) & 15;
4055 int base = (opcode >> 16) & 15;
4056 u32 address = reg[base].I + value;
4057 CPUWriteMemory(address, reg[dest].I);
4058 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4060 break;
4061 case 0x7a0:
4062 case 0x7a8:
4064 // STR Rd, [Rn, Rm, LSL #]!
4065 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4066 int dest = (opcode >> 12) & 15;
4067 int base = (opcode >> 16) & 15;
4068 u32 address = reg[base].I + offset;
4069 reg[base].I = address;
4070 CPUWriteMemory(address, reg[dest].I);
4071 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4073 break;
4074 case 0x7a2:
4075 case 0x7aa:
4077 // STR Rd, [Rn, Rm, LSR #]!
4078 int shift = (opcode >> 7) & 31;
4079 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4080 int dest = (opcode >> 12) & 15;
4081 int base = (opcode >> 16) & 15;
4082 u32 address = reg[base].I + offset;
4083 reg[base].I = address;
4084 CPUWriteMemory(address, reg[dest].I);
4085 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4087 break;
4088 case 0x7a4:
4089 case 0x7ac:
4091 // STR Rd, [Rn, Rm, ASR #]!
4092 int shift = (opcode >> 7) & 31;
4093 int offset;
4094 if (shift)
4095 offset = (int)((s32)reg[opcode & 15].I >> shift);
4096 else if (reg[opcode & 15].I & 0x80000000)
4097 offset = 0xFFFFFFFF;
4098 else
4099 offset = 0;
4100 int dest = (opcode >> 12) & 15;
4101 int base = (opcode >> 16) & 15;
4102 u32 address = reg[base].I + offset;
4103 reg[base].I = address;
4104 CPUWriteMemory(address, reg[dest].I);
4105 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4107 break;
4108 case 0x7a6:
4109 case 0x7ae:
4111 // STR Rd, [Rn, Rm, ROR #]!
4112 int shift = (opcode >> 7) & 31;
4113 u32 value = reg[opcode & 15].I;
4114 if (shift)
4116 ROR_VALUE;
4118 else
4120 RCR_VALUE;
4122 int dest = (opcode >> 12) & 15;
4123 int base = (opcode >> 16) & 15;
4124 u32 address = reg[base].I + value;
4125 reg[base].I = address;
4126 CPUWriteMemory(address, reg[dest].I);
4127 clockTicks += 2 + CPUUpdateTicksAccess32(address);
4129 break;
4130 case 0x610:
4131 case 0x618:
4132 // T versions are the same
4133 case 0x630:
4134 case 0x638:
4136 // LDR Rd, [Rn], -Rm, LSL #
4137 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4138 int dest = (opcode >> 12) & 15;
4139 int base = (opcode >> 16) & 15;
4140 u32 address = reg[base].I;
4141 reg[dest].I = CPUReadMemory(address);
4142 if (dest != base)
4143 reg[base].I = address - offset;
4144 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4145 if (dest == 15)
4147 clockTicks += 2;
4148 reg[15].I &= 0xFFFFFFFC;
4149 armNextPC = reg[15].I;
4150 reg[15].I += 4;
4153 break;
4154 case 0x612:
4155 case 0x61a:
4156 // T versions are the same
4157 case 0x632:
4158 case 0x63a:
4160 // LDR Rd, [Rn], -Rm, LSR #
4161 int shift = (opcode >> 7) & 31;
4162 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4163 int dest = (opcode >> 12) & 15;
4164 int base = (opcode >> 16) & 15;
4165 u32 address = reg[base].I;
4166 reg[dest].I = CPUReadMemory(address);
4167 if (dest != base)
4168 reg[base].I = address - offset;
4169 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4170 if (dest == 15)
4172 clockTicks += 2;
4173 reg[15].I &= 0xFFFFFFFC;
4174 armNextPC = reg[15].I;
4175 reg[15].I += 4;
4178 break;
4179 case 0x614:
4180 case 0x61c:
4181 // T versions are the same
4182 case 0x634:
4183 case 0x63c:
4185 // LDR Rd, [Rn], -Rm, ASR #
4186 int shift = (opcode >> 7) & 31;
4187 int offset;
4188 if (shift)
4189 offset = (int)((s32)reg[opcode & 15].I >> shift);
4190 else if (reg[opcode & 15].I & 0x80000000)
4191 offset = 0xFFFFFFFF;
4192 else
4193 offset = 0;
4194 int dest = (opcode >> 12) & 15;
4195 int base = (opcode >> 16) & 15;
4196 u32 address = reg[base].I;
4197 reg[dest].I = CPUReadMemory(address);
4198 if (dest != base)
4199 reg[base].I = address - offset;
4200 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4201 if (dest == 15)
4203 clockTicks += 2;
4204 reg[15].I &= 0xFFFFFFFC;
4205 armNextPC = reg[15].I;
4206 reg[15].I += 4;
4209 break;
4210 case 0x616:
4211 case 0x61e:
4212 // T versions are the same
4213 case 0x636:
4214 case 0x63e:
4216 // LDR Rd, [Rn], -Rm, ROR #
4217 int shift = (opcode >> 7) & 31;
4218 u32 value = reg[opcode & 15].I;
4219 if (shift)
4221 ROR_VALUE;
4223 else
4225 RCR_VALUE;
4227 int dest = (opcode >> 12) & 15;
4228 int base = (opcode >> 16) & 15;
4229 u32 address = reg[base].I;
4230 reg[dest].I = CPUReadMemory(address);
4231 if (dest != base)
4232 reg[base].I = address - value;
4233 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4234 if (dest == 15)
4236 clockTicks += 2;
4237 reg[15].I &= 0xFFFFFFFC;
4238 armNextPC = reg[15].I;
4239 reg[15].I += 4;
4242 break;
4243 case 0x690:
4244 case 0x698:
4245 // T versions are the same
4246 case 0x6b0:
4247 case 0x6b8:
4249 // LDR Rd, [Rn], Rm, LSL #
4250 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4251 int dest = (opcode >> 12) & 15;
4252 int base = (opcode >> 16) & 15;
4253 u32 address = reg[base].I;
4254 reg[dest].I = CPUReadMemory(address);
4255 if (dest != base)
4256 reg[base].I = address + offset;
4257 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4258 if (dest == 15)
4260 clockTicks += 2;
4261 reg[15].I &= 0xFFFFFFFC;
4262 armNextPC = reg[15].I;
4263 reg[15].I += 4;
4266 break;
4267 case 0x692:
4268 case 0x69a:
4269 // T versions are the same
4270 case 0x6b2:
4271 case 0x6ba:
4273 // LDR Rd, [Rn], Rm, LSR #
4274 int shift = (opcode >> 7) & 31;
4275 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4276 int dest = (opcode >> 12) & 15;
4277 int base = (opcode >> 16) & 15;
4278 u32 address = reg[base].I;
4279 reg[dest].I = CPUReadMemory(address);
4280 if (dest != base)
4281 reg[base].I = address + offset;
4282 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4283 if (dest == 15)
4285 clockTicks += 2;
4286 reg[15].I &= 0xFFFFFFFC;
4287 armNextPC = reg[15].I;
4288 reg[15].I += 4;
4291 break;
4292 case 0x694:
4293 case 0x69c:
4294 // T versions are the same
4295 case 0x6b4:
4296 case 0x6bc:
4298 // LDR Rd, [Rn], Rm, ASR #
4299 int shift = (opcode >> 7) & 31;
4300 int offset;
4301 if (shift)
4302 offset = (int)((s32)reg[opcode & 15].I >> shift);
4303 else if (reg[opcode & 15].I & 0x80000000)
4304 offset = 0xFFFFFFFF;
4305 else
4306 offset = 0;
4307 int dest = (opcode >> 12) & 15;
4308 int base = (opcode >> 16) & 15;
4309 u32 address = reg[base].I;
4310 reg[dest].I = CPUReadMemory(address);
4311 if (dest != base)
4312 reg[base].I = address + offset;
4313 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4314 if (dest == 15)
4316 clockTicks += 2;
4317 reg[15].I &= 0xFFFFFFFC;
4318 armNextPC = reg[15].I;
4319 reg[15].I += 4;
4322 break;
4323 case 0x696:
4324 case 0x69e:
4325 // T versions are the same
4326 case 0x6b6:
4327 case 0x6be:
4329 // LDR Rd, [Rn], Rm, ROR #
4330 int shift = (opcode >> 7) & 31;
4331 u32 value = reg[opcode & 15].I;
4332 if (shift)
4334 ROR_VALUE;
4336 else
4338 RCR_VALUE;
4340 int dest = (opcode >> 12) & 15;
4341 int base = (opcode >> 16) & 15;
4342 u32 address = reg[base].I;
4343 reg[dest].I = CPUReadMemory(address);
4344 if (dest != base)
4345 reg[base].I = address + value;
4346 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4347 if (dest == 15)
4349 clockTicks += 2;
4350 reg[15].I &= 0xFFFFFFFC;
4351 armNextPC = reg[15].I;
4352 reg[15].I += 4;
4355 break;
4356 case 0x710:
4357 case 0x718:
4359 // LDR Rd, [Rn, -Rm, LSL #]
4360 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4361 int dest = (opcode >> 12) & 15;
4362 int base = (opcode >> 16) & 15;
4363 u32 address = reg[base].I - offset;
4364 reg[dest].I = CPUReadMemory(address);
4365 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4366 if (dest == 15)
4368 clockTicks += 2;
4369 reg[15].I &= 0xFFFFFFFC;
4370 armNextPC = reg[15].I;
4371 reg[15].I += 4;
4374 break;
4375 case 0x712:
4376 case 0x71a:
4378 // LDR Rd, [Rn, -Rm, LSR #]
4379 int shift = (opcode >> 7) & 31;
4380 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4381 int dest = (opcode >> 12) & 15;
4382 int base = (opcode >> 16) & 15;
4383 u32 address = reg[base].I - offset;
4384 reg[dest].I = CPUReadMemory(address);
4385 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4386 if (dest == 15)
4388 clockTicks += 2;
4389 reg[15].I &= 0xFFFFFFFC;
4390 armNextPC = reg[15].I;
4391 reg[15].I += 4;
4394 break;
4395 case 0x714:
4396 case 0x71c:
4398 // LDR Rd, [Rn, -Rm, ASR #]
4399 int shift = (opcode >> 7) & 31;
4400 int offset;
4401 if (shift)
4402 offset = (int)((s32)reg[opcode & 15].I >> shift);
4403 else if (reg[opcode & 15].I & 0x80000000)
4404 offset = 0xFFFFFFFF;
4405 else
4406 offset = 0;
4407 int dest = (opcode >> 12) & 15;
4408 int base = (opcode >> 16) & 15;
4409 u32 address = reg[base].I - offset;
4410 reg[dest].I = CPUReadMemory(address);
4411 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4412 if (dest == 15)
4414 clockTicks += 2;
4415 reg[15].I &= 0xFFFFFFFC;
4416 armNextPC = reg[15].I;
4417 reg[15].I += 4;
4420 break;
4421 case 0x716:
4422 case 0x71e:
4424 // LDR Rd, [Rn, -Rm, ROR #]
4425 int shift = (opcode >> 7) & 31;
4426 u32 value = reg[opcode & 15].I;
4427 if (shift)
4429 ROR_VALUE;
4431 else
4433 RCR_VALUE;
4435 int dest = (opcode >> 12) & 15;
4436 int base = (opcode >> 16) & 15;
4437 u32 address = reg[base].I - value;
4438 reg[dest].I = CPUReadMemory(address);
4439 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4440 if (dest == 15)
4442 clockTicks += 2;
4443 reg[15].I &= 0xFFFFFFFC;
4444 armNextPC = reg[15].I;
4445 reg[15].I += 4;
4448 break;
4449 case 0x730:
4450 case 0x738:
4452 // LDR Rd, [Rn, -Rm, LSL #]!
4453 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4454 int dest = (opcode >> 12) & 15;
4455 int base = (opcode >> 16) & 15;
4456 u32 address = reg[base].I - offset;
4457 reg[dest].I = CPUReadMemory(address);
4458 if (dest != base)
4459 reg[base].I = address;
4460 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4461 if (dest == 15)
4463 clockTicks += 2;
4464 reg[15].I &= 0xFFFFFFFC;
4465 armNextPC = reg[15].I;
4466 reg[15].I += 4;
4469 break;
4470 case 0x732:
4471 case 0x73a:
4473 // LDR Rd, [Rn, -Rm, LSR #]!
4474 int shift = (opcode >> 7) & 31;
4475 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4476 int dest = (opcode >> 12) & 15;
4477 int base = (opcode >> 16) & 15;
4478 u32 address = reg[base].I - offset;
4479 reg[dest].I = CPUReadMemory(address);
4480 if (dest != base)
4481 reg[base].I = address;
4482 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4483 if (dest == 15)
4485 clockTicks += 2;
4486 reg[15].I &= 0xFFFFFFFC;
4487 armNextPC = reg[15].I;
4488 reg[15].I += 4;
4491 break;
4492 case 0x734:
4493 case 0x73c:
4495 // LDR Rd, [Rn, -Rm, ASR #]!
4496 int shift = (opcode >> 7) & 31;
4497 int offset;
4498 if (shift)
4499 offset = (int)((s32)reg[opcode & 15].I >> shift);
4500 else if (reg[opcode & 15].I & 0x80000000)
4501 offset = 0xFFFFFFFF;
4502 else
4503 offset = 0;
4504 int dest = (opcode >> 12) & 15;
4505 int base = (opcode >> 16) & 15;
4506 u32 address = reg[base].I - offset;
4507 reg[dest].I = CPUReadMemory(address);
4508 if (dest != base)
4509 reg[base].I = address;
4510 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4511 if (dest == 15)
4513 clockTicks += 2;
4514 reg[15].I &= 0xFFFFFFFC;
4515 armNextPC = reg[15].I;
4516 reg[15].I += 4;
4519 break;
4520 case 0x736:
4521 case 0x73e:
4523 // LDR Rd, [Rn, -Rm, ROR #]!
4524 int shift = (opcode >> 7) & 31;
4525 u32 value = reg[opcode & 15].I;
4526 if (shift)
4528 ROR_VALUE;
4530 else
4532 RCR_VALUE;
4534 int dest = (opcode >> 12) & 15;
4535 int base = (opcode >> 16) & 15;
4536 u32 address = reg[base].I - value;
4537 reg[dest].I = CPUReadMemory(address);
4538 if (dest != base)
4539 reg[base].I = address;
4540 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4541 if (dest == 15)
4543 clockTicks += 2;
4544 reg[15].I &= 0xFFFFFFFC;
4545 armNextPC = reg[15].I;
4546 reg[15].I += 4;
4549 break;
4550 case 0x790:
4551 case 0x798:
4553 // LDR Rd, [Rn, Rm, LSL #]
4554 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4555 int dest = (opcode >> 12) & 15;
4556 int base = (opcode >> 16) & 15;
4557 u32 address = reg[base].I + offset;
4558 reg[dest].I = CPUReadMemory(address);
4559 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4560 if (dest == 15)
4562 clockTicks += 2;
4563 reg[15].I &= 0xFFFFFFFC;
4564 armNextPC = reg[15].I;
4565 reg[15].I += 4;
4568 break;
4569 case 0x792:
4570 case 0x79a:
4572 // LDR Rd, [Rn, Rm, LSR #]
4573 int shift = (opcode >> 7) & 31;
4574 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4575 int dest = (opcode >> 12) & 15;
4576 int base = (opcode >> 16) & 15;
4577 u32 address = reg[base].I + offset;
4578 reg[dest].I = CPUReadMemory(address);
4579 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4580 if (dest == 15)
4582 clockTicks += 2;
4583 reg[15].I &= 0xFFFFFFFC;
4584 armNextPC = reg[15].I;
4585 reg[15].I += 4;
4588 break;
4589 case 0x794:
4590 case 0x79c:
4592 // LDR Rd, [Rn, Rm, ASR #]
4593 int shift = (opcode >> 7) & 31;
4594 int offset;
4595 if (shift)
4596 offset = (int)((s32)reg[opcode & 15].I >> shift);
4597 else if (reg[opcode & 15].I & 0x80000000)
4598 offset = 0xFFFFFFFF;
4599 else
4600 offset = 0;
4601 int dest = (opcode >> 12) & 15;
4602 int base = (opcode >> 16) & 15;
4603 u32 address = reg[base].I + offset;
4604 reg[dest].I = CPUReadMemory(address);
4605 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4606 if (dest == 15)
4608 clockTicks += 2;
4609 reg[15].I &= 0xFFFFFFFC;
4610 armNextPC = reg[15].I;
4611 reg[15].I += 4;
4614 break;
4615 case 0x796:
4616 case 0x79e:
4618 // LDR Rd, [Rn, Rm, ROR #]
4619 int shift = (opcode >> 7) & 31;
4620 u32 value = reg[opcode & 15].I;
4621 if (shift)
4623 ROR_VALUE;
4625 else
4627 RCR_VALUE;
4629 int dest = (opcode >> 12) & 15;
4630 int base = (opcode >> 16) & 15;
4631 u32 address = reg[base].I + value;
4632 reg[dest].I = CPUReadMemory(address);
4633 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4634 if (dest == 15)
4636 clockTicks += 2;
4637 reg[15].I &= 0xFFFFFFFC;
4638 armNextPC = reg[15].I;
4639 reg[15].I += 4;
4642 break;
4643 case 0x7b0:
4644 case 0x7b8:
4646 // LDR Rd, [Rn, Rm, LSL #]!
4647 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4648 int dest = (opcode >> 12) & 15;
4649 int base = (opcode >> 16) & 15;
4650 u32 address = reg[base].I + offset;
4651 reg[dest].I = CPUReadMemory(address);
4652 if (dest != base)
4653 reg[base].I = address;
4654 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4655 if (dest == 15)
4657 clockTicks += 2;
4658 reg[15].I &= 0xFFFFFFFC;
4659 armNextPC = reg[15].I;
4660 reg[15].I += 4;
4663 break;
4664 case 0x7b2:
4665 case 0x7ba:
4667 // LDR Rd, [Rn, Rm, LSR #]!
4668 int shift = (opcode >> 7) & 31;
4669 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4670 int dest = (opcode >> 12) & 15;
4671 int base = (opcode >> 16) & 15;
4672 u32 address = reg[base].I + offset;
4673 reg[dest].I = CPUReadMemory(address);
4674 if (dest != base)
4675 reg[base].I = address;
4676 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4677 if (dest == 15)
4679 clockTicks += 2;
4680 reg[15].I &= 0xFFFFFFFC;
4681 armNextPC = reg[15].I;
4682 reg[15].I += 4;
4685 break;
4686 case 0x7b4:
4687 case 0x7bc:
4689 // LDR Rd, [Rn, Rm, ASR #]!
4690 int shift = (opcode >> 7) & 31;
4691 int offset;
4692 if (shift)
4693 offset = (int)((s32)reg[opcode & 15].I >> shift);
4694 else if (reg[opcode & 15].I & 0x80000000)
4695 offset = 0xFFFFFFFF;
4696 else
4697 offset = 0;
4698 int dest = (opcode >> 12) & 15;
4699 int base = (opcode >> 16) & 15;
4700 u32 address = reg[base].I + offset;
4701 reg[dest].I = CPUReadMemory(address);
4702 if (dest != base)
4703 reg[base].I = address;
4704 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4705 if (dest == 15)
4707 clockTicks += 2;
4708 reg[15].I &= 0xFFFFFFFC;
4709 armNextPC = reg[15].I;
4710 reg[15].I += 4;
4713 break;
4714 case 0x7b6:
4715 case 0x7be:
4717 // LDR Rd, [Rn, Rm, ROR #]!
4718 int shift = (opcode >> 7) & 31;
4719 u32 value = reg[opcode & 15].I;
4720 if (shift)
4722 ROR_VALUE;
4724 else
4726 RCR_VALUE;
4728 int dest = (opcode >> 12) & 15;
4729 int base = (opcode >> 16) & 15;
4730 u32 address = reg[base].I + value;
4731 reg[dest].I = CPUReadMemory(address);
4732 if (dest != base)
4733 reg[base].I = address;
4734 clockTicks += 3 + CPUUpdateTicksAccess32(address);
4735 if (dest == 15)
4737 clockTicks += 2;
4738 reg[15].I &= 0xFFFFFFFC;
4739 armNextPC = reg[15].I;
4740 reg[15].I += 4;
4743 break;
4744 case 0x640:
4745 case 0x648:
4746 // T versions are the same
4747 case 0x660:
4748 case 0x668:
4750 // STRB Rd, [Rn], -Rm, LSL #
4751 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4752 int dest = (opcode >> 12) & 15;
4753 int base = (opcode >> 16) & 15;
4754 u32 address = reg[base].I;
4755 CPUWriteByte(address, reg[dest].B.B0);
4756 reg[base].I = address - offset;
4757 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4759 break;
4760 case 0x642:
4761 case 0x64a:
4762 // T versions are the same
4763 case 0x662:
4764 case 0x66a:
4766 // STRB Rd, [Rn], -Rm, LSR #
4767 int shift = (opcode >> 7) & 31;
4768 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4769 int dest = (opcode >> 12) & 15;
4770 int base = (opcode >> 16) & 15;
4771 u32 address = reg[base].I;
4772 CPUWriteByte(address, reg[dest].B.B0);
4773 reg[base].I = address - offset;
4774 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4776 break;
4777 case 0x644:
4778 case 0x64c:
4779 // T versions are the same
4780 case 0x664:
4781 case 0x66c:
4783 // STRB Rd, [Rn], -Rm, ASR #
4784 int shift = (opcode >> 7) & 31;
4785 int offset;
4786 if (shift)
4787 offset = (int)((s32)reg[opcode & 15].I >> shift);
4788 else if (reg[opcode & 15].I & 0x80000000)
4789 offset = 0xFFFFFFFF;
4790 else
4791 offset = 0;
4792 int dest = (opcode >> 12) & 15;
4793 int base = (opcode >> 16) & 15;
4794 u32 address = reg[base].I;
4795 CPUWriteByte(address, reg[dest].B.B0);
4796 reg[base].I = address - offset;
4797 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4799 break;
4800 case 0x646:
4801 case 0x64e:
4802 // T versions are the same
4803 case 0x666:
4804 case 0x66e:
4806 // STRB Rd, [Rn], -Rm, ROR #
4807 int shift = (opcode >> 7) & 31;
4808 u32 value = reg[opcode & 15].I;
4809 if (shift)
4811 ROR_VALUE;
4813 else
4815 RCR_VALUE;
4817 int dest = (opcode >> 12) & 15;
4818 int base = (opcode >> 16) & 15;
4819 u32 address = reg[base].I;
4820 CPUWriteByte(address, reg[dest].B.B0);
4821 reg[base].I = address - value;
4822 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4824 break;
4825 case 0x6c0:
4826 case 0x6c8:
4827 // T versions are the same
4828 case 0x6e0:
4829 case 0x6e8:
4831 // STRB Rd, [Rn], Rm, LSL #
4832 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4833 int dest = (opcode >> 12) & 15;
4834 int base = (opcode >> 16) & 15;
4835 u32 address = reg[base].I;
4836 CPUWriteByte(address, reg[dest].B.B0);
4837 reg[base].I = address + offset;
4838 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4840 break;
4841 case 0x6c2:
4842 case 0x6ca:
4843 // T versions are the same
4844 case 0x6e2:
4845 case 0x6ea:
4847 // STRB Rd, [Rn], Rm, LSR #
4848 int shift = (opcode >> 7) & 31;
4849 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4850 int dest = (opcode >> 12) & 15;
4851 int base = (opcode >> 16) & 15;
4852 u32 address = reg[base].I;
4853 CPUWriteByte(address, reg[dest].B.B0);
4854 reg[base].I = address + offset;
4855 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4857 break;
4858 case 0x6c4:
4859 case 0x6cc:
4860 // T versions are the same
4861 case 0x6e4:
4862 case 0x6ec:
4864 // STR Rd, [Rn], Rm, ASR #
4865 int shift = (opcode >> 7) & 31;
4866 int offset;
4867 if (shift)
4868 offset = (int)((s32)reg[opcode & 15].I >> shift);
4869 else if (reg[opcode & 15].I & 0x80000000)
4870 offset = 0xFFFFFFFF;
4871 else
4872 offset = 0;
4873 int dest = (opcode >> 12) & 15;
4874 int base = (opcode >> 16) & 15;
4875 u32 address = reg[base].I;
4876 CPUWriteByte(address, reg[dest].B.B0);
4877 reg[base].I = address + offset;
4878 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4880 break;
4881 case 0x6c6:
4882 case 0x6ce:
4883 // T versions are the same
4884 case 0x6e6:
4885 case 0x6ee:
4887 // STRB Rd, [Rn], Rm, ROR #
4888 int shift = (opcode >> 7) & 31;
4889 u32 value = reg[opcode & 15].I;
4890 if (shift)
4892 ROR_VALUE;
4894 else
4896 RCR_VALUE;
4898 int dest = (opcode >> 12) & 15;
4899 int base = (opcode >> 16) & 15;
4900 u32 address = reg[base].I;
4901 CPUWriteByte(address, reg[dest].B.B0);
4902 reg[base].I = address + value;
4903 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4905 break;
4906 case 0x740:
4907 case 0x748:
4909 // STRB Rd, [Rn, -Rm, LSL #]
4910 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4911 int dest = (opcode >> 12) & 15;
4912 int base = (opcode >> 16) & 15;
4913 u32 address = reg[base].I - offset;
4914 CPUWriteByte(address, reg[dest].B.B0);
4915 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4917 break;
4918 case 0x742:
4919 case 0x74a:
4921 // STRB Rd, [Rn, -Rm, LSR #]
4922 int shift = (opcode >> 7) & 31;
4923 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4924 int dest = (opcode >> 12) & 15;
4925 int base = (opcode >> 16) & 15;
4926 u32 address = reg[base].I - offset;
4927 CPUWriteByte(address, reg[dest].B.B0);
4928 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4930 break;
4931 case 0x744:
4932 case 0x74c:
4934 // STRB Rd, [Rn, -Rm, ASR #]
4935 int shift = (opcode >> 7) & 31;
4936 int offset;
4937 if (shift)
4938 offset = (int)((s32)reg[opcode & 15].I >> shift);
4939 else if (reg[opcode & 15].I & 0x80000000)
4940 offset = 0xFFFFFFFF;
4941 else
4942 offset = 0;
4943 int dest = (opcode >> 12) & 15;
4944 int base = (opcode >> 16) & 15;
4945 u32 address = reg[base].I - offset;
4946 CPUWriteByte(address, reg[dest].B.B0);
4947 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4949 break;
4950 case 0x746:
4951 case 0x74e:
4953 // STRB Rd, [Rn, -Rm, ROR #]
4954 int shift = (opcode >> 7) & 31;
4955 u32 value = reg[opcode & 15].I;
4956 if (shift)
4958 ROR_VALUE;
4960 else
4962 RCR_VALUE;
4964 int dest = (opcode >> 12) & 15;
4965 int base = (opcode >> 16) & 15;
4966 u32 address = reg[base].I - value;
4967 CPUWriteByte(address, reg[dest].B.B0);
4968 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4970 break;
4971 case 0x760:
4972 case 0x768:
4974 // STRB Rd, [Rn, -Rm, LSL #]!
4975 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
4976 int dest = (opcode >> 12) & 15;
4977 int base = (opcode >> 16) & 15;
4978 u32 address = reg[base].I - offset;
4979 reg[base].I = address;
4980 CPUWriteByte(address, reg[dest].B.B0);
4981 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4983 break;
4984 case 0x762:
4985 case 0x76a:
4987 // STRB Rd, [Rn, -Rm, LSR #]!
4988 int shift = (opcode >> 7) & 31;
4989 int offset = shift ? reg[opcode & 15].I >> shift : 0;
4990 int dest = (opcode >> 12) & 15;
4991 int base = (opcode >> 16) & 15;
4992 u32 address = reg[base].I - offset;
4993 reg[base].I = address;
4994 CPUWriteByte(address, reg[dest].B.B0);
4995 clockTicks += 2 + CPUUpdateTicksAccess16(address);
4997 break;
4998 case 0x764:
4999 case 0x76c:
5001 // STRB Rd, [Rn, -Rm, ASR #]!
5002 int shift = (opcode >> 7) & 31;
5003 int offset;
5004 if (shift)
5005 offset = (int)((s32)reg[opcode & 15].I >> shift);
5006 else if (reg[opcode & 15].I & 0x80000000)
5007 offset = 0xFFFFFFFF;
5008 else
5009 offset = 0;
5010 int dest = (opcode >> 12) & 15;
5011 int base = (opcode >> 16) & 15;
5012 u32 address = reg[base].I - offset;
5013 reg[base].I = address;
5014 CPUWriteByte(address, reg[dest].B.B0);
5015 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5017 break;
5018 case 0x766:
5019 case 0x76e:
5021 // STRB Rd, [Rn, -Rm, ROR #]!
5022 int shift = (opcode >> 7) & 31;
5023 u32 value = reg[opcode & 15].I;
5024 if (shift)
5026 ROR_VALUE;
5028 else
5030 RCR_VALUE;
5032 int dest = (opcode >> 12) & 15;
5033 int base = (opcode >> 16) & 15;
5034 u32 address = reg[base].I - value;
5035 reg[base].I = address;
5036 CPUWriteByte(address, reg[dest].B.B0);
5037 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5039 break;
5040 case 0x7c0:
5041 case 0x7c8:
5043 // STRB Rd, [Rn, Rm, LSL #]
5044 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5045 int dest = (opcode >> 12) & 15;
5046 int base = (opcode >> 16) & 15;
5047 u32 address = reg[base].I + offset;
5048 CPUWriteByte(address, reg[dest].B.B0);
5049 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5051 break;
5052 case 0x7c2:
5053 case 0x7ca:
5055 // STRB Rd, [Rn, Rm, LSR #]
5056 int shift = (opcode >> 7) & 31;
5057 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5058 int dest = (opcode >> 12) & 15;
5059 int base = (opcode >> 16) & 15;
5060 u32 address = reg[base].I + offset;
5061 CPUWriteByte(address, reg[dest].B.B0);
5062 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5064 break;
5065 case 0x7c4:
5066 case 0x7cc:
5068 // STRB Rd, [Rn, Rm, ASR #]
5069 int shift = (opcode >> 7) & 31;
5070 int offset;
5071 if (shift)
5072 offset = (int)((s32)reg[opcode & 15].I >> shift);
5073 else if (reg[opcode & 15].I & 0x80000000)
5074 offset = 0xFFFFFFFF;
5075 else
5076 offset = 0;
5077 int dest = (opcode >> 12) & 15;
5078 int base = (opcode >> 16) & 15;
5079 u32 address = reg[base].I + offset;
5080 CPUWriteByte(address, reg[dest].B.B0);
5081 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5083 break;
5084 case 0x7c6:
5085 case 0x7ce:
5087 // STRB Rd, [Rn, Rm, ROR #]
5088 int shift = (opcode >> 7) & 31;
5089 u32 value = reg[opcode & 15].I;
5090 if (shift)
5092 ROR_VALUE;
5094 else
5096 RCR_VALUE;
5098 int dest = (opcode >> 12) & 15;
5099 int base = (opcode >> 16) & 15;
5100 u32 address = reg[base].I + value;
5101 CPUWriteByte(address, reg[dest].B.B0);
5102 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5104 break;
5105 case 0x7e0:
5106 case 0x7e8:
5108 // STRB Rd, [Rn, Rm, LSL #]!
5109 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5110 int dest = (opcode >> 12) & 15;
5111 int base = (opcode >> 16) & 15;
5112 u32 address = reg[base].I + offset;
5113 reg[base].I = address;
5114 CPUWriteByte(address, reg[dest].B.B0);
5115 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5117 break;
5118 case 0x7e2:
5119 case 0x7ea:
5121 // STRB Rd, [Rn, Rm, LSR #]!
5122 int shift = (opcode >> 7) & 31;
5123 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5124 int dest = (opcode >> 12) & 15;
5125 int base = (opcode >> 16) & 15;
5126 u32 address = reg[base].I + offset;
5127 reg[base].I = address;
5128 CPUWriteByte(address, reg[dest].B.B0);
5129 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5131 break;
5132 case 0x7e4:
5133 case 0x7ec:
5135 // STRB Rd, [Rn, Rm, ASR #]!
5136 int shift = (opcode >> 7) & 31;
5137 int offset;
5138 if (shift)
5139 offset = (int)((s32)reg[opcode & 15].I >> shift);
5140 else if (reg[opcode & 15].I & 0x80000000)
5141 offset = 0xFFFFFFFF;
5142 else
5143 offset = 0;
5144 int dest = (opcode >> 12) & 15;
5145 int base = (opcode >> 16) & 15;
5146 u32 address = reg[base].I + offset;
5147 reg[base].I = address;
5148 CPUWriteByte(address, reg[dest].B.B0);
5149 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5151 break;
5152 case 0x7e6:
5153 case 0x7ee:
5155 // STRB Rd, [Rn, Rm, ROR #]!
5156 int shift = (opcode >> 7) & 31;
5157 u32 value = reg[opcode & 15].I;
5158 if (shift)
5160 ROR_VALUE;
5162 else
5164 RCR_VALUE;
5166 int dest = (opcode >> 12) & 15;
5167 int base = (opcode >> 16) & 15;
5168 u32 address = reg[base].I + value;
5169 reg[base].I = address;
5170 CPUWriteByte(address, reg[dest].B.B0);
5171 clockTicks += 2 + CPUUpdateTicksAccess16(address);
5173 break;
5174 case 0x650:
5175 case 0x658:
5176 // T versions are the same
5177 case 0x670:
5178 case 0x678:
5180 // LDRB Rd, [Rn], -Rm, LSL #
5181 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5182 int dest = (opcode >> 12) & 15;
5183 int base = (opcode >> 16) & 15;
5184 u32 address = reg[base].I;
5185 reg[dest].I = CPUReadByte(address);
5186 if (dest != base)
5187 reg[base].I = address - offset;
5188 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5190 break;
5191 case 0x652:
5192 case 0x65a:
5193 // T versions are the same
5194 case 0x672:
5195 case 0x67a:
5197 // LDRB Rd, [Rn], -Rm, LSR #
5198 int shift = (opcode >> 7) & 31;
5199 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5200 int dest = (opcode >> 12) & 15;
5201 int base = (opcode >> 16) & 15;
5202 u32 address = reg[base].I;
5203 reg[dest].I = CPUReadByte(address);
5204 if (dest != base)
5205 reg[base].I = address - offset;
5206 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5208 break;
5209 case 0x654:
5210 case 0x65c:
5211 // T versions are the same
5212 case 0x674:
5213 case 0x67c:
5215 // LDRB Rd, [Rn], -Rm, ASR #
5216 int shift = (opcode >> 7) & 31;
5217 int offset;
5218 if (shift)
5219 offset = (int)((s32)reg[opcode & 15].I >> shift);
5220 else if (reg[opcode & 15].I & 0x80000000)
5221 offset = 0xFFFFFFFF;
5222 else
5223 offset = 0;
5224 int dest = (opcode >> 12) & 15;
5225 int base = (opcode >> 16) & 15;
5226 u32 address = reg[base].I;
5227 reg[dest].I = CPUReadByte(address);
5228 if (dest != base)
5229 reg[base].I = address - offset;
5230 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5232 break;
5233 case 0x656:
5234 case 0x65e:
5235 // T versions are the same
5236 case 0x676:
5237 case 0x67e:
5239 // LDRB Rd, [Rn], -Rm, ROR #
5240 int shift = (opcode >> 7) & 31;
5241 u32 value = reg[opcode & 15].I;
5242 if (shift)
5244 ROR_VALUE;
5246 else
5248 RCR_VALUE;
5250 int dest = (opcode >> 12) & 15;
5251 int base = (opcode >> 16) & 15;
5252 u32 address = reg[base].I;
5253 reg[dest].I = CPUReadByte(address);
5254 if (dest != base)
5255 reg[base].I = address - value;
5256 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5258 break;
5259 case 0x6d0:
5260 case 0x6d8:
5261 // T versions are the same
5262 case 0x6f0:
5263 case 0x6f8:
5265 // LDRB Rd, [Rn], Rm, LSL #
5266 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5267 int dest = (opcode >> 12) & 15;
5268 int base = (opcode >> 16) & 15;
5269 u32 address = reg[base].I;
5270 reg[dest].I = CPUReadByte(address);
5271 if (dest != base)
5272 reg[base].I = address + offset;
5273 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5275 break;
5276 case 0x6d2:
5277 case 0x6da:
5278 // T versions are the same
5279 case 0x6f2:
5280 case 0x6fa:
5282 // LDRB Rd, [Rn], Rm, LSR #
5283 int shift = (opcode >> 7) & 31;
5284 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5285 int dest = (opcode >> 12) & 15;
5286 int base = (opcode >> 16) & 15;
5287 u32 address = reg[base].I;
5288 reg[dest].I = CPUReadByte(address);
5289 if (dest != base)
5290 reg[base].I = address + offset;
5291 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5293 break;
5294 case 0x6d4:
5295 case 0x6dc:
5296 // T versions are the same
5297 case 0x6f4:
5298 case 0x6fc:
5300 // LDRB Rd, [Rn], Rm, ASR #
5301 int shift = (opcode >> 7) & 31;
5302 int offset;
5303 if (shift)
5304 offset = (int)((s32)reg[opcode & 15].I >> shift);
5305 else if (reg[opcode & 15].I & 0x80000000)
5306 offset = 0xFFFFFFFF;
5307 else
5308 offset = 0;
5309 int dest = (opcode >> 12) & 15;
5310 int base = (opcode >> 16) & 15;
5311 u32 address = reg[base].I;
5312 reg[dest].I = CPUReadByte(address);
5313 if (dest != base)
5314 reg[base].I = address + offset;
5315 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5317 break;
5318 case 0x6d6:
5319 case 0x6de:
5320 // T versions are the same
5321 case 0x6f6:
5322 case 0x6fe:
5324 // LDRB Rd, [Rn], Rm, ROR #
5325 int shift = (opcode >> 7) & 31;
5326 u32 value = reg[opcode & 15].I;
5327 if (shift)
5329 ROR_VALUE;
5331 else
5333 RCR_VALUE;
5335 int dest = (opcode >> 12) & 15;
5336 int base = (opcode >> 16) & 15;
5337 u32 address = reg[base].I;
5338 reg[dest].I = CPUReadByte(address);
5339 if (dest != base)
5340 reg[base].I = address + value;
5341 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5343 break;
5344 case 0x750:
5345 case 0x758:
5347 // LDRB Rd, [Rn, -Rm, LSL #]
5348 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5349 int dest = (opcode >> 12) & 15;
5350 int base = (opcode >> 16) & 15;
5351 u32 address = reg[base].I - offset;
5352 reg[dest].I = CPUReadByte(address);
5353 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5355 break;
5356 case 0x752:
5357 case 0x75a:
5359 // LDRB Rd, [Rn, -Rm, LSR #]
5360 int shift = (opcode >> 7) & 31;
5361 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5362 int dest = (opcode >> 12) & 15;
5363 int base = (opcode >> 16) & 15;
5364 u32 address = reg[base].I - offset;
5365 reg[dest].I = CPUReadByte(address);
5366 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5368 break;
5369 case 0x754:
5370 case 0x75c:
5372 // LDRB Rd, [Rn, -Rm, ASR #]
5373 int shift = (opcode >> 7) & 31;
5374 int offset;
5375 if (shift)
5376 offset = (int)((s32)reg[opcode & 15].I >> shift);
5377 else if (reg[opcode & 15].I & 0x80000000)
5378 offset = 0xFFFFFFFF;
5379 else
5380 offset = 0;
5381 int dest = (opcode >> 12) & 15;
5382 int base = (opcode >> 16) & 15;
5383 u32 address = reg[base].I - offset;
5384 reg[dest].I = CPUReadByte(address);
5385 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5387 break;
5388 case 0x756:
5389 case 0x75e:
5391 // LDRB Rd, [Rn, -Rm, ROR #]
5392 int shift = (opcode >> 7) & 31;
5393 u32 value = reg[opcode & 15].I;
5394 if (shift)
5396 ROR_VALUE;
5398 else
5400 RCR_VALUE;
5402 int dest = (opcode >> 12) & 15;
5403 int base = (opcode >> 16) & 15;
5404 u32 address = reg[base].I - value;
5405 reg[dest].I = CPUReadByte(address);
5406 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5408 break;
5409 case 0x770:
5410 case 0x778:
5412 // LDRB Rd, [Rn, -Rm, LSL #]!
5413 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5414 int dest = (opcode >> 12) & 15;
5415 int base = (opcode >> 16) & 15;
5416 u32 address = reg[base].I - offset;
5417 reg[dest].I = CPUReadByte(address);
5418 if (dest != base)
5419 reg[base].I = address;
5420 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5422 break;
5423 case 0x772:
5424 case 0x77a:
5426 // LDRB Rd, [Rn, -Rm, LSR #]!
5427 int shift = (opcode >> 7) & 31;
5428 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5429 int dest = (opcode >> 12) & 15;
5430 int base = (opcode >> 16) & 15;
5431 u32 address = reg[base].I - offset;
5432 reg[dest].I = CPUReadByte(address);
5433 if (dest != base)
5434 reg[base].I = address;
5435 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5437 break;
5438 case 0x774:
5439 case 0x77c:
5441 // LDRB Rd, [Rn, -Rm, ASR #]!
5442 int shift = (opcode >> 7) & 31;
5443 int offset;
5444 if (shift)
5445 offset = (int)((s32)reg[opcode & 15].I >> shift);
5446 else if (reg[opcode & 15].I & 0x80000000)
5447 offset = 0xFFFFFFFF;
5448 else
5449 offset = 0;
5450 int dest = (opcode >> 12) & 15;
5451 int base = (opcode >> 16) & 15;
5452 u32 address = reg[base].I - offset;
5453 reg[dest].I = CPUReadByte(address);
5454 if (dest != base)
5455 reg[base].I = address;
5456 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5458 break;
5459 case 0x776:
5460 case 0x77e:
5462 // LDRB Rd, [Rn, -Rm, ROR #]!
5463 int shift = (opcode >> 7) & 31;
5464 u32 value = reg[opcode & 15].I;
5465 if (shift)
5467 ROR_VALUE;
5469 else
5471 RCR_VALUE;
5473 int dest = (opcode >> 12) & 15;
5474 int base = (opcode >> 16) & 15;
5475 u32 address = reg[base].I - value;
5476 reg[dest].I = CPUReadByte(address);
5477 if (dest != base)
5478 reg[base].I = address;
5479 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5481 break;
5482 case 0x7d0:
5483 case 0x7d8:
5485 // LDRB Rd, [Rn, Rm, LSL #]
5486 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5487 int dest = (opcode >> 12) & 15;
5488 int base = (opcode >> 16) & 15;
5489 u32 address = reg[base].I + offset;
5490 reg[dest].I = CPUReadByte(address);
5491 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5493 break;
5494 case 0x7d2:
5495 case 0x7da:
5497 // LDRB Rd, [Rn, Rm, LSR #]
5498 int shift = (opcode >> 7) & 31;
5499 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5500 int dest = (opcode >> 12) & 15;
5501 int base = (opcode >> 16) & 15;
5502 u32 address = reg[base].I + offset;
5503 reg[dest].I = CPUReadByte(address);
5504 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5506 break;
5507 case 0x7d4:
5508 case 0x7dc:
5510 // LDRB Rd, [Rn, Rm, ASR #]
5511 int shift = (opcode >> 7) & 31;
5512 int offset;
5513 if (shift)
5514 offset = (int)((s32)reg[opcode & 15].I >> shift);
5515 else if (reg[opcode & 15].I & 0x80000000)
5516 offset = 0xFFFFFFFF;
5517 else
5518 offset = 0;
5519 int dest = (opcode >> 12) & 15;
5520 int base = (opcode >> 16) & 15;
5521 u32 address = reg[base].I + offset;
5522 reg[dest].I = CPUReadByte(address);
5523 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5525 break;
5526 case 0x7d6:
5527 case 0x7de:
5529 // LDRB Rd, [Rn, Rm, ROR #]
5530 int shift = (opcode >> 7) & 31;
5531 u32 value = reg[opcode & 15].I;
5532 if (shift)
5534 ROR_VALUE;
5536 else
5538 RCR_VALUE;
5540 int dest = (opcode >> 12) & 15;
5541 int base = (opcode >> 16) & 15;
5542 u32 address = reg[base].I + value;
5543 reg[dest].I = CPUReadByte(address);
5544 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5546 break;
5547 case 0x7f0:
5548 case 0x7f8:
5550 // LDRB Rd, [Rn, Rm, LSL #]!
5551 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
5552 int dest = (opcode >> 12) & 15;
5553 int base = (opcode >> 16) & 15;
5554 u32 address = reg[base].I + offset;
5555 reg[dest].I = CPUReadByte(address);
5556 if (dest != base)
5557 reg[base].I = address;
5558 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5560 break;
5561 case 0x7f2:
5562 case 0x7fa:
5564 // LDRB Rd, [Rn, Rm, LSR #]!
5565 int shift = (opcode >> 7) & 31;
5566 int offset = shift ? reg[opcode & 15].I >> shift : 0;
5567 int dest = (opcode >> 12) & 15;
5568 int base = (opcode >> 16) & 15;
5569 u32 address = reg[base].I + offset;
5570 reg[dest].I = CPUReadByte(address);
5571 if (dest != base)
5572 reg[base].I = address;
5573 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5575 break;
5576 case 0x7f4:
5577 case 0x7fc:
5579 // LDRB Rd, [Rn, Rm, ASR #]!
5580 int shift = (opcode >> 7) & 31;
5581 int offset;
5582 if (shift)
5583 offset = (int)((s32)reg[opcode & 15].I >> shift);
5584 else if (reg[opcode & 15].I & 0x80000000)
5585 offset = 0xFFFFFFFF;
5586 else
5587 offset = 0;
5588 int dest = (opcode >> 12) & 15;
5589 int base = (opcode >> 16) & 15;
5590 u32 address = reg[base].I + offset;
5591 reg[dest].I = CPUReadByte(address);
5592 if (dest != base)
5593 reg[base].I = address;
5594 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5596 break;
5597 case 0x7f6:
5598 case 0x7fe:
5600 // LDRB Rd, [Rn, Rm, ROR #]!
5601 int shift = (opcode >> 7) & 31;
5602 u32 value = reg[opcode & 15].I;
5603 if (shift)
5605 ROR_VALUE;
5607 else
5609 RCR_VALUE;
5611 int dest = (opcode >> 12) & 15;
5612 int base = (opcode >> 16) & 15;
5613 u32 address = reg[base].I + value;
5614 reg[dest].I = CPUReadByte(address);
5615 if (dest != base)
5616 reg[base].I = address;
5617 clockTicks += 3 + CPUUpdateTicksAccess16(address);
5619 break;
5620 #define STMW_REG(val, num) \
5621 if (opcode & (val)) { \
5622 CPUWriteMemory(address, reg[(num)].I); \
5623 if (!offset) { \
5624 reg[base].I = temp; \
5625 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
5626 offset = 1; \
5627 } else { \
5628 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
5629 } \
5630 address += 4; \
5632 #define STM_REG(val, num) \
5633 if (opcode & (val)) { \
5634 CPUWriteMemory(address, reg[(num)].I); \
5635 if (!offset) { \
5636 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
5637 offset = 1; \
5638 } else { \
5639 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
5640 } \
5641 address += 4; \
5644 CASE_16(0x800)
5645 // STMDA Rn, {Rlist}
5647 int base = (opcode & 0x000F0000) >> 16;
5648 u32 temp = reg[base].I -
5649 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5650 u32 address = (temp + 4) & 0xFFFFFFFC;
5651 clockTicks += 2;
5652 int offset = 0;
5653 STM_REG(1, 0);
5654 STM_REG(2, 1);
5655 STM_REG(4, 2);
5656 STM_REG(8, 3);
5657 STM_REG(16, 4);
5658 STM_REG(32, 5);
5659 STM_REG(64, 6);
5660 STM_REG(128, 7);
5661 STM_REG(256, 8);
5662 STM_REG(512, 9);
5663 STM_REG(1024, 10);
5664 STM_REG(2048, 11);
5665 STM_REG(4096, 12);
5666 STM_REG(8192, 13);
5667 STM_REG(16384, 14);
5668 if (opcode & 32768)
5670 CPUWriteMemory(address, reg[15].I + 4);
5671 if (!offset)
5672 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5673 else
5674 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5677 break;
5678 CASE_16(0x820)
5680 // STMDA Rn!, {Rlist}
5681 int base = (opcode & 0x000F0000) >> 16;
5682 u32 temp = reg[base].I -
5683 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5684 u32 address = (temp + 4) & 0xFFFFFFFC;
5685 clockTicks += 2;
5686 int offset = 0;
5688 STMW_REG(1, 0);
5689 STMW_REG(2, 1);
5690 STMW_REG(4, 2);
5691 STMW_REG(8, 3);
5692 STMW_REG(16, 4);
5693 STMW_REG(32, 5);
5694 STMW_REG(64, 6);
5695 STMW_REG(128, 7);
5696 STMW_REG(256, 8);
5697 STMW_REG(512, 9);
5698 STMW_REG(1024, 10);
5699 STMW_REG(2048, 11);
5700 STMW_REG(4096, 12);
5701 STMW_REG(8192, 13);
5702 STMW_REG(16384, 14);
5703 if (opcode & 32768)
5705 CPUWriteMemory(address, reg[15].I + 4);
5706 if (!offset)
5707 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5708 else
5709 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5710 reg[base].I = temp;
5713 break;
5714 CASE_16(0x840)
5716 // STMDA Rn, {Rlist}^
5717 int base = (opcode & 0x000F0000) >> 16;
5718 u32 temp = reg[base].I -
5719 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5720 u32 address = (temp + 4) & 0xFFFFFFFC;
5721 clockTicks += 2;
5722 int offset = 0;
5724 STM_REG(1, 0);
5725 STM_REG(2, 1);
5726 STM_REG(4, 2);
5727 STM_REG(8, 3);
5728 STM_REG(16, 4);
5729 STM_REG(32, 5);
5730 STM_REG(64, 6);
5731 STM_REG(128, 7);
5733 if (armMode == 0x11)
5735 STM_REG(256, R8_FIQ);
5736 STM_REG(512, R9_FIQ);
5737 STM_REG(1024, R10_FIQ);
5738 STM_REG(2048, R11_FIQ);
5739 STM_REG(4096, R12_FIQ);
5741 else
5743 STM_REG(256, 8);
5744 STM_REG(512, 9);
5745 STM_REG(1024, 10);
5746 STM_REG(2048, 11);
5747 STM_REG(4096, 12);
5750 if (armMode != 0x10 && armMode != 0x1f)
5752 STM_REG(8192, R13_USR);
5753 STM_REG(16384, R14_USR);
5755 else
5757 STM_REG(8192, 13);
5758 STM_REG(16384, 14);
5761 if (opcode & 32768)
5763 CPUWriteMemory(address, reg[15].I + 4);
5764 if (!offset)
5765 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5766 else
5767 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5770 break;
5771 CASE_16(0x860)
5773 // STMDA Rn!, {Rlist}^
5774 int base = (opcode & 0x000F0000) >> 16;
5775 u32 temp = reg[base].I -
5776 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5777 u32 address = (temp + 4) & 0xFFFFFFFC;
5778 clockTicks += 2;
5779 int offset = 0;
5781 STMW_REG(1, 0);
5782 STMW_REG(2, 1);
5783 STMW_REG(4, 2);
5784 STMW_REG(8, 3);
5785 STMW_REG(16, 4);
5786 STMW_REG(32, 5);
5787 STMW_REG(64, 6);
5788 STMW_REG(128, 7);
5790 if (armMode == 0x11)
5792 STMW_REG(256, R8_FIQ);
5793 STMW_REG(512, R9_FIQ);
5794 STMW_REG(1024, R10_FIQ);
5795 STMW_REG(2048, R11_FIQ);
5796 STMW_REG(4096, R12_FIQ);
5798 else
5800 STMW_REG(256, 8);
5801 STMW_REG(512, 9);
5802 STMW_REG(1024, 10);
5803 STMW_REG(2048, 11);
5804 STMW_REG(4096, 12);
5807 if (armMode != 0x10 && armMode != 0x1f)
5809 STMW_REG(8192, R13_USR);
5810 STMW_REG(16384, R14_USR);
5812 else
5814 STMW_REG(8192, 13);
5815 STMW_REG(16384, 14);
5818 if (opcode & 32768)
5820 CPUWriteMemory(address, reg[15].I + 4);
5821 if (!offset)
5822 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5823 else
5824 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5825 reg[base].I = temp;
5828 break;
5830 CASE_16(0x880)
5832 // STMIA Rn, {Rlist}
5833 int base = (opcode & 0x000F0000) >> 16;
5834 u32 address = reg[base].I & 0xFFFFFFFC;
5835 clockTicks += 2;
5836 int offset = 0;
5837 STM_REG(1, 0);
5838 STM_REG(2, 1);
5839 STM_REG(4, 2);
5840 STM_REG(8, 3);
5841 STM_REG(16, 4);
5842 STM_REG(32, 5);
5843 STM_REG(64, 6);
5844 STM_REG(128, 7);
5845 STM_REG(256, 8);
5846 STM_REG(512, 9);
5847 STM_REG(1024, 10);
5848 STM_REG(2048, 11);
5849 STM_REG(4096, 12);
5850 STM_REG(8192, 13);
5851 STM_REG(16384, 14);
5852 if (opcode & 32768)
5854 CPUWriteMemory(address, reg[15].I + 4);
5855 if (!offset)
5856 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5857 else
5858 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5861 break;
5862 CASE_16(0x8a0)
5864 // STMIA Rn!, {Rlist}
5865 int base = (opcode & 0x000F0000) >> 16;
5866 u32 address = reg[base].I & 0xFFFFFFFC;
5867 clockTicks += 2;
5868 int offset = 0;
5869 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
5870 cpuBitsSet[(opcode >> 8) & 255]);
5871 STMW_REG(1, 0);
5872 STMW_REG(2, 1);
5873 STMW_REG(4, 2);
5874 STMW_REG(8, 3);
5875 STMW_REG(16, 4);
5876 STMW_REG(32, 5);
5877 STMW_REG(64, 6);
5878 STMW_REG(128, 7);
5879 STMW_REG(256, 8);
5880 STMW_REG(512, 9);
5881 STMW_REG(1024, 10);
5882 STMW_REG(2048, 11);
5883 STMW_REG(4096, 12);
5884 STMW_REG(8192, 13);
5885 STMW_REG(16384, 14);
5886 if (opcode & 32768)
5888 CPUWriteMemory(address, reg[15].I + 4);
5889 if (!offset)
5891 reg[base].I = temp;
5892 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5894 else
5895 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5898 break;
5899 CASE_16(0x8c0)
5901 // STMIA Rn, {Rlist}^
5902 int base = (opcode & 0x000F0000) >> 16;
5903 u32 address = reg[base].I & 0xFFFFFFFC;
5904 clockTicks += 2;
5905 int offset = 0;
5906 STM_REG(1, 0);
5907 STM_REG(2, 1);
5908 STM_REG(4, 2);
5909 STM_REG(8, 3);
5910 STM_REG(16, 4);
5911 STM_REG(32, 5);
5912 STM_REG(64, 6);
5913 STM_REG(128, 7);
5914 if (armMode == 0x11)
5916 STM_REG(256, R8_FIQ);
5917 STM_REG(512, R9_FIQ);
5918 STM_REG(1024, R10_FIQ);
5919 STM_REG(2048, R11_FIQ);
5920 STM_REG(4096, R12_FIQ);
5922 else
5924 STM_REG(256, 8);
5925 STM_REG(512, 9);
5926 STM_REG(1024, 10);
5927 STM_REG(2048, 11);
5928 STM_REG(4096, 12);
5930 if (armMode != 0x10 && armMode != 0x1f)
5932 STM_REG(8192, R13_USR);
5933 STM_REG(16384, R14_USR);
5935 else
5937 STM_REG(8192, 13);
5938 STM_REG(16384, 14);
5940 if (opcode & 32768)
5942 CPUWriteMemory(address, reg[15].I + 4);
5943 if (!offset)
5944 clockTicks += 1 + CPUUpdateTicksAccess32(address);
5945 else
5946 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5949 break;
5950 CASE_16(0x8e0)
5952 // STMIA Rn!, {Rlist}^
5953 int base = (opcode & 0x000F0000) >> 16;
5954 u32 address = reg[base].I & 0xFFFFFFFC;
5955 clockTicks += 2;
5956 int offset = 0;
5957 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
5958 cpuBitsSet[(opcode >> 8) & 255]);
5959 STMW_REG(1, 0);
5960 STMW_REG(2, 1);
5961 STMW_REG(4, 2);
5962 STMW_REG(8, 3);
5963 STMW_REG(16, 4);
5964 STMW_REG(32, 5);
5965 STMW_REG(64, 6);
5966 STMW_REG(128, 7);
5967 if (armMode == 0x11)
5969 STMW_REG(256, R8_FIQ);
5970 STMW_REG(512, R9_FIQ);
5971 STMW_REG(1024, R10_FIQ);
5972 STMW_REG(2048, R11_FIQ);
5973 STMW_REG(4096, R12_FIQ);
5975 else
5977 STMW_REG(256, 8);
5978 STMW_REG(512, 9);
5979 STMW_REG(1024, 10);
5980 STMW_REG(2048, 11);
5981 STMW_REG(4096, 12);
5983 if (armMode != 0x10 && armMode != 0x1f)
5985 STMW_REG(8192, R13_USR);
5986 STMW_REG(16384, R14_USR);
5988 else
5990 STMW_REG(8192, 13);
5991 STMW_REG(16384, 14);
5993 if (opcode & 32768)
5995 CPUWriteMemory(address, reg[15].I + 4);
5996 if (!offset)
5998 reg[base].I = temp;
5999 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6001 else
6002 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6005 break;
6007 CASE_16(0x900)
6009 // STMDB Rn, {Rlist}
6010 int base = (opcode & 0x000F0000) >> 16;
6011 u32 temp = reg[base].I -
6012 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6013 u32 address = temp & 0xFFFFFFFC;
6014 clockTicks += 2;
6015 int offset = 0;
6016 STM_REG(1, 0);
6017 STM_REG(2, 1);
6018 STM_REG(4, 2);
6019 STM_REG(8, 3);
6020 STM_REG(16, 4);
6021 STM_REG(32, 5);
6022 STM_REG(64, 6);
6023 STM_REG(128, 7);
6024 STM_REG(256, 8);
6025 STM_REG(512, 9);
6026 STM_REG(1024, 10);
6027 STM_REG(2048, 11);
6028 STM_REG(4096, 12);
6029 STM_REG(8192, 13);
6030 STM_REG(16384, 14);
6031 if (opcode & 32768)
6033 CPUWriteMemory(address, reg[15].I + 4);
6034 if (!offset)
6035 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6036 else
6037 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6040 break;
6041 CASE_16(0x920)
6043 // STMDB Rn!, {Rlist}
6044 int base = (opcode & 0x000F0000) >> 16;
6045 u32 temp = reg[base].I -
6046 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6047 u32 address = temp & 0xFFFFFFFC;
6048 clockTicks += 2;
6049 int offset = 0;
6051 STMW_REG(1, 0);
6052 STMW_REG(2, 1);
6053 STMW_REG(4, 2);
6054 STMW_REG(8, 3);
6055 STMW_REG(16, 4);
6056 STMW_REG(32, 5);
6057 STMW_REG(64, 6);
6058 STMW_REG(128, 7);
6059 STMW_REG(256, 8);
6060 STMW_REG(512, 9);
6061 STMW_REG(1024, 10);
6062 STMW_REG(2048, 11);
6063 STMW_REG(4096, 12);
6064 STMW_REG(8192, 13);
6065 STMW_REG(16384, 14);
6066 if (opcode & 32768)
6068 CPUWriteMemory(address, reg[15].I + 4);
6069 if (!offset)
6070 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6071 else
6072 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6073 reg[base].I = temp;
6076 break;
6077 CASE_16(0x940)
6079 // STMDB Rn, {Rlist}^
6080 int base = (opcode & 0x000F0000) >> 16;
6081 u32 temp = reg[base].I -
6082 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6083 u32 address = temp & 0xFFFFFFFC;
6084 clockTicks += 2;
6085 int offset = 0;
6087 STM_REG(1, 0);
6088 STM_REG(2, 1);
6089 STM_REG(4, 2);
6090 STM_REG(8, 3);
6091 STM_REG(16, 4);
6092 STM_REG(32, 5);
6093 STM_REG(64, 6);
6094 STM_REG(128, 7);
6096 if (armMode == 0x11)
6098 STM_REG(256, R8_FIQ);
6099 STM_REG(512, R9_FIQ);
6100 STM_REG(1024, R10_FIQ);
6101 STM_REG(2048, R11_FIQ);
6102 STM_REG(4096, R12_FIQ);
6104 else
6106 STM_REG(256, 8);
6107 STM_REG(512, 9);
6108 STM_REG(1024, 10);
6109 STM_REG(2048, 11);
6110 STM_REG(4096, 12);
6113 if (armMode != 0x10 && armMode != 0x1f)
6115 STM_REG(8192, R13_USR);
6116 STM_REG(16384, R14_USR);
6118 else
6120 STM_REG(8192, 13);
6121 STM_REG(16384, 14);
6124 if (opcode & 32768)
6126 CPUWriteMemory(address, reg[15].I + 4);
6127 if (!offset)
6128 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6129 else
6130 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6133 break;
6134 CASE_16(0x960)
6136 // STMDB Rn!, {Rlist}^
6137 int base = (opcode & 0x000F0000) >> 16;
6138 u32 temp = reg[base].I -
6139 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6140 u32 address = temp & 0xFFFFFFFC;
6141 clockTicks += 2;
6142 int offset = 0;
6144 STMW_REG(1, 0);
6145 STMW_REG(2, 1);
6146 STMW_REG(4, 2);
6147 STMW_REG(8, 3);
6148 STMW_REG(16, 4);
6149 STMW_REG(32, 5);
6150 STMW_REG(64, 6);
6151 STMW_REG(128, 7);
6153 if (armMode == 0x11)
6155 STMW_REG(256, R8_FIQ);
6156 STMW_REG(512, R9_FIQ);
6157 STMW_REG(1024, R10_FIQ);
6158 STMW_REG(2048, R11_FIQ);
6159 STMW_REG(4096, R12_FIQ);
6161 else
6163 STMW_REG(256, 8);
6164 STMW_REG(512, 9);
6165 STMW_REG(1024, 10);
6166 STMW_REG(2048, 11);
6167 STMW_REG(4096, 12);
6170 if (armMode != 0x10 && armMode != 0x1f)
6172 STMW_REG(8192, R13_USR);
6173 STMW_REG(16384, R14_USR);
6175 else
6177 STMW_REG(8192, 13);
6178 STMW_REG(16384, 14);
6181 if (opcode & 32768)
6183 CPUWriteMemory(address, reg[15].I + 4);
6184 if (!offset)
6185 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6186 else
6187 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6188 reg[base].I = temp;
6191 break;
6193 CASE_16(0x980)
6194 // STMIB Rn, {Rlist}
6196 int base = (opcode & 0x000F0000) >> 16;
6197 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
6198 clockTicks += 2;
6199 int offset = 0;
6200 STM_REG(1, 0);
6201 STM_REG(2, 1);
6202 STM_REG(4, 2);
6203 STM_REG(8, 3);
6204 STM_REG(16, 4);
6205 STM_REG(32, 5);
6206 STM_REG(64, 6);
6207 STM_REG(128, 7);
6208 STM_REG(256, 8);
6209 STM_REG(512, 9);
6210 STM_REG(1024, 10);
6211 STM_REG(2048, 11);
6212 STM_REG(4096, 12);
6213 STM_REG(8192, 13);
6214 STM_REG(16384, 14);
6215 if (opcode & 32768)
6217 CPUWriteMemory(address, reg[15].I + 4);
6218 if (!offset)
6219 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6220 else
6221 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6224 break;
6225 CASE_16(0x9a0)
6227 // STMIB Rn!, {Rlist}
6228 int base = (opcode & 0x000F0000) >> 16;
6229 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
6230 clockTicks += 2;
6231 int offset = 0;
6232 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
6233 cpuBitsSet[(opcode >> 8) & 255]);
6234 STMW_REG(1, 0);
6235 STMW_REG(2, 1);
6236 STMW_REG(4, 2);
6237 STMW_REG(8, 3);
6238 STMW_REG(16, 4);
6239 STMW_REG(32, 5);
6240 STMW_REG(64, 6);
6241 STMW_REG(128, 7);
6242 STMW_REG(256, 8);
6243 STMW_REG(512, 9);
6244 STMW_REG(1024, 10);
6245 STMW_REG(2048, 11);
6246 STMW_REG(4096, 12);
6247 STMW_REG(8192, 13);
6248 STMW_REG(16384, 14);
6249 if (opcode & 32768)
6251 CPUWriteMemory(address, reg[15].I + 4);
6252 if (!offset)
6254 reg[base].I = temp;
6255 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6257 else
6258 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6261 break;
6262 CASE_16(0x9c0)
6264 // STMIB Rn, {Rlist}^
6265 int base = (opcode & 0x000F0000) >> 16;
6266 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
6267 clockTicks += 2;
6268 int offset = 0;
6269 STM_REG(1, 0);
6270 STM_REG(2, 1);
6271 STM_REG(4, 2);
6272 STM_REG(8, 3);
6273 STM_REG(16, 4);
6274 STM_REG(32, 5);
6275 STM_REG(64, 6);
6276 STM_REG(128, 7);
6277 if (armMode == 0x11)
6279 STM_REG(256, R8_FIQ);
6280 STM_REG(512, R9_FIQ);
6281 STM_REG(1024, R10_FIQ);
6282 STM_REG(2048, R11_FIQ);
6283 STM_REG(4096, R12_FIQ);
6285 else
6287 STM_REG(256, 8);
6288 STM_REG(512, 9);
6289 STM_REG(1024, 10);
6290 STM_REG(2048, 11);
6291 STM_REG(4096, 12);
6293 if (armMode != 0x10 && armMode != 0x1f)
6295 STM_REG(8192, R13_USR);
6296 STM_REG(16384, R14_USR);
6298 else
6300 STM_REG(8192, 13);
6301 STM_REG(16384, 14);
6303 if (opcode & 32768)
6305 CPUWriteMemory(address, reg[15].I + 4);
6306 if (!offset)
6307 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6308 else
6309 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6312 break;
6313 CASE_16(0x9e0)
6315 // STMIB Rn!, {Rlist}^
6316 int base = (opcode & 0x000F0000) >> 16;
6317 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
6318 clockTicks += 2;
6319 int offset = 0;
6320 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
6321 cpuBitsSet[(opcode >> 8) & 255]);
6322 STMW_REG(1, 0);
6323 STMW_REG(2, 1);
6324 STMW_REG(4, 2);
6325 STMW_REG(8, 3);
6326 STMW_REG(16, 4);
6327 STMW_REG(32, 5);
6328 STMW_REG(64, 6);
6329 STMW_REG(128, 7);
6330 if (armMode == 0x11)
6332 STMW_REG(256, R8_FIQ);
6333 STMW_REG(512, R9_FIQ);
6334 STMW_REG(1024, R10_FIQ);
6335 STMW_REG(2048, R11_FIQ);
6336 STMW_REG(4096, R12_FIQ);
6338 else
6340 STMW_REG(256, 8);
6341 STMW_REG(512, 9);
6342 STMW_REG(1024, 10);
6343 STMW_REG(2048, 11);
6344 STMW_REG(4096, 12);
6346 if (armMode != 0x10 && armMode != 0x1f)
6348 STMW_REG(8192, R13_USR);
6349 STMW_REG(16384, R14_USR);
6351 else
6353 STMW_REG(8192, 13);
6354 STMW_REG(16384, 14);
6356 if (opcode & 32768)
6358 CPUWriteMemory(address, reg[15].I + 4);
6359 if (!offset)
6361 reg[base].I = temp;
6362 clockTicks += 1 + CPUUpdateTicksAccess32(address);
6364 else
6365 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6368 break;
6370 #define LDM_REG(val, num) \
6371 if (opcode & (val)) { \
6372 reg[(num)].I = CPUReadMemory(address); \
6373 if (offset) \
6374 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
6375 else { \
6376 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
6377 offset = 1; \
6378 } \
6379 address += 4; \
6382 CASE_16(0x810)
6384 // LDMDA Rn, {Rlist}
6385 int base = (opcode & 0x000F0000) >> 16;
6386 u32 temp = reg[base].I -
6387 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6388 u32 address = (temp + 4) & 0xFFFFFFFC;
6389 clockTicks += 2;
6390 int offset = 0;
6391 LDM_REG(1, 0);
6392 LDM_REG(2, 1);
6393 LDM_REG(4, 2);
6394 LDM_REG(8, 3);
6395 LDM_REG(16, 4);
6396 LDM_REG(32, 5);
6397 LDM_REG(64, 6);
6398 LDM_REG(128, 7);
6399 LDM_REG(256, 8);
6400 LDM_REG(512, 9);
6401 LDM_REG(1024, 10);
6402 LDM_REG(2048, 11);
6403 LDM_REG(4096, 12);
6404 LDM_REG(8192, 13);
6405 LDM_REG(16384, 14);
6406 if (opcode & 32768)
6408 reg[15].I = CPUReadMemory(address);
6409 if (!offset)
6410 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6411 else
6412 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6413 armNextPC = reg[15].I;
6414 reg[15].I += 4;
6417 break;
6418 CASE_16(0x830)
6420 // LDMDA Rn!, {Rlist}
6421 int base = (opcode & 0x000F0000) >> 16;
6422 u32 temp = reg[base].I -
6423 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6424 u32 address = (temp + 4) & 0xFFFFFFFC;
6425 clockTicks += 2;
6426 int offset = 0;
6427 LDM_REG(1, 0);
6428 LDM_REG(2, 1);
6429 LDM_REG(4, 2);
6430 LDM_REG(8, 3);
6431 LDM_REG(16, 4);
6432 LDM_REG(32, 5);
6433 LDM_REG(64, 6);
6434 LDM_REG(128, 7);
6435 LDM_REG(256, 8);
6436 LDM_REG(512, 9);
6437 LDM_REG(1024, 10);
6438 LDM_REG(2048, 11);
6439 LDM_REG(4096, 12);
6440 LDM_REG(8192, 13);
6441 LDM_REG(16384, 14);
6442 if (opcode & 32768)
6444 reg[15].I = CPUReadMemory(address);
6445 if (!offset)
6446 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6447 else
6448 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6449 armNextPC = reg[15].I;
6450 reg[15].I += 4;
6452 if (!(opcode & (1 << base)))
6453 reg[base].I = temp;
6455 break;
6456 CASE_16(0x850)
6458 // LDMDA Rn, {Rlist}^
6459 int base = (opcode & 0x000F0000) >> 16;
6460 u32 temp = reg[base].I -
6461 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6462 u32 address = (temp + 4) & 0xFFFFFFFC;
6463 clockTicks += 2;
6464 int offset = 0;
6465 if (opcode & 0x8000)
6467 LDM_REG(1, 0);
6468 LDM_REG(2, 1);
6469 LDM_REG(4, 2);
6470 LDM_REG(8, 3);
6471 LDM_REG(16, 4);
6472 LDM_REG(32, 5);
6473 LDM_REG(64, 6);
6474 LDM_REG(128, 7);
6475 LDM_REG(256, 8);
6476 LDM_REG(512, 9);
6477 LDM_REG(1024, 10);
6478 LDM_REG(2048, 11);
6479 LDM_REG(4096, 12);
6480 LDM_REG(8192, 13);
6481 LDM_REG(16384, 14);
6483 reg[15].I = CPUReadMemory(address);
6484 if (!offset)
6485 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6486 else
6487 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6489 CPUSwitchMode(reg[17].I & 0x1f, false);
6490 if (armState)
6492 armNextPC = reg[15].I & 0xFFFFFFFC;
6493 reg[15].I = armNextPC + 4;
6495 else
6497 armNextPC = reg[15].I & 0xFFFFFFFE;
6498 reg[15].I = armNextPC + 2;
6501 else
6503 LDM_REG(1, 0);
6504 LDM_REG(2, 1);
6505 LDM_REG(4, 2);
6506 LDM_REG(8, 3);
6507 LDM_REG(16, 4);
6508 LDM_REG(32, 5);
6509 LDM_REG(64, 6);
6510 LDM_REG(128, 7);
6512 if (armMode == 0x11)
6514 LDM_REG(256, R8_FIQ);
6515 LDM_REG(512, R9_FIQ);
6516 LDM_REG(1024, R10_FIQ);
6517 LDM_REG(2048, R11_FIQ);
6518 LDM_REG(4096, R12_FIQ);
6520 else
6522 LDM_REG(256, 8);
6523 LDM_REG(512, 9);
6524 LDM_REG(1024, 10);
6525 LDM_REG(2048, 11);
6526 LDM_REG(4096, 12);
6529 if (armMode != 0x10 && armMode != 0x1f)
6531 LDM_REG(8192, R13_USR);
6532 LDM_REG(16384, R14_USR);
6534 else
6536 LDM_REG(8192, 13);
6537 LDM_REG(16384, 14);
6541 break;
6542 CASE_16(0x870)
6544 // LDMDA Rn!, {Rlist}^
6545 int base = (opcode & 0x000F0000) >> 16;
6546 u32 temp = reg[base].I -
6547 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6548 u32 address = (temp + 4) & 0xFFFFFFFC;
6549 clockTicks += 2;
6550 int offset = 0;
6551 if (opcode & 0x8000)
6553 LDM_REG(1, 0);
6554 LDM_REG(2, 1);
6555 LDM_REG(4, 2);
6556 LDM_REG(8, 3);
6557 LDM_REG(16, 4);
6558 LDM_REG(32, 5);
6559 LDM_REG(64, 6);
6560 LDM_REG(128, 7);
6561 LDM_REG(256, 8);
6562 LDM_REG(512, 9);
6563 LDM_REG(1024, 10);
6564 LDM_REG(2048, 11);
6565 LDM_REG(4096, 12);
6566 LDM_REG(8192, 13);
6567 LDM_REG(16384, 14);
6569 reg[15].I = CPUReadMemory(address);
6570 if (!offset)
6571 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6572 else
6573 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6575 if (!(opcode & (1 << base)))
6576 reg[base].I = temp;
6578 CPUSwitchMode(reg[17].I & 0x1f, false);
6579 if (armState)
6581 armNextPC = reg[15].I & 0xFFFFFFFC;
6582 reg[15].I = armNextPC + 4;
6584 else
6586 armNextPC = reg[15].I & 0xFFFFFFFE;
6587 reg[15].I = armNextPC + 2;
6590 else
6592 LDM_REG(1, 0);
6593 LDM_REG(2, 1);
6594 LDM_REG(4, 2);
6595 LDM_REG(8, 3);
6596 LDM_REG(16, 4);
6597 LDM_REG(32, 5);
6598 LDM_REG(64, 6);
6599 LDM_REG(128, 7);
6601 if (armMode == 0x11)
6603 LDM_REG(256, R8_FIQ);
6604 LDM_REG(512, R9_FIQ);
6605 LDM_REG(1024, R10_FIQ);
6606 LDM_REG(2048, R11_FIQ);
6607 LDM_REG(4096, R12_FIQ);
6609 else
6611 LDM_REG(256, 8);
6612 LDM_REG(512, 9);
6613 LDM_REG(1024, 10);
6614 LDM_REG(2048, 11);
6615 LDM_REG(4096, 12);
6618 if (armMode != 0x10 && armMode != 0x1f)
6620 LDM_REG(8192, R13_USR);
6621 LDM_REG(16384, R14_USR);
6623 else
6625 LDM_REG(8192, 13);
6626 LDM_REG(16384, 14);
6629 if (!(opcode & (1 << base)))
6630 reg[base].I = temp;
6633 break;
6635 CASE_16(0x890)
6637 // LDMIA Rn, {Rlist}
6638 int base = (opcode & 0x000F0000) >> 16;
6639 u32 address = reg[base].I & 0xFFFFFFFC;
6640 clockTicks += 2;
6641 int offset = 0;
6642 LDM_REG(1, 0);
6643 LDM_REG(2, 1);
6644 LDM_REG(4, 2);
6645 LDM_REG(8, 3);
6646 LDM_REG(16, 4);
6647 LDM_REG(32, 5);
6648 LDM_REG(64, 6);
6649 LDM_REG(128, 7);
6650 LDM_REG(256, 8);
6651 LDM_REG(512, 9);
6652 LDM_REG(1024, 10);
6653 LDM_REG(2048, 11);
6654 LDM_REG(4096, 12);
6655 LDM_REG(8192, 13);
6656 LDM_REG(16384, 14);
6657 if (opcode & 32768)
6659 reg[15].I = CPUReadMemory(address);
6660 if (!offset)
6661 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6662 else
6663 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6664 armNextPC = reg[15].I;
6665 reg[15].I += 4;
6668 break;
6669 CASE_16(0x8b0)
6671 // LDMIA Rn!, {Rlist}
6672 int base = (opcode & 0x000F0000) >> 16;
6673 u32 temp = reg[base].I +
6674 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6675 u32 address = reg[base].I & 0xFFFFFFFC;
6676 clockTicks += 2;
6677 int offset = 0;
6678 LDM_REG(1, 0);
6679 LDM_REG(2, 1);
6680 LDM_REG(4, 2);
6681 LDM_REG(8, 3);
6682 LDM_REG(16, 4);
6683 LDM_REG(32, 5);
6684 LDM_REG(64, 6);
6685 LDM_REG(128, 7);
6686 LDM_REG(256, 8);
6687 LDM_REG(512, 9);
6688 LDM_REG(1024, 10);
6689 LDM_REG(2048, 11);
6690 LDM_REG(4096, 12);
6691 LDM_REG(8192, 13);
6692 LDM_REG(16384, 14);
6693 if (opcode & 32768)
6695 reg[15].I = CPUReadMemory(address);
6696 if (!offset)
6697 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6698 else
6699 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6700 armNextPC = reg[15].I;
6701 reg[15].I += 4;
6703 if (!(opcode & (1 << base)))
6704 reg[base].I = temp;
6706 break;
6707 CASE_16(0x8d0)
6709 // LDMIA Rn, {Rlist}^
6710 int base = (opcode & 0x000F0000) >> 16;
6711 u32 address = reg[base].I & 0xFFFFFFFC;
6712 clockTicks += 2;
6713 int offset = 0;
6714 if (opcode & 0x8000)
6716 LDM_REG(1, 0);
6717 LDM_REG(2, 1);
6718 LDM_REG(4, 2);
6719 LDM_REG(8, 3);
6720 LDM_REG(16, 4);
6721 LDM_REG(32, 5);
6722 LDM_REG(64, 6);
6723 LDM_REG(128, 7);
6724 LDM_REG(256, 8);
6725 LDM_REG(512, 9);
6726 LDM_REG(1024, 10);
6727 LDM_REG(2048, 11);
6728 LDM_REG(4096, 12);
6729 LDM_REG(8192, 13);
6730 LDM_REG(16384, 14);
6732 reg[15].I = CPUReadMemory(address);
6733 if (!offset)
6734 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6735 else
6736 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6738 CPUSwitchMode(reg[17].I & 0x1f, false);
6739 if (armState)
6741 armNextPC = reg[15].I & 0xFFFFFFFC;
6742 reg[15].I = armNextPC + 4;
6744 else
6746 armNextPC = reg[15].I & 0xFFFFFFFE;
6747 reg[15].I = armNextPC + 2;
6750 else
6752 LDM_REG(1, 0);
6753 LDM_REG(2, 1);
6754 LDM_REG(4, 2);
6755 LDM_REG(8, 3);
6756 LDM_REG(16, 4);
6757 LDM_REG(32, 5);
6758 LDM_REG(64, 6);
6759 LDM_REG(128, 7);
6761 if (armMode == 0x11)
6763 LDM_REG(256, R8_FIQ);
6764 LDM_REG(512, R9_FIQ);
6765 LDM_REG(1024, R10_FIQ);
6766 LDM_REG(2048, R11_FIQ);
6767 LDM_REG(4096, R12_FIQ);
6769 else
6771 LDM_REG(256, 8);
6772 LDM_REG(512, 9);
6773 LDM_REG(1024, 10);
6774 LDM_REG(2048, 11);
6775 LDM_REG(4096, 12);
6778 if (armMode != 0x10 && armMode != 0x1f)
6780 LDM_REG(8192, R13_USR);
6781 LDM_REG(16384, R14_USR);
6783 else
6785 LDM_REG(8192, 13);
6786 LDM_REG(16384, 14);
6790 break;
6791 CASE_16(0x8f0)
6793 // LDMIA Rn!, {Rlist}^
6794 int base = (opcode & 0x000F0000) >> 16;
6795 u32 temp = reg[base].I +
6796 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6797 u32 address = reg[base].I & 0xFFFFFFFC;
6798 clockTicks += 2;
6799 int offset = 0;
6800 if (opcode & 0x8000)
6802 LDM_REG(1, 0);
6803 LDM_REG(2, 1);
6804 LDM_REG(4, 2);
6805 LDM_REG(8, 3);
6806 LDM_REG(16, 4);
6807 LDM_REG(32, 5);
6808 LDM_REG(64, 6);
6809 LDM_REG(128, 7);
6810 LDM_REG(256, 8);
6811 LDM_REG(512, 9);
6812 LDM_REG(1024, 10);
6813 LDM_REG(2048, 11);
6814 LDM_REG(4096, 12);
6815 LDM_REG(8192, 13);
6816 LDM_REG(16384, 14);
6818 reg[15].I = CPUReadMemory(address);
6819 if (!offset)
6820 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6821 else
6822 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6824 if (!(opcode & (1 << base)))
6825 reg[base].I = temp;
6827 CPUSwitchMode(reg[17].I & 0x1f, false);
6828 if (armState)
6830 armNextPC = reg[15].I & 0xFFFFFFFC;
6831 reg[15].I = armNextPC + 4;
6833 else
6835 armNextPC = reg[15].I & 0xFFFFFFFE;
6836 reg[15].I = armNextPC + 2;
6839 else
6841 LDM_REG(1, 0);
6842 LDM_REG(2, 1);
6843 LDM_REG(4, 2);
6844 LDM_REG(8, 3);
6845 LDM_REG(16, 4);
6846 LDM_REG(32, 5);
6847 LDM_REG(64, 6);
6848 LDM_REG(128, 7);
6850 if (armMode == 0x11)
6852 LDM_REG(256, R8_FIQ);
6853 LDM_REG(512, R9_FIQ);
6854 LDM_REG(1024, R10_FIQ);
6855 LDM_REG(2048, R11_FIQ);
6856 LDM_REG(4096, R12_FIQ);
6858 else
6860 LDM_REG(256, 8);
6861 LDM_REG(512, 9);
6862 LDM_REG(1024, 10);
6863 LDM_REG(2048, 11);
6864 LDM_REG(4096, 12);
6867 if (armMode != 0x10 && armMode != 0x1f)
6869 LDM_REG(8192, R13_USR);
6870 LDM_REG(16384, R14_USR);
6872 else
6874 LDM_REG(8192, 13);
6875 LDM_REG(16384, 14);
6878 if (!(opcode & (1 << base)))
6879 reg[base].I = temp;
6882 break;
6884 CASE_16(0x910)
6886 // LDMDB Rn, {Rlist}
6887 int base = (opcode & 0x000F0000) >> 16;
6888 u32 temp = reg[base].I -
6889 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6890 u32 address = temp & 0xFFFFFFFC;
6891 clockTicks += 2;
6892 int offset = 0;
6893 LDM_REG(1, 0);
6894 LDM_REG(2, 1);
6895 LDM_REG(4, 2);
6896 LDM_REG(8, 3);
6897 LDM_REG(16, 4);
6898 LDM_REG(32, 5);
6899 LDM_REG(64, 6);
6900 LDM_REG(128, 7);
6901 LDM_REG(256, 8);
6902 LDM_REG(512, 9);
6903 LDM_REG(1024, 10);
6904 LDM_REG(2048, 11);
6905 LDM_REG(4096, 12);
6906 LDM_REG(8192, 13);
6907 LDM_REG(16384, 14);
6908 if (opcode & 32768)
6910 reg[15].I = CPUReadMemory(address);
6911 if (!offset)
6912 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6913 else
6914 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6915 armNextPC = reg[15].I;
6916 reg[15].I += 4;
6919 break;
6920 CASE_16(0x930)
6922 // LDMDB Rn!, {Rlist}
6923 int base = (opcode & 0x000F0000) >> 16;
6924 u32 temp = reg[base].I -
6925 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6926 u32 address = temp & 0xFFFFFFFC;
6927 clockTicks += 2;
6928 int offset = 0;
6929 LDM_REG(1, 0);
6930 LDM_REG(2, 1);
6931 LDM_REG(4, 2);
6932 LDM_REG(8, 3);
6933 LDM_REG(16, 4);
6934 LDM_REG(32, 5);
6935 LDM_REG(64, 6);
6936 LDM_REG(128, 7);
6937 LDM_REG(256, 8);
6938 LDM_REG(512, 9);
6939 LDM_REG(1024, 10);
6940 LDM_REG(2048, 11);
6941 LDM_REG(4096, 12);
6942 LDM_REG(8192, 13);
6943 LDM_REG(16384, 14);
6944 if (opcode & 32768)
6946 reg[15].I = CPUReadMemory(address);
6947 if (!offset)
6948 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6949 else
6950 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6951 armNextPC = reg[15].I;
6952 reg[15].I += 4;
6954 if (!(opcode & (1 << base)))
6955 reg[base].I = temp;
6957 break;
6958 CASE_16(0x950)
6960 // LDMDB Rn, {Rlist}^
6961 int base = (opcode & 0x000F0000) >> 16;
6962 u32 temp = reg[base].I -
6963 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6964 u32 address = temp & 0xFFFFFFFC;
6965 clockTicks += 2;
6966 int offset = 0;
6967 if (opcode & 0x8000)
6969 LDM_REG(1, 0);
6970 LDM_REG(2, 1);
6971 LDM_REG(4, 2);
6972 LDM_REG(8, 3);
6973 LDM_REG(16, 4);
6974 LDM_REG(32, 5);
6975 LDM_REG(64, 6);
6976 LDM_REG(128, 7);
6977 LDM_REG(256, 8);
6978 LDM_REG(512, 9);
6979 LDM_REG(1024, 10);
6980 LDM_REG(2048, 11);
6981 LDM_REG(4096, 12);
6982 LDM_REG(8192, 13);
6983 LDM_REG(16384, 14);
6985 reg[15].I = CPUReadMemory(address);
6986 if (!offset)
6987 clockTicks += 2 + CPUUpdateTicksAccess32(address);
6988 else
6989 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6991 CPUSwitchMode(reg[17].I & 0x1f, false);
6992 if (armState)
6994 armNextPC = reg[15].I & 0xFFFFFFFC;
6995 reg[15].I = armNextPC + 4;
6997 else
6999 armNextPC = reg[15].I & 0xFFFFFFFE;
7000 reg[15].I = armNextPC + 2;
7003 else
7005 LDM_REG(1, 0);
7006 LDM_REG(2, 1);
7007 LDM_REG(4, 2);
7008 LDM_REG(8, 3);
7009 LDM_REG(16, 4);
7010 LDM_REG(32, 5);
7011 LDM_REG(64, 6);
7012 LDM_REG(128, 7);
7014 if (armMode == 0x11)
7016 LDM_REG(256, R8_FIQ);
7017 LDM_REG(512, R9_FIQ);
7018 LDM_REG(1024, R10_FIQ);
7019 LDM_REG(2048, R11_FIQ);
7020 LDM_REG(4096, R12_FIQ);
7022 else
7024 LDM_REG(256, 8);
7025 LDM_REG(512, 9);
7026 LDM_REG(1024, 10);
7027 LDM_REG(2048, 11);
7028 LDM_REG(4096, 12);
7031 if (armMode != 0x10 && armMode != 0x1f)
7033 LDM_REG(8192, R13_USR);
7034 LDM_REG(16384, R14_USR);
7036 else
7038 LDM_REG(8192, 13);
7039 LDM_REG(16384, 14);
7043 break;
7044 CASE_16(0x970)
7046 // LDMDB Rn!, {Rlist}^
7047 int base = (opcode & 0x000F0000) >> 16;
7048 u32 temp = reg[base].I -
7049 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
7050 u32 address = temp & 0xFFFFFFFC;
7051 clockTicks += 2;
7052 int offset = 0;
7053 if (opcode & 0x8000)
7055 LDM_REG(1, 0);
7056 LDM_REG(2, 1);
7057 LDM_REG(4, 2);
7058 LDM_REG(8, 3);
7059 LDM_REG(16, 4);
7060 LDM_REG(32, 5);
7061 LDM_REG(64, 6);
7062 LDM_REG(128, 7);
7063 LDM_REG(256, 8);
7064 LDM_REG(512, 9);
7065 LDM_REG(1024, 10);
7066 LDM_REG(2048, 11);
7067 LDM_REG(4096, 12);
7068 LDM_REG(8192, 13);
7069 LDM_REG(16384, 14);
7071 reg[15].I = CPUReadMemory(address);
7072 if (!offset)
7073 clockTicks += 2 + CPUUpdateTicksAccess32(address);
7074 else
7075 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7077 if (!(opcode & (1 << base)))
7078 reg[base].I = temp;
7080 CPUSwitchMode(reg[17].I & 0x1f, false);
7081 if (armState)
7083 armNextPC = reg[15].I & 0xFFFFFFFC;
7084 reg[15].I = armNextPC + 4;
7086 else
7088 armNextPC = reg[15].I & 0xFFFFFFFE;
7089 reg[15].I = armNextPC + 2;
7092 else
7094 LDM_REG(1, 0);
7095 LDM_REG(2, 1);
7096 LDM_REG(4, 2);
7097 LDM_REG(8, 3);
7098 LDM_REG(16, 4);
7099 LDM_REG(32, 5);
7100 LDM_REG(64, 6);
7101 LDM_REG(128, 7);
7103 if (armMode == 0x11)
7105 LDM_REG(256, R8_FIQ);
7106 LDM_REG(512, R9_FIQ);
7107 LDM_REG(1024, R10_FIQ);
7108 LDM_REG(2048, R11_FIQ);
7109 LDM_REG(4096, R12_FIQ);
7111 else
7113 LDM_REG(256, 8);
7114 LDM_REG(512, 9);
7115 LDM_REG(1024, 10);
7116 LDM_REG(2048, 11);
7117 LDM_REG(4096, 12);
7120 if (armMode != 0x10 && armMode != 0x1f)
7122 LDM_REG(8192, R13_USR);
7123 LDM_REG(16384, R14_USR);
7125 else
7127 LDM_REG(8192, 13);
7128 LDM_REG(16384, 14);
7131 if (!(opcode & (1 << base)))
7132 reg[base].I = temp;
7135 break;
7137 CASE_16(0x990)
7139 // LDMIB Rn, {Rlist}
7140 int base = (opcode & 0x000F0000) >> 16;
7141 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
7142 clockTicks += 2;
7143 int offset = 0;
7144 LDM_REG(1, 0);
7145 LDM_REG(2, 1);
7146 LDM_REG(4, 2);
7147 LDM_REG(8, 3);
7148 LDM_REG(16, 4);
7149 LDM_REG(32, 5);
7150 LDM_REG(64, 6);
7151 LDM_REG(128, 7);
7152 LDM_REG(256, 8);
7153 LDM_REG(512, 9);
7154 LDM_REG(1024, 10);
7155 LDM_REG(2048, 11);
7156 LDM_REG(4096, 12);
7157 LDM_REG(8192, 13);
7158 LDM_REG(16384, 14);
7159 if (opcode & 32768)
7161 reg[15].I = CPUReadMemory(address);
7162 if (!offset)
7163 clockTicks += 2 + CPUUpdateTicksAccess32(address);
7164 else
7165 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7166 armNextPC = reg[15].I;
7167 reg[15].I += 4;
7170 break;
7171 CASE_16(0x9b0)
7173 // LDMIB Rn!, {Rlist}
7174 int base = (opcode & 0x000F0000) >> 16;
7175 u32 temp = reg[base].I +
7176 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
7177 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
7178 clockTicks += 2;
7179 int offset = 0;
7180 LDM_REG(1, 0);
7181 LDM_REG(2, 1);
7182 LDM_REG(4, 2);
7183 LDM_REG(8, 3);
7184 LDM_REG(16, 4);
7185 LDM_REG(32, 5);
7186 LDM_REG(64, 6);
7187 LDM_REG(128, 7);
7188 LDM_REG(256, 8);
7189 LDM_REG(512, 9);
7190 LDM_REG(1024, 10);
7191 LDM_REG(2048, 11);
7192 LDM_REG(4096, 12);
7193 LDM_REG(8192, 13);
7194 LDM_REG(16384, 14);
7195 if (opcode & 32768)
7197 reg[15].I = CPUReadMemory(address);
7198 if (!offset)
7199 clockTicks += 2 + CPUUpdateTicksAccess32(address);
7200 else
7201 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7202 armNextPC = reg[15].I;
7203 reg[15].I += 4;
7205 if (!(opcode & (1 << base)))
7206 reg[base].I = temp;
7208 break;
7209 CASE_16(0x9d0)
7211 // LDMIB Rn, {Rlist}^
7212 int base = (opcode & 0x000F0000) >> 16;
7213 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
7214 clockTicks += 2;
7215 int offset = 0;
7216 if (opcode & 0x8000)
7218 LDM_REG(1, 0);
7219 LDM_REG(2, 1);
7220 LDM_REG(4, 2);
7221 LDM_REG(8, 3);
7222 LDM_REG(16, 4);
7223 LDM_REG(32, 5);
7224 LDM_REG(64, 6);
7225 LDM_REG(128, 7);
7226 LDM_REG(256, 8);
7227 LDM_REG(512, 9);
7228 LDM_REG(1024, 10);
7229 LDM_REG(2048, 11);
7230 LDM_REG(4096, 12);
7231 LDM_REG(8192, 13);
7232 LDM_REG(16384, 14);
7234 reg[15].I = CPUReadMemory(address);
7235 if (!offset)
7236 clockTicks += 2 + CPUUpdateTicksAccess32(address);
7237 else
7238 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7240 CPUSwitchMode(reg[17].I & 0x1f, false);
7241 if (armState)
7243 armNextPC = reg[15].I & 0xFFFFFFFC;
7244 reg[15].I = armNextPC + 4;
7246 else
7248 armNextPC = reg[15].I & 0xFFFFFFFE;
7249 reg[15].I = armNextPC + 2;
7252 else
7254 LDM_REG(1, 0);
7255 LDM_REG(2, 1);
7256 LDM_REG(4, 2);
7257 LDM_REG(8, 3);
7258 LDM_REG(16, 4);
7259 LDM_REG(32, 5);
7260 LDM_REG(64, 6);
7261 LDM_REG(128, 7);
7263 if (armMode == 0x11)
7265 LDM_REG(256, R8_FIQ);
7266 LDM_REG(512, R9_FIQ);
7267 LDM_REG(1024, R10_FIQ);
7268 LDM_REG(2048, R11_FIQ);
7269 LDM_REG(4096, R12_FIQ);
7271 else
7273 LDM_REG(256, 8);
7274 LDM_REG(512, 9);
7275 LDM_REG(1024, 10);
7276 LDM_REG(2048, 11);
7277 LDM_REG(4096, 12);
7280 if (armMode != 0x10 && armMode != 0x1f)
7282 LDM_REG(8192, R13_USR);
7283 LDM_REG(16384, R14_USR);
7285 else
7287 LDM_REG(8192, 13);
7288 LDM_REG(16384, 14);
7292 break;
7293 CASE_16(0x9f0)
7295 // LDMIB Rn!, {Rlist}^
7296 int base = (opcode & 0x000F0000) >> 16;
7297 u32 temp = reg[base].I +
7298 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
7299 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
7300 clockTicks += 2;
7301 int offset = 0;
7302 if (opcode & 0x8000)
7304 LDM_REG(1, 0);
7305 LDM_REG(2, 1);
7306 LDM_REG(4, 2);
7307 LDM_REG(8, 3);
7308 LDM_REG(16, 4);
7309 LDM_REG(32, 5);
7310 LDM_REG(64, 6);
7311 LDM_REG(128, 7);
7312 LDM_REG(256, 8);
7313 LDM_REG(512, 9);
7314 LDM_REG(1024, 10);
7315 LDM_REG(2048, 11);
7316 LDM_REG(4096, 12);
7317 LDM_REG(8192, 13);
7318 LDM_REG(16384, 14);
7320 reg[15].I = CPUReadMemory(address);
7321 if (!offset)
7322 clockTicks += 2 + CPUUpdateTicksAccess32(address);
7323 else
7324 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7326 if (!(opcode & (1 << base)))
7327 reg[base].I = temp;
7329 CPUSwitchMode(reg[17].I & 0x1f, false);
7330 if (armState)
7332 armNextPC = reg[15].I & 0xFFFFFFFC;
7333 reg[15].I = armNextPC + 4;
7335 else
7337 armNextPC = reg[15].I & 0xFFFFFFFE;
7338 reg[15].I = armNextPC + 2;
7341 else
7343 LDM_REG(1, 0);
7344 LDM_REG(2, 1);
7345 LDM_REG(4, 2);
7346 LDM_REG(8, 3);
7347 LDM_REG(16, 4);
7348 LDM_REG(32, 5);
7349 LDM_REG(64, 6);
7350 LDM_REG(128, 7);
7352 if (armMode == 0x11)
7354 LDM_REG(256, R8_FIQ);
7355 LDM_REG(512, R9_FIQ);
7356 LDM_REG(1024, R10_FIQ);
7357 LDM_REG(2048, R11_FIQ);
7358 LDM_REG(4096, R12_FIQ);
7360 else
7362 LDM_REG(256, 8);
7363 LDM_REG(512, 9);
7364 LDM_REG(1024, 10);
7365 LDM_REG(2048, 11);
7366 LDM_REG(4096, 12);
7369 if (armMode != 0x10 && armMode != 0x1f)
7371 LDM_REG(8192, R13_USR);
7372 LDM_REG(16384, R14_USR);
7374 else
7376 LDM_REG(8192, 13);
7377 LDM_REG(16384, 14);
7380 if (!(opcode & (1 << base)))
7381 reg[base].I = temp;
7384 break;
7385 CASE_256(0xa00)
7387 // B <offset>
7388 clockTicks += 3;
7389 int offset = opcode & 0x00FFFFFF;
7390 if (offset & 0x00800000)
7392 offset |= 0xFF000000;
7394 offset <<= 2;
7395 reg[15].I += offset;
7396 armNextPC = reg[15].I;
7397 reg[15].I += 4;
7399 break;
7400 CASE_256(0xb00)
7402 // BL <offset>
7403 clockTicks += 3;
7404 int offset = opcode & 0x00FFFFFF;
7405 if (offset & 0x00800000)
7407 offset |= 0xFF000000;
7409 offset <<= 2;
7410 reg[14].I = reg[15].I - 4;
7411 reg[15].I += offset;
7412 armNextPC = reg[15].I;
7413 reg[15].I += 4;
7415 break;
7416 CASE_256(0xf00)
7417 // SWI <comment>
7418 clockTicks += 3;
7419 CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
7420 break;
7421 #ifdef GP_SUPPORT
7422 case 0xe11:
7423 case 0xe13:
7424 case 0xe15:
7425 case 0xe17:
7426 case 0xe19:
7427 case 0xe1b:
7428 case 0xe1d:
7429 case 0xe1f:
7430 // MRC
7431 break;
7432 case 0xe01:
7433 case 0xe03:
7434 case 0xe05:
7435 case 0xe07:
7436 case 0xe09:
7437 case 0xe0b:
7438 case 0xe0d:
7439 case 0xe0f:
7440 // MRC
7441 break;
7442 #endif
7443 default:
7444 #ifdef GBA_LOGGING
7445 if (systemVerbose & VERBOSE_UNDEFINED)
7446 log("Undefined ARM instruction %08x at %08x\n", opcode,
7447 armNextPC - 4);
7448 #endif
7449 CPUUndefinedException();
7450 break;
7451 // END