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