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