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