revive PC build, support Linux
[gpsp.git] / cpu_threaded.c
CommitLineData
2823a4c8 1/* gameplaySP
2 *
3 * Copyright (C) 2006 Exophase <exophase@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20// Not-so-important todo:
21// - stm reglist writeback when base is in the list needs adjustment
22// - block memory needs psr swapping and user mode reg swapping
23
24#include <stdio.h>
25#include "common.h"
26
27u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
28u8 *rom_translation_ptr = rom_translation_cache;
29
30u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
31u8 *ram_translation_ptr = ram_translation_cache;
32u32 iwram_code_min = 0xFFFFFFFF;
33u32 iwram_code_max = 0xFFFFFFFF;
34u32 ewram_code_min = 0xFFFFFFFF;
35u32 ewram_code_max = 0xFFFFFFFF;
36
37u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
38u8 *bios_translation_ptr = bios_translation_cache;
39
40u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];
41
42// Default
43u32 idle_loop_target_pc = 0xFFFFFFFF;
44u32 force_pc_update_target = 0xFFFFFFFF;
45u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
46u32 translation_gate_targets = 0;
47u32 iwram_stack_optimize = 1;
48u32 allow_smc_ram_u8 = 1;
49u32 allow_smc_ram_u16 = 1;
50u32 allow_smc_ram_u32 = 1;
51
52typedef struct
53{
54 u8 *block_offset;
55 u16 flag_data;
56 u8 condition;
57 u8 update_cycles;
58} block_data_type;
59
60typedef struct
61{
62 u32 branch_target;
63 u8 *branch_source;
64} block_exit_type;
65
66extern u8 bit_count[256];
67
68#define arm_decode_data_proc_reg() \
69 u32 rn = (opcode >> 16) & 0x0F; \
70 u32 rd = (opcode >> 12) & 0x0F; \
71 u32 rm = opcode & 0x0F \
72
73#define arm_decode_data_proc_imm() \
74 u32 rn = (opcode >> 16) & 0x0F; \
75 u32 rd = (opcode >> 12) & 0x0F; \
76 u32 imm = opcode & 0xFF; \
77 u32 imm_ror = ((opcode >> 8) & 0x0F) * 2 \
78
79#define arm_decode_psr_reg() \
80 u32 psr_field = (opcode >> 16) & 0x0F; \
81 u32 rd = (opcode >> 12) & 0x0F; \
82 u32 rm = opcode & 0x0F \
83
84#define arm_decode_psr_imm() \
85 u32 psr_field = (opcode >> 16) & 0x0F; \
86 u32 rd = (opcode >> 12) & 0x0F; \
87 u32 imm = opcode & 0xFF; \
88 u32 imm_ror = ((opcode >> 8) & 0x0F) * 2 \
89
90#define arm_decode_branchx() \
91 u32 rn = opcode & 0x0F \
92
93#define arm_decode_multiply() \
94 u32 rd = (opcode >> 16) & 0x0F; \
95 u32 rn = (opcode >> 12) & 0x0F; \
96 u32 rs = (opcode >> 8) & 0x0F; \
97 u32 rm = opcode & 0x0F \
98
99#define arm_decode_multiply_long() \
100 u32 rdhi = (opcode >> 16) & 0x0F; \
101 u32 rdlo = (opcode >> 12) & 0x0F; \
102 u32 rs = (opcode >> 8) & 0x0F; \
103 u32 rm = opcode & 0x0F \
104
105#define arm_decode_swap() \
106 u32 rn = (opcode >> 16) & 0x0F; \
107 u32 rd = (opcode >> 12) & 0x0F; \
108 u32 rm = opcode & 0x0F \
109
110#define arm_decode_half_trans_r() \
111 u32 rn = (opcode >> 16) & 0x0F; \
112 u32 rd = (opcode >> 12) & 0x0F; \
113 u32 rm = opcode & 0x0F \
114
115#define arm_decode_half_trans_of() \
116 u32 rn = (opcode >> 16) & 0x0F; \
117 u32 rd = (opcode >> 12) & 0x0F; \
118 u32 offset = ((opcode >> 4) & 0xF0) | (opcode & 0x0F) \
119
120#define arm_decode_data_trans_imm() \
121 u32 rn = (opcode >> 16) & 0x0F; \
122 u32 rd = (opcode >> 12) & 0x0F; \
123 u32 offset = opcode & 0x0FFF \
124
125#define arm_decode_data_trans_reg() \
126 u32 rn = (opcode >> 16) & 0x0F; \
127 u32 rd = (opcode >> 12) & 0x0F; \
128 u32 rm = opcode & 0x0F \
129
130#define arm_decode_block_trans() \
131 u32 rn = (opcode >> 16) & 0x0F; \
132 u32 reg_list = opcode & 0xFFFF \
133
134#define arm_decode_branch() \
135 s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6 \
136
137#define thumb_decode_shift() \
138 u32 imm = (opcode >> 6) & 0x1F; \
139 u32 rs = (opcode >> 3) & 0x07; \
140 u32 rd = opcode & 0x07 \
141
142#define thumb_decode_add_sub() \
143 u32 rn = (opcode >> 6) & 0x07; \
144 u32 rs = (opcode >> 3) & 0x07; \
145 u32 rd = opcode & 0x07 \
146
147#define thumb_decode_add_sub_imm() \
148 u32 imm = (opcode >> 6) & 0x07; \
149 u32 rs = (opcode >> 3) & 0x07; \
150 u32 rd = opcode & 0x07 \
151
152#define thumb_decode_imm() \
153 u32 imm = opcode & 0xFF \
154
155#define thumb_decode_alu_op() \
156 u32 rs = (opcode >> 3) & 0x07; \
157 u32 rd = opcode & 0x07 \
158
159#define thumb_decode_hireg_op() \
160 u32 rs = (opcode >> 3) & 0x0F; \
161 u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x07) \
162
163#define thumb_decode_mem_reg() \
164 u32 ro = (opcode >> 6) & 0x07; \
165 u32 rb = (opcode >> 3) & 0x07; \
166 u32 rd = opcode & 0x07 \
167
168#define thumb_decode_mem_imm() \
169 u32 imm = (opcode >> 6) & 0x1F; \
170 u32 rb = (opcode >> 3) & 0x07; \
171 u32 rd = opcode & 0x07 \
172
173#define thumb_decode_add_sp() \
174 u32 imm = opcode & 0x7F \
175
176#define thumb_decode_rlist() \
177 u32 reg_list = opcode & 0xFF \
178
179#define thumb_decode_branch_cond() \
180 s32 offset = (s8)(opcode & 0xFF) \
181
182#define thumb_decode_swi() \
183 u32 comment = opcode & 0xFF \
184
185#define thumb_decode_branch() \
186 u32 offset = opcode & 0x07FF \
187
188
189#ifdef PSP_BUILD
190
191#include "psp/mips_emit.h"
192
d5e0983c 193#elif defined(ARM_ARCH)
2823a4c8 194
d5e0983c 195#include "arm/arm_emit.h"
2823a4c8 196
197#else
198
199#include "x86/x86_emit.h"
200
201#endif
202
203
204#define check_pc_region(pc) \
205 new_pc_region = (pc >> 15); \
206 if(new_pc_region != pc_region) \
207 { \
208 pc_region = new_pc_region; \
209 pc_address_block = memory_map_read[new_pc_region]; \
210 \
211 if(pc_address_block == NULL) \
212 pc_address_block = load_gamepak_page(pc_region & 0x3FF); \
213 } \
214
215#define translate_arm_instruction() \
216 check_pc_region(pc); \
217 opcode = address32(pc_address_block, (pc & 0x7FFF)); \
218 condition = block_data[block_data_position].condition; \
219 \
220 if((condition != last_condition) || (condition >= 0x20)) \
221 { \
222 if((last_condition & 0x0F) != 0x0E) \
223 { \
224 generate_branch_patch_conditional(backpatch_address, translation_ptr); \
225 } \
226 \
227 last_condition = condition; \
228 \
229 condition &= 0x0F; \
230 \
231 if(condition != 0x0E) \
232 { \
233 arm_conditional_block_header(); \
234 } \
235 } \
236 \
237 switch((opcode >> 20) & 0xFF) \
238 { \
239 case 0x00: \
240 if((opcode & 0x90) == 0x90) \
241 { \
242 if(opcode & 0x20) \
243 { \
244 /* STRH rd, [rn], -rm */ \
245 arm_access_memory(store, down, post, u16, half_reg); \
246 } \
247 else \
248 { \
249 /* MUL rd, rm, rs */ \
250 arm_multiply(no, no); \
251 } \
252 } \
253 else \
254 { \
255 /* AND rd, rn, reg_op */ \
256 arm_data_proc(and, reg, no_flags); \
257 } \
258 break; \
259 \
260 case 0x01: \
261 if((opcode & 0x90) == 0x90) \
262 { \
263 switch((opcode >> 5) & 0x03) \
264 { \
265 case 0: \
266 /* MULS rd, rm, rs */ \
267 arm_multiply(no, yes); \
268 break; \
269 \
270 case 1: \
271 /* LDRH rd, [rn], -rm */ \
272 arm_access_memory(load, down, post, u16, half_reg); \
273 break; \
274 \
275 case 2: \
276 /* LDRSB rd, [rn], -rm */ \
277 arm_access_memory(load, down, post, s8, half_reg); \
278 break; \
279 \
280 case 3: \
281 /* LDRSH rd, [rn], -rm */ \
282 arm_access_memory(load, down, post, s16, half_reg); \
283 break; \
284 } \
285 } \
286 else \
287 { \
288 /* ANDS rd, rn, reg_op */ \
289 arm_data_proc(ands, reg_flags, flags); \
290 } \
291 break; \
292 \
293 case 0x02: \
294 if((opcode & 0x90) == 0x90) \
295 { \
296 if(opcode & 0x20) \
297 { \
298 /* STRH rd, [rn], -rm */ \
299 arm_access_memory(store, down, post, u16, half_reg); \
300 } \
301 else \
302 { \
303 /* MLA rd, rm, rs, rn */ \
304 arm_multiply(yes, no); \
305 } \
306 } \
307 else \
308 { \
309 /* EOR rd, rn, reg_op */ \
310 arm_data_proc(eor, reg, no_flags); \
311 } \
312 break; \
313 \
314 case 0x03: \
315 if((opcode & 0x90) == 0x90) \
316 { \
317 switch((opcode >> 5) & 0x03) \
318 { \
319 case 0: \
320 /* MLAS rd, rm, rs, rn */ \
321 arm_multiply(yes, yes); \
322 break; \
323 \
324 case 1: \
325 /* LDRH rd, [rn], -rm */ \
326 arm_access_memory(load, down, post, u16, half_reg); \
327 break; \
328 \
329 case 2: \
330 /* LDRSB rd, [rn], -rm */ \
331 arm_access_memory(load, down, post, s8, half_reg); \
332 break; \
333 \
334 case 3: \
335 /* LDRSH rd, [rn], -rm */ \
336 arm_access_memory(load, down, post, s16, half_reg); \
337 break; \
338 } \
339 } \
340 else \
341 { \
342 /* EORS rd, rn, reg_op */ \
343 arm_data_proc(eors, reg_flags, flags); \
344 } \
345 break; \
346 \
347 case 0x04: \
348 if((opcode & 0x90) == 0x90) \
349 { \
350 /* STRH rd, [rn], -imm */ \
351 arm_access_memory(store, down, post, u16, half_imm); \
352 } \
353 else \
354 { \
355 /* SUB rd, rn, reg_op */ \
356 arm_data_proc(sub, reg, no_flags); \
357 } \
358 break; \
359 \
360 case 0x05: \
361 if((opcode & 0x90) == 0x90) \
362 { \
363 switch((opcode >> 5) & 0x03) \
364 { \
365 case 1: \
366 /* LDRH rd, [rn], -imm */ \
367 arm_access_memory(load, down, post, u16, half_imm); \
368 break; \
369 \
370 case 2: \
371 /* LDRSB rd, [rn], -imm */ \
372 arm_access_memory(load, down, post, s8, half_imm); \
373 break; \
374 \
375 case 3: \
376 /* LDRSH rd, [rn], -imm */ \
377 arm_access_memory(load, down, post, s16, half_imm); \
378 break; \
379 } \
380 } \
381 else \
382 { \
383 /* SUBS rd, rn, reg_op */ \
384 arm_data_proc(subs, reg, flags); \
385 } \
386 break; \
387 \
388 case 0x06: \
389 if((opcode & 0x90) == 0x90) \
390 { \
391 /* STRH rd, [rn], -imm */ \
392 arm_access_memory(store, down, post, u16, half_imm); \
393 } \
394 else \
395 { \
396 /* RSB rd, rn, reg_op */ \
397 arm_data_proc(rsb, reg, no_flags); \
398 } \
399 break; \
400 \
401 case 0x07: \
402 if((opcode & 0x90) == 0x90) \
403 { \
404 switch((opcode >> 5) & 0x03) \
405 { \
406 case 1: \
407 /* LDRH rd, [rn], -imm */ \
408 arm_access_memory(load, down, post, u16, half_imm); \
409 break; \
410 \
411 case 2: \
412 /* LDRSB rd, [rn], -imm */ \
413 arm_access_memory(load, down, post, s8, half_imm); \
414 break; \
415 \
416 case 3: \
417 /* LDRSH rd, [rn], -imm */ \
418 arm_access_memory(load, down, post, s16, half_imm); \
419 break; \
420 } \
421 } \
422 else \
423 { \
424 /* RSBS rd, rn, reg_op */ \
425 arm_data_proc(rsbs, reg, flags); \
426 } \
427 break; \
428 \
429 case 0x08: \
430 if((opcode & 0x90) == 0x90) \
431 { \
432 if(opcode & 0x20) \
433 { \
434 /* STRH rd, [rn], +rm */ \
435 arm_access_memory(store, up, post, u16, half_reg); \
436 } \
437 else \
438 { \
439 /* UMULL rd, rm, rs */ \
440 arm_multiply_long(u64, no, no); \
441 } \
442 } \
443 else \
444 { \
445 /* ADD rd, rn, reg_op */ \
446 arm_data_proc(add, reg, no_flags); \
447 } \
448 break; \
449 \
450 case 0x09: \
451 if((opcode & 0x90) == 0x90) \
452 { \
453 switch((opcode >> 5) & 0x03) \
454 { \
455 case 0: \
456 /* UMULLS rdlo, rdhi, rm, rs */ \
457 arm_multiply_long(u64, no, yes); \
458 break; \
459 \
460 case 1: \
461 /* LDRH rd, [rn], +rm */ \
462 arm_access_memory(load, up, post, u16, half_reg); \
463 break; \
464 \
465 case 2: \
466 /* LDRSB rd, [rn], +rm */ \
467 arm_access_memory(load, up, post, s8, half_reg); \
468 break; \
469 \
470 case 3: \
471 /* LDRSH rd, [rn], +rm */ \
472 arm_access_memory(load, up, post, s16, half_reg); \
473 break; \
474 } \
475 } \
476 else \
477 { \
478 /* ADDS rd, rn, reg_op */ \
479 arm_data_proc(adds, reg, flags); \
480 } \
481 break; \
482 \
483 case 0x0A: \
484 if((opcode & 0x90) == 0x90) \
485 { \
486 if(opcode & 0x20) \
487 { \
488 /* STRH rd, [rn], +rm */ \
489 arm_access_memory(store, up, post, u16, half_reg); \
490 } \
491 else \
492 { \
493 /* UMLAL rd, rm, rs */ \
494 arm_multiply_long(u64_add, yes, no); \
495 } \
496 } \
497 else \
498 { \
499 /* ADC rd, rn, reg_op */ \
500 arm_data_proc(adc, reg, no_flags); \
501 } \
502 break; \
503 \
504 case 0x0B: \
505 if((opcode & 0x90) == 0x90) \
506 { \
507 switch((opcode >> 5) & 0x03) \
508 { \
509 case 0: \
510 /* UMLALS rdlo, rdhi, rm, rs */ \
511 arm_multiply_long(u64_add, yes, yes); \
512 break; \
513 \
514 case 1: \
515 /* LDRH rd, [rn], +rm */ \
516 arm_access_memory(load, up, post, u16, half_reg); \
517 break; \
518 \
519 case 2: \
520 /* LDRSB rd, [rn], +rm */ \
521 arm_access_memory(load, up, post, s8, half_reg); \
522 break; \
523 \
524 case 3: \
525 /* LDRSH rd, [rn], +rm */ \
526 arm_access_memory(load, up, post, s16, half_reg); \
527 break; \
528 } \
529 } \
530 else \
531 { \
532 /* ADCS rd, rn, reg_op */ \
533 arm_data_proc(adcs, reg, flags); \
534 } \
535 break; \
536 \
537 case 0x0C: \
538 if((opcode & 0x90) == 0x90) \
539 { \
540 if(opcode & 0x20) \
541 { \
542 /* STRH rd, [rn], +imm */ \
543 arm_access_memory(store, up, post, u16, half_imm); \
544 } \
545 else \
546 { \
547 /* SMULL rd, rm, rs */ \
548 arm_multiply_long(s64, no, no); \
549 } \
550 } \
551 else \
552 { \
553 /* SBC rd, rn, reg_op */ \
554 arm_data_proc(sbc, reg, no_flags); \
555 } \
556 break; \
557 \
558 case 0x0D: \
559 if((opcode & 0x90) == 0x90) \
560 { \
561 switch((opcode >> 5) & 0x03) \
562 { \
563 case 0: \
564 /* SMULLS rdlo, rdhi, rm, rs */ \
565 arm_multiply_long(s64, no, yes); \
566 break; \
567 \
568 case 1: \
569 /* LDRH rd, [rn], +imm */ \
570 arm_access_memory(load, up, post, u16, half_imm); \
571 break; \
572 \
573 case 2: \
574 /* LDRSB rd, [rn], +imm */ \
575 arm_access_memory(load, up, post, s8, half_imm); \
576 break; \
577 \
578 case 3: \
579 /* LDRSH rd, [rn], +imm */ \
580 arm_access_memory(load, up, post, s16, half_imm); \
581 break; \
582 } \
583 } \
584 else \
585 { \
586 /* SBCS rd, rn, reg_op */ \
587 arm_data_proc(sbcs, reg, flags); \
588 } \
589 break; \
590 \
591 case 0x0E: \
592 if((opcode & 0x90) == 0x90) \
593 { \
594 if(opcode & 0x20) \
595 { \
596 /* STRH rd, [rn], +imm */ \
597 arm_access_memory(store, up, post, u16, half_imm); \
598 } \
599 else \
600 { \
601 /* SMLAL rd, rm, rs */ \
602 arm_multiply_long(s64_add, yes, no); \
603 } \
604 } \
605 else \
606 { \
607 /* RSC rd, rn, reg_op */ \
608 arm_data_proc(rsc, reg, no_flags); \
609 } \
610 break; \
611 \
612 case 0x0F: \
613 if((opcode & 0x90) == 0x90) \
614 { \
615 switch((opcode >> 5) & 0x03) \
616 { \
617 case 0: \
618 /* SMLALS rdlo, rdhi, rm, rs */ \
619 arm_multiply_long(s64_add, yes, yes); \
620 break; \
621 \
622 case 1: \
623 /* LDRH rd, [rn], +imm */ \
624 arm_access_memory(load, up, post, u16, half_imm); \
625 break; \
626 \
627 case 2: \
628 /* LDRSB rd, [rn], +imm */ \
629 arm_access_memory(load, up, post, s8, half_imm); \
630 break; \
631 \
632 case 3: \
633 /* LDRSH rd, [rn], +imm */ \
634 arm_access_memory(load, up, post, s16, half_imm); \
635 break; \
636 } \
637 } \
638 else \
639 { \
640 /* RSCS rd, rn, reg_op */ \
641 arm_data_proc(rscs, reg, flags); \
642 } \
643 break; \
644 \
645 case 0x10: \
646 if((opcode & 0x90) == 0x90) \
647 { \
648 if(opcode & 0x20) \
649 { \
650 /* STRH rd, [rn - rm] */ \
651 arm_access_memory(store, down, pre, u16, half_reg); \
652 } \
653 else \
654 { \
655 /* SWP rd, rm, [rn] */ \
656 arm_swap(u32); \
657 } \
658 } \
659 else \
660 { \
661 /* MRS rd, cpsr */ \
662 arm_psr(reg, read, cpsr); \
663 } \
664 break; \
665 \
666 case 0x11: \
667 if((opcode & 0x90) == 0x90) \
668 { \
669 switch((opcode >> 5) & 0x03) \
670 { \
671 case 1: \
672 /* LDRH rd, [rn - rm] */ \
673 arm_access_memory(load, down, pre, u16, half_reg); \
674 break; \
675 \
676 case 2: \
677 /* LDRSB rd, [rn - rm] */ \
678 arm_access_memory(load, down, pre, s8, half_reg); \
679 break; \
680 \
681 case 3: \
682 /* LDRSH rd, [rn - rm] */ \
683 arm_access_memory(load, down, pre, s16, half_reg); \
684 break; \
685 } \
686 } \
687 else \
688 { \
689 /* TST rd, rn, reg_op */ \
690 arm_data_proc_test(tst, reg_flags); \
691 } \
692 break; \
693 \
694 case 0x12: \
695 if((opcode & 0x90) == 0x90) \
696 { \
697 /* STRH rd, [rn - rm]! */ \
698 arm_access_memory(store, down, pre_wb, u16, half_reg); \
699 } \
700 else \
701 { \
702 if(opcode & 0x10) \
703 { \
704 /* BX rn */ \
705 arm_bx(); \
706 } \
707 else \
708 { \
709 /* MSR cpsr, rm */ \
710 arm_psr(reg, store, cpsr); \
711 } \
712 } \
713 break; \
714 \
715 case 0x13: \
716 if((opcode & 0x90) == 0x90) \
717 { \
718 switch((opcode >> 5) & 0x03) \
719 { \
720 case 1: \
721 /* LDRH rd, [rn - rm]! */ \
722 arm_access_memory(load, down, pre_wb, u16, half_reg); \
723 break; \
724 \
725 case 2: \
726 /* LDRSB rd, [rn - rm]! */ \
727 arm_access_memory(load, down, pre_wb, s8, half_reg); \
728 break; \
729 \
730 case 3: \
731 /* LDRSH rd, [rn - rm]! */ \
732 arm_access_memory(load, down, pre_wb, s16, half_reg); \
733 break; \
734 } \
735 } \
736 else \
737 { \
738 /* TEQ rd, rn, reg_op */ \
739 arm_data_proc_test(teq, reg_flags); \
740 } \
741 break; \
742 \
743 case 0x14: \
744 if((opcode & 0x90) == 0x90) \
745 { \
746 if(opcode & 0x20) \
747 { \
748 /* STRH rd, [rn - imm] */ \
749 arm_access_memory(store, down, pre, u16, half_imm); \
750 } \
751 else \
752 { \
753 /* SWPB rd, rm, [rn] */ \
754 arm_swap(u8); \
755 } \
756 } \
757 else \
758 { \
759 /* MRS rd, spsr */ \
760 arm_psr(reg, read, spsr); \
761 } \
762 break; \
763 \
764 case 0x15: \
765 if((opcode & 0x90) == 0x90) \
766 { \
767 switch((opcode >> 5) & 0x03) \
768 { \
769 case 1: \
770 /* LDRH rd, [rn - imm] */ \
771 arm_access_memory(load, down, pre, u16, half_imm); \
772 break; \
773 \
774 case 2: \
775 /* LDRSB rd, [rn - imm] */ \
776 arm_access_memory(load, down, pre, s8, half_imm); \
777 break; \
778 \
779 case 3: \
780 /* LDRSH rd, [rn - imm] */ \
781 arm_access_memory(load, down, pre, s16, half_imm); \
782 break; \
783 } \
784 } \
785 else \
786 { \
787 /* CMP rn, reg_op */ \
788 arm_data_proc_test(cmp, reg); \
789 } \
790 break; \
791 \
792 case 0x16: \
793 if((opcode & 0x90) == 0x90) \
794 { \
795 /* STRH rd, [rn - imm]! */ \
796 arm_access_memory(store, down, pre_wb, u16, half_imm); \
797 } \
798 else \
799 { \
800 /* MSR spsr, rm */ \
801 arm_psr(reg, store, spsr); \
802 } \
803 break; \
804 \
805 case 0x17: \
806 if((opcode & 0x90) == 0x90) \
807 { \
808 switch((opcode >> 5) & 0x03) \
809 { \
810 case 1: \
811 /* LDRH rd, [rn - imm]! */ \
812 arm_access_memory(load, down, pre_wb, u16, half_imm); \
813 break; \
814 \
815 case 2: \
816 /* LDRSB rd, [rn - imm]! */ \
817 arm_access_memory(load, down, pre_wb, s8, half_imm); \
818 break; \
819 \
820 case 3: \
821 /* LDRSH rd, [rn - imm]! */ \
822 arm_access_memory(load, down, pre_wb, s16, half_imm); \
823 break; \
824 } \
825 } \
826 else \
827 { \
828 /* CMN rd, rn, reg_op */ \
829 arm_data_proc_test(cmn, reg); \
830 } \
831 break; \
832 \
833 case 0x18: \
834 if((opcode & 0x90) == 0x90) \
835 { \
836 /* STRH rd, [rn + rm] */ \
837 arm_access_memory(store, up, pre, u16, half_reg); \
838 } \
839 else \
840 { \
841 /* ORR rd, rn, reg_op */ \
842 arm_data_proc(orr, reg, no_flags); \
843 } \
844 break; \
845 \
846 case 0x19: \
847 if((opcode & 0x90) == 0x90) \
848 { \
849 switch((opcode >> 5) & 0x03) \
850 { \
851 case 1: \
852 /* LDRH rd, [rn + rm] */ \
853 arm_access_memory(load, up, pre, u16, half_reg); \
854 break; \
855 \
856 case 2: \
857 /* LDRSB rd, [rn + rm] */ \
858 arm_access_memory(load, up, pre, s8, half_reg); \
859 break; \
860 \
861 case 3: \
862 /* LDRSH rd, [rn + rm] */ \
863 arm_access_memory(load, up, pre, s16, half_reg); \
864 break; \
865 } \
866 } \
867 else \
868 { \
869 /* ORRS rd, rn, reg_op */ \
870 arm_data_proc(orrs, reg_flags, flags); \
871 } \
872 break; \
873 \
874 case 0x1A: \
875 if((opcode & 0x90) == 0x90) \
876 { \
877 /* STRH rd, [rn + rm]! */ \
878 arm_access_memory(store, up, pre_wb, u16, half_reg); \
879 } \
880 else \
881 { \
882 /* MOV rd, reg_op */ \
883 arm_data_proc_unary(mov, reg, no_flags); \
884 } \
885 break; \
886 \
887 case 0x1B: \
888 if((opcode & 0x90) == 0x90) \
889 { \
890 switch((opcode >> 5) & 0x03) \
891 { \
892 case 1: \
893 /* LDRH rd, [rn + rm]! */ \
894 arm_access_memory(load, up, pre_wb, u16, half_reg); \
895 break; \
896 \
897 case 2: \
898 /* LDRSB rd, [rn + rm]! */ \
899 arm_access_memory(load, up, pre_wb, s8, half_reg); \
900 break; \
901 \
902 case 3: \
903 /* LDRSH rd, [rn + rm]! */ \
904 arm_access_memory(load, up, pre_wb, s16, half_reg); \
905 break; \
906 } \
907 } \
908 else \
909 { \
910 /* MOVS rd, reg_op */ \
911 arm_data_proc_unary(movs, reg_flags, flags); \
912 } \
913 break; \
914 \
915 case 0x1C: \
916 if((opcode & 0x90) == 0x90) \
917 { \
918 /* STRH rd, [rn + imm] */ \
919 arm_access_memory(store, up, pre, u16, half_imm); \
920 } \
921 else \
922 { \
923 /* BIC rd, rn, reg_op */ \
924 arm_data_proc(bic, reg, no_flags); \
925 } \
926 break; \
927 \
928 case 0x1D: \
929 if((opcode & 0x90) == 0x90) \
930 { \
931 switch((opcode >> 5) & 0x03) \
932 { \
933 case 1: \
934 /* LDRH rd, [rn + imm] */ \
935 arm_access_memory(load, up, pre, u16, half_imm); \
936 break; \
937 \
938 case 2: \
939 /* LDRSB rd, [rn + imm] */ \
940 arm_access_memory(load, up, pre, s8, half_imm); \
941 break; \
942 \
943 case 3: \
944 /* LDRSH rd, [rn + imm] */ \
945 arm_access_memory(load, up, pre, s16, half_imm); \
946 break; \
947 } \
948 } \
949 else \
950 { \
951 /* BICS rd, rn, reg_op */ \
952 arm_data_proc(bics, reg_flags, flags); \
953 } \
954 break; \
955 \
956 case 0x1E: \
957 if((opcode & 0x90) == 0x90) \
958 { \
959 /* STRH rd, [rn + imm]! */ \
960 arm_access_memory(store, up, pre_wb, u16, half_imm); \
961 } \
962 else \
963 { \
964 /* MVN rd, reg_op */ \
965 arm_data_proc_unary(mvn, reg, no_flags); \
966 } \
967 break; \
968 \
969 case 0x1F: \
970 if((opcode & 0x90) == 0x90) \
971 { \
972 switch((opcode >> 5) & 0x03) \
973 { \
974 case 1: \
975 /* LDRH rd, [rn + imm]! */ \
976 arm_access_memory(load, up, pre_wb, u16, half_imm); \
977 break; \
978 \
979 case 2: \
980 /* LDRSB rd, [rn + imm]! */ \
981 arm_access_memory(load, up, pre_wb, s8, half_imm); \
982 break; \
983 \
984 case 3: \
985 /* LDRSH rd, [rn + imm]! */ \
986 arm_access_memory(load, up, pre_wb, s16, half_imm); \
987 break; \
988 } \
989 } \
990 else \
991 { \
992 /* MVNS rd, rn, reg_op */ \
993 arm_data_proc_unary(mvns, reg_flags, flags); \
994 } \
995 break; \
996 \
997 case 0x20: \
998 /* AND rd, rn, imm */ \
999 arm_data_proc(and, imm, no_flags); \
1000 break; \
1001 \
1002 case 0x21: \
1003 /* ANDS rd, rn, imm */ \
1004 arm_data_proc(ands, imm_flags, flags); \
1005 break; \
1006 \
1007 case 0x22: \
1008 /* EOR rd, rn, imm */ \
1009 arm_data_proc(eor, imm, no_flags); \
1010 break; \
1011 \
1012 case 0x23: \
1013 /* EORS rd, rn, imm */ \
1014 arm_data_proc(eors, imm_flags, flags); \
1015 break; \
1016 \
1017 case 0x24: \
1018 /* SUB rd, rn, imm */ \
1019 arm_data_proc(sub, imm, no_flags); \
1020 break; \
1021 \
1022 case 0x25: \
1023 /* SUBS rd, rn, imm */ \
1024 arm_data_proc(subs, imm, flags); \
1025 break; \
1026 \
1027 case 0x26: \
1028 /* RSB rd, rn, imm */ \
1029 arm_data_proc(rsb, imm, no_flags); \
1030 break; \
1031 \
1032 case 0x27: \
1033 /* RSBS rd, rn, imm */ \
1034 arm_data_proc(rsbs, imm, flags); \
1035 break; \
1036 \
1037 case 0x28: \
1038 /* ADD rd, rn, imm */ \
1039 arm_data_proc(add, imm, no_flags); \
1040 break; \
1041 \
1042 case 0x29: \
1043 /* ADDS rd, rn, imm */ \
1044 arm_data_proc(adds, imm, flags); \
1045 break; \
1046 \
1047 case 0x2A: \
1048 /* ADC rd, rn, imm */ \
1049 arm_data_proc(adc, imm, no_flags); \
1050 break; \
1051 \
1052 case 0x2B: \
1053 /* ADCS rd, rn, imm */ \
1054 arm_data_proc(adcs, imm, flags); \
1055 break; \
1056 \
1057 case 0x2C: \
1058 /* SBC rd, rn, imm */ \
1059 arm_data_proc(sbc, imm, no_flags); \
1060 break; \
1061 \
1062 case 0x2D: \
1063 /* SBCS rd, rn, imm */ \
1064 arm_data_proc(sbcs, imm, flags); \
1065 break; \
1066 \
1067 case 0x2E: \
1068 /* RSC rd, rn, imm */ \
1069 arm_data_proc(rsc, imm, no_flags); \
1070 break; \
1071 \
1072 case 0x2F: \
1073 /* RSCS rd, rn, imm */ \
1074 arm_data_proc(rscs, imm, flags); \
1075 break; \
1076 \
1077 case 0x30 ... 0x31: \
1078 /* TST rn, imm */ \
1079 arm_data_proc_test(tst, imm); \
1080 break; \
1081 \
1082 case 0x32: \
1083 /* MSR cpsr, imm */ \
1084 arm_psr(imm, store, cpsr); \
1085 break; \
1086 \
1087 case 0x33: \
1088 /* TEQ rn, imm */ \
1089 arm_data_proc_test(teq, imm); \
1090 break; \
1091 \
1092 case 0x34 ... 0x35: \
1093 /* CMP rn, imm */ \
1094 arm_data_proc_test(cmp, imm); \
1095 break; \
1096 \
1097 case 0x36: \
1098 /* MSR spsr, imm */ \
1099 arm_psr(imm, store, spsr); \
1100 break; \
1101 \
1102 case 0x37: \
1103 /* CMN rn, imm */ \
1104 arm_data_proc_test(cmn, imm); \
1105 break; \
1106 \
1107 case 0x38: \
1108 /* ORR rd, rn, imm */ \
1109 arm_data_proc(orr, imm, no_flags); \
1110 break; \
1111 \
1112 case 0x39: \
1113 /* ORRS rd, rn, imm */ \
1114 arm_data_proc(orrs, imm_flags, flags); \
1115 break; \
1116 \
1117 case 0x3A: \
1118 /* MOV rd, imm */ \
1119 arm_data_proc_unary(mov, imm, no_flags); \
1120 break; \
1121 \
1122 case 0x3B: \
1123 /* MOVS rd, imm */ \
1124 arm_data_proc_unary(movs, imm_flags, flags); \
1125 break; \
1126 \
1127 case 0x3C: \
1128 /* BIC rd, rn, imm */ \
1129 arm_data_proc(bic, imm, no_flags); \
1130 break; \
1131 \
1132 case 0x3D: \
1133 /* BICS rd, rn, imm */ \
1134 arm_data_proc(bics, imm_flags, flags); \
1135 break; \
1136 \
1137 case 0x3E: \
1138 /* MVN rd, imm */ \
1139 arm_data_proc_unary(mvn, imm, no_flags); \
1140 break; \
1141 \
1142 case 0x3F: \
1143 /* MVNS rd, imm */ \
1144 arm_data_proc_unary(mvns, imm_flags, flags); \
1145 break; \
1146 \
1147 case 0x40: \
1148 /* STR rd, [rn], -imm */ \
1149 arm_access_memory(store, down, post, u32, imm); \
1150 break; \
1151 \
1152 case 0x41: \
1153 /* LDR rd, [rn], -imm */ \
1154 arm_access_memory(load, down, post, u32, imm); \
1155 break; \
1156 \
1157 case 0x42: \
1158 /* STRT rd, [rn], -imm */ \
1159 arm_access_memory(store, down, post, u32, imm); \
1160 break; \
1161 \
1162 case 0x43: \
1163 /* LDRT rd, [rn], -imm */ \
1164 arm_access_memory(load, down, post, u32, imm); \
1165 break; \
1166 \
1167 case 0x44: \
1168 /* STRB rd, [rn], -imm */ \
1169 arm_access_memory(store, down, post, u8, imm); \
1170 break; \
1171 \
1172 case 0x45: \
1173 /* LDRB rd, [rn], -imm */ \
1174 arm_access_memory(load, down, post, u8, imm); \
1175 break; \
1176 \
1177 case 0x46: \
1178 /* STRBT rd, [rn], -imm */ \
1179 arm_access_memory(store, down, post, u8, imm); \
1180 break; \
1181 \
1182 case 0x47: \
1183 /* LDRBT rd, [rn], -imm */ \
1184 arm_access_memory(load, down, post, u8, imm); \
1185 break; \
1186 \
1187 case 0x48: \
1188 /* STR rd, [rn], +imm */ \
1189 arm_access_memory(store, up, post, u32, imm); \
1190 break; \
1191 \
1192 case 0x49: \
1193 /* LDR rd, [rn], +imm */ \
1194 arm_access_memory(load, up, post, u32, imm); \
1195 break; \
1196 \
1197 case 0x4A: \
1198 /* STRT rd, [rn], +imm */ \
1199 arm_access_memory(store, up, post, u32, imm); \
1200 break; \
1201 \
1202 case 0x4B: \
1203 /* LDRT rd, [rn], +imm */ \
1204 arm_access_memory(load, up, post, u32, imm); \
1205 break; \
1206 \
1207 case 0x4C: \
1208 /* STRB rd, [rn], +imm */ \
1209 arm_access_memory(store, up, post, u8, imm); \
1210 break; \
1211 \
1212 case 0x4D: \
1213 /* LDRB rd, [rn], +imm */ \
1214 arm_access_memory(load, up, post, u8, imm); \
1215 break; \
1216 \
1217 case 0x4E: \
1218 /* STRBT rd, [rn], +imm */ \
1219 arm_access_memory(store, up, post, u8, imm); \
1220 break; \
1221 \
1222 case 0x4F: \
1223 /* LDRBT rd, [rn], +imm */ \
1224 arm_access_memory(load, up, post, u8, imm); \
1225 break; \
1226 \
1227 case 0x50: \
1228 /* STR rd, [rn - imm] */ \
1229 arm_access_memory(store, down, pre, u32, imm); \
1230 break; \
1231 \
1232 case 0x51: \
1233 /* LDR rd, [rn - imm] */ \
1234 arm_access_memory(load, down, pre, u32, imm); \
1235 break; \
1236 \
1237 case 0x52: \
1238 /* STR rd, [rn - imm]! */ \
1239 arm_access_memory(store, down, pre_wb, u32, imm); \
1240 break; \
1241 \
1242 case 0x53: \
1243 /* LDR rd, [rn - imm]! */ \
1244 arm_access_memory(load, down, pre_wb, u32, imm); \
1245 break; \
1246 \
1247 case 0x54: \
1248 /* STRB rd, [rn - imm] */ \
1249 arm_access_memory(store, down, pre, u8, imm); \
1250 break; \
1251 \
1252 case 0x55: \
1253 /* LDRB rd, [rn - imm] */ \
1254 arm_access_memory(load, down, pre, u8, imm); \
1255 break; \
1256 \
1257 case 0x56: \
1258 /* STRB rd, [rn - imm]! */ \
1259 arm_access_memory(store, down, pre_wb, u8, imm); \
1260 break; \
1261 \
1262 case 0x57: \
1263 /* LDRB rd, [rn - imm]! */ \
1264 arm_access_memory(load, down, pre_wb, u8, imm); \
1265 break; \
1266 \
1267 case 0x58: \
1268 /* STR rd, [rn + imm] */ \
1269 arm_access_memory(store, up, pre, u32, imm); \
1270 break; \
1271 \
1272 case 0x59: \
1273 /* LDR rd, [rn + imm] */ \
1274 arm_access_memory(load, up, pre, u32, imm); \
1275 break; \
1276 \
1277 case 0x5A: \
1278 /* STR rd, [rn + imm]! */ \
1279 arm_access_memory(store, up, pre_wb, u32, imm); \
1280 break; \
1281 \
1282 case 0x5B: \
1283 /* LDR rd, [rn + imm]! */ \
1284 arm_access_memory(load, up, pre_wb, u32, imm); \
1285 break; \
1286 \
1287 case 0x5C: \
1288 /* STRB rd, [rn + imm] */ \
1289 arm_access_memory(store, up, pre, u8, imm); \
1290 break; \
1291 \
1292 case 0x5D: \
1293 /* LDRB rd, [rn + imm] */ \
1294 arm_access_memory(load, up, pre, u8, imm); \
1295 break; \
1296 \
1297 case 0x5E: \
1298 /* STRB rd, [rn + imm]! */ \
1299 arm_access_memory(store, up, pre_wb, u8, imm); \
1300 break; \
1301 \
1302 case 0x5F: \
1303 /* LDRBT rd, [rn + imm]! */ \
1304 arm_access_memory(load, up, pre_wb, u8, imm); \
1305 break; \
1306 \
1307 case 0x60: \
1308 /* STR rd, [rn], -rm */ \
1309 arm_access_memory(store, down, post, u32, reg); \
1310 break; \
1311 \
1312 case 0x61: \
1313 /* LDR rd, [rn], -rm */ \
1314 arm_access_memory(load, down, post, u32, reg); \
1315 break; \
1316 \
1317 case 0x62: \
1318 /* STRT rd, [rn], -rm */ \
1319 arm_access_memory(store, down, post, u32, reg); \
1320 break; \
1321 \
1322 case 0x63: \
1323 /* LDRT rd, [rn], -rm */ \
1324 arm_access_memory(load, down, post, u32, reg); \
1325 break; \
1326 \
1327 case 0x64: \
1328 /* STRB rd, [rn], -rm */ \
1329 arm_access_memory(store, down, post, u8, reg); \
1330 break; \
1331 \
1332 case 0x65: \
1333 /* LDRB rd, [rn], -rm */ \
1334 arm_access_memory(load, down, post, u8, reg); \
1335 break; \
1336 \
1337 case 0x66: \
1338 /* STRBT rd, [rn], -rm */ \
1339 arm_access_memory(store, down, post, u8, reg); \
1340 break; \
1341 \
1342 case 0x67: \
1343 /* LDRBT rd, [rn], -rm */ \
1344 arm_access_memory(load, down, post, u8, reg); \
1345 break; \
1346 \
1347 case 0x68: \
1348 /* STR rd, [rn], +rm */ \
1349 arm_access_memory(store, up, post, u32, reg); \
1350 break; \
1351 \
1352 case 0x69: \
1353 /* LDR rd, [rn], +rm */ \
1354 arm_access_memory(load, up, post, u32, reg); \
1355 break; \
1356 \
1357 case 0x6A: \
1358 /* STRT rd, [rn], +rm */ \
1359 arm_access_memory(store, up, post, u32, reg); \
1360 break; \
1361 \
1362 case 0x6B: \
1363 /* LDRT rd, [rn], +rm */ \
1364 arm_access_memory(load, up, post, u32, reg); \
1365 break; \
1366 \
1367 case 0x6C: \
1368 /* STRB rd, [rn], +rm */ \
1369 arm_access_memory(store, up, post, u8, reg); \
1370 break; \
1371 \
1372 case 0x6D: \
1373 /* LDRB rd, [rn], +rm */ \
1374 arm_access_memory(load, up, post, u8, reg); \
1375 break; \
1376 \
1377 case 0x6E: \
1378 /* STRBT rd, [rn], +rm */ \
1379 arm_access_memory(store, up, post, u8, reg); \
1380 break; \
1381 \
1382 case 0x6F: \
1383 /* LDRBT rd, [rn], +rm */ \
1384 arm_access_memory(load, up, post, u8, reg); \
1385 break; \
1386 \
1387 case 0x70: \
1388 /* STR rd, [rn - rm] */ \
1389 arm_access_memory(store, down, pre, u32, reg); \
1390 break; \
1391 \
1392 case 0x71: \
1393 /* LDR rd, [rn - rm] */ \
1394 arm_access_memory(load, down, pre, u32, reg); \
1395 break; \
1396 \
1397 case 0x72: \
1398 /* STR rd, [rn - rm]! */ \
1399 arm_access_memory(store, down, pre_wb, u32, reg); \
1400 break; \
1401 \
1402 case 0x73: \
1403 /* LDR rd, [rn - rm]! */ \
1404 arm_access_memory(load, down, pre_wb, u32, reg); \
1405 break; \
1406 \
1407 case 0x74: \
1408 /* STRB rd, [rn - rm] */ \
1409 arm_access_memory(store, down, pre, u8, reg); \
1410 break; \
1411 \
1412 case 0x75: \
1413 /* LDRB rd, [rn - rm] */ \
1414 arm_access_memory(load, down, pre, u8, reg); \
1415 break; \
1416 \
1417 case 0x76: \
1418 /* STRB rd, [rn - rm]! */ \
1419 arm_access_memory(store, down, pre_wb, u8, reg); \
1420 break; \
1421 \
1422 case 0x77: \
1423 /* LDRB rd, [rn - rm]! */ \
1424 arm_access_memory(load, down, pre_wb, u8, reg); \
1425 break; \
1426 \
1427 case 0x78: \
1428 /* STR rd, [rn + rm] */ \
1429 arm_access_memory(store, up, pre, u32, reg); \
1430 break; \
1431 \
1432 case 0x79: \
1433 /* LDR rd, [rn + rm] */ \
1434 arm_access_memory(load, up, pre, u32, reg); \
1435 break; \
1436 \
1437 case 0x7A: \
1438 /* STR rd, [rn + rm]! */ \
1439 arm_access_memory(store, up, pre_wb, u32, reg); \
1440 break; \
1441 \
1442 case 0x7B: \
1443 /* LDR rd, [rn + rm]! */ \
1444 arm_access_memory(load, up, pre_wb, u32, reg); \
1445 break; \
1446 \
1447 case 0x7C: \
1448 /* STRB rd, [rn + rm] */ \
1449 arm_access_memory(store, up, pre, u8, reg); \
1450 break; \
1451 \
1452 case 0x7D: \
1453 /* LDRB rd, [rn + rm] */ \
1454 arm_access_memory(load, up, pre, u8, reg); \
1455 break; \
1456 \
1457 case 0x7E: \
1458 /* STRB rd, [rn + rm]! */ \
1459 arm_access_memory(store, up, pre_wb, u8, reg); \
1460 break; \
1461 \
1462 case 0x7F: \
1463 /* LDRBT rd, [rn + rm]! */ \
1464 arm_access_memory(load, up, pre_wb, u8, reg); \
1465 break; \
1466 \
1467 case 0x80: \
1468 /* STMDA rn, rlist */ \
1469 arm_block_memory(store, down_a, no, no); \
1470 break; \
1471 \
1472 case 0x81: \
1473 /* LDMDA rn, rlist */ \
1474 arm_block_memory(load, down_a, no, no); \
1475 break; \
1476 \
1477 case 0x82: \
1478 /* STMDA rn!, rlist */ \
1479 arm_block_memory(store, down_a, down, no); \
1480 break; \
1481 \
1482 case 0x83: \
1483 /* LDMDA rn!, rlist */ \
1484 arm_block_memory(load, down_a, down, no); \
1485 break; \
1486 \
1487 case 0x84: \
1488 /* STMDA rn, rlist^ */ \
1489 arm_block_memory(store, down_a, no, yes); \
1490 break; \
1491 \
1492 case 0x85: \
1493 /* LDMDA rn, rlist^ */ \
1494 arm_block_memory(load, down_a, no, yes); \
1495 break; \
1496 \
1497 case 0x86: \
1498 /* STMDA rn!, rlist^ */ \
1499 arm_block_memory(store, down_a, down, yes); \
1500 break; \
1501 \
1502 case 0x87: \
1503 /* LDMDA rn!, rlist^ */ \
1504 arm_block_memory(load, down_a, down, yes); \
1505 break; \
1506 \
1507 case 0x88: \
1508 /* STMIA rn, rlist */ \
1509 arm_block_memory(store, no, no, no); \
1510 break; \
1511 \
1512 case 0x89: \
1513 /* LDMIA rn, rlist */ \
1514 arm_block_memory(load, no, no, no); \
1515 break; \
1516 \
1517 case 0x8A: \
1518 /* STMIA rn!, rlist */ \
1519 arm_block_memory(store, no, up, no); \
1520 break; \
1521 \
1522 case 0x8B: \
1523 /* LDMIA rn!, rlist */ \
1524 arm_block_memory(load, no, up, no); \
1525 break; \
1526 \
1527 case 0x8C: \
1528 /* STMIA rn, rlist^ */ \
1529 arm_block_memory(store, no, no, yes); \
1530 break; \
1531 \
1532 case 0x8D: \
1533 /* LDMIA rn, rlist^ */ \
1534 arm_block_memory(load, no, no, yes); \
1535 break; \
1536 \
1537 case 0x8E: \
1538 /* STMIA rn!, rlist^ */ \
1539 arm_block_memory(store, no, up, yes); \
1540 break; \
1541 \
1542 case 0x8F: \
1543 /* LDMIA rn!, rlist^ */ \
1544 arm_block_memory(load, no, up, yes); \
1545 break; \
1546 \
1547 case 0x90: \
1548 /* STMDB rn, rlist */ \
1549 arm_block_memory(store, down_b, no, no); \
1550 break; \
1551 \
1552 case 0x91: \
1553 /* LDMDB rn, rlist */ \
1554 arm_block_memory(load, down_b, no, no); \
1555 break; \
1556 \
1557 case 0x92: \
1558 /* STMDB rn!, rlist */ \
1559 arm_block_memory(store, down_b, down, no); \
1560 break; \
1561 \
1562 case 0x93: \
1563 /* LDMDB rn!, rlist */ \
1564 arm_block_memory(load, down_b, down, no); \
1565 break; \
1566 \
1567 case 0x94: \
1568 /* STMDB rn, rlist^ */ \
1569 arm_block_memory(store, down_b, no, yes); \
1570 break; \
1571 \
1572 case 0x95: \
1573 /* LDMDB rn, rlist^ */ \
1574 arm_block_memory(load, down_b, no, yes); \
1575 break; \
1576 \
1577 case 0x96: \
1578 /* STMDB rn!, rlist^ */ \
1579 arm_block_memory(store, down_b, down, yes); \
1580 break; \
1581 \
1582 case 0x97: \
1583 /* LDMDB rn!, rlist^ */ \
1584 arm_block_memory(load, down_b, down, yes); \
1585 break; \
1586 \
1587 case 0x98: \
1588 /* STMIB rn, rlist */ \
1589 arm_block_memory(store, up, no, no); \
1590 break; \
1591 \
1592 case 0x99: \
1593 /* LDMIB rn, rlist */ \
1594 arm_block_memory(load, up, no, no); \
1595 break; \
1596 \
1597 case 0x9A: \
1598 /* STMIB rn!, rlist */ \
1599 arm_block_memory(store, up, up, no); \
1600 break; \
1601 \
1602 case 0x9B: \
1603 /* LDMIB rn!, rlist */ \
1604 arm_block_memory(load, up, up, no); \
1605 break; \
1606 \
1607 case 0x9C: \
1608 /* STMIB rn, rlist^ */ \
1609 arm_block_memory(store, up, no, yes); \
1610 break; \
1611 \
1612 case 0x9D: \
1613 /* LDMIB rn, rlist^ */ \
1614 arm_block_memory(load, up, no, yes); \
1615 break; \
1616 \
1617 case 0x9E: \
1618 /* STMIB rn!, rlist^ */ \
1619 arm_block_memory(store, up, up, yes); \
1620 break; \
1621 \
1622 case 0x9F: \
1623 /* LDMIB rn!, rlist^ */ \
1624 arm_block_memory(load, up, up, yes); \
1625 break; \
1626 \
1627 case 0xA0 ... 0xAF: \
1628 { \
1629 /* B offset */ \
1630 arm_b(); \
1631 break; \
1632 } \
1633 \
1634 case 0xB0 ... 0xBF: \
1635 { \
1636 /* BL offset */ \
1637 arm_bl(); \
1638 break; \
1639 } \
1640 \
1641 case 0xC0 ... 0xEF: \
1642 /* coprocessor instructions, reserved on GBA */ \
1643 break; \
1644 \
1645 case 0xF0 ... 0xFF: \
1646 { \
1647 /* SWI comment */ \
1648 arm_swi(); \
1649 break; \
1650 } \
1651 } \
1652 \
1653 pc += 4 \
1654
1655#define arm_flag_status() \
1656
1657#define translate_thumb_instruction() \
1658 flag_status = block_data[block_data_position].flag_data; \
1659 check_pc_region(pc); \
1660 last_opcode = opcode; \
1661 opcode = address16(pc_address_block, (pc & 0x7FFF)); \
1662 \
1663 switch((opcode >> 8) & 0xFF) \
1664 { \
1665 case 0x00 ... 0x07: \
1666 /* LSL rd, rs, imm */ \
1667 thumb_shift(shift, lsl, imm); \
1668 break; \
1669 \
1670 case 0x08 ... 0x0F: \
1671 /* LSR rd, rs, imm */ \
1672 thumb_shift(shift, lsr, imm); \
1673 break; \
1674 \
1675 case 0x10 ... 0x17: \
1676 /* ASR rd, rs, imm */ \
1677 thumb_shift(shift, asr, imm); \
1678 break; \
1679 \
1680 case 0x18 ... 0x19: \
1681 /* ADD rd, rs, rn */ \
1682 thumb_data_proc(add_sub, adds, reg, rd, rs, rn); \
1683 break; \
1684 \
1685 case 0x1A ... 0x1B: \
1686 /* SUB rd, rs, rn */ \
1687 thumb_data_proc(add_sub, subs, reg, rd, rs, rn); \
1688 break; \
1689 \
1690 case 0x1C ... 0x1D: \
1691 /* ADD rd, rs, imm */ \
1692 thumb_data_proc(add_sub_imm, adds, imm, rd, rs, imm); \
1693 break; \
1694 \
1695 case 0x1E ... 0x1F: \
1696 /* SUB rd, rs, imm */ \
1697 thumb_data_proc(add_sub_imm, subs, imm, rd, rs, imm); \
1698 break; \
1699 \
1700 case 0x20: \
1701 /* MOV r0, imm */ \
1702 thumb_data_proc_unary(imm, movs, imm, 0, imm); \
1703 break; \
1704 \
1705 case 0x21: \
1706 /* MOV r1, imm */ \
1707 thumb_data_proc_unary(imm, movs, imm, 1, imm); \
1708 break; \
1709 \
1710 case 0x22: \
1711 /* MOV r2, imm */ \
1712 thumb_data_proc_unary(imm, movs, imm, 2, imm); \
1713 break; \
1714 \
1715 case 0x23: \
1716 /* MOV r3, imm */ \
1717 thumb_data_proc_unary(imm, movs, imm, 3, imm); \
1718 break; \
1719 \
1720 case 0x24: \
1721 /* MOV r4, imm */ \
1722 thumb_data_proc_unary(imm, movs, imm, 4, imm); \
1723 break; \
1724 \
1725 case 0x25: \
1726 /* MOV r5, imm */ \
1727 thumb_data_proc_unary(imm, movs, imm, 5, imm); \
1728 break; \
1729 \
1730 case 0x26: \
1731 /* MOV r6, imm */ \
1732 thumb_data_proc_unary(imm, movs, imm, 6, imm); \
1733 break; \
1734 \
1735 case 0x27: \
1736 /* MOV r7, imm */ \
1737 thumb_data_proc_unary(imm, movs, imm, 7, imm); \
1738 break; \
1739 \
1740 case 0x28: \
1741 /* CMP r0, imm */ \
1742 thumb_data_proc_test(imm, cmp, imm, 0, imm); \
1743 break; \
1744 \
1745 case 0x29: \
1746 /* CMP r1, imm */ \
1747 thumb_data_proc_test(imm, cmp, imm, 1, imm); \
1748 break; \
1749 \
1750 case 0x2A: \
1751 /* CMP r2, imm */ \
1752 thumb_data_proc_test(imm, cmp, imm, 2, imm); \
1753 break; \
1754 \
1755 case 0x2B: \
1756 /* CMP r3, imm */ \
1757 thumb_data_proc_test(imm, cmp, imm, 3, imm); \
1758 break; \
1759 \
1760 case 0x2C: \
1761 /* CMP r4, imm */ \
1762 thumb_data_proc_test(imm, cmp, imm, 4, imm); \
1763 break; \
1764 \
1765 case 0x2D: \
1766 /* CMP r5, imm */ \
1767 thumb_data_proc_test(imm, cmp, imm, 5, imm); \
1768 break; \
1769 \
1770 case 0x2E: \
1771 /* CMP r6, imm */ \
1772 thumb_data_proc_test(imm, cmp, imm, 6, imm); \
1773 break; \
1774 \
1775 case 0x2F: \
1776 /* CMP r7, imm */ \
1777 thumb_data_proc_test(imm, cmp, imm, 7, imm); \
1778 break; \
1779 \
1780 case 0x30: \
1781 /* ADD r0, imm */ \
1782 thumb_data_proc(imm, adds, imm, 0, 0, imm); \
1783 break; \
1784 \
1785 case 0x31: \
1786 /* ADD r1, imm */ \
1787 thumb_data_proc(imm, adds, imm, 1, 1, imm); \
1788 break; \
1789 \
1790 case 0x32: \
1791 /* ADD r2, imm */ \
1792 thumb_data_proc(imm, adds, imm, 2, 2, imm); \
1793 break; \
1794 \
1795 case 0x33: \
1796 /* ADD r3, imm */ \
1797 thumb_data_proc(imm, adds, imm, 3, 3, imm); \
1798 break; \
1799 \
1800 case 0x34: \
1801 /* ADD r4, imm */ \
1802 thumb_data_proc(imm, adds, imm, 4, 4, imm); \
1803 break; \
1804 \
1805 case 0x35: \
1806 /* ADD r5, imm */ \
1807 thumb_data_proc(imm, adds, imm, 5, 5, imm); \
1808 break; \
1809 \
1810 case 0x36: \
1811 /* ADD r6, imm */ \
1812 thumb_data_proc(imm, adds, imm, 6, 6, imm); \
1813 break; \
1814 \
1815 case 0x37: \
1816 /* ADD r7, imm */ \
1817 thumb_data_proc(imm, adds, imm, 7, 7, imm); \
1818 break; \
1819 \
1820 case 0x38: \
1821 /* SUB r0, imm */ \
1822 thumb_data_proc(imm, subs, imm, 0, 0, imm); \
1823 break; \
1824 \
1825 case 0x39: \
1826 /* SUB r1, imm */ \
1827 thumb_data_proc(imm, subs, imm, 1, 1, imm); \
1828 break; \
1829 \
1830 case 0x3A: \
1831 /* SUB r2, imm */ \
1832 thumb_data_proc(imm, subs, imm, 2, 2, imm); \
1833 break; \
1834 \
1835 case 0x3B: \
1836 /* SUB r3, imm */ \
1837 thumb_data_proc(imm, subs, imm, 3, 3, imm); \
1838 break; \
1839 \
1840 case 0x3C: \
1841 /* SUB r4, imm */ \
1842 thumb_data_proc(imm, subs, imm, 4, 4, imm); \
1843 break; \
1844 \
1845 case 0x3D: \
1846 /* SUB r5, imm */ \
1847 thumb_data_proc(imm, subs, imm, 5, 5, imm); \
1848 break; \
1849 \
1850 case 0x3E: \
1851 /* SUB r6, imm */ \
1852 thumb_data_proc(imm, subs, imm, 6, 6, imm); \
1853 break; \
1854 \
1855 case 0x3F: \
1856 /* SUB r7, imm */ \
1857 thumb_data_proc(imm, subs, imm, 7, 7, imm); \
1858 break; \
1859 \
1860 case 0x40: \
1861 switch((opcode >> 6) & 0x03) \
1862 { \
1863 case 0x00: \
1864 /* AND rd, rs */ \
1865 thumb_data_proc(alu_op, ands, reg, rd, rd, rs); \
1866 break; \
1867 \
1868 case 0x01: \
1869 /* EOR rd, rs */ \
1870 thumb_data_proc(alu_op, eors, reg, rd, rd, rs); \
1871 break; \
1872 \
1873 case 0x02: \
1874 /* LSL rd, rs */ \
1875 thumb_shift(alu_op, lsl, reg); \
1876 break; \
1877 \
1878 case 0x03: \
1879 /* LSR rd, rs */ \
1880 thumb_shift(alu_op, lsr, reg); \
1881 break; \
1882 } \
1883 break; \
1884 \
1885 case 0x41: \
1886 switch((opcode >> 6) & 0x03) \
1887 { \
1888 case 0x00: \
1889 /* ASR rd, rs */ \
1890 thumb_shift(alu_op, asr, reg); \
1891 break; \
1892 \
1893 case 0x01: \
1894 /* ADC rd, rs */ \
1895 thumb_data_proc(alu_op, adcs, reg, rd, rd, rs); \
1896 break; \
1897 \
1898 case 0x02: \
1899 /* SBC rd, rs */ \
1900 thumb_data_proc(alu_op, sbcs, reg, rd, rd, rs); \
1901 break; \
1902 \
1903 case 0x03: \
1904 /* ROR rd, rs */ \
1905 thumb_shift(alu_op, ror, reg); \
1906 break; \
1907 } \
1908 break; \
1909 \
1910 case 0x42: \
1911 switch((opcode >> 6) & 0x03) \
1912 { \
1913 case 0x00: \
1914 /* TST rd, rs */ \
1915 thumb_data_proc_test(alu_op, tst, reg, rd, rs); \
1916 break; \
1917 \
1918 case 0x01: \
1919 /* NEG rd, rs */ \
1920 thumb_data_proc_unary(alu_op, neg, reg, rd, rs); \
1921 break; \
1922 \
1923 case 0x02: \
1924 /* CMP rd, rs */ \
1925 thumb_data_proc_test(alu_op, cmp, reg, rd, rs); \
1926 break; \
1927 \
1928 case 0x03: \
1929 /* CMN rd, rs */ \
1930 thumb_data_proc_test(alu_op, cmn, reg, rd, rs); \
1931 break; \
1932 } \
1933 break; \
1934 \
1935 case 0x43: \
1936 switch((opcode >> 6) & 0x03) \
1937 { \
1938 case 0x00: \
1939 /* ORR rd, rs */ \
1940 thumb_data_proc(alu_op, orrs, reg, rd, rd, rs); \
1941 break; \
1942 \
1943 case 0x01: \
1944 /* MUL rd, rs */ \
1945 thumb_data_proc(alu_op, muls, reg, rd, rd, rs); \
1946 break; \
1947 \
1948 case 0x02: \
1949 /* BIC rd, rs */ \
1950 thumb_data_proc(alu_op, bics, reg, rd, rd, rs); \
1951 break; \
1952 \
1953 case 0x03: \
1954 /* MVN rd, rs */ \
1955 thumb_data_proc_unary(alu_op, mvns, reg, rd, rs); \
1956 break; \
1957 } \
1958 break; \
1959 \
1960 case 0x44: \
1961 /* ADD rd, rs */ \
1962 thumb_data_proc_hi(add); \
1963 break; \
1964 \
1965 case 0x45: \
1966 /* CMP rd, rs */ \
1967 thumb_data_proc_test_hi(cmp); \
1968 break; \
1969 \
1970 case 0x46: \
1971 /* MOV rd, rs */ \
1972 thumb_data_proc_mov_hi(); \
1973 break; \
1974 \
1975 case 0x47: \
1976 /* BX rs */ \
1977 thumb_bx(); \
1978 break; \
1979 \
1980 case 0x48: \
1981 /* LDR r0, [pc + imm] */ \
1982 thumb_access_memory(load, imm, 0, 0, 0, pc_relative, \
1983 (pc & ~2) + (imm * 4) + 4, u32); \
1984 break; \
1985 \
1986 case 0x49: \
1987 /* LDR r1, [pc + imm] */ \
1988 thumb_access_memory(load, imm, 1, 0, 0, pc_relative, \
1989 (pc & ~2) + (imm * 4) + 4, u32); \
1990 break; \
1991 \
1992 case 0x4A: \
1993 /* LDR r2, [pc + imm] */ \
1994 thumb_access_memory(load, imm, 2, 0, 0, pc_relative, \
1995 (pc & ~2) + (imm * 4) + 4, u32); \
1996 break; \
1997 \
1998 case 0x4B: \
1999 /* LDR r3, [pc + imm] */ \
2000 thumb_access_memory(load, imm, 3, 0, 0, pc_relative, \
2001 (pc & ~2) + (imm * 4) + 4, u32); \
2002 break; \
2003 \
2004 case 0x4C: \
2005 /* LDR r4, [pc + imm] */ \
2006 thumb_access_memory(load, imm, 4, 0, 0, pc_relative, \
2007 (pc & ~2) + (imm * 4) + 4, u32); \
2008 break; \
2009 \
2010 case 0x4D: \
2011 /* LDR r5, [pc + imm] */ \
2012 thumb_access_memory(load, imm, 5, 0, 0, pc_relative, \
2013 (pc & ~2) + (imm * 4) + 4, u32); \
2014 break; \
2015 \
2016 case 0x4E: \
2017 /* LDR r6, [pc + imm] */ \
2018 thumb_access_memory(load, imm, 6, 0, 0, pc_relative, \
2019 (pc & ~2) + (imm * 4) + 4, u32); \
2020 break; \
2021 \
2022 case 0x4F: \
2023 /* LDR r7, [pc + imm] */ \
2024 thumb_access_memory(load, imm, 7, 0, 0, pc_relative, \
2025 (pc & ~2) + (imm * 4) + 4, u32); \
2026 break; \
2027 \
2028 case 0x50 ... 0x51: \
2029 /* STR rd, [rb + ro] */ \
2030 thumb_access_memory(store, mem_reg, rd, rb, ro, reg_reg, 0, u32); \
2031 break; \
2032 \
2033 case 0x52 ... 0x53: \
2034 /* STRH rd, [rb + ro] */ \
2035 thumb_access_memory(store, mem_reg, rd, rb, ro, reg_reg, 0, u16); \
2036 break; \
2037 \
2038 case 0x54 ... 0x55: \
2039 /* STRB rd, [rb + ro] */ \
2040 thumb_access_memory(store, mem_reg, rd, rb, ro, reg_reg, 0, u8); \
2041 break; \
2042 \
2043 case 0x56 ... 0x57: \
2044 /* LDSB rd, [rb + ro] */ \
2045 thumb_access_memory(load, mem_reg, rd, rb, ro, reg_reg, 0, s8); \
2046 break; \
2047 \
2048 case 0x58 ... 0x59: \
2049 /* LDR rd, [rb + ro] */ \
2050 thumb_access_memory(load, mem_reg, rd, rb, ro, reg_reg, 0, u32); \
2051 break; \
2052 \
2053 case 0x5A ... 0x5B: \
2054 /* LDRH rd, [rb + ro] */ \
2055 thumb_access_memory(load, mem_reg, rd, rb, ro, reg_reg, 0, u16); \
2056 break; \
2057 \
2058 case 0x5C ... 0x5D: \
2059 /* LDRB rd, [rb + ro] */ \
2060 thumb_access_memory(load, mem_reg, rd, rb, ro, reg_reg, 0, u8); \
2061 break; \
2062 \
2063 case 0x5E ... 0x5F: \
2064 /* LDSH rd, [rb + ro] */ \
2065 thumb_access_memory(load, mem_reg, rd, rb, ro, reg_reg, 0, s16); \
2066 break; \
2067 \
2068 case 0x60 ... 0x67: \
2069 /* STR rd, [rb + imm] */ \
2070 thumb_access_memory(store, mem_imm, rd, rb, 0, reg_imm, (imm * 4), \
2071 u32); \
2072 break; \
2073 \
2074 case 0x68 ... 0x6F: \
2075 /* LDR rd, [rb + imm] */ \
2076 thumb_access_memory(load, mem_imm, rd, rb, 0, reg_imm, (imm * 4), u32); \
2077 break; \
2078 \
2079 case 0x70 ... 0x77: \
2080 /* STRB rd, [rb + imm] */ \
2081 thumb_access_memory(store, mem_imm, rd, rb, 0, reg_imm, imm, u8); \
2082 break; \
2083 \
2084 case 0x78 ... 0x7F: \
2085 /* LDRB rd, [rb + imm] */ \
2086 thumb_access_memory(load, mem_imm, rd, rb, 0, reg_imm, imm, u8); \
2087 break; \
2088 \
2089 case 0x80 ... 0x87: \
2090 /* STRH rd, [rb + imm] */ \
2091 thumb_access_memory(store, mem_imm, rd, rb, 0, reg_imm, \
2092 (imm * 2), u16); \
2093 break; \
2094 \
2095 case 0x88 ... 0x8F: \
2096 /* LDRH rd, [rb + imm] */ \
2097 thumb_access_memory(load, mem_imm, rd, rb, 0, reg_imm, (imm * 2), u16); \
2098 break; \
2099 \
2100 case 0x90: \
2101 /* STR r0, [sp + imm] */ \
2102 thumb_access_memory(store, imm, 0, 13, 0, reg_imm_sp, imm, u32); \
2103 break; \
2104 \
2105 case 0x91: \
2106 /* STR r1, [sp + imm] */ \
2107 thumb_access_memory(store, imm, 1, 13, 0, reg_imm_sp, imm, u32); \
2108 break; \
2109 \
2110 case 0x92: \
2111 /* STR r2, [sp + imm] */ \
2112 thumb_access_memory(store, imm, 2, 13, 0, reg_imm_sp, imm, u32); \
2113 break; \
2114 \
2115 case 0x93: \
2116 /* STR r3, [sp + imm] */ \
2117 thumb_access_memory(store, imm, 3, 13, 0, reg_imm_sp, imm, u32); \
2118 break; \
2119 \
2120 case 0x94: \
2121 /* STR r4, [sp + imm] */ \
2122 thumb_access_memory(store, imm, 4, 13, 0, reg_imm_sp, imm, u32); \
2123 break; \
2124 \
2125 case 0x95: \
2126 /* STR r5, [sp + imm] */ \
2127 thumb_access_memory(store, imm, 5, 13, 0, reg_imm_sp, imm, u32); \
2128 break; \
2129 \
2130 case 0x96: \
2131 /* STR r6, [sp + imm] */ \
2132 thumb_access_memory(store, imm, 6, 13, 0, reg_imm_sp, imm, u32); \
2133 break; \
2134 \
2135 case 0x97: \
2136 /* STR r7, [sp + imm] */ \
2137 thumb_access_memory(store, imm, 7, 13, 0, reg_imm_sp, imm, u32); \
2138 break; \
2139 \
2140 case 0x98: \
2141 /* LDR r0, [sp + imm] */ \
2142 thumb_access_memory(load, imm, 0, 13, 0, reg_imm_sp, imm, u32); \
2143 break; \
2144 \
2145 case 0x99: \
2146 /* LDR r1, [sp + imm] */ \
2147 thumb_access_memory(load, imm, 1, 13, 0, reg_imm_sp, imm, u32); \
2148 break; \
2149 \
2150 case 0x9A: \
2151 /* LDR r2, [sp + imm] */ \
2152 thumb_access_memory(load, imm, 2, 13, 0, reg_imm_sp, imm, u32); \
2153 break; \
2154 \
2155 case 0x9B: \
2156 /* LDR r3, [sp + imm] */ \
2157 thumb_access_memory(load, imm, 3, 13, 0, reg_imm_sp, imm, u32); \
2158 break; \
2159 \
2160 case 0x9C: \
2161 /* LDR r4, [sp + imm] */ \
2162 thumb_access_memory(load, imm, 4, 13, 0, reg_imm_sp, imm, u32); \
2163 break; \
2164 \
2165 case 0x9D: \
2166 /* LDR r5, [sp + imm] */ \
2167 thumb_access_memory(load, imm, 5, 13, 0, reg_imm_sp, imm, u32); \
2168 break; \
2169 \
2170 case 0x9E: \
2171 /* LDR r6, [sp + imm] */ \
2172 thumb_access_memory(load, imm, 6, 13, 0, reg_imm_sp, imm, u32); \
2173 break; \
2174 \
2175 case 0x9F: \
2176 /* LDR r7, [sp + imm] */ \
2177 thumb_access_memory(load, imm, 7, 13, 0, reg_imm_sp, imm, u32); \
2178 break; \
2179 \
2180 case 0xA0: \
2181 /* ADD r0, pc, +imm */ \
2182 thumb_load_pc(0); \
2183 break; \
2184 \
2185 case 0xA1: \
2186 /* ADD r1, pc, +imm */ \
2187 thumb_load_pc(1); \
2188 break; \
2189 \
2190 case 0xA2: \
2191 /* ADD r2, pc, +imm */ \
2192 thumb_load_pc(2); \
2193 break; \
2194 \
2195 case 0xA3: \
2196 /* ADD r3, pc, +imm */ \
2197 thumb_load_pc(3); \
2198 break; \
2199 \
2200 case 0xA4: \
2201 /* ADD r4, pc, +imm */ \
2202 thumb_load_pc(4); \
2203 break; \
2204 \
2205 case 0xA5: \
2206 /* ADD r5, pc, +imm */ \
2207 thumb_load_pc(5); \
2208 break; \
2209 \
2210 case 0xA6: \
2211 /* ADD r6, pc, +imm */ \
2212 thumb_load_pc(6); \
2213 break; \
2214 \
2215 case 0xA7: \
2216 /* ADD r7, pc, +imm */ \
2217 thumb_load_pc(7); \
2218 break; \
2219 \
2220 case 0xA8: \
2221 /* ADD r0, sp, +imm */ \
2222 thumb_load_sp(0); \
2223 break; \
2224 \
2225 case 0xA9: \
2226 /* ADD r1, sp, +imm */ \
2227 thumb_load_sp(1); \
2228 break; \
2229 \
2230 case 0xAA: \
2231 /* ADD r2, sp, +imm */ \
2232 thumb_load_sp(2); \
2233 break; \
2234 \
2235 case 0xAB: \
2236 /* ADD r3, sp, +imm */ \
2237 thumb_load_sp(3); \
2238 break; \
2239 \
2240 case 0xAC: \
2241 /* ADD r4, sp, +imm */ \
2242 thumb_load_sp(4); \
2243 break; \
2244 \
2245 case 0xAD: \
2246 /* ADD r5, sp, +imm */ \
2247 thumb_load_sp(5); \
2248 break; \
2249 \
2250 case 0xAE: \
2251 /* ADD r6, sp, +imm */ \
2252 thumb_load_sp(6); \
2253 break; \
2254 \
2255 case 0xAF: \
2256 /* ADD r7, sp, +imm */ \
2257 thumb_load_sp(7); \
2258 break; \
2259 \
2260 case 0xB0 ... 0xB3: \
2261 if((opcode >> 7) & 0x01) \
2262 { \
2263 /* ADD sp, -imm */ \
2264 thumb_adjust_sp(down); \
2265 } \
2266 else \
2267 { \
2268 /* ADD sp, +imm */ \
2269 thumb_adjust_sp(up); \
2270 } \
2271 break; \
2272 \
2273 case 0xB4: \
2274 /* PUSH rlist */ \
2275 thumb_block_memory(store, down, no, 13); \
2276 break; \
2277 \
2278 case 0xB5: \
2279 /* PUSH rlist, lr */ \
2280 thumb_block_memory(store, push_lr, push_lr, 13); \
2281 break; \
2282 \
2283 case 0xBC: \
2284 /* POP rlist */ \
2285 thumb_block_memory(load, no, up, 13); \
2286 break; \
2287 \
2288 case 0xBD: \
2289 /* POP rlist, pc */ \
2290 thumb_block_memory(load, no, pop_pc, 13); \
2291 break; \
2292 \
2293 case 0xC0: \
2294 /* STMIA r0!, rlist */ \
2295 thumb_block_memory(store, no, up, 0); \
2296 break; \
2297 \
2298 case 0xC1: \
2299 /* STMIA r1!, rlist */ \
2300 thumb_block_memory(store, no, up, 1); \
2301 break; \
2302 \
2303 case 0xC2: \
2304 /* STMIA r2!, rlist */ \
2305 thumb_block_memory(store, no, up, 2); \
2306 break; \
2307 \
2308 case 0xC3: \
2309 /* STMIA r3!, rlist */ \
2310 thumb_block_memory(store, no, up, 3); \
2311 break; \
2312 \
2313 case 0xC4: \
2314 /* STMIA r4!, rlist */ \
2315 thumb_block_memory(store, no, up, 4); \
2316 break; \
2317 \
2318 case 0xC5: \
2319 /* STMIA r5!, rlist */ \
2320 thumb_block_memory(store, no, up, 5); \
2321 break; \
2322 \
2323 case 0xC6: \
2324 /* STMIA r6!, rlist */ \
2325 thumb_block_memory(store, no, up, 6); \
2326 break; \
2327 \
2328 case 0xC7: \
2329 /* STMIA r7!, rlist */ \
2330 thumb_block_memory(store, no, up, 7); \
2331 break; \
2332 \
2333 case 0xC8: \
2334 /* LDMIA r0!, rlist */ \
2335 thumb_block_memory(load, no, up, 0); \
2336 break; \
2337 \
2338 case 0xC9: \
2339 /* LDMIA r1!, rlist */ \
2340 thumb_block_memory(load, no, up, 1); \
2341 break; \
2342 \
2343 case 0xCA: \
2344 /* LDMIA r2!, rlist */ \
2345 thumb_block_memory(load, no, up, 2); \
2346 break; \
2347 \
2348 case 0xCB: \
2349 /* LDMIA r3!, rlist */ \
2350 thumb_block_memory(load, no, up, 3); \
2351 break; \
2352 \
2353 case 0xCC: \
2354 /* LDMIA r4!, rlist */ \
2355 thumb_block_memory(load, no, up, 4); \
2356 break; \
2357 \
2358 case 0xCD: \
2359 /* LDMIA r5!, rlist */ \
2360 thumb_block_memory(load, no, up, 5); \
2361 break; \
2362 \
2363 case 0xCE: \
2364 /* LDMIA r6!, rlist */ \
2365 thumb_block_memory(load, no, up, 6); \
2366 break; \
2367 \
2368 case 0xCF: \
2369 /* LDMIA r7!, rlist */ \
2370 thumb_block_memory(load, no, up, 7); \
2371 break; \
2372 \
2373 case 0xD0: \
2374 /* BEQ label */ \
2375 thumb_conditional_branch(eq); \
2376 break; \
2377 \
2378 case 0xD1: \
2379 /* BNE label */ \
2380 thumb_conditional_branch(ne); \
2381 break; \
2382 \
2383 case 0xD2: \
2384 /* BCS label */ \
2385 thumb_conditional_branch(cs); \
2386 break; \
2387 \
2388 case 0xD3: \
2389 /* BCC label */ \
2390 thumb_conditional_branch(cc); \
2391 break; \
2392 \
2393 case 0xD4: \
2394 /* BMI label */ \
2395 thumb_conditional_branch(mi); \
2396 break; \
2397 \
2398 case 0xD5: \
2399 /* BPL label */ \
2400 thumb_conditional_branch(pl); \
2401 break; \
2402 \
2403 case 0xD6: \
2404 /* BVS label */ \
2405 thumb_conditional_branch(vs); \
2406 break; \
2407 \
2408 case 0xD7: \
2409 /* BVC label */ \
2410 thumb_conditional_branch(vc); \
2411 break; \
2412 \
2413 case 0xD8: \
2414 /* BHI label */ \
2415 thumb_conditional_branch(hi); \
2416 break; \
2417 \
2418 case 0xD9: \
2419 /* BLS label */ \
2420 thumb_conditional_branch(ls); \
2421 break; \
2422 \
2423 case 0xDA: \
2424 /* BGE label */ \
2425 thumb_conditional_branch(ge); \
2426 break; \
2427 \
2428 case 0xDB: \
2429 /* BLT label */ \
2430 thumb_conditional_branch(lt); \
2431 break; \
2432 \
2433 case 0xDC: \
2434 /* BGT label */ \
2435 thumb_conditional_branch(gt); \
2436 break; \
2437 \
2438 case 0xDD: \
2439 /* BLE label */ \
2440 thumb_conditional_branch(le); \
2441 break; \
2442 \
2443 case 0xDF: \
2444 { \
2445 /* SWI comment */ \
2446 thumb_swi(); \
2447 break; \
2448 } \
2449 \
2450 case 0xE0 ... 0xE7: \
2451 { \
2452 /* B label */ \
2453 thumb_b(); \
2454 break; \
2455 } \
2456 \
2457 case 0xF0 ... 0xF7: \
2458 { \
2459 /* (low word) BL label */ \
2460 /* This should possibly generate code if not in conjunction with a BLH \
2461 next, but I don't think anyone will do that. */ \
2462 break; \
2463 } \
2464 \
2465 case 0xF8 ... 0xFF: \
2466 { \
2467 /* (high word) BL label */ \
2468 /* This might not be preceeding a BL low word (Golden Sun 2), if so \
2469 it must be handled like an indirect branch. */ \
2470 if((last_opcode >= 0xF000) && (last_opcode < 0xF800)) \
2471 { \
2472 thumb_bl(); \
2473 } \
2474 else \
2475 { \
2476 thumb_blh(); \
2477 } \
2478 break; \
2479 } \
2480 } \
2481 \
2482 pc += 2 \
2483
2484#define thumb_flag_modifies_all() \
2485 flag_status |= 0xFF \
2486
2487#define thumb_flag_modifies_zn() \
2488 flag_status |= 0xCC \
2489
2490#define thumb_flag_modifies_znc() \
2491 flag_status |= 0xEE \
2492
2493#define thumb_flag_modifies_zn_maybe_c() \
2494 flag_status |= 0xCE \
2495
2496#define thumb_flag_modifies_c() \
2497 flag_status |= 0x22 \
2498
2499#define thumb_flag_requires_c() \
2500 flag_status |= 0x200 \
2501
2502#define thumb_flag_requires_all() \
2503 flag_status |= 0xF00 \
2504
2505#define thumb_flag_status() \
2506{ \
2507 u16 flag_status = 0; \
2508 switch((opcode >> 8) & 0xFF) \
2509 { \
2510 /* left shift by imm */ \
2511 case 0x00 ... 0x07: \
2512 thumb_flag_modifies_zn(); \
2513 if(((opcode >> 6) & 0x1F) != 0) \
2514 { \
2515 thumb_flag_modifies_c(); \
2516 } \
2517 break; \
2518 \
2519 /* right shift by imm */ \
2520 case 0x08 ... 0x17: \
2521 thumb_flag_modifies_znc(); \
2522 break; \
2523 \
2524 /* add, subtract */ \
2525 case 0x18 ... 0x1F: \
2526 thumb_flag_modifies_all(); \
2527 break; \
2528 \
2529 /* mov reg, imm */ \
2530 case 0x20 ... 0x27: \
2531 thumb_flag_modifies_zn(); \
2532 break; \
2533 \
2534 /* cmp reg, imm; add, subtract */ \
2535 case 0x28 ... 0x3F: \
2536 thumb_flag_modifies_all(); \
2537 break; \
2538 \
2539 case 0x40: \
2540 switch((opcode >> 6) & 0x03) \
2541 { \
2542 case 0x00: \
2543 /* AND rd, rs */ \
2544 thumb_flag_modifies_zn(); \
2545 break; \
2546 \
2547 case 0x01: \
2548 /* EOR rd, rs */ \
2549 thumb_flag_modifies_zn(); \
2550 break; \
2551 \
2552 case 0x02: \
2553 /* LSL rd, rs */ \
2554 thumb_flag_modifies_zn_maybe_c(); \
2555 break; \
2556 \
2557 case 0x03: \
2558 /* LSR rd, rs */ \
2559 thumb_flag_modifies_zn_maybe_c(); \
2560 break; \
2561 } \
2562 break; \
2563 \
2564 case 0x41: \
2565 switch((opcode >> 6) & 0x03) \
2566 { \
2567 case 0x00: \
2568 /* ASR rd, rs */ \
2569 thumb_flag_modifies_zn_maybe_c(); \
2570 break; \
2571 \
2572 case 0x01: \
2573 /* ADC rd, rs */ \
2574 thumb_flag_modifies_all(); \
2575 thumb_flag_requires_c(); \
2576 break; \
2577 \
2578 case 0x02: \
2579 /* SBC rd, rs */ \
2580 thumb_flag_modifies_all(); \
2581 thumb_flag_requires_c(); \
2582 break; \
2583 \
2584 case 0x03: \
2585 /* ROR rd, rs */ \
2586 thumb_flag_modifies_zn_maybe_c(); \
2587 break; \
2588 } \
2589 break; \
2590 \
2591 /* TST, NEG, CMP, CMN */ \
2592 case 0x42: \
2593 thumb_flag_modifies_all(); \
2594 break; \
2595 \
2596 /* ORR, MUL, BIC, MVN */ \
2597 case 0x43: \
2598 thumb_flag_modifies_zn(); \
2599 break; \
2600 \
2601 case 0x45: \
2602 /* CMP rd, rs */ \
2603 thumb_flag_modifies_all(); \
2604 break; \
2605 \
2606 /* mov might change PC (fall through if so) */ \
2607 case 0x46: \
2608 if((opcode & 0xFF87) != 0x4687) \
2609 break; \
2610 \
2611 /* branches (can change PC) */ \
2612 case 0x47: \
2613 case 0xBD: \
2614 case 0xD0 ... 0xE7: \
2615 case 0xF0 ... 0xFF: \
2616 thumb_flag_requires_all(); \
2617 break; \
2618 } \
2619 block_data[block_data_position].flag_data = flag_status; \
2620} \
2621
2622u8 *ram_block_ptrs[1024 * 64];
2623u32 ram_block_tag_top = 0x0101;
2624
2625u8 *bios_block_ptrs[1024 * 8];
2626u32 bios_block_tag_top = 0x0101;
2627
2628// This function will return a pointer to a translated block of code. If it
2629// doesn't exist it will translate it, if it does it will pass it back.
2630
2631// type should be "arm", "thumb", or "dual." For arm or thumb the PC should
2632// be a real PC, for dual the least significant bit will determine if it's
2633// ARM or Thumb mode.
2634
2635#define block_lookup_address_pc_arm() \
2636 pc &= ~0x03
2637
2638#define block_lookup_address_pc_thumb() \
2639 pc &= ~0x01 \
2640
2641#define block_lookup_address_pc_dual() \
2642 u32 thumb = pc & 0x01; \
2643 \
2644 if(thumb) \
2645 { \
2646 pc--; \
2647 reg[REG_CPSR] |= 0x20; \
2648 } \
2649 else \
2650 { \
2651 pc = (pc + 2) & ~0x03; \
2652 reg[REG_CPSR] &= ~0x20; \
2653 } \
2654
2655#define ram_translation_region TRANSLATION_REGION_RAM
2656#define rom_translation_region TRANSLATION_REGION_ROM
2657#define bios_translation_region TRANSLATION_REGION_BIOS
2658
2659#define block_lookup_translate_arm(mem_type, smc_enable) \
2660 translation_result = translate_block_arm(pc, mem_type##_translation_region, \
2661 smc_enable) \
2662
2663#define block_lookup_translate_thumb(mem_type, smc_enable) \
2664 translation_result = translate_block_thumb(pc, \
2665 mem_type##_translation_region, smc_enable) \
2666
2667#define block_lookup_translate_dual(mem_type, smc_enable) \
2668 if(thumb) \
2669 { \
2670 translation_result = translate_block_thumb(pc, \
2671 mem_type##_translation_region, smc_enable); \
2672 } \
2673 else \
2674 { \
2675 translation_result = translate_block_arm(pc, \
2676 mem_type##_translation_region, smc_enable); \
2677 } \
2678
2679// 0x0101 is the smallest tag that can be used. 0xFFFF is marked
2680// in the middle of blocks and used for write guarding, it doesn't
2681// indicate a valid block either (it's okay to compile a new block
2682// that overlaps the earlier one, although this should be relatively
2683// uncommon)
2684
2685#define fill_tag_arm(mem_type) \
2686 location[0] = mem_type##_block_tag_top; \
2687 location[1] = 0xFFFF \
2688
2689#define fill_tag_thumb(mem_type) \
2690 *location = mem_type##_block_tag_top \
2691
2692#define fill_tag_dual(mem_type) \
2693 if(thumb) \
2694 fill_tag_thumb(mem_type); \
2695 else \
2696 fill_tag_arm(mem_type) \
2697
2698#define block_lookup_translate(instruction_type, mem_type, smc_enable) \
2699 block_tag = *location; \
2700 if((block_tag < 0x0101) || (block_tag == 0xFFFF)) \
2701 { \
2702 __label__ redo; \
2703 s32 translation_result; \
2704 \
2705 redo: \
2706 \
2707 translation_recursion_level++; \
2708 block_address = mem_type##_translation_ptr + block_prologue_size; \
2709 mem_type##_block_ptrs[mem_type##_block_tag_top] = block_address; \
2710 fill_tag_##instruction_type(mem_type); \
2711 mem_type##_block_tag_top++; \
2712 \
2713 block_lookup_translate_##instruction_type(mem_type, smc_enable); \
2714 translation_recursion_level--; \
2715 \
2716 /* If the translation failed then pass that failure on if we're in \
2717 a recursive level, or try again if we've hit the bottom. */ \
2718 if(translation_result == -1) \
2719 { \
2720 if(translation_recursion_level) \
2721 return NULL; \
2722 \
2723 goto redo; \
2724 } \
2725 \
2726 if(translation_recursion_level == 0) \
2727 translate_invalidate_dcache(); \
2728 } \
2729 else \
2730 { \
2731 block_address = mem_type##_block_ptrs[block_tag]; \
2732 } \
2733
2734u32 translation_recursion_level = 0;
2735u32 translation_flush_count = 0;
2736
2737
2738#define block_lookup_address_builder(type) \
2739u8 function_cc *block_lookup_address_##type(u32 pc) \
2740{ \
2741 u16 *location; \
2742 u32 block_tag; \
2743 u8 *block_address; \
2744 \
2745 /* Starting at the beginning, we allow for one translation cache flush. */ \
2746 if(translation_recursion_level == 0) \
2747 translation_flush_count = 0; \
2748 block_lookup_address_pc_##type(); \
2749 \
2750 switch(pc >> 24) \
2751 { \
2752 case 0x0: \
2753 bios_region_read_allow(); \
2754 location = (u16 *)(bios_rom + pc + 0x4000); \
2755 block_lookup_translate(type, bios, 0); \
2756 if(translation_recursion_level == 0) \
2757 bios_region_read_allow(); \
2758 break; \
2759 \
2760 case 0x2: \
2761 location = (u16 *)(ewram + (pc & 0x7FFF) + ((pc & 0x38000) * 2)); \
2762 block_lookup_translate(type, ram, 1); \
2763 if(translation_recursion_level == 0) \
2764 bios_region_read_protect(); \
2765 break; \
2766 \
2767 case 0x3: \
2768 location = (u16 *)(iwram + (pc & 0x7FFF)); \
2769 block_lookup_translate(type, ram, 1); \
2770 if(translation_recursion_level == 0) \
2771 bios_region_read_protect(); \
2772 break; \
2773 \
2774 case 0x8 ... 0xD: \
2775 { \
2776 u32 hash_target = ((pc * 2654435761U) >> 16) & \
2777 (ROM_BRANCH_HASH_SIZE - 1); \
2778 u32 *block_ptr = rom_branch_hash[hash_target]; \
2779 u32 **block_ptr_address = rom_branch_hash + hash_target; \
2780 \
2781 while(block_ptr) \
2782 { \
2783 if(block_ptr[0] == pc) \
2784 { \
2785 block_address = (u8 *)(block_ptr + 2) + block_prologue_size; \
2786 break; \
2787 } \
2788 \
2789 block_ptr_address = (u32 **)(block_ptr + 1); \
2790 block_ptr = (u32 *)block_ptr[1]; \
2791 } \
2792 \
2793 if(block_ptr == NULL) \
2794 { \
2795 __label__ redo; \
2796 s32 translation_result; \
2797 \
2798 redo: \
2799 \
2800 translation_recursion_level++; \
2801 ((u32 *)rom_translation_ptr)[0] = pc; \
2802 ((u32 **)rom_translation_ptr)[1] = NULL; \
2803 *block_ptr_address = (u32 *)rom_translation_ptr; \
2804 rom_translation_ptr += 8; \
2805 block_address = rom_translation_ptr + block_prologue_size; \
2806 block_lookup_translate_##type(rom, 0); \
2807 translation_recursion_level--; \
2808 \
2809 /* If the translation failed then pass that failure on if we're in \
2810 a recursive level, or try again if we've hit the bottom. */ \
2811 if(translation_result == -1) \
2812 { \
2813 if(translation_recursion_level) \
2814 return NULL; \
2815 \
2816 goto redo; \
2817 } \
2818 \
2819 if(translation_recursion_level == 0) \
2820 translate_invalidate_dcache(); \
2821 } \
2822 if(translation_recursion_level == 0) \
2823 bios_region_read_protect(); \
2824 break; \
2825 } \
2826 \
2827 default: \
2828 /* If we're at the bottom, it means we're actually trying to jump to an \
2829 address that we can't handle. Otherwise, it means that code scanned \
2830 has reached an address that can't be handled, which means that we \
2831 have most likely hit an area that doesn't contain code yet (for \
2832 instance, in RAM). If such a thing happens, return -1 and the \
2833 block translater will naively link it (it'll be okay, since it \
2834 should never be hit) */ \
2835 if(translation_recursion_level == 0) \
2836 { \
2837 char buffer[256]; \
2838 sprintf(buffer, "bad jump %x (%x) (%x)\n", pc, reg[REG_PC], \
2839 last_instruction); \
eac69717 2840 printf("%s", buffer); \
2823a4c8 2841 quit(); \
2842 } \
2843 block_address = (u8 *)(-1); \
2844 break; \
2845 } \
2846 \
2847 return block_address; \
2848} \
2849
2850block_lookup_address_builder(arm);
2851block_lookup_address_builder(thumb);
2852block_lookup_address_builder(dual);
2853
2854// Potential exit point: If the rd field is pc for instructions is 0x0F,
2855// the instruction is b/bl/bx, or the instruction is ldm with PC in the
2856// register list.
2857// All instructions with upper 3 bits less than 100b have an rd field
2858// except bx, where the bits must be 0xF there anyway, multiplies,
2859// which cannot have 0xF in the corresponding fields, and msr, which
2860// has 0x0F there but doesn't end things (therefore must be special
2861// checked against). Because MSR and BX overlap both are checked for.
2862
2863#define arm_exit_point \
2864 (((opcode < 0x8000000) && ((opcode & 0x000F000) == 0x000F000) && \
2865 ((opcode & 0xDB0F000) != 0x120F000)) || \
2866 ((opcode & 0x12FFF10) == 0x12FFF10) || \
2867 ((opcode & 0x8108000) == 0x8108000) || \
2868 ((opcode >= 0xA000000) && (opcode < 0xF000000)) || \
2869 ((opcode > 0xF000000) && (!swi_hle_handle[((opcode >> 16) & 0xFF)]))) \
2870
2871#define arm_opcode_branch \
2872 ((opcode & 0xE000000) == 0xA000000) \
2873
2874#define arm_opcode_swi \
2875 ((opcode & 0xF000000) == 0xF000000) \
2876
2877#define arm_opcode_unconditional_branch \
2878 (condition == 0x0E) \
2879
2880#define arm_load_opcode() \
2881 opcode = address32(pc_address_block, (block_end_pc & 0x7FFF)); \
2882 condition = opcode >> 28; \
2883 \
2884 opcode &= 0xFFFFFFF; \
2885 \
2886 block_end_pc += 4 \
2887
2888#define arm_branch_target() \
2889 branch_target = (block_end_pc + 4 + (((s32)(opcode & 0xFFFFFF) << 8) >> 6)) \
2890
2891// Contiguous conditional block flags modification - it will set 0x20 in the
2892// condition's bits if this instruction modifies flags. Taken from the CPU
2893// switch so it'd better be right this time.
2894
2895#define arm_set_condition(_condition) \
2896 block_data[block_data_position].condition = _condition; \
2897 switch((opcode >> 20) & 0xFF) \
2898 { \
2899 case 0x01: \
2900 case 0x03: \
2901 case 0x09: \
2902 case 0x0B: \
2903 case 0x0D: \
2904 case 0x0F: \
2905 if((((opcode >> 5) & 0x03) == 0) || ((opcode & 0x90) != 0x90)) \
2906 block_data[block_data_position].condition |= 0x20; \
2907 break; \
2908 \
2909 case 0x05: \
2910 case 0x07: \
2911 case 0x11: \
2912 case 0x13: \
2913 case 0x15 ... 0x17: \
2914 case 0x19: \
2915 case 0x1B: \
2916 case 0x1D: \
2917 case 0x1F: \
2918 if((opcode & 0x90) != 0x90) \
2919 block_data[block_data_position].condition |= 0x20; \
2920 break; \
2921 \
2922 case 0x12: \
2923 if(((opcode & 0x90) != 0x90) && !(opcode & 0x10)) \
2924 block_data[block_data_position].condition |= 0x20; \
2925 break; \
2926 \
2927 case 0x21: \
2928 case 0x23: \
2929 case 0x25: \
2930 case 0x27: \
2931 case 0x29: \
2932 case 0x2B: \
2933 case 0x2D: \
2934 case 0x2F ... 0x37: \
2935 case 0x39: \
2936 case 0x3B: \
2937 case 0x3D: \
2938 case 0x3F: \
2939 block_data[block_data_position].condition |= 0x20; \
2940 break; \
2941 } \
2942
2943#define arm_link_block() \
2944 translation_target = block_lookup_address_arm(branch_target) \
2945
2946#define arm_instruction_width 4
2947
2948#define arm_base_cycles() \
2949 cycle_count += waitstate_cycles_sequential[pc >> 24][2] \
2950
2951// For now this just sets a variable that says flags should always be
2952// computed.
2953
2954#define arm_dead_flag_eliminate() \
2955 flag_status = 0xF \
2956
2957// The following Thumb instructions can exit:
2958// b, bl, bx, swi, pop {... pc}, and mov pc, ..., the latter being a hireg
2959// op only. Rather simpler to identify than the ARM set.
2960
2961#define thumb_exit_point \
2962 (((opcode >= 0xD000) && (opcode < 0xDF00)) || \
2963 (((opcode & 0xFF00) == 0xDF00) && \
2964 (!swi_hle_handle[opcode & 0xFF])) || \
2965 ((opcode >= 0xE000) && (opcode < 0xE800)) || \
2966 ((opcode & 0xFF00) == 0x4700) || \
2967 ((opcode & 0xFF00) == 0xBD00) || \
2968 ((opcode & 0xFF87) == 0x4687) || \
2969 ((opcode >= 0xF800))) \
2970
2971#define thumb_opcode_branch \
2972 (((opcode >= 0xD000) && (opcode < 0xDF00)) || \
2973 ((opcode >= 0xE000) && (opcode < 0xE800)) || \
2974 (opcode >= 0xF800)) \
2975
2976#define thumb_opcode_swi \
2977 ((opcode & 0xFF00) == 0xDF00) \
2978
2979#define thumb_opcode_unconditional_branch \
2980 ((opcode < 0xD000) || (opcode >= 0xDF00)) \
2981
2982#define thumb_load_opcode() \
2983 last_opcode = opcode; \
2984 opcode = address16(pc_address_block, (block_end_pc & 0x7FFF)); \
2985 \
2986 block_end_pc += 2 \
2987
2988#define thumb_branch_target() \
2989 if(opcode < 0xE000) \
2990 { \
2991 branch_target = block_end_pc + 2 + ((s8)(opcode & 0xFF) * 2); \
2992 } \
2993 else \
2994 \
2995 if(opcode < 0xF800) \
2996 { \
2997 branch_target = block_end_pc + 2 + ((s32)((opcode & 0x7FF) << 21) >> 20); \
2998 } \
2999 else \
3000 { \
3001 if((last_opcode >= 0xF000) && (last_opcode < 0xF800)) \
3002 { \
3003 branch_target = \
3004 (block_end_pc + ((s32)((last_opcode & 0x07FF) << 21) >> 9) + \
3005 ((opcode & 0x07FF) * 2)); \
3006 } \
3007 else \
3008 { \
3009 goto no_direct_branch; \
3010 } \
3011 } \
3012
3013#define thumb_set_condition(_condition) \
3014
3015#define thumb_link_block() \
3016 if(branch_target != 0x00000008) \
3017 translation_target = block_lookup_address_thumb(branch_target); \
3018 else \
3019 translation_target = block_lookup_address_arm(branch_target) \
3020
3021#define thumb_instruction_width 2
3022
3023#define thumb_base_cycles() \
3024 cycle_count += waitstate_cycles_sequential[pc >> 24][1] \
3025
3026// Here's how this works: each instruction has three different sets of flag
3027// attributes, each consisiting of a 4bit mask describing how that instruction
3028// interacts with the 4 main flags (N/Z/C/V).
3029// The first set, in bits 0:3, is the set of flags the instruction may
3030// modify. After this pass this is changed to the set of flags the instruction
3031// should modify - if the bit for the corresponding flag is not set then code
3032// does not have to be generated to calculate the flag for that instruction.
3033
3034// The second set, in bits 7:4, is the set of flags that the instruction must
3035// modify (ie, for shifts by the register values the instruction may not
3036// always modify the C flag, and thus the C bit won't be set here).
3037
3038// The third set, in bits 11:8, is the set of flags that the instruction uses
3039// in its computation, or the set of flags that will be needed after the
3040// instruction is done. For any instructions that change the PC all of the
3041// bits should be set because it is (for now) unknown what flags will be
3042// needed after it arrives at its destination. Instructions that use the
3043// carry flag as input will have it set as well.
3044
3045// The algorithm is a simple liveness analysis procedure: It starts at the
3046// bottom of the instruction stream and sets a "currently needed" mask to
3047// the flags needed mask of the current instruction. Then it moves down
3048// an instruction, ANDs that instructions "should generate" mask by the
3049// "currently needed" mask, then ANDs the "currently needed" mask by
3050// the 1's complement of the instruction's "must generate" mask, and ORs
3051// the "currently needed" mask by the instruction's "flags needed" mask.
3052
3053#define thumb_dead_flag_eliminate() \
3054{ \
3055 u32 needed_mask; \
3056 needed_mask = block_data[block_data_position].flag_data >> 8; \
3057 \
3058 block_data_position--; \
3059 while(block_data_position >= 0) \
3060 { \
3061 flag_status = block_data[block_data_position].flag_data; \
3062 block_data[block_data_position].flag_data = \
3063 (flag_status & needed_mask); \
3064 needed_mask &= ~((flag_status >> 4) & 0x0F); \
3065 needed_mask |= flag_status >> 8; \
3066 block_data_position--; \
3067 } \
3068} \
3069
3070#define MAX_BLOCK_SIZE 8192
3071#define MAX_EXITS 256
3072
3073block_data_type block_data[MAX_BLOCK_SIZE];
3074block_exit_type block_exits[MAX_EXITS];
3075
3076#define smc_write_arm_yes() \
3077 if(address32(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) == 0x0000) \
3078 { \
3079 address32(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) = \
3080 0xFFFFFFFF; \
3081 } \
3082
3083#define smc_write_thumb_yes() \
3084 if(address16(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) == 0x0000) \
3085 { \
3086 address16(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) = 0xFFFF; \
3087 } \
3088
3089#define smc_write_arm_no() \
3090
3091#define smc_write_thumb_no() \
3092
3093#define scan_block(type, smc_write_op) \
3094{ \
3095 __label__ block_end; \
3096 /* Find the end of the block */ \
3097 do \
3098 { \
3099 check_pc_region(block_end_pc); \
3100 smc_write_##type##_##smc_write_op(); \
3101 type##_load_opcode(); \
3102 type##_flag_status(); \
3103 \
3104 if(type##_exit_point) \
3105 { \
3106 /* Branch/branch with link */ \
3107 if(type##_opcode_branch) \
3108 { \
3109 __label__ no_direct_branch; \
3110 type##_branch_target(); \
3111 block_exits[block_exit_position].branch_target = branch_target; \
3112 block_exit_position++; \
3113 \
3114 /* Give the branch target macro somewhere to bail if it turns out to \
3115 be an indirect branch (ala malformed Thumb bl) */ \
3116 no_direct_branch:; \
3117 } \
3118 \
3119 /* SWI branches to the BIOS, this will likely change when \
3120 some HLE BIOS is implemented. */ \
3121 if(type##_opcode_swi) \
3122 { \
3123 block_exits[block_exit_position].branch_target = 0x00000008; \
3124 block_exit_position++; \
3125 } \
3126 \
3127 type##_set_condition(condition | 0x10); \
3128 \
3129 /* Only unconditional branches can end the block. */ \
3130 if(type##_opcode_unconditional_branch) \
3131 { \
3132 /* Check to see if any prior block exits branch after here, \
3133 if so don't end the block. Starts from the top and works \
3134 down because the most recent branch is most likely to \
3135 join after the end (if/then form) */ \
3136 for(i = block_exit_position - 2; i >= 0; i--) \
3137 { \
3138 if(block_exits[i].branch_target == block_end_pc) \
3139 break; \
3140 } \
3141 \
3142 if(i < 0) \
3143 break; \
3144 } \
3145 if(block_exit_position == MAX_EXITS) \
3146 break; \
3147 } \
3148 else \
3149 { \
3150 type##_set_condition(condition); \
3151 } \
3152 \
3153 for(i = 0; i < translation_gate_targets; i++) \
3154 { \
3155 if(block_end_pc == translation_gate_target_pc[i]) \
3156 goto block_end; \
3157 } \
3158 \
3159 block_data[block_data_position].update_cycles = 0; \
3160 block_data_position++; \
3161 if((block_data_position == MAX_BLOCK_SIZE) || \
3162 (block_end_pc == 0x3007FF0) || (block_end_pc == 0x203FFFF0)) \
3163 { \
3164 break; \
3165 } \
3166 } while(1); \
3167 \
3168 block_end:; \
3169} \
3170
3171#define arm_fix_pc() \
3172 pc &= ~0x03 \
3173
3174#define thumb_fix_pc() \
3175 pc &= ~0x01 \
3176
3177#define translate_block_builder(type) \
3178s32 translate_block_##type(u32 pc, translation_region_type \
3179 translation_region, u32 smc_enable) \
3180{ \
3181 u32 opcode; \
3182 u32 last_opcode; \
3183 u32 condition; \
3184 u32 last_condition; \
3185 u32 pc_region = (pc >> 15); \
3186 u32 new_pc_region; \
3187 u8 *pc_address_block = memory_map_read[pc_region]; \
3188 u32 block_start_pc = pc; \
3189 u32 block_end_pc = pc; \
3190 u32 block_exit_position = 0; \
3191 s32 block_data_position = 0; \
3192 u32 external_block_exit_position = 0; \
3193 u32 branch_target; \
3194 u32 cycle_count = 0; \
3195 u8 *translation_target; \
3196 u8 *backpatch_address; \
3197 u8 *translation_ptr; \
3198 u8 *translation_cache_limit; \
3199 s32 i; \
3200 u32 flag_status; \
3201 block_exit_type external_block_exits[MAX_EXITS]; \
3202 generate_block_extra_vars_##type(); \
3203 type##_fix_pc(); \
3204 \
3205 if(pc_address_block == NULL) \
3206 pc_address_block = load_gamepak_page(pc_region & 0x3FF); \
3207 \
3208 switch(translation_region) \
3209 { \
3210 case TRANSLATION_REGION_RAM: \
3211 if(pc >= 0x3000000) \
3212 { \
3213 if((pc < iwram_code_min) || (iwram_code_min == 0xFFFFFFFF)) \
3214 iwram_code_min = pc; \
3215 } \
3216 else \
3217 \
3218 if(pc >= 0x2000000) \
3219 { \
3220 if((pc < ewram_code_min) || (ewram_code_min == 0xFFFFFFFF)) \
3221 ewram_code_min = pc; \
3222 } \
3223 \
3224 translation_ptr = ram_translation_ptr; \
3225 translation_cache_limit = \
3226 ram_translation_cache + RAM_TRANSLATION_CACHE_SIZE - \
3227 TRANSLATION_CACHE_LIMIT_THRESHOLD; \
3228 break; \
3229 \
3230 case TRANSLATION_REGION_ROM: \
3231 translation_ptr = rom_translation_ptr; \
3232 translation_cache_limit = \
3233 rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE - \
3234 TRANSLATION_CACHE_LIMIT_THRESHOLD; \
3235 break; \
3236 \
3237 case TRANSLATION_REGION_BIOS: \
3238 translation_ptr = bios_translation_ptr; \
3239 translation_cache_limit = bios_translation_cache + \
3240 BIOS_TRANSLATION_CACHE_SIZE; \
3241 break; \
3242 } \
3243 \
3244 generate_block_prologue(); \
3245 \
3246 /* This is a function because it's used a lot more than it might seem (all \
3247 of the data processing functions can access it), and its expansion was \
3248 massacreing the compiler. */ \
3249 \
3250 if(smc_enable) \
3251 { \
3252 scan_block(type, yes); \
3253 } \
3254 else \
3255 { \
3256 scan_block(type, no); \
3257 } \
3258 \
3259 for(i = 0; i < block_exit_position; i++) \
3260 { \
3261 branch_target = block_exits[i].branch_target; \
3262 \
3263 if((branch_target > block_start_pc) && \
3264 (branch_target < block_end_pc)) \
3265 { \
3266 block_data[(branch_target - block_start_pc) / \
3267 type##_instruction_width].update_cycles = 1; \
3268 } \
3269 } \
3270 \
3271 type##_dead_flag_eliminate(); \
3272 \
3273 block_exit_position = 0; \
3274 block_data_position = 0; \
3275 \
3276 last_condition = 0x0E; \
3277 \
3278 while(pc != block_end_pc) \
3279 { \
3280 block_data[block_data_position].block_offset = translation_ptr; \
3281 type##_base_cycles(); \
3282 /*generate_step_debug();*/ \
3283 \
3284 translate_##type##_instruction(); \
3285 block_data_position++; \
3286 \
3287 /* If it went too far the cache needs to be flushed and the process \
3288 restarted. Because we might already be nested several stages in \
3289 a simple recursive call here won't work, it has to pedal out to \
3290 the beginning. */ \
3291 \
3292 if(translation_ptr > translation_cache_limit) \
3293 { \
3294 translation_flush_count++; \
3295 \
3296 switch(translation_region) \
3297 { \
3298 case TRANSLATION_REGION_RAM: \
3299 flush_translation_cache_ram(); \
3300 break; \
3301 \
3302 case TRANSLATION_REGION_ROM: \
3303 flush_translation_cache_rom(); \
3304 break; \
3305 \
3306 case TRANSLATION_REGION_BIOS: \
3307 flush_translation_cache_bios(); \
3308 break; \
3309 } \
3310 \
3311 return -1; \
3312 } \
3313 \
3314 /* If the next instruction is a block entry point update the \
3315 cycle counter and update */ \
3316 if(block_data[block_data_position].update_cycles == 1) \
3317 { \
3318 generate_cycle_update(); \
3319 } \
3320 } \
3321 for(i = 0; i < translation_gate_targets; i++) \
3322 { \
3323 if(pc == translation_gate_target_pc[i]) \
3324 { \
3325 generate_translation_gate(type); \
3326 break; \
3327 } \
3328 } \
3329 \
3330 for(i = 0; i < block_exit_position; i++) \
3331 { \
3332 branch_target = block_exits[i].branch_target; \
3333 \
3334 if((branch_target >= block_start_pc) && (branch_target < block_end_pc)) \
3335 { \
3336 /* Internal branch, patch to recorded address */ \
3337 translation_target = \
3338 block_data[(branch_target - block_start_pc) / \
3339 type##_instruction_width].block_offset; \
3340 \
3341 generate_branch_patch_unconditional(block_exits[i].branch_source, \
3342 translation_target); \
3343 } \
3344 else \
3345 { \
3346 /* External branch, save for later */ \
3347 external_block_exits[external_block_exit_position].branch_target = \
3348 branch_target; \
3349 external_block_exits[external_block_exit_position].branch_source = \
3350 block_exits[i].branch_source; \
3351 external_block_exit_position++; \
3352 } \
3353 } \
3354 \
3355 switch(translation_region) \
3356 { \
3357 case TRANSLATION_REGION_RAM: \
3358 if(pc >= 0x3000000) \
3359 { \
3360 if((pc > iwram_code_max) || (iwram_code_max == 0xFFFFFFFF)) \
3361 iwram_code_max = pc; \
3362 } \
3363 else \
3364 \
3365 if(pc >= 0x2000000) \
3366 { \
3367 if((pc > ewram_code_max) || (ewram_code_max == 0xFFFFFFFF)) \
3368 ewram_code_max = pc; \
3369 } \
3370 \
3371 ram_translation_ptr = translation_ptr; \
3372 break; \
3373 \
3374 case TRANSLATION_REGION_ROM: \
3375 rom_translation_ptr = translation_ptr; \
3376 break; \
3377 \
3378 case TRANSLATION_REGION_BIOS: \
3379 bios_translation_ptr = translation_ptr; \
3380 break; \
3381 } \
3382 \
3383 for(i = 0; i < external_block_exit_position; i++) \
3384 { \
3385 branch_target = external_block_exits[i].branch_target; \
3386 type##_link_block(); \
3387 if(translation_target == NULL) \
3388 return -1; \
3389 generate_branch_patch_unconditional( \
3390 external_block_exits[i].branch_source, translation_target); \
3391 } \
3392 \
3393 return 0; \
3394} \
3395
3396translate_block_builder(arm);
3397translate_block_builder(thumb);
3398
3399void flush_translation_cache_ram()
3400{
3401 flush_ram_count++;
3402/* printf("ram flush %d (pc %x), %x to %x, %x to %x\n",
3403 flush_ram_count, reg[REG_PC], iwram_code_min, iwram_code_max,
3404 ewram_code_min, ewram_code_max); */
3405
3406#ifndef PC_BUILD
3407 invalidate_icache_region(ram_translation_cache,
3408 (ram_translation_ptr - ram_translation_cache) + 0x100);
3409#endif
eac69717 3410#ifdef ARM_ARCH
f50ad10a 3411 last_ram_translation_ptr = ram_translation_cache;
eac69717 3412#endif
3413 ram_translation_ptr = ram_translation_cache;
2823a4c8 3414 ram_block_tag_top = 0x0101;
3415 if(iwram_code_min != 0xFFFFFFFF)
3416 {
3417 iwram_code_min &= 0x7FFF;
3418 iwram_code_max &= 0x7FFF;
3419 memset(iwram + iwram_code_min, 0, iwram_code_max - iwram_code_min);
3420 }
3421
3422 if(ewram_code_min != 0xFFFFFFFF)
3423 {
3424 u32 ewram_code_min_page;
3425 u32 ewram_code_max_page;
3426 u32 ewram_code_min_offset;
3427 u32 ewram_code_max_offset;
3428 u32 i;
3429
3430 ewram_code_min &= 0x3FFFF;
3431 ewram_code_max &= 0x3FFFF;
3432
3433 ewram_code_min_page = ewram_code_min >> 15;
3434 ewram_code_max_page = ewram_code_max >> 15;
3435 ewram_code_min_offset = ewram_code_min & 0x7FFF;
3436 ewram_code_max_offset = ewram_code_max & 0x7FFF;
3437
3438 if(ewram_code_min_page == ewram_code_max_page)
3439 {
3440 memset(ewram + (ewram_code_min_page * 0x10000) +
3441 ewram_code_min_offset, 0,
3442 ewram_code_max_offset - ewram_code_min_offset);
3443 }
3444 else
3445 {
3446 for(i = ewram_code_min_page + 1; i < ewram_code_max_page; i++)
3447 {
3448 memset(ewram + (i * 0x10000), 0, 0x8000);
3449 }
3450
3451 memset(ewram, 0, ewram_code_max_offset);
3452 }
3453 }
3454
3455 iwram_code_min = 0xFFFFFFFF;
3456 iwram_code_max = 0xFFFFFFFF;
3457 ewram_code_min = 0xFFFFFFFF;
3458 ewram_code_max = 0xFFFFFFFF;
3459}
3460
3461void flush_translation_cache_rom()
3462{
3463#ifndef PC_BUILD
3464 invalidate_icache_region(rom_translation_cache,
3465 rom_translation_ptr - rom_translation_cache + 0x100);
3466#endif
eac69717 3467#ifdef ARM_ARCH
3468 last_rom_translation_ptr = rom_translation_cache;
3469#endif
2823a4c8 3470
3471 rom_translation_ptr = rom_translation_cache;
3472 memset(rom_branch_hash, 0, sizeof(rom_branch_hash));
3473}
3474
3475void flush_translation_cache_bios()
3476{
3477#ifndef PC_BUILD
3478 invalidate_icache_region(bios_translation_cache,
3479 bios_translation_ptr - bios_translation_cache + 0x100);
3480#endif
eac69717 3481#ifdef ARM_ARCH
3482 last_bios_translation_ptr = bios_translation_cache;
3483#endif
2823a4c8 3484
3485 bios_block_tag_top = 0x0101;
3486 bios_translation_ptr = bios_translation_cache;
3487 memset(bios_rom + 0x4000, 0, 0x4000);
3488}
3489
ee0a3871 3490#define cache_dump_prefix ""
2823a4c8 3491
3492void dump_translation_cache()
3493{
3494 file_open(ram_cache, cache_dump_prefix "ram_cache.bin", write);
3495 file_write(ram_cache, ram_translation_cache,
3496 ram_translation_ptr - ram_translation_cache);
3497 file_close(ram_cache);
3498
3499 file_open(rom_cache, cache_dump_prefix "rom_cache.bin", write);
3500 file_write(rom_cache, rom_translation_cache,
3501 rom_translation_ptr - rom_translation_cache);
3502 file_close(rom_cache);
3503
3504 file_open(bios_cache, cache_dump_prefix "bios_cache.bin", write);
3505 file_write(bios_cache, bios_translation_cache,
3506 bios_translation_ptr - bios_translation_cache);
3507 file_close(bios_cache);
3508}
3509