revive PC build, support Linux
[gpsp.git] / cpu_threaded.c
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
27 u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
28 u8 *rom_translation_ptr = rom_translation_cache;
29
30 u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
31 u8 *ram_translation_ptr = ram_translation_cache;
32 u32 iwram_code_min = 0xFFFFFFFF;
33 u32 iwram_code_max = 0xFFFFFFFF;
34 u32 ewram_code_min = 0xFFFFFFFF;
35 u32 ewram_code_max = 0xFFFFFFFF;
36
37 u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
38 u8 *bios_translation_ptr = bios_translation_cache;
39
40 u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];
41
42 // Default
43 u32 idle_loop_target_pc = 0xFFFFFFFF;
44 u32 force_pc_update_target = 0xFFFFFFFF;
45 u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
46 u32 translation_gate_targets = 0;
47 u32 iwram_stack_optimize = 1;
48 u32 allow_smc_ram_u8 = 1;
49 u32 allow_smc_ram_u16 = 1;
50 u32 allow_smc_ram_u32 = 1;
51
52 typedef struct
53 {
54   u8 *block_offset;
55   u16 flag_data;
56   u8 condition;
57   u8 update_cycles;
58 } block_data_type;
59
60 typedef struct
61 {
62   u32 branch_target;
63   u8 *branch_source;
64 } block_exit_type;
65
66 extern 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
193 #elif defined(ARM_ARCH)
194
195 #include "arm/arm_emit.h"
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
2622 u8 *ram_block_ptrs[1024 * 64];
2623 u32 ram_block_tag_top = 0x0101;
2624
2625 u8 *bios_block_ptrs[1024 * 8];
2626 u32 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
2734 u32 translation_recursion_level = 0;
2735 u32 translation_flush_count = 0;
2736
2737
2738 #define block_lookup_address_builder(type)                                    \
2739 u8 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);                                                   \
2840         printf("%s", buffer);                                                 \
2841         quit();                                                               \
2842       }                                                                       \
2843       block_address = (u8 *)(-1);                                             \
2844       break;                                                                  \
2845   }                                                                           \
2846                                                                               \
2847   return block_address;                                                       \
2848 }                                                                             \
2849
2850 block_lookup_address_builder(arm);
2851 block_lookup_address_builder(thumb);
2852 block_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
3073 block_data_type block_data[MAX_BLOCK_SIZE];
3074 block_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)                                         \
3178 s32 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
3396 translate_block_builder(arm);
3397 translate_block_builder(thumb);
3398
3399 void 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
3410 #ifdef ARM_ARCH
3411   last_ram_translation_ptr = ram_translation_cache;
3412 #endif
3413   ram_translation_ptr = ram_translation_cache;
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
3461 void 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
3467 #ifdef ARM_ARCH
3468   last_rom_translation_ptr = rom_translation_cache;
3469 #endif
3470
3471   rom_translation_ptr = rom_translation_cache;
3472   memset(rom_branch_hash, 0, sizeof(rom_branch_hash));
3473 }
3474
3475 void 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
3481 #ifdef ARM_ARCH
3482   last_bios_translation_ptr = bios_translation_cache;
3483 #endif
3484
3485   bios_block_tag_top = 0x0101;
3486   bios_translation_ptr = bios_translation_cache;
3487   memset(bios_rom + 0x4000, 0, 0x4000);
3488 }
3489
3490 #define cache_dump_prefix ""
3491
3492 void 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