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 // Important todo:
21 // - stm reglist writeback when base is in the list needs adjustment
22 // - block memory needs psr swapping and user mode reg swapping
23 
24 #include "common.h"
25 
26 u32 memory_region_access_read_u8[16];
27 u32 memory_region_access_read_s8[16];
28 u32 memory_region_access_read_u16[16];
29 u32 memory_region_access_read_s16[16];
30 u32 memory_region_access_read_u32[16];
31 u32 memory_region_access_write_u8[16];
32 u32 memory_region_access_write_u16[16];
33 u32 memory_region_access_write_u32[16];
34 u32 memory_reads_u8;
35 u32 memory_reads_s8;
36 u32 memory_reads_u16;
37 u32 memory_reads_s16;
38 u32 memory_reads_u32;
39 u32 memory_writes_u8;
40 u32 memory_writes_u16;
41 u32 memory_writes_u32;
42 
43 const u8 bit_count[256] =
44 {
45   0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3,
46   4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
47   4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2,
48   3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
49   4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4,
50   5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,
51   3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
52   3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
53   4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
54   6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5,
55   5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6,
56   7, 7, 8
57 };
58 
59 
60 #ifdef REGISTER_USAGE_ANALYZE
61 
62 u64 instructions_total = 0;
63 
64 u64 arm_reg_freq[16];
65 u64 arm_reg_access_total = 0;
66 u64 arm_instructions_total = 0;
67 
68 u64 thumb_reg_freq[16];
69 u64 thumb_reg_access_total = 0;
70 u64 thumb_instructions_total = 0;
71 
72 // mla/long mla's addition operand are not counted yet.
73 
74 #define using_register(instruction_set, register, type)                       \
75   instruction_set##_reg_freq[register]++;                                     \
76   instruction_set##_reg_access_total++                                        \
77 
78 #define using_register_list(instruction_set, rlist, count)                    \
79 {                                                                             \
80   u32 i;                                                                      \
81   for(i = 0; i < count; i++)                                                  \
82   {                                                                           \
83     if((reg_list >> i) & 0x01)                                                \
84     {                                                                         \
85       using_register(instruction_set, i, memory_target);                      \
86     }                                                                         \
87   }                                                                           \
88 }                                                                             \
89 
90 #define using_instruction(instruction_set)                                    \
91   instruction_set##_instructions_total++;                                     \
92   instructions_total++                                                        \
93 
sort_tagged_element(const void * _a,const void * _b)94 int sort_tagged_element(const void *_a, const void *_b)
95 {
96   const u64 *a = _a;
97   const u64 *b = _b;
98 
99   return (int)(b[1] - a[1]);
100 }
101 
print_register_usage(void)102 void print_register_usage(void)
103 {
104   u32 i;
105   u64 arm_reg_freq_tagged[32];
106   u64 thumb_reg_freq_tagged[32];
107   double percent;
108   double percent_total = 0.0;
109 
110   for(i = 0; i < 16; i++)
111   {
112     arm_reg_freq_tagged[i * 2] = i;
113     arm_reg_freq_tagged[(i * 2) + 1] = arm_reg_freq[i];
114     thumb_reg_freq_tagged[i * 2] = i;
115     thumb_reg_freq_tagged[(i * 2) + 1] = thumb_reg_freq[i];
116   }
117 
118   qsort(arm_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
119   qsort(thumb_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
120 
121   printf("ARM register usage (%lf%% ARM instructions):\n",
122    (arm_instructions_total * 100.0) / instructions_total);
123   for(i = 0; i < 16; i++)
124   {
125     percent = (arm_reg_freq_tagged[(i * 2) + 1] * 100.0) /
126      arm_reg_access_total;
127     percent_total += percent;
128     printf("r%02d: %lf%% (-- %lf%%)\n",
129      (u32)arm_reg_freq_tagged[(i * 2)], percent, percent_total);
130   }
131 
132   percent_total = 0.0;
133 
134   printf("\nThumb register usage (%lf%% Thumb instructions):\n",
135    (thumb_instructions_total * 100.0) / instructions_total);
136   for(i = 0; i < 16; i++)
137   {
138     percent = (thumb_reg_freq_tagged[(i * 2) + 1] * 100.0) /
139      thumb_reg_access_total;
140     percent_total += percent;
141     printf("r%02d: %lf%% (-- %lf%%)\n",
142      (u32)thumb_reg_freq_tagged[(i * 2)], percent, percent_total);
143   }
144 
145   memset(arm_reg_freq, 0, sizeof(u64) * 16);
146   memset(thumb_reg_freq, 0, sizeof(u64) * 16);
147   arm_reg_access_total = 0;
148   thumb_reg_access_total = 0;
149 }
150 
151 #else
152 
153 #define using_register(instruction_set, register, type)                       \
154 
155 #define using_register_list(instruction_set, rlist, count)                    \
156 
157 #define using_instruction(instruction_set)                                    \
158 
159 #endif
160 
161 
162 #define arm_decode_data_proc_reg(opcode)                                      \
163   u32 rn = (opcode >> 16) & 0x0F;                                             \
164   u32 rd = (opcode >> 12) & 0x0F;                                             \
165   u32 rm = opcode & 0x0F;                                                     \
166   (void)rd;                                                                   \
167   (void)rn;                                                                   \
168   using_register(arm, rd, op_dest);                                           \
169   using_register(arm, rn, op_src);                                            \
170   using_register(arm, rm, op_src)                                             \
171 
172 #define arm_decode_data_proc_imm(opcode)                                      \
173   u32 imm;                                                                    \
174   u32 rn = (opcode >> 16) & 0x0F;                                             \
175   u32 rd = (opcode >> 12) & 0x0F;                                             \
176   (void)rd;                                                                   \
177   (void)rn;                                                                   \
178   ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2);                        \
179   using_register(arm, rd, op_dest);                                           \
180   using_register(arm, rn, op_src)                                             \
181 
182 #define arm_decode_psr_reg(opcode)                                            \
183   u32 psr_field = (opcode >> 16) & 0x0F;                                      \
184   u32 rd = (opcode >> 12) & 0x0F;                                             \
185   u32 rm = opcode & 0x0F;                                                     \
186   (void)rd;                                                                   \
187   (void)rm;                                                                   \
188   (void)psr_field;                                                            \
189   using_register(arm, rd, op_dest);                                           \
190   using_register(arm, rm, op_src)                                             \
191 
192 #define arm_decode_psr_imm(opcode)                                            \
193   u32 imm;                                                                    \
194   u32 psr_field = (opcode >> 16) & 0x0F;                                      \
195   u32 rd = (opcode >> 12) & 0x0F;                                             \
196   (void)rd;                                                                   \
197   ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2);                        \
198   using_register(arm, rd, op_dest)                                            \
199 
200 #define arm_decode_branchx(opcode)                                            \
201   u32 rn = opcode & 0x0F;                                                     \
202   using_register(arm, rn, branch_target)                                      \
203 
204 #define arm_decode_multiply()                                                 \
205   u32 rd = (opcode >> 16) & 0x0F;                                             \
206   u32 rn = (opcode >> 12) & 0x0F;                                             \
207   u32 rs = (opcode >> 8) & 0x0F;                                              \
208   u32 rm = opcode & 0x0F;                                                     \
209   (void)rn;                                                                   \
210   using_register(arm, rd, op_dest);                                           \
211   using_register(arm, rn, op_src);                                            \
212   using_register(arm, rm, op_src)                                             \
213 
214 #define arm_decode_multiply_long()                                            \
215   u32 rdhi = (opcode >> 16) & 0x0F;                                           \
216   u32 rdlo = (opcode >> 12) & 0x0F;                                           \
217   u32 rn = (opcode >> 8) & 0x0F;                                              \
218   u32 rm = opcode & 0x0F;                                                     \
219   using_register(arm, rdhi, op_dest);                                         \
220   using_register(arm, rdlo, op_dest);                                         \
221   using_register(arm, rn, op_src);                                            \
222   using_register(arm, rm, op_src)                                             \
223 
224 #define arm_decode_swap()                                                     \
225   u32 rn = (opcode >> 16) & 0x0F;                                             \
226   u32 rd = (opcode >> 12) & 0x0F;                                             \
227   u32 rm = opcode & 0x0F;                                                     \
228   using_register(arm, rd, memory_target);                                     \
229   using_register(arm, rn, memory_base);                                       \
230   using_register(arm, rm, memory_target)                                      \
231 
232 #define arm_decode_half_trans_r()                                             \
233   u32 rn = (opcode >> 16) & 0x0F;                                             \
234   u32 rd = (opcode >> 12) & 0x0F;                                             \
235   u32 rm = opcode & 0x0F;                                                     \
236   using_register(arm, rd, memory_target);                                     \
237   using_register(arm, rn, memory_base);                                       \
238   using_register(arm, rm, memory_offset)                                      \
239 
240 #define arm_decode_half_trans_of()                                            \
241   u32 rn = (opcode >> 16) & 0x0F;                                             \
242   u32 rd = (opcode >> 12) & 0x0F;                                             \
243   u32 offset = ((opcode >> 4) & 0xF0) | (opcode & 0x0F);                      \
244   using_register(arm, rd, memory_target);                                     \
245   using_register(arm, rn, memory_base)                                        \
246 
247 #define arm_decode_data_trans_imm()                                           \
248   u32 rn = (opcode >> 16) & 0x0F;                                             \
249   u32 rd = (opcode >> 12) & 0x0F;                                             \
250   u32 offset = opcode & 0x0FFF;                                               \
251   using_register(arm, rd, memory_target);                                     \
252   using_register(arm, rn, memory_base)                                        \
253 
254 #define arm_decode_data_trans_reg()                                           \
255   u32 rn = (opcode >> 16) & 0x0F;                                             \
256   u32 rd = (opcode >> 12) & 0x0F;                                             \
257   u32 rm = opcode & 0x0F;                                                     \
258   using_register(arm, rd, memory_target);                                     \
259   using_register(arm, rn, memory_base);                                       \
260   using_register(arm, rm, memory_offset)                                      \
261 
262 #define arm_decode_block_trans()                                              \
263   u32 rn = (opcode >> 16) & 0x0F;                                             \
264   u32 reg_list = opcode & 0xFFFF;                                             \
265   using_register(arm, rn, memory_base);                                       \
266   using_register_list(arm, reg_list, 16)                                      \
267 
268 #define arm_decode_branch()                                                   \
269   s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6                           \
270 
271 
272 #define thumb_decode_shift()                                                  \
273   u32 imm = (opcode >> 6) & 0x1F;                                             \
274   u32 rs = (opcode >> 3) & 0x07;                                              \
275   u32 rd = opcode & 0x07;                                                     \
276   using_register(thumb, rd, op_dest);                                         \
277   using_register(thumb, rs, op_shift)                                         \
278 
279 #define thumb_decode_add_sub()                                                \
280   u32 rn = (opcode >> 6) & 0x07;                                              \
281   u32 rs = (opcode >> 3) & 0x07;                                              \
282   u32 rd = opcode & 0x07;                                                     \
283   using_register(thumb, rd, op_dest);                                         \
284   using_register(thumb, rn, op_src);                                          \
285   using_register(thumb, rn, op_src)                                           \
286 
287 #define thumb_decode_add_sub_imm()                                            \
288   u32 imm = (opcode >> 6) & 0x07;                                             \
289   u32 rs = (opcode >> 3) & 0x07;                                              \
290   u32 rd = opcode & 0x07;                                                     \
291   using_register(thumb, rd, op_src_dest);                                     \
292   using_register(thumb, rs, op_src)                                           \
293 
294 #define thumb_decode_imm()                                                    \
295   u32 imm = opcode & 0xFF;                                                    \
296   using_register(thumb, ((opcode >> 8) & 0x07), op_dest)                      \
297 
298 #define thumb_decode_alu_op()                                                 \
299   u32 rs = (opcode >> 3) & 0x07;                                              \
300   u32 rd = opcode & 0x07;                                                     \
301   using_register(thumb, rd, op_src_dest);                                     \
302   using_register(thumb, rs, op_src)                                           \
303 
304 #define thumb_decode_hireg_op()                                               \
305   u32 rs = (opcode >> 3) & 0x0F;                                              \
306   u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x07);                          \
307   (void)rd;                                                                   \
308   using_register(thumb, rd, op_src_dest);                                     \
309   using_register(thumb, rs, op_src)                                           \
310 
311 
312 #define thumb_decode_mem_reg()                                                \
313   u32 ro = (opcode >> 6) & 0x07;                                              \
314   u32 rb = (opcode >> 3) & 0x07;                                              \
315   u32 rd = opcode & 0x07;                                                     \
316   using_register(thumb, rd, memory_target);                                   \
317   using_register(thumb, rb, memory_base);                                     \
318   using_register(thumb, ro, memory_offset)                                    \
319 
320 
321 #define thumb_decode_mem_imm()                                                \
322   u32 imm = (opcode >> 6) & 0x1F;                                             \
323   u32 rb = (opcode >> 3) & 0x07;                                              \
324   u32 rd = opcode & 0x07;                                                     \
325   using_register(thumb, rd, memory_target);                                   \
326   using_register(thumb, rb, memory_base)                                      \
327 
328 
329 #define thumb_decode_add_sp()                                                 \
330   u32 imm = opcode & 0x7F;                                                    \
331   using_register(thumb, REG_SP, op_dest)                                      \
332 
333 #define thumb_decode_rlist()                                                  \
334   u32 reg_list = opcode & 0xFF;                                               \
335   using_register_list(thumb, rlist, 8)                                        \
336 
337 #define thumb_decode_branch_cond()                                            \
338   s32 offset = (s8)(opcode & 0xFF)                                            \
339 
340 #define thumb_decode_swi()                                                    \
341   u32 comment = opcode & 0xFF                                                 \
342 
343 #define thumb_decode_branch()                                                 \
344   u32 offset = opcode & 0x07FF                                                \
345 
346 
347 #define get_shift_register(dest)                                              \
348   u32 shift = reg[(opcode >> 8) & 0x0F];                                      \
349   using_register(arm, ((opcode >> 8) & 0x0F), op_shift);                      \
350   dest = reg[rm];                                                             \
351   if(rm == 15)                                                                \
352     dest += 4                                                                 \
353 
354 
355 #define calculate_z_flag(dest)                                                \
356   z_flag = (dest == 0)                                                        \
357 
358 #define calculate_n_flag(dest)                                                \
359   n_flag = ((signed)dest < 0)                                                 \
360 
361 #define calculate_c_flag_sub(dest, src_a, src_b)                              \
362   c_flag = ((unsigned)src_b <= (unsigned)src_a)                               \
363 
364 #define calculate_v_flag_sub(dest, src_a, src_b)                              \
365   v_flag = ((signed)src_b > (signed)src_a) != ((signed)dest < 0)              \
366 
367 #define calculate_c_flag_add(dest, src_a, src_b)                              \
368   c_flag = ((unsigned)dest < (unsigned)src_a)                                 \
369 
370 #define calculate_v_flag_add(dest, src_a, src_b)                              \
371   v_flag = ((signed)dest < (signed)src_a) != ((signed)src_b < 0)              \
372 
373 
374 #define calculate_reg_sh()                                                    \
375   u32 reg_sh = 0;                                                             \
376   switch((opcode >> 4) & 0x07)                                                \
377   {                                                                           \
378     /* LSL imm */                                                             \
379     case 0x0:                                                                 \
380     {                                                                         \
381       reg_sh = reg[rm] << ((opcode >> 7) & 0x1F);                             \
382       break;                                                                  \
383     }                                                                         \
384                                                                               \
385     /* LSL reg */                                                             \
386     case 0x1:                                                                 \
387     {                                                                         \
388       get_shift_register(reg_sh);                                             \
389       if(shift <= 31)                                                         \
390         reg_sh = reg_sh << shift;                                             \
391       else                                                                    \
392         reg_sh = 0;                                                           \
393       break;                                                                  \
394     }                                                                         \
395                                                                               \
396     /* LSR imm */                                                             \
397     case 0x2:                                                                 \
398     {                                                                         \
399       u32 imm = (opcode >> 7) & 0x1F;                                         \
400       if(imm == 0)                                                            \
401         reg_sh = 0;                                                           \
402       else                                                                    \
403         reg_sh = reg[rm] >> imm;                                              \
404       break;                                                                  \
405     }                                                                         \
406                                                                               \
407     /* LSR reg */                                                             \
408     case 0x3:                                                                 \
409     {                                                                         \
410       get_shift_register(reg_sh);                                             \
411       if(shift <= 31)                                                         \
412         reg_sh = reg_sh >> shift;                                             \
413       else                                                                    \
414         reg_sh = 0;                                                           \
415       break;                                                                  \
416     }                                                                         \
417                                                                               \
418     /* ASR imm */                                                             \
419     case 0x4:                                                                 \
420     {                                                                         \
421       u32 imm = (opcode >> 7) & 0x1F;                                         \
422       reg_sh = reg[rm];                                                       \
423                                                                               \
424       if(imm == 0)                                                            \
425         reg_sh = (s32)reg_sh >> 31;                                           \
426       else                                                                    \
427         reg_sh = (s32)reg_sh >> imm;                                          \
428       break;                                                                  \
429     }                                                                         \
430                                                                               \
431     /* ASR reg */                                                             \
432     case 0x5:                                                                 \
433     {                                                                         \
434       get_shift_register(reg_sh);                                             \
435       if(shift <= 31)                                                         \
436         reg_sh = (s32)reg_sh >> shift;                                        \
437       else                                                                    \
438         reg_sh = (s32)reg_sh >> 31;                                           \
439       break;                                                                  \
440     }                                                                         \
441                                                                               \
442     /* ROR imm */                                                             \
443     case 0x6:                                                                 \
444     {                                                                         \
445       u32 imm = (opcode >> 7) & 0x1F;                                         \
446                                                                               \
447       if(imm == 0)                                                            \
448         reg_sh = (reg[rm] >> 1) | (c_flag << 31);                             \
449       else                                                                    \
450         ror(reg_sh, reg[rm], imm);                                            \
451       break;                                                                  \
452     }                                                                         \
453                                                                               \
454     /* ROR reg */                                                             \
455     case 0x7:                                                                 \
456     {                                                                         \
457       get_shift_register(reg_sh);                                             \
458       ror(reg_sh, reg_sh, shift);                                             \
459       break;                                                                  \
460     }                                                                         \
461   }                                                                           \
462 
463 #define calculate_reg_sh_flags()                                              \
464   u32 reg_sh = 0;                                                             \
465   switch((opcode >> 4) & 0x07)                                                \
466   {                                                                           \
467     /* LSL imm */                                                             \
468     case 0x0:                                                                 \
469     {                                                                         \
470       u32 imm = (opcode >> 7) & 0x1F;                                         \
471       reg_sh = reg[rm];                                                       \
472                                                                               \
473       if(imm != 0)                                                            \
474       {                                                                       \
475         c_flag = (reg_sh >> (32 - imm)) & 0x01;                               \
476         reg_sh <<= imm;                                                       \
477       }                                                                       \
478                                                                               \
479       break;                                                                  \
480     }                                                                         \
481                                                                               \
482     /* LSL reg */                                                             \
483     case 0x1:                                                                 \
484     {                                                                         \
485       get_shift_register(reg_sh);                                             \
486       if(shift != 0)                                                          \
487       {                                                                       \
488         if(shift > 31)                                                        \
489         {                                                                     \
490           if(shift == 32)                                                     \
491             c_flag = reg_sh & 0x01;                                           \
492           else                                                                \
493             c_flag = 0;                                                       \
494           reg_sh = 0;                                                         \
495         }                                                                     \
496         else                                                                  \
497         {                                                                     \
498           c_flag = (reg_sh >> (32 - shift)) & 0x01;                           \
499           reg_sh <<= shift;                                                   \
500         }                                                                     \
501       }                                                                       \
502       break;                                                                  \
503     }                                                                         \
504                                                                               \
505     /* LSR imm */                                                             \
506     case 0x2:                                                                 \
507     {                                                                         \
508       u32 imm = (opcode >> 7) & 0x1F;                                         \
509       reg_sh = reg[rm];                                                       \
510       if(imm == 0)                                                            \
511       {                                                                       \
512         c_flag = reg_sh >> 31;                                                \
513         reg_sh = 0;                                                           \
514       }                                                                       \
515       else                                                                    \
516       {                                                                       \
517         c_flag = (reg_sh >> (imm - 1)) & 0x01;                                \
518         reg_sh >>= imm;                                                       \
519       }                                                                       \
520       break;                                                                  \
521     }                                                                         \
522                                                                               \
523     /* LSR reg */                                                             \
524     case 0x3:                                                                 \
525     {                                                                         \
526       get_shift_register(reg_sh);                                             \
527       if(shift != 0)                                                          \
528       {                                                                       \
529         if(shift > 31)                                                        \
530         {                                                                     \
531           if(shift == 32)                                                     \
532             c_flag = (reg_sh >> 31) & 0x01;                                   \
533           else                                                                \
534             c_flag = 0;                                                       \
535           reg_sh = 0;                                                         \
536         }                                                                     \
537         else                                                                  \
538         {                                                                     \
539           c_flag = (reg_sh >> (shift - 1)) & 0x01;                            \
540           reg_sh >>= shift;                                                   \
541         }                                                                     \
542       }                                                                       \
543       break;                                                                  \
544     }                                                                         \
545                                                                               \
546     /* ASR imm */                                                             \
547     case 0x4:                                                                 \
548     {                                                                         \
549       u32 imm = (opcode >> 7) & 0x1F;                                         \
550       reg_sh = reg[rm];                                                       \
551       if(imm == 0)                                                            \
552       {                                                                       \
553         reg_sh = (s32)reg_sh >> 31;                                           \
554         c_flag = reg_sh & 0x01;                                               \
555       }                                                                       \
556       else                                                                    \
557       {                                                                       \
558         c_flag = (reg_sh >> (imm - 1)) & 0x01;                                \
559         reg_sh = (s32)reg_sh >> imm;                                          \
560       }                                                                       \
561       break;                                                                  \
562     }                                                                         \
563                                                                               \
564     /* ASR reg */                                                             \
565     case 0x5:                                                                 \
566     {                                                                         \
567       get_shift_register(reg_sh);                                             \
568       if(shift != 0)                                                          \
569       {                                                                       \
570         if(shift > 31)                                                        \
571         {                                                                     \
572           reg_sh = (s32)reg_sh >> 31;                                         \
573           c_flag = reg_sh & 0x01;                                             \
574         }                                                                     \
575         else                                                                  \
576         {                                                                     \
577           c_flag = (reg_sh >> (shift - 1)) & 0x01;                            \
578           reg_sh = (s32)reg_sh >> shift;                                      \
579         }                                                                     \
580       }                                                                       \
581       break;                                                                  \
582     }                                                                         \
583                                                                               \
584     /* ROR imm */                                                             \
585     case 0x6:                                                                 \
586     {                                                                         \
587       u32 imm = (opcode >> 7) & 0x1F;                                         \
588       reg_sh = reg[rm];                                                       \
589       if(imm == 0)                                                            \
590       {                                                                       \
591         u32 old_c_flag = c_flag;                                              \
592         c_flag = reg_sh & 0x01;                                               \
593         reg_sh = (reg_sh >> 1) | (old_c_flag << 31);                          \
594       }                                                                       \
595       else                                                                    \
596       {                                                                       \
597         c_flag = (reg_sh >> (imm - 1)) & 0x01;                                \
598         ror(reg_sh, reg_sh, imm);                                             \
599       }                                                                       \
600       break;                                                                  \
601     }                                                                         \
602                                                                               \
603     /* ROR reg */                                                             \
604     case 0x7:                                                                 \
605     {                                                                         \
606       get_shift_register(reg_sh);                                             \
607       if(shift != 0)                                                          \
608       {                                                                       \
609         c_flag = (reg_sh >> (shift - 1)) & 0x01;                              \
610         ror(reg_sh, reg_sh, shift);                                           \
611       }                                                                       \
612       break;                                                                  \
613     }                                                                         \
614   }                                                                           \
615 
616 #define calculate_reg_offset()                                                \
617   u32 reg_offset = 0;                                                         \
618   switch((opcode >> 5) & 0x03)                                                \
619   {                                                                           \
620     /* LSL imm */                                                             \
621     case 0x0:                                                                 \
622     {                                                                         \
623       reg_offset = reg[rm] << ((opcode >> 7) & 0x1F);                         \
624       break;                                                                  \
625     }                                                                         \
626                                                                               \
627     /* LSR imm */                                                             \
628     case 0x1:                                                                 \
629     {                                                                         \
630       u32 imm = (opcode >> 7) & 0x1F;                                         \
631       if(imm == 0)                                                            \
632         reg_offset = 0;                                                       \
633       else                                                                    \
634         reg_offset = reg[rm] >> imm;                                          \
635       break;                                                                  \
636     }                                                                         \
637                                                                               \
638     /* ASR imm */                                                             \
639     case 0x2:                                                                 \
640     {                                                                         \
641       u32 imm = (opcode >> 7) & 0x1F;                                         \
642       if(imm == 0)                                                            \
643         reg_offset = (s32)reg[rm] >> 31;                                      \
644       else                                                                    \
645         reg_offset = (s32)reg[rm] >> imm;                                     \
646       break;                                                                  \
647     }                                                                         \
648                                                                               \
649     /* ROR imm */                                                             \
650     case 0x3:                                                                 \
651     {                                                                         \
652       u32 imm = (opcode >> 7) & 0x1F;                                         \
653       if(imm == 0)                                                            \
654         reg_offset = (reg[rm] >> 1) | (c_flag << 31);                         \
655       else                                                                    \
656         ror(reg_offset, reg[rm], imm);                                        \
657       break;                                                                  \
658     }                                                                         \
659   }                                                                           \
660 
661 #define calculate_flags_add(dest, src_a, src_b)                               \
662   calculate_z_flag(dest);                                                     \
663   calculate_n_flag(dest);                                                     \
664   calculate_c_flag_add(dest, src_a, src_b);                                   \
665   calculate_v_flag_add(dest, src_a, src_b)                                    \
666 
667 #define calculate_flags_sub(dest, src_a, src_b)                               \
668   calculate_z_flag(dest);                                                     \
669   calculate_n_flag(dest);                                                     \
670   calculate_c_flag_sub(dest, src_a, src_b);                                   \
671   calculate_v_flag_sub(dest, src_a, src_b)                                    \
672 
673 #define calculate_flags_logic(dest)                                           \
674   calculate_z_flag(dest);                                                     \
675   calculate_n_flag(dest)                                                      \
676 
677 #define extract_flags()                                                       \
678   n_flag = reg[REG_CPSR] >> 31;                                               \
679   z_flag = (reg[REG_CPSR] >> 30) & 0x01;                                      \
680   c_flag = (reg[REG_CPSR] >> 29) & 0x01;                                      \
681   v_flag = (reg[REG_CPSR] >> 28) & 0x01;                                      \
682 
683 #define collapse_flags()                                                      \
684   reg[REG_CPSR] = (n_flag << 31) | (z_flag << 30) | (c_flag << 29) |          \
685    (v_flag << 28) | (reg[REG_CPSR] & 0xFF)                                    \
686 
687 #define memory_region(r_dest, l_dest, address)                                \
688   r_dest = memory_regions[address >> 24];                                     \
689   l_dest = memory_limits[address >> 24]                                       \
690 
691 
692 #define pc_region()                                                           \
693   memory_region(pc_region, pc_limit, pc)                                      \
694 
695 #define check_pc_region()                                                     \
696   new_pc_region = (pc >> 15);                                                 \
697   if(new_pc_region != pc_region)                                              \
698   {                                                                           \
699     pc_region = new_pc_region;                                                \
700     pc_address_block = memory_map_read[new_pc_region];                        \
701                                                                               \
702     if(!pc_address_block)                                                     \
703       pc_address_block = load_gamepak_page(pc_region & 0x3FF);                \
704   }                                                                           \
705 
706 u32 branch_targets = 0;
707 u32 high_frequency_branch_targets = 0;
708 
709 #define BRANCH_ACTIVITY_THRESHOLD 50
710 
711 #define arm_update_pc()                                                       \
712   pc = reg[REG_PC]                                                            \
713 
714 #define arm_pc_offset(val)                                                    \
715   pc += val;                                                                  \
716   reg[REG_PC] = pc                                                            \
717 
718 #define arm_pc_offset_update(val)                                             \
719   pc += val;                                                                  \
720   reg[REG_PC] = pc                                                            \
721 
722 #define arm_pc_offset_update_direct(val)                                      \
723   pc = val;                                                                   \
724   reg[REG_PC] = pc                                                            \
725 
726 
727 // It should be okay to still generate result flags, spsr will overwrite them.
728 // This is pretty infrequent (returning from interrupt handlers, et al) so
729 // probably not worth optimizing for.
730 
731 #define check_for_interrupts()                                                \
732   if((io_registers[REG_IE] & io_registers[REG_IF]) &&                         \
733    io_registers[REG_IME] && ((reg[REG_CPSR] & 0x80) == 0))                    \
734   {                                                                           \
735     reg_mode[MODE_IRQ][6] = reg[REG_PC] + 4;                                  \
736     spsr[MODE_IRQ] = reg[REG_CPSR];                                           \
737     reg[REG_CPSR] = 0xD2;                                                     \
738     reg[REG_PC] = 0x00000018;                                                 \
739     arm_update_pc();                                                          \
740     set_cpu_mode(MODE_IRQ);                                                   \
741     goto arm_loop;                                                            \
742   }                                                                           \
743 
744 #define arm_spsr_restore()                                                    \
745   if(rd == 15)                                                                \
746   {                                                                           \
747     if(reg[CPU_MODE] != MODE_USER)                                            \
748     {                                                                         \
749       reg[REG_CPSR] = spsr[reg[CPU_MODE]];                                    \
750       extract_flags();                                                        \
751       set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]);                          \
752       check_for_interrupts();                                                 \
753     }                                                                         \
754     arm_update_pc();                                                          \
755                                                                               \
756     if(reg[REG_CPSR] & 0x20)                                                  \
757       goto thumb_loop;                                                        \
758   }                                                                           \
759 
760 #define arm_data_proc_flags_reg()                                             \
761   arm_decode_data_proc_reg(opcode);                                           \
762   calculate_reg_sh_flags()                                                    \
763 
764 #define arm_data_proc_reg()                                                   \
765   arm_decode_data_proc_reg(opcode);                                           \
766   calculate_reg_sh()                                                          \
767 
768 #define arm_data_proc_flags_imm()                                             \
769   arm_decode_data_proc_imm(opcode)                                            \
770 
771 #define arm_data_proc_imm()                                                   \
772   arm_decode_data_proc_imm(opcode)                                            \
773 
774 #define arm_data_proc(expr, type)                                             \
775 {                                                                             \
776   u32 dest;                                                                   \
777   arm_pc_offset(8);                                                           \
778   arm_data_proc_##type();                                                     \
779   dest = expr;                                                                \
780   arm_pc_offset(-4);                                                          \
781   reg[rd] = dest;                                                             \
782                                                                               \
783   if(rd == 15)                                                                \
784   {                                                                           \
785     arm_update_pc();                                                          \
786   }                                                                           \
787 }                                                                             \
788 
789 #define flags_vars(src_a, src_b)                                              \
790   u32 dest;                                                                   \
791   const u32 _sa = src_a;                                                      \
792   const u32 _sb = src_b                                                       \
793 
794 #define arm_data_proc_logic_flags(expr, type)                                 \
795 {                                                                             \
796   arm_pc_offset(8);                                                           \
797   arm_data_proc_flags_##type();                                               \
798   u32 dest = expr;                                                            \
799   calculate_flags_logic(dest);                                                \
800   arm_pc_offset(-4);                                                          \
801   reg[rd] = dest;                                                             \
802   arm_spsr_restore();                                                         \
803 }                                                                             \
804 
805 #define arm_data_proc_add_flags(src_a, src_b, type)                           \
806 {                                                                             \
807   arm_pc_offset(8);                                                           \
808   arm_data_proc_##type();                                                     \
809   flags_vars(src_a, src_b);                                                   \
810   dest = _sa + _sb;                                                           \
811   calculate_flags_add(dest, _sa, _sb);                                        \
812   arm_pc_offset(-4);                                                          \
813   reg[rd] = dest;                                                             \
814   arm_spsr_restore();                                                         \
815 }
816 
817 #define arm_data_proc_sub_flags(src_a, src_b, type)                           \
818 {                                                                             \
819   arm_pc_offset(8);                                                           \
820   arm_data_proc_##type();                                                     \
821   flags_vars(src_a, src_b);                                                   \
822   dest = _sa - _sb;                                                           \
823   calculate_flags_sub(dest, _sa, _sb);                                        \
824   arm_pc_offset(-4);                                                          \
825   reg[rd] = dest;                                                             \
826   arm_spsr_restore();                                                         \
827 }                                                                             \
828 
829 #define arm_data_proc_test_logic(expr, type)                                  \
830 {                                                                             \
831   arm_pc_offset(8);                                                           \
832   arm_data_proc_flags_##type();                                               \
833   u32 dest = expr;                                                            \
834   calculate_flags_logic(dest);                                                \
835   arm_pc_offset(-4);                                                          \
836 }                                                                             \
837 
838 #define arm_data_proc_test_add(src_a, src_b, type)                            \
839 {                                                                             \
840   arm_pc_offset(8);                                                           \
841   arm_data_proc_##type();                                                     \
842   flags_vars(src_a, src_b);                                                   \
843   dest = _sa + _sb;                                                           \
844   calculate_flags_add(dest, _sa, _sb);                                        \
845   arm_pc_offset(-4);                                                          \
846 }                                                                             \
847 
848 #define arm_data_proc_test_sub(src_a, src_b, type)                            \
849 {                                                                             \
850   arm_pc_offset(8);                                                           \
851   arm_data_proc_##type();                                                     \
852   flags_vars(src_a, src_b);                                                   \
853   dest = _sa - _sb;                                                           \
854   calculate_flags_sub(dest, _sa, _sb);                                        \
855   arm_pc_offset(-4);                                                          \
856 }                                                                             \
857 
858 #define arm_multiply_flags_yes(_dest)                                         \
859   calculate_z_flag(_dest);                                                    \
860   calculate_n_flag(_dest);                                                    \
861 
862 #define arm_multiply_flags_no(_dest)                                          \
863 
864 #define arm_multiply_long_flags_yes(_dest_lo, _dest_hi)                       \
865   z_flag = (_dest_lo == 0) & (_dest_hi == 0);                                 \
866   calculate_n_flag(_dest_hi)                                                  \
867 
868 #define arm_multiply_long_flags_no(_dest_lo, _dest_hi)                        \
869 
870 #define arm_multiply(add_op, flags)                                           \
871 {                                                                             \
872   u32 dest;                                                                   \
873   arm_decode_multiply();                                                      \
874   dest = (reg[rm] * reg[rs]) add_op;                                          \
875   arm_multiply_flags_##flags(dest);                                           \
876   reg[rd] = dest;                                                             \
877   arm_pc_offset(4);                                                           \
878 }                                                                             \
879 
880 #define arm_multiply_long_addop(type)                                         \
881   + ((type##64)((((type##64)reg[rdhi]) << 32) | reg[rdlo]));                  \
882 
883 #define arm_multiply_long(add_op, flags, type)                                \
884 {                                                                             \
885   type##64 dest;                                                              \
886   u32 dest_lo;                                                                \
887   u32 dest_hi;                                                                \
888   arm_decode_multiply_long();                                                 \
889   dest = ((type##64)((type##32)reg[rm]) *                                     \
890    (type##64)((type##32)reg[rn])) add_op;                                     \
891   dest_lo = (u32)dest;                                                        \
892   dest_hi = (u32)(dest >> 32);                                                \
893   arm_multiply_long_flags_##flags(dest_lo, dest_hi);                          \
894   reg[rdlo] = dest_lo;                                                        \
895   reg[rdhi] = dest_hi;                                                        \
896   arm_pc_offset(4);                                                           \
897 }                                                                             \
898 
899 const u32 psr_masks[16] =
900 {
901   0x00000000, 0x000000FF, 0x0000FF00, 0x0000FFFF, 0x00FF0000,
902   0x00FF00FF, 0x00FFFF00, 0x00FFFFFF, 0xFF000000, 0xFF0000FF,
903   0xFF00FF00, 0xFF00FFFF, 0xFFFF0000, 0xFFFF00FF, 0xFFFFFF00,
904   0xFFFFFFFF
905 };
906 
907 #define arm_psr_read(dummy, psr_reg)                                          \
908   collapse_flags();                                                           \
909   reg[rd] = psr_reg                                                           \
910 
911 #define arm_psr_store_cpsr(source)                                            \
912   reg[REG_CPSR] = (source & store_mask) | (reg[REG_CPSR] & (~store_mask));    \
913   extract_flags();                                                            \
914   if(store_mask & 0xFF)                                                       \
915   {                                                                           \
916     set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]);                            \
917     check_for_interrupts();                                                   \
918   }                                                                           \
919 
920 #define arm_psr_store_spsr(source)                                            \
921   u32 _psr = spsr[reg[CPU_MODE]];                                             \
922   spsr[reg[CPU_MODE]] = (source & store_mask) | (_psr & (~store_mask))        \
923 
924 #define arm_psr_store(source, psr_reg)                                        \
925   const u32 store_mask = psr_masks[psr_field];                                \
926   arm_psr_store_##psr_reg(source)                                             \
927 
928 #define arm_psr_src_reg reg[rm]
929 
930 #define arm_psr_src_imm imm
931 
932 #define arm_psr(op_type, transfer_type, psr_reg)                              \
933 {                                                                             \
934   arm_decode_psr_##op_type(opcode);                                           \
935   arm_pc_offset(4);                                                           \
936   arm_psr_##transfer_type(arm_psr_src_##op_type, psr_reg);                    \
937 }                                                                             \
938 
939 #define arm_data_trans_reg()                                                  \
940   arm_decode_data_trans_reg();                                                \
941   calculate_reg_offset()                                                      \
942 
943 #define arm_data_trans_imm()                                                  \
944   arm_decode_data_trans_imm()                                                 \
945 
946 #define arm_data_trans_half_reg()                                             \
947   arm_decode_half_trans_r()                                                   \
948 
949 #define arm_data_trans_half_imm()                                             \
950   arm_decode_half_trans_of()                                                  \
951 
952 #define aligned_address_mask8  0xF0000000
953 #define aligned_address_mask16 0xF0000001
954 #define aligned_address_mask32 0xF0000003
955 
956 #define fast_read_memory(size, type, address, dest)                           \
957 {                                                                             \
958   u8 *map;                                                                    \
959   u32 _address = address;                                                     \
960                                                                               \
961   if(_address < 0x10000000)                                                   \
962   {                                                                           \
963     memory_region_access_read_##type[_address >> 24]++;                       \
964     memory_reads_##type++;                                                    \
965   }                                                                           \
966   if(((_address >> 24) == 0) && (pc >= 0x4000))                               \
967   {                                                                           \
968     dest = *((type *)((u8 *)&bios_read_protect + (_address & 0x03)));         \
969   }                                                                           \
970   else                                                                        \
971                                                                               \
972   if(((_address & aligned_address_mask##size) == 0) &&                        \
973    (map = memory_map_read[_address >> 15]))                                   \
974   {                                                                           \
975     dest = *((type *)((u8 *)map + (_address & 0x7FFF)));                      \
976   }                                                                           \
977   else                                                                        \
978   {                                                                           \
979     dest = (type)read_memory##size(_address);                                 \
980   }                                                                           \
981 }                                                                             \
982 
983 #define fast_read_memory_s16(address, dest)                                   \
984 {                                                                             \
985   u8 *map;                                                                    \
986   u32 _address = address;                                                     \
987   if(_address < 0x10000000)                                                   \
988   {                                                                           \
989     memory_region_access_read_s16[_address >> 24]++;                          \
990     memory_reads_s16++;                                                       \
991   }                                                                           \
992   if(((_address & aligned_address_mask16) == 0) &&                            \
993    (map = memory_map_read[_address >> 15]))                                   \
994   {                                                                           \
995     dest = *((s16 *)((u8 *)map + (_address & 0x7FFF)));                       \
996   }                                                                           \
997   else                                                                        \
998   {                                                                           \
999     dest = (s16)read_memory16_signed(_address);                               \
1000   }                                                                           \
1001 }                                                                             \
1002 
1003 
1004 #define fast_write_memory(size, type, address, value)                         \
1005 {                                                                             \
1006   u8 *map;                                                                    \
1007   u32 _address = (address) & ~(aligned_address_mask##size & 0x03);            \
1008   if(_address < 0x10000000)                                                   \
1009   {                                                                           \
1010     memory_region_access_write_##type[_address >> 24]++;                      \
1011     memory_writes_##type++;                                                   \
1012   }                                                                           \
1013                                                                               \
1014   if(((_address & aligned_address_mask##size) == 0) &&                        \
1015    (map = memory_map_write[_address >> 15]))                                  \
1016   {                                                                           \
1017     *((type *)((u8 *)map + (_address & 0x7FFF))) = value;                     \
1018   }                                                                           \
1019   else                                                                        \
1020   {                                                                           \
1021     cpu_alert = write_memory##size(_address, value);                          \
1022     if(cpu_alert)                                                             \
1023       goto alert;                                                             \
1024   }                                                                           \
1025 }                                                                             \
1026 
1027 #define load_aligned32(address, dest)                                         \
1028 {                                                                             \
1029   u32 _address = address;                                                     \
1030   u8 *map = memory_map_read[_address >> 15];                                  \
1031   if(_address < 0x10000000)                                                   \
1032   {                                                                           \
1033     memory_region_access_read_u32[_address >> 24]++;                          \
1034     memory_reads_u32++;                                                       \
1035   }                                                                           \
1036   if(map)                                                                     \
1037   {                                                                           \
1038     dest = address32(map, _address & 0x7FFF);                                 \
1039   }                                                                           \
1040   else                                                                        \
1041   {                                                                           \
1042     dest = read_memory32(_address);                                           \
1043   }                                                                           \
1044 }                                                                             \
1045 
1046 #define store_aligned32(address, value)                                       \
1047 {                                                                             \
1048   u32 _address = address;                                                     \
1049   u8 *map = memory_map_write[_address >> 15];                                 \
1050   if(_address < 0x10000000)                                                   \
1051   {                                                                           \
1052     memory_region_access_write_u32[_address >> 24]++;                         \
1053     memory_writes_u32++;                                                      \
1054   }                                                                           \
1055   if(map)                                                                     \
1056   {                                                                           \
1057     address32(map, _address & 0x7FFF) = value;                                \
1058   }                                                                           \
1059   else                                                                        \
1060   {                                                                           \
1061     cpu_alert = write_memory32(_address, value);                              \
1062     if(cpu_alert)                                                             \
1063       goto alert;                                                             \
1064   }                                                                           \
1065 }                                                                             \
1066 
1067 #define load_memory_u8(address, dest)                                         \
1068   fast_read_memory(8, u8, address, dest)                                      \
1069 
1070 #define load_memory_u16(address, dest)                                        \
1071   fast_read_memory(16, u16, address, dest)                                    \
1072 
1073 #define load_memory_u32(address, dest)                                        \
1074   fast_read_memory(32, u32, address, dest)                                    \
1075 
1076 #define load_memory_s8(address, dest)                                         \
1077   fast_read_memory(8, s8, address, dest)                                      \
1078 
1079 #define load_memory_s16(address, dest)                                        \
1080   fast_read_memory_s16(address, dest)                                         \
1081 
1082 #define store_memory_u8(address, value)                                       \
1083   fast_write_memory(8, u8, address, value)                                    \
1084 
1085 #define store_memory_u16(address, value)                                      \
1086   fast_write_memory(16, u16, address, value)                                  \
1087 
1088 #define store_memory_u32(address, value)                                      \
1089   fast_write_memory(32, u32, address, value)                                  \
1090 
1091 #define no_op                                                                 \
1092 
1093 #define arm_access_memory_writeback_yes(off_op)                               \
1094   reg[rn] = address off_op                                                    \
1095 
1096 #define arm_access_memory_writeback_no(off_op)                                \
1097 
1098 #define arm_access_memory_pc_preadjust_load()                                 \
1099 
1100 #define arm_access_memory_pc_preadjust_store()                                \
1101   u32 reg_op = reg[rd];                                                       \
1102   if(rd == 15)                                                                \
1103     reg_op += 4                                                               \
1104 
1105 #define arm_access_memory_pc_postadjust_load()                                \
1106   arm_update_pc()                                                             \
1107 
1108 #define arm_access_memory_pc_postadjust_store()                               \
1109 
1110 #define load_reg_op reg[rd]                                                   \
1111 
1112 #define store_reg_op reg_op                                                   \
1113 
1114 #define arm_access_memory(access_type, off_op, off_type, mem_type,            \
1115  wb, wb_off_op)                                                               \
1116 {                                                                             \
1117   arm_pc_offset(8);                                                           \
1118   arm_data_trans_##off_type();                                                \
1119   u32 address = reg[rn] off_op;                                               \
1120   arm_access_memory_pc_preadjust_##access_type();                             \
1121                                                                               \
1122   arm_pc_offset(-4);                                                          \
1123   arm_access_memory_writeback_##wb(wb_off_op);                                \
1124   access_type##_memory_##mem_type(address, access_type##_reg_op);             \
1125   arm_access_memory_pc_postadjust_##access_type();                            \
1126 }                                                                             \
1127 
1128 #define word_bit_count(word)                                                  \
1129   (bit_count[word >> 8] + bit_count[word & 0xFF])                             \
1130 
1131 #define sprint_no(access_type, offset_type, writeback_type)                   \
1132 
1133 #define sprint_yes(access_type, offset_type, writeback_type)                  \
1134   printf("sbit on %s %s %s\n", #access_type, #offset_type, #writeback_type)   \
1135 
1136 #define arm_block_writeback_load()                                            \
1137   if(!((reg_list >> rn) & 0x01))                                              \
1138   {                                                                           \
1139     reg[rn] = address;                                                        \
1140   }                                                                           \
1141 
1142 #define arm_block_writeback_store()                                           \
1143   reg[rn] = address                                                           \
1144 
1145 #define arm_block_writeback_yes(access_type)                                  \
1146   arm_block_writeback_##access_type()                                         \
1147 
1148 #define arm_block_writeback_no(access_type)                                   \
1149 
1150 #define load_block_memory(address, dest)                                      \
1151   dest = address32(address_region, (address + offset) & 0x7FFF)               \
1152 
1153 #define store_block_memory(address, dest)                                     \
1154   address32(address_region, (address + offset) & 0x7FFF) = dest               \
1155 
1156 #define arm_block_memory_offset_down_a()                                      \
1157   (base - (word_bit_count(reg_list) * 4) + 4)                                 \
1158 
1159 #define arm_block_memory_offset_down_b()                                      \
1160   (base - (word_bit_count(reg_list) * 4))                                     \
1161 
1162 #define arm_block_memory_offset_no()                                          \
1163   (base)                                                                      \
1164 
1165 #define arm_block_memory_offset_up()                                          \
1166   (base + 4)                                                                  \
1167 
1168 #define arm_block_memory_writeback_down()                                     \
1169   reg[rn] = base - (word_bit_count(reg_list) * 4)                             \
1170 
1171 #define arm_block_memory_writeback_up()                                       \
1172   reg[rn] = base + (word_bit_count(reg_list) * 4)                             \
1173 
1174 #define arm_block_memory_writeback_no()                                       \
1175 
1176 #define arm_block_memory_load_pc()                                            \
1177   load_aligned32(address, pc);                                                \
1178   reg[REG_PC] = pc                                                            \
1179 
1180 #define arm_block_memory_store_pc()                                           \
1181   store_aligned32(address, pc + 4)                                            \
1182 
1183 #define arm_block_memory(access_type, offset_type, writeback_type, s_bit)     \
1184 {                                                                             \
1185   arm_decode_block_trans();                                                   \
1186   u32 base = reg[rn];                                                         \
1187   u32 address = arm_block_memory_offset_##offset_type() & 0xFFFFFFFC;         \
1188   u32 i;                                                                      \
1189                                                                               \
1190   arm_block_memory_writeback_##writeback_type();                              \
1191                                                                               \
1192   for(i = 0; i < 15; i++)                                                     \
1193   {                                                                           \
1194     if((reg_list >> i) & 0x01)                                                \
1195     {                                                                         \
1196       access_type##_aligned32(address, reg[i]);                               \
1197       address += 4;                                                           \
1198     }                                                                         \
1199   }                                                                           \
1200                                                                               \
1201   arm_pc_offset(4);                                                           \
1202   if(reg_list & 0x8000)                                                       \
1203   {                                                                           \
1204     arm_block_memory_##access_type##_pc();                                    \
1205   }                                                                           \
1206 }                                                                             \
1207 
1208 #define arm_swap(type)                                                        \
1209 {                                                                             \
1210   arm_decode_swap();                                                          \
1211   u32 temp;                                                                   \
1212   load_memory_##type(reg[rn], temp);                                          \
1213   store_memory_##type(reg[rn], reg[rm]);                                      \
1214   reg[rd] = temp;                                                             \
1215   arm_pc_offset(4);                                                           \
1216 }                                                                             \
1217 
1218 #define arm_next_instruction()                                                \
1219 {                                                                             \
1220   arm_pc_offset(4);                                                           \
1221   goto skip_instruction;                                                      \
1222 }                                                                             \
1223 
1224 #define thumb_update_pc()                                                     \
1225   pc = reg[REG_PC]                                                            \
1226 
1227 #define thumb_pc_offset(val)                                                  \
1228   pc += val;                                                                  \
1229   reg[REG_PC] = pc                                                            \
1230 
1231 #define thumb_pc_offset_update(val)                                           \
1232   pc += val;                                                                  \
1233   reg[REG_PC] = pc                                                            \
1234 
1235 #define thumb_pc_offset_update_direct(val)                                    \
1236   pc = val;                                                                   \
1237   reg[REG_PC] = pc                                                            \
1238 
1239 // Types: add_sub, add_sub_imm, alu_op, imm
1240 // Affects N/Z/C/V flags
1241 
1242 #define thumb_add(type, dest_reg, src_a, src_b)                               \
1243 {                                                                             \
1244   thumb_decode_##type();                                                      \
1245   const u32 _sa = src_a;                                                      \
1246   const u32 _sb = src_b;                                                      \
1247   u32 dest = _sa + _sb;                                                       \
1248   calculate_flags_add(dest, _sa, _sb);                                        \
1249   reg[dest_reg] = dest;                                                       \
1250   thumb_pc_offset(2);                                                         \
1251 }                                                                             \
1252 
1253 #define thumb_add_noflags(type, dest_reg, src_a, src_b)                       \
1254 {                                                                             \
1255   thumb_decode_##type();                                                      \
1256   u32 dest = (src_a) + (src_b);                                               \
1257   reg[dest_reg] = dest;                                                       \
1258   thumb_pc_offset(2);                                                         \
1259 }                                                                             \
1260 
1261 #define thumb_sub(type, dest_reg, src_a, src_b)                               \
1262 {                                                                             \
1263   thumb_decode_##type();                                                      \
1264   const u32 _sa = src_a;                                                      \
1265   const u32 _sb = src_b;                                                      \
1266   u32 dest = _sa - _sb;                                                       \
1267   calculate_flags_sub(dest, _sa, _sb);                                        \
1268   reg[dest_reg] = dest;                                                       \
1269   thumb_pc_offset(2);                                                         \
1270 }                                                                             \
1271 
1272 // Affects N/Z flags
1273 
1274 #define thumb_logic(type, dest_reg, expr)                                     \
1275 {                                                                             \
1276   thumb_decode_##type();                                                      \
1277   u32 dest = expr;                                                            \
1278   calculate_flags_logic(dest);                                                \
1279   reg[dest_reg] = dest;                                                       \
1280   thumb_pc_offset(2);                                                         \
1281 }                                                                             \
1282 
1283 // Decode types: shift, alu_op
1284 // Operation types: lsl, lsr, asr, ror
1285 // Affects N/Z/C flags
1286 
1287 #define thumb_shift_lsl_reg()                                                 \
1288   u32 shift = reg[rs];                                                        \
1289   u32 dest = reg[rd];                                                         \
1290   if(shift != 0)                                                              \
1291   {                                                                           \
1292     if(shift > 31)                                                            \
1293     {                                                                         \
1294       if(shift == 32)                                                         \
1295         c_flag = dest & 0x01;                                                 \
1296       else                                                                    \
1297         c_flag = 0;                                                           \
1298       dest = 0;                                                               \
1299     }                                                                         \
1300     else                                                                      \
1301     {                                                                         \
1302       c_flag = (dest >> (32 - shift)) & 0x01;                                 \
1303       dest <<= shift;                                                         \
1304     }                                                                         \
1305   }                                                                           \
1306 
1307 #define thumb_shift_lsr_reg()                                                 \
1308   u32 shift = reg[rs];                                                        \
1309   u32 dest = reg[rd];                                                         \
1310   if(shift != 0)                                                              \
1311   {                                                                           \
1312     if(shift > 31)                                                            \
1313     {                                                                         \
1314       if(shift == 32)                                                         \
1315         c_flag = dest >> 31;                                                  \
1316       else                                                                    \
1317         c_flag = 0;                                                           \
1318       dest = 0;                                                               \
1319     }                                                                         \
1320     else                                                                      \
1321     {                                                                         \
1322       c_flag = (dest >> (shift - 1)) & 0x01;                                  \
1323       dest >>= shift;                                                         \
1324     }                                                                         \
1325   }                                                                           \
1326 
1327 #define thumb_shift_asr_reg()                                                 \
1328   u32 shift = reg[rs];                                                        \
1329   u32 dest = reg[rd];                                                         \
1330   if(shift != 0)                                                              \
1331   {                                                                           \
1332     if(shift > 31)                                                            \
1333     {                                                                         \
1334       dest = (s32)dest >> 31;                                                 \
1335       c_flag = dest & 0x01;                                                   \
1336     }                                                                         \
1337     else                                                                      \
1338     {                                                                         \
1339       c_flag = (dest >> (shift - 1)) & 0x01;                                  \
1340       dest = (s32)dest >> shift;                                              \
1341     }                                                                         \
1342   }                                                                           \
1343 
1344 #define thumb_shift_ror_reg()                                                 \
1345   u32 shift = reg[rs];                                                        \
1346   u32 dest = reg[rd];                                                         \
1347   if(shift != 0)                                                              \
1348   {                                                                           \
1349     c_flag = (dest >> (shift - 1)) & 0x01;                                    \
1350     ror(dest, dest, shift);                                                   \
1351   }                                                                           \
1352 
1353 #define thumb_shift_lsl_imm()                                                 \
1354   u32 dest = reg[rs];                                                         \
1355   if(imm != 0)                                                                \
1356   {                                                                           \
1357     c_flag = (dest >> (32 - imm)) & 0x01;                                     \
1358     dest <<= imm;                                                             \
1359   }                                                                           \
1360 
1361 #define thumb_shift_lsr_imm()                                                 \
1362   u32 dest;                                                                   \
1363   if(imm == 0)                                                                \
1364   {                                                                           \
1365     dest = 0;                                                                 \
1366     c_flag = reg[rs] >> 31;                                                   \
1367   }                                                                           \
1368   else                                                                        \
1369   {                                                                           \
1370     dest = reg[rs];                                                           \
1371     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1372     dest >>= imm;                                                             \
1373   }                                                                           \
1374 
1375 #define thumb_shift_asr_imm()                                                 \
1376   u32 dest;                                                                   \
1377   if(imm == 0)                                                                \
1378   {                                                                           \
1379     dest = (s32)reg[rs] >> 31;                                                \
1380     c_flag = dest & 0x01;                                                     \
1381   }                                                                           \
1382   else                                                                        \
1383   {                                                                           \
1384     dest = reg[rs];                                                           \
1385     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1386     dest = (s32)dest >> imm;                                                  \
1387   }                                                                           \
1388 
1389 #define thumb_shift_ror_imm()                                                 \
1390   u32 dest = reg[rs];                                                         \
1391   if(imm == 0)                                                                \
1392   {                                                                           \
1393     u32 old_c_flag = c_flag;                                                  \
1394     c_flag = dest & 0x01;                                                     \
1395     dest = (dest >> 1) | (old_c_flag << 31);                                  \
1396   }                                                                           \
1397   else                                                                        \
1398   {                                                                           \
1399     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1400     ror(dest, dest, imm);                                                     \
1401   }                                                                           \
1402 
1403 #define thumb_shift(decode_type, op_type, value_type)                         \
1404 {                                                                             \
1405   thumb_decode_##decode_type();                                               \
1406   thumb_shift_##op_type##_##value_type();                                     \
1407   calculate_flags_logic(dest);                                                \
1408   reg[rd] = dest;                                                             \
1409   thumb_pc_offset(2);                                                         \
1410 }                                                                             \
1411 
1412 #define thumb_test_add(type, src_a, src_b)                                    \
1413 {                                                                             \
1414   thumb_decode_##type();                                                      \
1415   const u32 _sa = src_a;                                                      \
1416   const u32 _sb = src_b;                                                      \
1417   u32 dest = _sa + _sb;                                                       \
1418   calculate_flags_add(dest, src_a, src_b);                                    \
1419   thumb_pc_offset(2);                                                         \
1420 }                                                                             \
1421 
1422 #define thumb_test_sub(type, src_a, src_b)                                    \
1423 {                                                                             \
1424   thumb_decode_##type();                                                      \
1425   const u32 _sa = src_a;                                                      \
1426   const u32 _sb = src_b;                                                      \
1427   u32 dest = _sa - _sb;                                                       \
1428   calculate_flags_sub(dest, src_a, src_b);                                    \
1429   thumb_pc_offset(2);                                                         \
1430 }                                                                             \
1431 
1432 #define thumb_test_logic(type, expr)                                          \
1433 {                                                                             \
1434   thumb_decode_##type();                                                      \
1435   u32 dest = expr;                                                            \
1436   calculate_flags_logic(dest);                                                \
1437   thumb_pc_offset(2);                                                         \
1438 }
1439 
1440 #define thumb_hireg_op(expr)                                                  \
1441 {                                                                             \
1442   thumb_pc_offset(4);                                                         \
1443   thumb_decode_hireg_op();                                                    \
1444   u32 dest = expr;                                                            \
1445   thumb_pc_offset(-2);                                                        \
1446   if(rd == 15)                                                                \
1447   {                                                                           \
1448     reg[REG_PC] = dest & ~0x01;                                               \
1449     thumb_update_pc();                                                        \
1450   }                                                                           \
1451   else                                                                        \
1452   {                                                                           \
1453     reg[rd] = dest;                                                           \
1454   }                                                                           \
1455 }                                                                             \
1456 
1457 // Operation types: imm, mem_reg, mem_imm
1458 
1459 #define thumb_access_memory(access_type, op_type, address, reg_op,            \
1460  mem_type)                                                                    \
1461 {                                                                             \
1462   thumb_decode_##op_type();                                                   \
1463   access_type##_memory_##mem_type(address, reg_op);                           \
1464   thumb_pc_offset(2);                                                         \
1465 }                                                                             \
1466 
1467 #define thumb_block_address_preadjust_no_op()                                 \
1468 
1469 #define thumb_block_address_preadjust_up()                                    \
1470   address += bit_count[reg_list] * 4                                          \
1471 
1472 #define thumb_block_address_preadjust_down()                                  \
1473   address -= bit_count[reg_list] * 4                                          \
1474 
1475 #define thumb_block_address_preadjust_push_lr()                               \
1476   address -= (bit_count[reg_list] + 1) * 4                                    \
1477 
1478 #define thumb_block_address_postadjust_no_op()                                \
1479 
1480 #define thumb_block_address_postadjust_up()                                   \
1481   address += offset                                                           \
1482 
1483 #define thumb_block_address_postadjust_down()                                 \
1484   address -= offset                                                           \
1485 
1486 #define thumb_block_address_postadjust_pop_pc()                               \
1487   load_memory_u32(address + offset, pc);                                      \
1488   pc &= ~0x01;                                                                \
1489   reg[REG_PC] = pc;                                                           \
1490   address += offset + 4                                                       \
1491 
1492 #define thumb_block_address_postadjust_push_lr()                              \
1493   store_memory_u32(address + offset, reg[REG_LR]);                            \
1494 
1495 #define thumb_block_memory_wb_load(base_reg)                                  \
1496   if(!((reg_list >> base_reg) & 0x01))                                        \
1497   {                                                                           \
1498     reg[base_reg] = address;                                                  \
1499   }                                                                           \
1500 
1501 #define thumb_block_memory_wb_store(base_reg)                                 \
1502   reg[base_reg] = address                                                     \
1503 
1504 #define thumb_block_memory(access_type, pre_op, post_op, base_reg)            \
1505 {                                                                             \
1506   u32 i;                                                                      \
1507   u32 offset = 0;                                                             \
1508   thumb_decode_rlist();                                                       \
1509   using_register(thumb, base_reg, memory_base);                               \
1510   u32 address = reg[base_reg] & ~0x03;                                        \
1511   thumb_block_address_preadjust_##pre_op();                                   \
1512                                                                               \
1513   for(i = 0; i < 8; i++)                                                      \
1514   {                                                                           \
1515     if((reg_list >> i) & 1)                                                   \
1516     {                                                                         \
1517       access_type##_aligned32(address + offset, reg[i]);                      \
1518       offset += 4;                                                            \
1519     }                                                                         \
1520   }                                                                           \
1521                                                                               \
1522   thumb_pc_offset(2);                                                         \
1523                                                                               \
1524   thumb_block_address_postadjust_##post_op();                                 \
1525   thumb_block_memory_wb_##access_type(base_reg);                              \
1526 }                                                                             \
1527 
1528 #define thumb_conditional_branch(condition)                                   \
1529 {                                                                             \
1530   thumb_decode_branch_cond();                                                 \
1531   if(condition)                                                               \
1532   {                                                                           \
1533     thumb_pc_offset((offset * 2) + 4);                                        \
1534   }                                                                           \
1535   else                                                                        \
1536   {                                                                           \
1537     thumb_pc_offset(2);                                                       \
1538   }                                                                           \
1539 }                                                                             \
1540 
1541 // When a mode change occurs from non-FIQ to non-FIQ retire the current
1542 // reg[13] and reg[14] into reg_mode[cpu_mode][5] and reg_mode[cpu_mode][6]
1543 // respectively and load into reg[13] and reg[14] reg_mode[new_mode][5] and
1544 // reg_mode[new_mode][6]. When swapping to/from FIQ retire/load reg[8]
1545 // through reg[14] to/from reg_mode[MODE_FIQ][0] through reg_mode[MODE_FIQ][6].
1546 
1547 u32 reg_mode[7][7];
1548 
1549 u32 cpu_modes[32] =
1550 {
1551   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1552   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1553   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1554   MODE_INVALID, MODE_USER, MODE_FIQ, MODE_IRQ, MODE_SUPERVISOR, MODE_INVALID,
1555   MODE_INVALID, MODE_INVALID, MODE_ABORT, MODE_INVALID, MODE_INVALID,
1556   MODE_INVALID, MODE_INVALID, MODE_UNDEFINED, MODE_INVALID, MODE_INVALID,
1557   MODE_USER
1558 };
1559 
1560 u32 cpu_modes_cpsr[7] = { 0x10, 0x11, 0x12, 0x13, 0x17, 0x1B, 0x1F };
1561 
1562 // When switching modes set spsr[new_mode] to cpsr. Modifying PC as the
1563 // target of a data proc instruction will set cpsr to spsr[cpu_mode].
1564 
1565 u32 initial_reg[64];
1566 u32 *reg = initial_reg;
1567 u32 spsr[6];
1568 
1569 // ARM/Thumb mode is stored in the flags directly, this is simpler than
1570 // shadowing it since it has a constant 1bit represenation.
1571 
1572 char *reg_names[16] =
1573 {
1574   " r0", " r1", " r2", " r3", " r4", " r5", " r6", " r7",
1575   " r8", " r9", "r10", " fp", " ip", " sp", " lr", " pc"
1576 };
1577 
1578 char *cpu_mode_names[] =
1579 {
1580   "user", "irq", "fiq", "svsr", "abrt", "undf", "invd"
1581 };
1582 
1583 u32 instruction_count = 0;
1584 
1585 u32 output_field = 0;
1586 const u32 num_output_fields = 2;
1587 
1588 u32 last_instruction = 0;
1589 
1590 u32 in_interrupt = 0;
1591 
set_cpu_mode(cpu_mode_type new_mode)1592 void set_cpu_mode(cpu_mode_type new_mode)
1593 {
1594   u32 i;
1595   cpu_mode_type cpu_mode = reg[CPU_MODE];
1596 
1597   if(cpu_mode == new_mode)
1598      return;
1599 
1600   if(new_mode == MODE_FIQ)
1601   {
1602      for(i = 8; i < 15; i++)
1603         reg_mode[cpu_mode][i - 8] = reg[i];
1604   }
1605   else
1606   {
1607      reg_mode[cpu_mode][5] = reg[REG_SP];
1608      reg_mode[cpu_mode][6] = reg[REG_LR];
1609   }
1610 
1611   if(cpu_mode == MODE_FIQ)
1612   {
1613      for(i = 8; i < 15; i++)
1614         reg[i] = reg_mode[new_mode][i - 8];
1615   }
1616   else
1617   {
1618      reg[REG_SP] = reg_mode[new_mode][5];
1619      reg[REG_LR] = reg_mode[new_mode][6];
1620   }
1621 
1622   reg[CPU_MODE] = new_mode;
1623 }
1624 
raise_interrupt(irq_type irq_raised)1625 void raise_interrupt(irq_type irq_raised)
1626 {
1627   // The specific IRQ must be enabled in IE, master IRQ enable must be on,
1628   // and it must be on in the flags.
1629   io_registers[REG_IF] |= irq_raised;
1630 
1631   if((io_registers[REG_IE] & irq_raised) && io_registers[REG_IME] &&
1632    ((reg[REG_CPSR] & 0x80) == 0))
1633   {
1634     bios_read_protect = 0xe55ec002;
1635 
1636     // Interrupt handler in BIOS
1637     reg_mode[MODE_IRQ][6] = reg[REG_PC] + 4;
1638     spsr[MODE_IRQ] = reg[REG_CPSR];
1639     reg[REG_CPSR] = 0xD2;
1640     reg[REG_PC] = 0x00000018;
1641 
1642     bios_region_read_allow();
1643 
1644     set_cpu_mode(MODE_IRQ);
1645     reg[CPU_HALT_STATE] = CPU_ACTIVE;
1646     reg[CHANGED_PC_STATUS] = 1;
1647   }
1648 }
1649 
1650 #ifndef HAVE_DYNAREC
1651 u8 *memory_map_read [8 * 1024];
1652 u8 *memory_map_write[8 * 1024];
1653 #endif
1654 
execute_arm(u32 cycles)1655 void execute_arm(u32 cycles)
1656 {
1657   u32 pc = reg[REG_PC];
1658   u32 opcode;
1659   u32 condition;
1660   u32 n_flag, z_flag, c_flag, v_flag;
1661   u32 pc_region = (pc >> 15);
1662   u8 *pc_address_block = memory_map_read[pc_region];
1663   u32 new_pc_region;
1664   s32 cycles_remaining;
1665   u32 cycles_per_instruction = global_cycles_per_instruction;
1666   cpu_alert_type cpu_alert;
1667 
1668   u32 old_pc;
1669 
1670   (void)old_pc;
1671 
1672   if(!pc_address_block)
1673     pc_address_block = load_gamepak_page(pc_region & 0x3FF);
1674 
1675   while(1)
1676   {
1677     cycles_remaining = cycles;
1678     pc = reg[REG_PC];
1679     extract_flags();
1680 
1681     if(reg[REG_CPSR] & 0x20)
1682       goto thumb_loop;
1683 
1684     do
1685     {
1686 arm_loop:
1687 
1688        collapse_flags();
1689        cycles_per_instruction = global_cycles_per_instruction;
1690 
1691        old_pc = pc;
1692 
1693        /* Execute ARM instruction */
1694        using_instruction(arm);
1695        check_pc_region();
1696        pc &= ~0x03;
1697        opcode = address32(pc_address_block, (pc & 0x7FFF));
1698        condition = opcode >> 28;
1699 
1700        switch(condition)
1701        {
1702           case 0x0:
1703              /* EQ */
1704              if(!z_flag)
1705                 arm_next_instruction();
1706              break;
1707           case 0x1:
1708              /* NE      */
1709              if(z_flag)
1710                 arm_next_instruction();
1711              break;
1712           case 0x2:
1713              /* CS       */
1714              if(!c_flag)
1715                 arm_next_instruction();
1716              break;
1717           case 0x3:
1718              /* CC       */
1719              if(c_flag)
1720                 arm_next_instruction();
1721              break;
1722           case 0x4:
1723              /* MI       */
1724              if(!n_flag)
1725                 arm_next_instruction();
1726              break;
1727 
1728           case 0x5:
1729              /* PL       */
1730              if(n_flag)
1731                 arm_next_instruction();
1732              break;
1733 
1734           case 0x6:
1735              /* VS       */
1736              if(!v_flag)
1737                 arm_next_instruction();
1738              break;
1739 
1740           case 0x7:
1741              /* VC       */
1742              if(v_flag)
1743                 arm_next_instruction();
1744              break;
1745 
1746           case 0x8:
1747              /* HI       */
1748              if((c_flag == 0) | z_flag)
1749                 arm_next_instruction();
1750              break;
1751 
1752           case 0x9:
1753              /* LS       */
1754              if(c_flag & (z_flag ^ 1))
1755                 arm_next_instruction();
1756              break;
1757 
1758           case 0xA:
1759              /* GE       */
1760              if(n_flag != v_flag)
1761                 arm_next_instruction();
1762              break;
1763 
1764           case 0xB:
1765              /* LT       */
1766              if(n_flag == v_flag)
1767                 arm_next_instruction();
1768              break;
1769 
1770           case 0xC:
1771              /* GT       */
1772              if(z_flag | (n_flag != v_flag))
1773                 arm_next_instruction();
1774              break;
1775 
1776           case 0xD:
1777              /* LE       */
1778              if((z_flag == 0) & (n_flag == v_flag))
1779                 arm_next_instruction();
1780              break;
1781 
1782           case 0xE:
1783              /* AL       */
1784              break;
1785 
1786           case 0xF:
1787              /* Reserved - treat as "never" */
1788              arm_next_instruction();
1789              break;
1790        }
1791 
1792        switch((opcode >> 20) & 0xFF)
1793        {
1794           case 0x00:
1795              if((opcode & 0x90) == 0x90)
1796              {
1797                 if(opcode & 0x20)
1798                 {
1799                    /* STRH rd, [rn], -rm */
1800                    arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);
1801                 }
1802                 else
1803                 {
1804                    /* MUL rd, rm, rs */
1805                    arm_multiply(no_op, no);
1806                 }
1807              }
1808              else
1809              {
1810                 /* AND rd, rn, reg_op */
1811                 arm_data_proc(reg[rn] & reg_sh, reg);
1812              }
1813              break;
1814 
1815           case 0x01:
1816              if((opcode & 0x90) == 0x90)
1817              {
1818                 switch((opcode >> 5) & 0x03)
1819                 {
1820                    case 0:
1821                       /* MULS rd, rm, rs */
1822                       arm_multiply(no_op, yes);
1823                       break;
1824 
1825                    case 1:
1826                       /* LDRH rd, [rn], -rm */
1827                       arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);
1828                       break;
1829 
1830                    case 2:
1831                       /* LDRSB rd, [rn], -rm */
1832                       arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);
1833                       break;
1834 
1835                    case 3:
1836                       /* LDRSH rd, [rn], -rm */
1837                       arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);
1838                       break;
1839                 }
1840              }
1841              else
1842              {
1843                 /* ANDS rd, rn, reg_op */
1844                 arm_data_proc_logic_flags(reg[rn] & reg_sh, reg);
1845              }
1846              break;
1847 
1848           case 0x02:
1849              if((opcode & 0x90) == 0x90)
1850              {
1851                 if(opcode & 0x20)
1852                 {
1853                    /* STRH rd, [rn], -rm */
1854                    arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);
1855                 }
1856                 else
1857                 {
1858                    /* MLA rd, rm, rs, rn */
1859                    arm_multiply(+ reg[rn], no);
1860                 }
1861              }
1862              else
1863              {
1864                 /* EOR rd, rn, reg_op */
1865                 arm_data_proc(reg[rn] ^ reg_sh, reg);
1866              }
1867              break;
1868 
1869           case 0x03:
1870              if((opcode & 0x90) == 0x90)
1871              {
1872                 switch((opcode >> 5) & 0x03)
1873                 {
1874                    case 0:
1875                       /* MLAS rd, rm, rs, rn */
1876                       arm_multiply(+ reg[rn], yes);
1877                       break;
1878 
1879                    case 1:
1880                       /* LDRH rd, [rn], -rm */
1881                       arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);
1882                       break;
1883 
1884                    case 2:
1885                       /* LDRSB rd, [rn], -rm */
1886                       arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);
1887                       break;
1888 
1889                    case 3:
1890                       /* LDRSH rd, [rn], -rm */
1891                       arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);
1892                       break;
1893                 }
1894              }
1895              else
1896              {
1897                 /* EORS rd, rn, reg_op */
1898                 arm_data_proc_logic_flags(reg[rn] ^ reg_sh, reg);
1899              }
1900              break;
1901 
1902           case 0x04:
1903              if((opcode & 0x90) == 0x90)
1904              {
1905                 /* STRH rd, [rn], -imm */
1906                 arm_access_memory(store, no_op, half_imm, u16, yes, - offset);
1907              }
1908              else
1909              {
1910                 /* SUB rd, rn, reg_op */
1911                 arm_data_proc(reg[rn] - reg_sh, reg);
1912              }
1913              break;
1914 
1915           case 0x05:
1916              if((opcode & 0x90) == 0x90)
1917              {
1918                 switch((opcode >> 5) & 0x03)
1919                 {
1920                    case 1:
1921                       /* LDRH rd, [rn], -imm */
1922                       arm_access_memory(load, no_op, half_imm, u16, yes, - offset);
1923                       break;
1924 
1925                    case 2:
1926                       /* LDRSB rd, [rn], -imm */
1927                       arm_access_memory(load, no_op, half_imm, s8, yes, - offset);
1928                       break;
1929 
1930                    case 3:
1931                       /* LDRSH rd, [rn], -imm */
1932                       arm_access_memory(load, no_op, half_imm, s16, yes, - offset);
1933                       break;
1934                 }
1935              }
1936              else
1937              {
1938                 /* SUBS rd, rn, reg_op */
1939                 arm_data_proc_sub_flags(reg[rn], reg_sh, reg);
1940              }
1941              break;
1942 
1943           case 0x06:
1944              if((opcode & 0x90) == 0x90)
1945              {
1946                 /* STRH rd, [rn], -imm */
1947                 arm_access_memory(store, no_op, half_imm, u16, yes, - offset);
1948              }
1949              else
1950              {
1951                 /* RSB rd, rn, reg_op */
1952                 arm_data_proc(reg_sh - reg[rn], reg);
1953              }
1954              break;
1955 
1956           case 0x07:
1957              if((opcode & 0x90) == 0x90)
1958              {
1959                 switch((opcode >> 5) & 0x03)
1960                 {
1961                    case 1:
1962                       /* LDRH rd, [rn], -imm */
1963                       arm_access_memory(load, no_op, half_imm, u16, yes, - offset);
1964                       break;
1965 
1966                    case 2:
1967                       /* LDRSB rd, [rn], -imm */
1968                       arm_access_memory(load, no_op, half_imm, s8, yes, - offset);
1969                       break;
1970 
1971                    case 3:
1972                       /* LDRSH rd, [rn], -imm */
1973                       arm_access_memory(load, no_op, half_imm, s16, yes, - offset);
1974                       break;
1975                 }
1976              }
1977              else
1978              {
1979                 /* RSBS rd, rn, reg_op */
1980                 arm_data_proc_sub_flags(reg_sh, reg[rn], reg);
1981              }
1982              break;
1983 
1984           case 0x08:
1985              if((opcode & 0x90) == 0x90)
1986              {
1987                 if(opcode & 0x20)
1988                 {
1989                    /* STRH rd, [rn], +rm */
1990                    arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);
1991                 }
1992                 else
1993                 {
1994                    /* UMULL rd, rm, rs */
1995                    arm_multiply_long(no_op, no, u);
1996                 }
1997              }
1998              else
1999              {
2000                 /* ADD rd, rn, reg_op */
2001                 arm_data_proc(reg[rn] + reg_sh, reg);
2002              }
2003              break;
2004 
2005           case 0x09:
2006              if((opcode & 0x90) == 0x90)
2007              {
2008                 switch((opcode >> 5) & 0x03)
2009                 {
2010                    case 0:
2011                       /* UMULLS rdlo, rdhi, rm, rs */
2012                       arm_multiply_long(no_op, yes, u);
2013                       break;
2014 
2015                    case 1:
2016                       /* LDRH rd, [rn], +rm */
2017                       arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);
2018                       break;
2019 
2020                    case 2:
2021                       /* LDRSB rd, [rn], +rm */
2022                       arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);
2023                       break;
2024 
2025                    case 3:
2026                       /* LDRSH rd, [rn], +rm */
2027                       arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);
2028                       break;
2029                 }
2030              }
2031              else
2032              {
2033                 /* ADDS rd, rn, reg_op */
2034                 arm_data_proc_add_flags(reg[rn], reg_sh, reg);
2035              }
2036              break;
2037 
2038           case 0x0A:
2039              if((opcode & 0x90) == 0x90)
2040              {
2041                 if(opcode & 0x20)
2042                 {
2043                    /* STRH rd, [rn], +rm */
2044                    arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);
2045                 }
2046                 else
2047                 {
2048                    /* UMLAL rd, rm, rs */
2049                    arm_multiply_long(arm_multiply_long_addop(u), no, u);
2050                 }
2051              }
2052              else
2053              {
2054                 /* ADC rd, rn, reg_op */
2055                 arm_data_proc(reg[rn] + reg_sh + c_flag, reg);
2056              }
2057              break;
2058 
2059           case 0x0B:
2060              if((opcode & 0x90) == 0x90)
2061              {
2062                 switch((opcode >> 5) & 0x03)
2063                 {
2064                    case 0:
2065                       /* UMLALS rdlo, rdhi, rm, rs */
2066                       arm_multiply_long(arm_multiply_long_addop(u), yes, u);
2067                       break;
2068 
2069                    case 1:
2070                       /* LDRH rd, [rn], +rm */
2071                       arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);
2072                       break;
2073 
2074                    case 2:
2075                       /* LDRSB rd, [rn], +rm */
2076                       arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);
2077                       break;
2078 
2079                    case 3:
2080                       /* LDRSH rd, [rn], +rm */
2081                       arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);
2082                       break;
2083                 }
2084              }
2085              else
2086              {
2087                 /* ADCS rd, rn, reg_op */
2088                 arm_data_proc_add_flags(reg[rn], reg_sh + c_flag, reg);
2089              }
2090              break;
2091 
2092           case 0x0C:
2093              if((opcode & 0x90) == 0x90)
2094              {
2095                 if(opcode & 0x20)
2096                 {
2097                    /* STRH rd, [rn], +imm */
2098                    arm_access_memory(store, no_op, half_imm, u16, yes, + offset);
2099                 }
2100                 else
2101                 {
2102                    /* SMULL rd, rm, rs */
2103                    arm_multiply_long(no_op, no, s);
2104                 }
2105              }
2106              else
2107              {
2108                 /* SBC rd, rn, reg_op */
2109                 arm_data_proc(reg[rn] - (reg_sh + (c_flag ^ 1)), reg);
2110              }
2111              break;
2112 
2113           case 0x0D:
2114              if((opcode & 0x90) == 0x90)
2115              {
2116                 switch((opcode >> 5) & 0x03)
2117                 {
2118                    case 0:
2119                       /* SMULLS rdlo, rdhi, rm, rs */
2120                       arm_multiply_long(no_op, yes, s);
2121                       break;
2122 
2123                    case 1:
2124                       /* LDRH rd, [rn], +imm */
2125                       arm_access_memory(load, no_op, half_imm, u16, yes, + offset);
2126                       break;
2127 
2128                    case 2:
2129                       /* LDRSB rd, [rn], +imm */
2130                       arm_access_memory(load, no_op, half_imm, s8, yes, + offset);
2131                       break;
2132 
2133                    case 3:
2134                       /* LDRSH rd, [rn], +imm */
2135                       arm_access_memory(load, no_op, half_imm, s16, yes, + offset);
2136                       break;
2137                 }
2138              }
2139              else
2140              {
2141                 /* SBCS rd, rn, reg_op */
2142                 arm_data_proc_sub_flags(reg[rn], (reg_sh + (c_flag ^ 1)), reg);
2143              }
2144              break;
2145 
2146           case 0x0E:
2147              if((opcode & 0x90) == 0x90)
2148              {
2149                 if(opcode & 0x20)
2150                 {
2151                    /* STRH rd, [rn], +imm */
2152                    arm_access_memory(store, no_op, half_imm, u16, yes, + offset);
2153                 }
2154                 else
2155                 {
2156                    /* SMLAL rd, rm, rs */
2157                    arm_multiply_long(arm_multiply_long_addop(s), no, s);
2158                 }
2159              }
2160              else
2161              {
2162                 /* RSC rd, rn, reg_op */
2163                 arm_data_proc(reg_sh - reg[rn] + c_flag - 1, reg);
2164              }
2165              break;
2166 
2167           case 0x0F:
2168              if((opcode & 0x90) == 0x90)
2169              {
2170                 switch((opcode >> 5) & 0x03)
2171                 {
2172                    case 0:
2173                       /* SMLALS rdlo, rdhi, rm, rs */
2174                       arm_multiply_long(arm_multiply_long_addop(s), yes, s);
2175                       break;
2176 
2177                    case 1:
2178                       /* LDRH rd, [rn], +imm */
2179                       arm_access_memory(load, no_op, half_imm, u16, yes, + offset);
2180                       break;
2181 
2182                    case 2:
2183                       /* LDRSB rd, [rn], +imm */
2184                       arm_access_memory(load, no_op, half_imm, s8, yes, + offset);
2185                       break;
2186 
2187                    case 3:
2188                       /* LDRSH rd, [rn], +imm */
2189                       arm_access_memory(load, no_op, half_imm, s16, yes, + offset);
2190                       break;
2191                 }
2192              }
2193              else
2194              {
2195                 /* RSCS rd, rn, reg_op */
2196                 arm_data_proc_sub_flags((reg_sh + c_flag - 1), reg[rn], reg);
2197              }
2198              break;
2199 
2200           case 0x10:
2201              if((opcode & 0x90) == 0x90)
2202              {
2203                 if(opcode & 0x20)
2204                 {
2205                    /* STRH rd, [rn - rm] */
2206                    arm_access_memory(store, - reg[rm], half_reg, u16, no, no_op);
2207                 }
2208                 else
2209                 {
2210                    /* SWP rd, rm, [rn] */
2211                    arm_swap(u32);
2212                 }
2213              }
2214              else
2215              {
2216                 /* MRS rd, cpsr */
2217                 arm_psr(reg, read, reg[REG_CPSR]);
2218              }
2219              break;
2220 
2221           case 0x11:
2222              if((opcode & 0x90) == 0x90)
2223              {
2224                 switch((opcode >> 5) & 0x03)
2225                 {
2226                    case 1:
2227                       /* LDRH rd, [rn - rm] */
2228                       arm_access_memory(load, - reg[rm], half_reg, u16, no, no_op);
2229                       break;
2230 
2231                    case 2:
2232                       /* LDRSB rd, [rn - rm] */
2233                       arm_access_memory(load, - reg[rm], half_reg, s8, no, no_op);
2234                       break;
2235 
2236                    case 3:
2237                       /* LDRSH rd, [rn - rm] */
2238                       arm_access_memory(load, - reg[rm], half_reg, s16, no, no_op);
2239                       break;
2240                 }
2241              }
2242              else
2243              {
2244                 /* TST rd, rn, reg_op */
2245                 arm_data_proc_test_logic(reg[rn] & reg_sh, reg);
2246              }
2247              break;
2248 
2249           case 0x12:
2250              if((opcode & 0x90) == 0x90)
2251              {
2252                 /* STRH rd, [rn - rm]! */
2253                 arm_access_memory(store, - reg[rm], half_reg, u16, yes, no_op);
2254              }
2255              else
2256              {
2257                 if(opcode & 0x10)
2258                 {
2259                    /* BX rn */
2260                    arm_decode_branchx(opcode);
2261                    u32 src = reg[rn];
2262                    if(src & 0x01)
2263                    {
2264                       src -= 1;
2265                       arm_pc_offset_update_direct(src);
2266                       reg[REG_CPSR] |= 0x20;
2267                       goto thumb_loop;
2268                    }
2269                    else
2270                    {
2271                       arm_pc_offset_update_direct(src);
2272                    }
2273                 }
2274                 else
2275                 {
2276                    /* MSR cpsr, rm */
2277                    arm_psr(reg, store, cpsr);
2278                 }
2279              }
2280              break;
2281 
2282           case 0x13:
2283              if((opcode & 0x90) == 0x90)
2284              {
2285                 switch((opcode >> 5) & 0x03)
2286                 {
2287                    case 1:
2288                       /* LDRH rd, [rn - rm]! */
2289                       arm_access_memory(load, - reg[rm], half_reg, u16, yes, no_op);
2290                       break;
2291 
2292                    case 2:
2293                       /* LDRSB rd, [rn - rm]! */
2294                       arm_access_memory(load, - reg[rm], half_reg, s8, yes, no_op);
2295                       break;
2296 
2297                    case 3:
2298                       /* LDRSH rd, [rn - rm]! */
2299                       arm_access_memory(load, - reg[rm], half_reg, s16, yes, no_op);
2300                       break;
2301                 }
2302              }
2303              else
2304              {
2305                 /* TEQ rd, rn, reg_op */
2306                 arm_data_proc_test_logic(reg[rn] ^ reg_sh, reg);
2307              }
2308              break;
2309 
2310           case 0x14:
2311              if((opcode & 0x90) == 0x90)
2312              {
2313                 if(opcode & 0x20)
2314                 {
2315                    /* STRH rd, [rn - imm] */
2316                    arm_access_memory(store, - offset, half_imm, u16, no, no_op);
2317                 }
2318                 else
2319                 {
2320                    /* SWPB rd, rm, [rn] */
2321                    arm_swap(u8);
2322                 }
2323              }
2324              else
2325              {
2326                 /* MRS rd, spsr */
2327                 arm_psr(reg, read, spsr[reg[CPU_MODE]]);
2328              }
2329              break;
2330 
2331           case 0x15:
2332              if((opcode & 0x90) == 0x90)
2333              {
2334                 switch((opcode >> 5) & 0x03)
2335                 {
2336                    case 1:
2337                       /* LDRH rd, [rn - imm] */
2338                       arm_access_memory(load, - offset, half_imm, u16, no, no_op);
2339                       break;
2340 
2341                    case 2:
2342                       /* LDRSB rd, [rn - imm] */
2343                       arm_access_memory(load, - offset, half_imm, s8, no, no_op);
2344                       break;
2345 
2346                    case 3:
2347                       /* LDRSH rd, [rn - imm] */
2348                       arm_access_memory(load, - offset, half_imm, s16, no, no_op);
2349                       break;
2350                 }
2351              }
2352              else
2353              {
2354                 /* CMP rn, reg_op */
2355                 arm_data_proc_test_sub(reg[rn], reg_sh, reg);
2356              }
2357              break;
2358 
2359           case 0x16:
2360              if((opcode & 0x90) == 0x90)
2361              {
2362                 /* STRH rd, [rn - imm]! */
2363                 arm_access_memory(store, - offset, half_imm, u16, yes, no_op);
2364              }
2365              else
2366              {
2367                 /* MSR spsr, rm */
2368                 arm_psr(reg, store, spsr);
2369              }
2370              break;
2371 
2372           case 0x17:
2373              if((opcode & 0x90) == 0x90)
2374              {
2375                 switch((opcode >> 5) & 0x03)
2376                 {
2377                    case 1:
2378                       /* LDRH rd, [rn - imm]! */
2379                       arm_access_memory(load, - offset, half_imm, u16, yes, no_op);
2380                       break;
2381 
2382                    case 2:
2383                       /* LDRSB rd, [rn - imm]! */
2384                       arm_access_memory(load, - offset, half_imm, s8, yes, no_op);
2385                       break;
2386 
2387                    case 3:
2388                       /* LDRSH rd, [rn - imm]! */
2389                       arm_access_memory(load, - offset, half_imm, s16, yes, no_op);
2390                       break;
2391                 }
2392              }
2393              else
2394              {
2395                 /* CMN rd, rn, reg_op */
2396                 arm_data_proc_test_add(reg[rn], reg_sh, reg);
2397              }
2398              break;
2399 
2400           case 0x18:
2401              if((opcode & 0x90) == 0x90)
2402              {
2403                 /* STRH rd, [rn + rm] */
2404                 arm_access_memory(store, + reg[rm], half_reg, u16, no, no_op);
2405              }
2406              else
2407              {
2408                 /* ORR rd, rn, reg_op */
2409                 arm_data_proc(reg[rn] | reg_sh, reg);
2410              }
2411              break;
2412 
2413           case 0x19:
2414              if((opcode & 0x90) == 0x90)
2415              {
2416                 switch((opcode >> 5) & 0x03)
2417                 {
2418                    case 1:
2419                       /* LDRH rd, [rn + rm] */
2420                       arm_access_memory(load, + reg[rm], half_reg, u16, no, no_op);
2421                       break;
2422 
2423                    case 2:
2424                       /* LDRSB rd, [rn + rm] */
2425                       arm_access_memory(load, + reg[rm], half_reg, s8, no, no_op);
2426                       break;
2427 
2428                    case 3:
2429                       /* LDRSH rd, [rn + rm] */
2430                       arm_access_memory(load, + reg[rm], half_reg, s16, no, no_op);
2431                       break;
2432                 }
2433              }
2434              else
2435              {
2436                 /* ORRS rd, rn, reg_op */
2437                 arm_data_proc_logic_flags(reg[rn] | reg_sh, reg);
2438              }
2439              break;
2440 
2441           case 0x1A:
2442              if((opcode & 0x90) == 0x90)
2443              {
2444                 /* STRH rd, [rn + rm]! */
2445                 arm_access_memory(store, + reg[rm], half_reg, u16, yes, no_op);
2446              }
2447              else
2448              {
2449                 /* MOV rd, reg_op */
2450                 arm_data_proc(reg_sh, reg);
2451              }
2452              break;
2453 
2454           case 0x1B:
2455              if((opcode & 0x90) == 0x90)
2456              {
2457                 switch((opcode >> 5) & 0x03)
2458                 {
2459                    case 1:
2460                       /* LDRH rd, [rn + rm]! */
2461                       arm_access_memory(load, + reg[rm], half_reg, u16, yes, no_op);
2462                       break;
2463 
2464                    case 2:
2465                       /* LDRSB rd, [rn + rm]! */
2466                       arm_access_memory(load, + reg[rm], half_reg, s8, yes, no_op);
2467                       break;
2468 
2469                    case 3:
2470                       /* LDRSH rd, [rn + rm]! */
2471                       arm_access_memory(load, + reg[rm], half_reg, s16, yes, no_op);
2472                       break;
2473                 }
2474              }
2475              else
2476              {
2477                 /* MOVS rd, reg_op */
2478                 arm_data_proc_logic_flags(reg_sh, reg);
2479              }
2480              break;
2481 
2482           case 0x1C:
2483              if((opcode & 0x90) == 0x90)
2484              {
2485                 /* STRH rd, [rn + imm] */
2486                 arm_access_memory(store, + offset, half_imm, u16, no, no_op);
2487              }
2488              else
2489              {
2490                 /* BIC rd, rn, reg_op */
2491                 arm_data_proc(reg[rn] & (~reg_sh), reg);
2492              }
2493              break;
2494 
2495           case 0x1D:
2496              if((opcode & 0x90) == 0x90)
2497              {
2498                 switch((opcode >> 5) & 0x03)
2499                 {
2500                    case 1:
2501                       /* LDRH rd, [rn + imm] */
2502                       arm_access_memory(load, + offset, half_imm, u16, no, no_op);
2503                       break;
2504 
2505                    case 2:
2506                       /* LDRSB rd, [rn + imm] */
2507                       arm_access_memory(load, + offset, half_imm, s8, no, no_op);
2508                       break;
2509 
2510                    case 3:
2511                       /* LDRSH rd, [rn + imm] */
2512                       arm_access_memory(load, + offset, half_imm, s16, no, no_op);
2513                       break;
2514                 }
2515              }
2516              else
2517              {
2518                 /* BICS rd, rn, reg_op */
2519                 arm_data_proc_logic_flags(reg[rn] & (~reg_sh), reg);
2520              }
2521              break;
2522 
2523           case 0x1E:
2524              if((opcode & 0x90) == 0x90)
2525              {
2526                 /* STRH rd, [rn + imm]! */
2527                 arm_access_memory(store, + offset, half_imm, u16, yes, no_op);
2528              }
2529              else
2530              {
2531                 /* MVN rd, reg_op */
2532                 arm_data_proc(~reg_sh, reg);
2533              }
2534              break;
2535 
2536           case 0x1F:
2537              if((opcode & 0x90) == 0x90)
2538              {
2539                 switch((opcode >> 5) & 0x03)
2540                 {
2541                    case 1:
2542                       /* LDRH rd, [rn + imm]! */
2543                       arm_access_memory(load, + offset, half_imm, u16, yes, no_op);
2544                       break;
2545 
2546                    case 2:
2547                       /* LDRSB rd, [rn + imm]! */
2548                       arm_access_memory(load, + offset, half_imm, s8, yes, no_op);
2549                       break;
2550 
2551                    case 3:
2552                       /* LDRSH rd, [rn + imm]! */
2553                       arm_access_memory(load, + offset, half_imm, s16, yes, no_op);
2554                       break;
2555                 }
2556              }
2557              else
2558              {
2559                 /* MVNS rd, rn, reg_op */
2560                 arm_data_proc_logic_flags(~reg_sh, reg);
2561              }
2562              break;
2563 
2564           case 0x20:
2565              /* AND rd, rn, imm */
2566              arm_data_proc(reg[rn] & imm, imm);
2567              break;
2568 
2569           case 0x21:
2570              /* ANDS rd, rn, imm */
2571              arm_data_proc_logic_flags(reg[rn] & imm, imm);
2572              break;
2573 
2574           case 0x22:
2575              /* EOR rd, rn, imm */
2576              arm_data_proc(reg[rn] ^ imm, imm);
2577              break;
2578 
2579           case 0x23:
2580              /* EORS rd, rn, imm */
2581              arm_data_proc_logic_flags(reg[rn] ^ imm, imm);
2582              break;
2583 
2584           case 0x24:
2585              /* SUB rd, rn, imm */
2586              arm_data_proc(reg[rn] - imm, imm);
2587              break;
2588 
2589           case 0x25:
2590              /* SUBS rd, rn, imm */
2591              arm_data_proc_sub_flags(reg[rn], imm, imm);
2592              break;
2593 
2594           case 0x26:
2595              /* RSB rd, rn, imm */
2596              arm_data_proc(imm - reg[rn], imm);
2597              break;
2598 
2599           case 0x27:
2600              /* RSBS rd, rn, imm */
2601              arm_data_proc_sub_flags(imm, reg[rn], imm);
2602              break;
2603 
2604           case 0x28:
2605              /* ADD rd, rn, imm */
2606              arm_data_proc(reg[rn] + imm, imm);
2607              break;
2608 
2609           case 0x29:
2610              /* ADDS rd, rn, imm */
2611              arm_data_proc_add_flags(reg[rn], imm, imm);
2612              break;
2613 
2614           case 0x2A:
2615              /* ADC rd, rn, imm */
2616              arm_data_proc(reg[rn] + imm + c_flag, imm);
2617              break;
2618 
2619           case 0x2B:
2620              /* ADCS rd, rn, imm */
2621              arm_data_proc_add_flags(reg[rn] + imm, c_flag, imm);
2622              break;
2623 
2624           case 0x2C:
2625              /* SBC rd, rn, imm */
2626              arm_data_proc(reg[rn] - imm + c_flag - 1, imm);
2627              break;
2628 
2629           case 0x2D:
2630              /* SBCS rd, rn, imm */
2631              arm_data_proc_sub_flags(reg[rn], (imm + (c_flag ^ 1)), imm);
2632              break;
2633 
2634           case 0x2E:
2635              /* RSC rd, rn, imm */
2636              arm_data_proc(imm - reg[rn] + c_flag - 1, imm);
2637              break;
2638 
2639           case 0x2F:
2640              /* RSCS rd, rn, imm */
2641              arm_data_proc_sub_flags((imm + c_flag - 1), reg[rn], imm);
2642              break;
2643 
2644           case 0x30:
2645           case 0x31:
2646              /* TST rn, imm */
2647              arm_data_proc_test_logic(reg[rn] & imm, imm);
2648              break;
2649 
2650           case 0x32:
2651              /* MSR cpsr, imm */
2652              arm_psr(imm, store, cpsr);
2653              break;
2654 
2655           case 0x33:
2656              /* TEQ rn, imm */
2657              arm_data_proc_test_logic(reg[rn] ^ imm, imm);
2658              break;
2659 
2660           case 0x34:
2661           case 0x35:
2662              /* CMP rn, imm */
2663              arm_data_proc_test_sub(reg[rn], imm, imm);
2664              break;
2665 
2666           case 0x36:
2667              /* MSR spsr, imm */
2668              arm_psr(imm, store, spsr);
2669              break;
2670 
2671           case 0x37:
2672              /* CMN rn, imm */
2673              arm_data_proc_test_add(reg[rn], imm, imm);
2674              break;
2675 
2676           case 0x38:
2677              /* ORR rd, rn, imm */
2678              arm_data_proc(reg[rn] | imm, imm);
2679              break;
2680 
2681           case 0x39:
2682              /* ORRS rd, rn, imm */
2683              arm_data_proc_logic_flags(reg[rn] | imm, imm);
2684              break;
2685 
2686           case 0x3A:
2687              /* MOV rd, imm */
2688              arm_data_proc(imm, imm);
2689              break;
2690 
2691           case 0x3B:
2692              /* MOVS rd, imm */
2693              arm_data_proc_logic_flags(imm, imm);
2694              break;
2695 
2696           case 0x3C:
2697              /* BIC rd, rn, imm */
2698              arm_data_proc(reg[rn] & (~imm), imm);
2699              break;
2700 
2701           case 0x3D:
2702              /* BICS rd, rn, imm */
2703              arm_data_proc_logic_flags(reg[rn] & (~imm), imm);
2704              break;
2705 
2706           case 0x3E:
2707              /* MVN rd, imm */
2708              arm_data_proc(~imm, imm);
2709              break;
2710 
2711           case 0x3F:
2712              /* MVNS rd, imm */
2713              arm_data_proc_logic_flags(~imm, imm);
2714              break;
2715 
2716           case 0x40:
2717              /* STR rd, [rn], -imm */
2718              arm_access_memory(store, no_op, imm, u32, yes, - offset);
2719              break;
2720 
2721           case 0x41:
2722              /* LDR rd, [rn], -imm */
2723              arm_access_memory(load, no_op, imm, u32, yes, - offset);
2724              break;
2725 
2726           case 0x42:
2727              /* STRT rd, [rn], -imm */
2728              arm_access_memory(store, no_op, imm, u32, yes, - offset);
2729              break;
2730 
2731           case 0x43:
2732              /* LDRT rd, [rn], -imm */
2733              arm_access_memory(load, no_op, imm, u32, yes, - offset);
2734              break;
2735 
2736           case 0x44:
2737              /* STRB rd, [rn], -imm */
2738              arm_access_memory(store, no_op, imm, u8, yes, - offset);
2739              break;
2740 
2741           case 0x45:
2742              /* LDRB rd, [rn], -imm */
2743              arm_access_memory(load, no_op, imm, u8, yes, - offset);
2744              break;
2745 
2746           case 0x46:
2747              /* STRBT rd, [rn], -imm */
2748              arm_access_memory(store, no_op, imm, u8, yes, - offset);
2749              break;
2750 
2751           case 0x47:
2752              /* LDRBT rd, [rn], -imm */
2753              arm_access_memory(load, no_op, imm, u8, yes, - offset);
2754              break;
2755 
2756           case 0x48:
2757              /* STR rd, [rn], +imm */
2758              arm_access_memory(store, no_op, imm, u32, yes, + offset);
2759              break;
2760 
2761           case 0x49:
2762              /* LDR rd, [rn], +imm */
2763              arm_access_memory(load, no_op, imm, u32, yes, + offset);
2764              break;
2765 
2766           case 0x4A:
2767              /* STRT rd, [rn], +imm */
2768              arm_access_memory(store, no_op, imm, u32, yes, + offset);
2769              break;
2770 
2771           case 0x4B:
2772              /* LDRT rd, [rn], +imm */
2773              arm_access_memory(load, no_op, imm, u32, yes, + offset);
2774              break;
2775 
2776           case 0x4C:
2777              /* STRB rd, [rn], +imm */
2778              arm_access_memory(store, no_op, imm, u8, yes, + offset);
2779              break;
2780 
2781           case 0x4D:
2782              /* LDRB rd, [rn], +imm */
2783              arm_access_memory(load, no_op, imm, u8, yes, + offset);
2784              break;
2785 
2786           case 0x4E:
2787              /* STRBT rd, [rn], +imm */
2788              arm_access_memory(store, no_op, imm, u8, yes, + offset);
2789              break;
2790 
2791           case 0x4F:
2792              /* LDRBT rd, [rn], +imm */
2793              arm_access_memory(load, no_op, imm, u8, yes, + offset);
2794              break;
2795 
2796           case 0x50:
2797              /* STR rd, [rn - imm] */
2798              arm_access_memory(store, - offset, imm, u32, no, no_op);
2799              break;
2800 
2801           case 0x51:
2802              /* LDR rd, [rn - imm] */
2803              arm_access_memory(load, - offset, imm, u32, no, no_op);
2804              break;
2805 
2806           case 0x52:
2807              /* STR rd, [rn - imm]! */
2808              arm_access_memory(store, - offset, imm, u32, yes, no_op);
2809              break;
2810 
2811           case 0x53:
2812              /* LDR rd, [rn - imm]! */
2813              arm_access_memory(load, - offset, imm, u32, yes, no_op);
2814              break;
2815 
2816           case 0x54:
2817              /* STRB rd, [rn - imm] */
2818              arm_access_memory(store, - offset, imm, u8, no, no_op);
2819              break;
2820 
2821           case 0x55:
2822              /* LDRB rd, [rn - imm] */
2823              arm_access_memory(load, - offset, imm, u8, no, no_op);
2824              break;
2825 
2826           case 0x56:
2827              /* STRB rd, [rn - imm]! */
2828              arm_access_memory(store, - offset, imm, u8, yes, no_op);
2829              break;
2830 
2831           case 0x57:
2832              /* LDRB rd, [rn - imm]! */
2833              arm_access_memory(load, - offset, imm, u8, yes, no_op);
2834              break;
2835 
2836           case 0x58:
2837              /* STR rd, [rn + imm] */
2838              arm_access_memory(store, + offset, imm, u32, no, no_op);
2839              break;
2840 
2841           case 0x59:
2842              /* LDR rd, [rn + imm] */
2843              arm_access_memory(load, + offset, imm, u32, no, no_op);
2844              break;
2845 
2846           case 0x5A:
2847              /* STR rd, [rn + imm]! */
2848              arm_access_memory(store, + offset, imm, u32, yes, no_op);
2849              break;
2850 
2851           case 0x5B:
2852              /* LDR rd, [rn + imm]! */
2853              arm_access_memory(load, + offset, imm, u32, yes, no_op);
2854              break;
2855 
2856           case 0x5C:
2857              /* STRB rd, [rn + imm] */
2858              arm_access_memory(store, + offset, imm, u8, no, no_op);
2859              break;
2860 
2861           case 0x5D:
2862              /* LDRB rd, [rn + imm] */
2863              arm_access_memory(load, + offset, imm, u8, no, no_op);
2864              break;
2865 
2866           case 0x5E:
2867              /* STRB rd, [rn + imm]! */
2868              arm_access_memory(store, + offset, imm, u8, yes, no_op);
2869              break;
2870 
2871           case 0x5F:
2872              /* LDRBT rd, [rn + imm]! */
2873              arm_access_memory(load, + offset, imm, u8, yes, no_op);
2874              break;
2875 
2876           case 0x60:
2877              /* STR rd, [rn], -reg_op */
2878              arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);
2879              break;
2880 
2881           case 0x61:
2882              /* LDR rd, [rn], -reg_op */
2883              arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);
2884              break;
2885 
2886           case 0x62:
2887              /* STRT rd, [rn], -reg_op */
2888              arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);
2889              break;
2890 
2891           case 0x63:
2892              /* LDRT rd, [rn], -reg_op */
2893              arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);
2894              break;
2895 
2896           case 0x64:
2897              /* STRB rd, [rn], -reg_op */
2898              arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);
2899              break;
2900 
2901           case 0x65:
2902              /* LDRB rd, [rn], -reg_op */
2903              arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);
2904              break;
2905 
2906           case 0x66:
2907              /* STRBT rd, [rn], -reg_op */
2908              arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);
2909              break;
2910 
2911           case 0x67:
2912              /* LDRBT rd, [rn], -reg_op */
2913              arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);
2914              break;
2915 
2916           case 0x68:
2917              /* STR rd, [rn], +reg_op */
2918              arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);
2919              break;
2920 
2921           case 0x69:
2922              /* LDR rd, [rn], +reg_op */
2923              arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);
2924              break;
2925 
2926           case 0x6A:
2927              /* STRT rd, [rn], +reg_op */
2928              arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);
2929              break;
2930 
2931           case 0x6B:
2932              /* LDRT rd, [rn], +reg_op */
2933              arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);
2934              break;
2935 
2936           case 0x6C:
2937              /* STRB rd, [rn], +reg_op */
2938              arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);
2939              break;
2940 
2941           case 0x6D:
2942              /* LDRB rd, [rn], +reg_op */
2943              arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);
2944              break;
2945 
2946           case 0x6E:
2947              /* STRBT rd, [rn], +reg_op */
2948              arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);
2949              break;
2950 
2951           case 0x6F:
2952              /* LDRBT rd, [rn], +reg_op */
2953              arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);
2954              break;
2955 
2956           case 0x70:
2957              /* STR rd, [rn - reg_op] */
2958              arm_access_memory(store, - reg_offset, reg, u32, no, no_op);
2959              break;
2960 
2961           case 0x71:
2962              /* LDR rd, [rn - reg_op] */
2963              arm_access_memory(load, - reg_offset, reg, u32, no, no_op);
2964              break;
2965 
2966           case 0x72:
2967              /* STR rd, [rn - reg_op]! */
2968              arm_access_memory(store, - reg_offset, reg, u32, yes, no_op);
2969              break;
2970 
2971           case 0x73:
2972              /* LDR rd, [rn - reg_op]! */
2973              arm_access_memory(load, - reg_offset, reg, u32, yes, no_op);
2974              break;
2975 
2976           case 0x74:
2977              /* STRB rd, [rn - reg_op] */
2978              arm_access_memory(store, - reg_offset, reg, u8, no, no_op);
2979              break;
2980 
2981           case 0x75:
2982              /* LDRB rd, [rn - reg_op] */
2983              arm_access_memory(load, - reg_offset, reg, u8, no, no_op);
2984              break;
2985 
2986           case 0x76:
2987              /* STRB rd, [rn - reg_op]! */
2988              arm_access_memory(store, - reg_offset, reg, u8, yes, no_op);
2989              break;
2990 
2991           case 0x77:
2992              /* LDRB rd, [rn - reg_op]! */
2993              arm_access_memory(load, - reg_offset, reg, u8, yes, no_op);
2994              break;
2995 
2996           case 0x78:
2997              /* STR rd, [rn + reg_op] */
2998              arm_access_memory(store, + reg_offset, reg, u32, no, no_op);
2999              break;
3000 
3001           case 0x79:
3002              /* LDR rd, [rn + reg_op] */
3003              arm_access_memory(load, + reg_offset, reg, u32, no, no_op);
3004              break;
3005 
3006           case 0x7A:
3007              /* STR rd, [rn + reg_op]! */
3008              arm_access_memory(store, + reg_offset, reg, u32, yes, no_op);
3009              break;
3010 
3011           case 0x7B:
3012              /* LDR rd, [rn + reg_op]! */
3013              arm_access_memory(load, + reg_offset, reg, u32, yes, no_op);
3014              break;
3015 
3016           case 0x7C:
3017              /* STRB rd, [rn + reg_op] */
3018              arm_access_memory(store, + reg_offset, reg, u8, no, no_op);
3019              break;
3020 
3021           case 0x7D:
3022              /* LDRB rd, [rn + reg_op] */
3023              arm_access_memory(load, + reg_offset, reg, u8, no, no_op);
3024              break;
3025 
3026           case 0x7E:
3027              /* STRB rd, [rn + reg_op]! */
3028              arm_access_memory(store, + reg_offset, reg, u8, yes, no_op);
3029              break;
3030 
3031           case 0x7F:
3032              /* LDRBT rd, [rn + reg_op]! */
3033              arm_access_memory(load, + reg_offset, reg, u8, yes, no_op);
3034              break;
3035 
3036           case 0x80:
3037              /* STMDA rn, rlist */
3038              arm_block_memory(store, down_a, no, no);
3039              break;
3040 
3041           case 0x81:
3042              /* LDMDA rn, rlist */
3043              arm_block_memory(load, down_a, no, no);
3044              break;
3045 
3046           case 0x82:
3047              /* STMDA rn!, rlist */
3048              arm_block_memory(store, down_a, down, no);
3049              break;
3050 
3051           case 0x83:
3052              /* LDMDA rn!, rlist */
3053              arm_block_memory(load, down_a, down, no);
3054              break;
3055 
3056           case 0x84:
3057              /* STMDA rn, rlist^ */
3058              arm_block_memory(store, down_a, no, yes);
3059              break;
3060 
3061           case 0x85:
3062              /* LDMDA rn, rlist^ */
3063              arm_block_memory(load, down_a, no, yes);
3064              break;
3065 
3066           case 0x86:
3067              /* STMDA rn!, rlist^ */
3068              arm_block_memory(store, down_a, down, yes);
3069              break;
3070 
3071           case 0x87:
3072              /* LDMDA rn!, rlist^ */
3073              arm_block_memory(load, down_a, down, yes);
3074              break;
3075 
3076           case 0x88:
3077              /* STMIA rn, rlist */
3078              arm_block_memory(store, no, no, no);
3079              break;
3080 
3081           case 0x89:
3082              /* LDMIA rn, rlist */
3083              arm_block_memory(load, no, no, no);
3084              break;
3085 
3086           case 0x8A:
3087              /* STMIA rn!, rlist */
3088              arm_block_memory(store, no, up, no);
3089              break;
3090 
3091           case 0x8B:
3092              /* LDMIA rn!, rlist */
3093              arm_block_memory(load, no, up, no);
3094              break;
3095 
3096           case 0x8C:
3097              /* STMIA rn, rlist^ */
3098              arm_block_memory(store, no, no, yes);
3099              break;
3100 
3101           case 0x8D:
3102              /* LDMIA rn, rlist^ */
3103              arm_block_memory(load, no, no, yes);
3104              break;
3105 
3106           case 0x8E:
3107              /* STMIA rn!, rlist^ */
3108              arm_block_memory(store, no, up, yes);
3109              break;
3110 
3111           case 0x8F:
3112              /* LDMIA rn!, rlist^ */
3113              arm_block_memory(load, no, up, yes);
3114              break;
3115 
3116           case 0x90:
3117              /* STMDB rn, rlist */
3118              arm_block_memory(store, down_b, no, no);
3119              break;
3120 
3121           case 0x91:
3122              /* LDMDB rn, rlist */
3123              arm_block_memory(load, down_b, no, no);
3124              break;
3125 
3126           case 0x92:
3127              /* STMDB rn!, rlist */
3128              arm_block_memory(store, down_b, down, no);
3129              break;
3130 
3131           case 0x93:
3132              /* LDMDB rn!, rlist */
3133              arm_block_memory(load, down_b, down, no);
3134              break;
3135 
3136           case 0x94:
3137              /* STMDB rn, rlist^ */
3138              arm_block_memory(store, down_b, no, yes);
3139              break;
3140 
3141           case 0x95:
3142              /* LDMDB rn, rlist^ */
3143              arm_block_memory(load, down_b, no, yes);
3144              break;
3145 
3146           case 0x96:
3147              /* STMDB rn!, rlist^ */
3148              arm_block_memory(store, down_b, down, yes);
3149              break;
3150 
3151           case 0x97:
3152              /* LDMDB rn!, rlist^ */
3153              arm_block_memory(load, down_b, down, yes);
3154              break;
3155 
3156           case 0x98:
3157              /* STMIB rn, rlist */
3158              arm_block_memory(store, up, no, no);
3159              break;
3160 
3161           case 0x99:
3162              /* LDMIB rn, rlist */
3163              arm_block_memory(load, up, no, no);
3164              break;
3165 
3166           case 0x9A:
3167              /* STMIB rn!, rlist */
3168              arm_block_memory(store, up, up, no);
3169              break;
3170 
3171           case 0x9B:
3172              /* LDMIB rn!, rlist */
3173              arm_block_memory(load, up, up, no);
3174              break;
3175 
3176           case 0x9C:
3177              /* STMIB rn, rlist^ */
3178              arm_block_memory(store, up, no, yes);
3179              break;
3180 
3181           case 0x9D:
3182              /* LDMIB rn, rlist^ */
3183              arm_block_memory(load, up, no, yes);
3184              break;
3185 
3186           case 0x9E:
3187              /* STMIB rn!, rlist^ */
3188              arm_block_memory(store, up, up, yes);
3189              break;
3190 
3191           case 0x9F:
3192              /* LDMIB rn!, rlist^ */
3193              arm_block_memory(load, up, up, yes);
3194              break;
3195 
3196           case 0xA0:
3197           case 0xA1:
3198           case 0xA2:
3199           case 0xA3:
3200           case 0xA4:
3201           case 0xA5:
3202           case 0xA6:
3203           case 0xA7:
3204           case 0xA8:
3205           case 0xA9:
3206           case 0xAA:
3207           case 0xAB:
3208           case 0xAC:
3209           case 0xAD:
3210           case 0xAE:
3211           case 0xAF:
3212              {
3213                 /* B offset */
3214                 arm_decode_branch();
3215                 arm_pc_offset_update(offset + 8);
3216                 break;
3217              }
3218 
3219           case 0xB0:
3220           case 0xB1:
3221           case 0xB2:
3222           case 0xB3:
3223           case 0xB4:
3224           case 0xB5:
3225           case 0xB6:
3226           case 0xB7:
3227           case 0xB8:
3228           case 0xB9:
3229           case 0xBA:
3230           case 0xBB:
3231           case 0xBC:
3232           case 0xBD:
3233           case 0xBE:
3234           case 0xBF:
3235              {
3236                 /* BL offset */
3237                 arm_decode_branch();
3238                 reg[REG_LR] = pc + 4;
3239                 arm_pc_offset_update(offset + 8);
3240                 break;
3241              }
3242 
3243 #ifdef HAVE_UNUSED
3244           case 0xC0 ... 0xEF:
3245              /* coprocessor instructions, reserved on GBA */
3246              break;
3247 #endif
3248 
3249           case 0xF0:
3250           case 0xF1:
3251           case 0xF2:
3252           case 0xF3:
3253           case 0xF4:
3254           case 0xF5:
3255           case 0xF6:
3256           case 0xF7:
3257           case 0xF8:
3258           case 0xF9:
3259           case 0xFA:
3260           case 0xFB:
3261           case 0xFC:
3262           case 0xFD:
3263           case 0xFE:
3264           case 0xFF:
3265              {
3266                 /* SWI comment */
3267                 u32 swi_comment = opcode & 0x00FFFFFF;
3268 
3269                 switch(swi_comment >> 16)
3270                 {
3271                    /* Jump to BIOS SWI handler */
3272                    default:
3273                       reg_mode[MODE_SUPERVISOR][6] = pc + 4;
3274                       collapse_flags();
3275                       spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
3276                       reg[REG_PC] = 0x00000008;
3277                       arm_update_pc();
3278                       reg[REG_CPSR] = (reg[REG_CPSR] & ~0x1F) | 0x13;
3279                       set_cpu_mode(MODE_SUPERVISOR);
3280                       break;
3281                 }
3282                 break;
3283              }
3284        }
3285 
3286 skip_instruction:
3287 
3288        /* End of Execute ARM instruction */
3289        cycles_remaining -= cycles_per_instruction;
3290 
3291        if (pc == idle_loop_target_pc && cycles_remaining > 0) cycles_remaining = 0;
3292     } while(cycles_remaining > 0);
3293 
3294     collapse_flags();
3295     cycles = update_gba();
3296     continue;
3297 
3298     do
3299     {
3300 thumb_loop:
3301 
3302        collapse_flags();
3303 
3304        old_pc = pc;
3305 
3306        /* Execute THUMB instruction */
3307 
3308        using_instruction(thumb);
3309        check_pc_region();
3310        pc &= ~0x01;
3311        opcode = address16(pc_address_block, (pc & 0x7FFF));
3312 
3313        switch((opcode >> 8) & 0xFF)
3314        {
3315           case 0x00:
3316           case 0x01:
3317           case 0x02:
3318           case 0x03:
3319           case 0x04:
3320           case 0x05:
3321           case 0x06:
3322           case 0x07:
3323              /* LSL rd, rs, offset */
3324              thumb_shift(shift, lsl, imm);
3325              break;
3326 
3327           case 0x08:
3328           case 0x09:
3329           case 0x0A:
3330           case 0x0B:
3331           case 0x0C:
3332           case 0x0D:
3333           case 0x0E:
3334           case 0x0F:
3335              /* LSR rd, rs, offset */
3336              thumb_shift(shift, lsr, imm);
3337              break;
3338 
3339           case 0x10:
3340           case 0x11:
3341           case 0x12:
3342           case 0x13:
3343           case 0x14:
3344           case 0x15:
3345           case 0x16:
3346           case 0x17:
3347              /* ASR rd, rs, offset */
3348              thumb_shift(shift, asr, imm);
3349              break;
3350 
3351           case 0x18:
3352           case 0x19:
3353              /* ADD rd, rs, rn */
3354              thumb_add(add_sub, rd, reg[rs], reg[rn]);
3355              break;
3356 
3357           case 0x1A:
3358           case 0x1B:
3359              /* SUB rd, rs, rn */
3360              thumb_sub(add_sub, rd, reg[rs], reg[rn]);
3361              break;
3362 
3363           case 0x1C:
3364           case 0x1D:
3365              /* ADD rd, rs, imm */
3366              thumb_add(add_sub_imm, rd, reg[rs], imm);
3367              break;
3368 
3369           case 0x1E:
3370           case 0x1F:
3371              /* SUB rd, rs, imm */
3372              thumb_sub(add_sub_imm, rd, reg[rs], imm);
3373              break;
3374 
3375           case 0x20:
3376              /* MOV r0, imm */
3377              thumb_logic(imm, 0, imm);
3378              break;
3379 
3380           case 0x21:
3381              /* MOV r1, imm */
3382              thumb_logic(imm, 1, imm);
3383              break;
3384 
3385           case 0x22:
3386              /* MOV r2, imm */
3387              thumb_logic(imm, 2, imm);
3388              break;
3389 
3390           case 0x23:
3391              /* MOV r3, imm */
3392              thumb_logic(imm, 3, imm);
3393              break;
3394 
3395           case 0x24:
3396              /* MOV r4, imm */
3397              thumb_logic(imm, 4, imm);
3398              break;
3399 
3400           case 0x25:
3401              /* MOV r5, imm */
3402              thumb_logic(imm, 5, imm);
3403              break;
3404 
3405           case 0x26:
3406              /* MOV r6, imm */
3407              thumb_logic(imm, 6, imm);
3408              break;
3409 
3410           case 0x27:
3411              /* MOV r7, imm */
3412              thumb_logic(imm, 7, imm);
3413              break;
3414 
3415           case 0x28:
3416              /* CMP r0, imm */
3417              thumb_test_sub(imm, reg[0], imm);
3418              break;
3419 
3420           case 0x29:
3421              /* CMP r1, imm */
3422              thumb_test_sub(imm, reg[1], imm);
3423              break;
3424 
3425           case 0x2A:
3426              /* CMP r2, imm */
3427              thumb_test_sub(imm, reg[2], imm);
3428              break;
3429 
3430           case 0x2B:
3431              /* CMP r3, imm */
3432              thumb_test_sub(imm, reg[3], imm);
3433              break;
3434 
3435           case 0x2C:
3436              /* CMP r4, imm */
3437              thumb_test_sub(imm, reg[4], imm);
3438              break;
3439 
3440           case 0x2D:
3441              /* CMP r5, imm */
3442              thumb_test_sub(imm, reg[5], imm);
3443              break;
3444 
3445           case 0x2E:
3446              /* CMP r6, imm */
3447              thumb_test_sub(imm, reg[6], imm);
3448              break;
3449 
3450           case 0x2F:
3451              /* CMP r7, imm */
3452              thumb_test_sub(imm, reg[7], imm);
3453              break;
3454 
3455           case 0x30:
3456              /* ADD r0, imm */
3457              thumb_add(imm, 0, reg[0], imm);
3458              break;
3459 
3460           case 0x31:
3461              /* ADD r1, imm */
3462              thumb_add(imm, 1, reg[1], imm);
3463              break;
3464 
3465           case 0x32:
3466              /* ADD r2, imm */
3467              thumb_add(imm, 2, reg[2], imm);
3468              break;
3469 
3470           case 0x33:
3471              /* ADD r3, imm */
3472              thumb_add(imm, 3, reg[3], imm);
3473              break;
3474 
3475           case 0x34:
3476              /* ADD r4, imm */
3477              thumb_add(imm, 4, reg[4], imm);
3478              break;
3479 
3480           case 0x35:
3481              /* ADD r5, imm */
3482              thumb_add(imm, 5, reg[5], imm);
3483              break;
3484 
3485           case 0x36:
3486              /* ADD r6, imm */
3487              thumb_add(imm, 6, reg[6], imm);
3488              break;
3489 
3490           case 0x37:
3491              /* ADD r7, imm */
3492              thumb_add(imm, 7, reg[7], imm);
3493              break;
3494 
3495           case 0x38:
3496              /* SUB r0, imm */
3497              thumb_sub(imm, 0, reg[0], imm);
3498              break;
3499 
3500           case 0x39:
3501              /* SUB r1, imm */
3502              thumb_sub(imm, 1, reg[1], imm);
3503              break;
3504 
3505           case 0x3A:
3506              /* SUB r2, imm */
3507              thumb_sub(imm, 2, reg[2], imm);
3508              break;
3509 
3510           case 0x3B:
3511              /* SUB r3, imm */
3512              thumb_sub(imm, 3, reg[3], imm);
3513              break;
3514 
3515           case 0x3C:
3516              /* SUB r4, imm */
3517              thumb_sub(imm, 4, reg[4], imm);
3518              break;
3519 
3520           case 0x3D:
3521              /* SUB r5, imm */
3522              thumb_sub(imm, 5, reg[5], imm);
3523              break;
3524 
3525           case 0x3E:
3526              /* SUB r6, imm */
3527              thumb_sub(imm, 6, reg[6], imm);
3528              break;
3529 
3530           case 0x3F:
3531              /* SUB r7, imm */
3532              thumb_sub(imm, 7, reg[7], imm);
3533              break;
3534 
3535           case 0x40:
3536              switch((opcode >> 6) & 0x03)
3537              {
3538                 case 0x00:
3539                    /* AND rd, rs */
3540                    thumb_logic(alu_op, rd, reg[rd] & reg[rs]);
3541                    break;
3542 
3543                 case 0x01:
3544                    /* EOR rd, rs */
3545                    thumb_logic(alu_op, rd, reg[rd] ^ reg[rs]);
3546                    break;
3547 
3548                 case 0x02:
3549                    /* LSL rd, rs */
3550                    thumb_shift(alu_op, lsl, reg);
3551                    break;
3552 
3553                 case 0x03:
3554                    /* LSR rd, rs */
3555                    thumb_shift(alu_op, lsr, reg);
3556                    break;
3557              }
3558              break;
3559 
3560           case 0x41:
3561              switch((opcode >> 6) & 0x03)
3562              {
3563                 case 0x00:
3564                    /* ASR rd, rs */
3565                    thumb_shift(alu_op, asr, reg);
3566                    break;
3567 
3568                 case 0x01:
3569                    /* ADC rd, rs */
3570                    thumb_add(alu_op, rd, reg[rd] + reg[rs], c_flag);
3571                    break;
3572 
3573                 case 0x02:
3574                    /* SBC rd, rs */
3575                    thumb_sub(alu_op, rd, reg[rd] - reg[rs], (c_flag ^ 1));
3576                    break;
3577 
3578                 case 0x03:
3579                    /* ROR rd, rs */
3580                    thumb_shift(alu_op, ror, reg);
3581                    break;
3582              }
3583              break;
3584 
3585           case 0x42:
3586              switch((opcode >> 6) & 0x03)
3587              {
3588                 case 0x00:
3589                    /* TST rd, rs */
3590                    thumb_test_logic(alu_op, reg[rd] & reg[rs]);
3591                    break;
3592 
3593                 case 0x01:
3594                    /* NEG rd, rs */
3595                    thumb_sub(alu_op, rd, 0, reg[rs]);
3596                    break;
3597 
3598                 case 0x02:
3599                    /* CMP rd, rs */
3600                    thumb_test_sub(alu_op, reg[rd], reg[rs]);
3601                    break;
3602 
3603                 case 0x03:
3604                    /* CMN rd, rs */
3605                    thumb_test_add(alu_op, reg[rd], reg[rs]);
3606                    break;
3607              }
3608              break;
3609 
3610           case 0x43:
3611              switch((opcode >> 6) & 0x03)
3612              {
3613                 case 0x00:
3614                    /* ORR rd, rs */
3615                    thumb_logic(alu_op, rd, reg[rd] | reg[rs]);
3616                    break;
3617 
3618                 case 0x01:
3619                    /* MUL rd, rs */
3620                    thumb_logic(alu_op, rd, reg[rd] * reg[rs]);
3621                    break;
3622 
3623                 case 0x02:
3624                    /* BIC rd, rs */
3625                    thumb_logic(alu_op, rd, reg[rd] & (~reg[rs]));
3626                    break;
3627 
3628                 case 0x03:
3629                    /* MVN rd, rs */
3630                    thumb_logic(alu_op, rd, ~reg[rs]);
3631                    break;
3632              }
3633              break;
3634 
3635           case 0x44:
3636              /* ADD rd, rs */
3637              thumb_hireg_op(reg[rd] + reg[rs]);
3638              break;
3639 
3640           case 0x45:
3641              /* CMP rd, rs */
3642              {
3643                 thumb_pc_offset(4);
3644                 thumb_decode_hireg_op();
3645                 u32 _sa = reg[rd];
3646                 u32 _sb = reg[rs];
3647                 u32 dest = _sa - _sb;
3648                 thumb_pc_offset(-2);
3649                 calculate_flags_sub(dest, _sa, _sb);
3650              }
3651              break;
3652 
3653           case 0x46:
3654              /* MOV rd, rs */
3655              thumb_hireg_op(reg[rs]);
3656              break;
3657 
3658           case 0x47:
3659              /* BX rs */
3660              {
3661                 thumb_decode_hireg_op();
3662                 u32 src;
3663                 thumb_pc_offset(4);
3664                 src = reg[rs];
3665                 if(src & 0x01)
3666                 {
3667                    src -= 1;
3668                    thumb_pc_offset_update_direct(src);
3669                 }
3670                 else
3671                 {
3672                    /* Switch to ARM mode */
3673                    thumb_pc_offset_update_direct(src);
3674                    reg[REG_CPSR] &= ~0x20;
3675                    collapse_flags();
3676                    goto arm_loop;
3677                 }
3678              }
3679              break;
3680 
3681           case 0x48:
3682              /* LDR r0, [pc + imm] */
3683              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[0], u32);
3684              break;
3685 
3686           case 0x49:
3687              /* LDR r1, [pc + imm] */
3688              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[1], u32);
3689              break;
3690 
3691           case 0x4A:
3692              /* LDR r2, [pc + imm] */
3693              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[2], u32);
3694              break;
3695 
3696           case 0x4B:
3697              /* LDR r3, [pc + imm] */
3698              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[3], u32);
3699              break;
3700 
3701           case 0x4C:
3702              /* LDR r4, [pc + imm] */
3703              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[4], u32);
3704              break;
3705 
3706           case 0x4D:
3707              /* LDR r5, [pc + imm] */
3708              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[5], u32);
3709              break;
3710 
3711           case 0x4E:
3712              /* LDR r6, [pc + imm] */
3713              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[6], u32);
3714              break;
3715 
3716           case 0x4F:
3717              /* LDR r7, [pc + imm] */
3718              thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[7], u32);
3719              break;
3720 
3721           case 0x50:
3722           case 0x51:
3723              /* STR rd, [rb + ro] */
3724              thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u32);
3725              break;
3726 
3727           case 0x52:
3728           case 0x53:
3729              /* STRH rd, [rb + ro] */
3730              thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u16);
3731              break;
3732 
3733           case 0x54:
3734           case 0x55:
3735              /* STRB rd, [rb + ro] */
3736              thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u8);
3737              break;
3738 
3739           case 0x56:
3740           case 0x57:
3741              /* LDSB rd, [rb + ro] */
3742              thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s8);
3743              break;
3744 
3745           case 0x58:
3746           case 0x59:
3747              /* LDR rd, [rb + ro] */
3748              thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u32);
3749              break;
3750 
3751           case 0x5A:
3752           case 0x5B:
3753              /* LDRH rd, [rb + ro] */
3754              thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u16);
3755              break;
3756 
3757           case 0x5C:
3758           case 0x5D:
3759              /* LDRB rd, [rb + ro] */
3760              thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u8);
3761              break;
3762 
3763           case 0x5E:
3764           case 0x5F:
3765              /* LDSH rd, [rb + ro] */
3766              thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s16);
3767              break;
3768 
3769           case 0x60:
3770           case 0x61:
3771           case 0x62:
3772           case 0x63:
3773           case 0x64:
3774           case 0x65:
3775           case 0x66:
3776           case 0x67:
3777              /* STR rd, [rb + imm] */
3778              thumb_access_memory(store, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
3779              break;
3780 
3781           case 0x68:
3782           case 0x69:
3783           case 0x6A:
3784           case 0x6B:
3785           case 0x6C:
3786           case 0x6D:
3787           case 0x6E:
3788           case 0x6F:
3789              /* LDR rd, [rb + imm] */
3790              thumb_access_memory(load, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
3791              break;
3792 
3793           case 0x70:
3794           case 0x71:
3795           case 0x72:
3796           case 0x73:
3797           case 0x74:
3798           case 0x75:
3799           case 0x76:
3800           case 0x77:
3801              /* STRB rd, [rb + imm] */
3802              thumb_access_memory(store, mem_imm, reg[rb] + imm, reg[rd], u8);
3803              break;
3804 
3805           case 0x78:
3806           case 0x79:
3807           case 0x7A:
3808           case 0x7B:
3809           case 0x7C:
3810           case 0x7D:
3811           case 0x7E:
3812           case 0x7F:
3813              /* LDRB rd, [rb + imm] */
3814              thumb_access_memory(load, mem_imm, reg[rb] + imm, reg[rd], u8);
3815              break;
3816 
3817           case 0x80:
3818           case 0x81:
3819           case 0x82:
3820           case 0x83:
3821           case 0x84:
3822           case 0x85:
3823           case 0x86:
3824           case 0x87:
3825              /* STRH rd, [rb + imm] */
3826              thumb_access_memory(store, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
3827              break;
3828 
3829           case 0x88:
3830           case 0x89:
3831           case 0x8A:
3832           case 0x8B:
3833           case 0x8C:
3834           case 0x8D:
3835           case 0x8E:
3836           case 0x8F:
3837              /* LDRH rd, [rb + imm] */
3838              thumb_access_memory(load, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
3839              break;
3840 
3841           case 0x90:
3842              /* STR r0, [sp + imm] */
3843              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
3844              break;
3845 
3846           case 0x91:
3847              /* STR r1, [sp + imm] */
3848              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
3849              break;
3850 
3851           case 0x92:
3852              /* STR r2, [sp + imm] */
3853              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
3854              break;
3855 
3856           case 0x93:
3857              /* STR r3, [sp + imm] */
3858              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
3859              break;
3860 
3861           case 0x94:
3862              /* STR r4, [sp + imm] */
3863              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
3864              break;
3865 
3866           case 0x95:
3867              /* STR r5, [sp + imm] */
3868              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
3869              break;
3870 
3871           case 0x96:
3872              /* STR r6, [sp + imm] */
3873              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
3874              break;
3875 
3876           case 0x97:
3877              /* STR r7, [sp + imm] */
3878              thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
3879              break;
3880 
3881           case 0x98:
3882              /* LDR r0, [sp + imm] */
3883              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
3884              break;
3885 
3886           case 0x99:
3887              /* LDR r1, [sp + imm] */
3888              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
3889              break;
3890 
3891           case 0x9A:
3892              /* LDR r2, [sp + imm] */
3893              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
3894              break;
3895 
3896           case 0x9B:
3897              /* LDR r3, [sp + imm] */
3898              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
3899              break;
3900 
3901           case 0x9C:
3902              /* LDR r4, [sp + imm] */
3903              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
3904              break;
3905 
3906           case 0x9D:
3907              /* LDR r5, [sp + imm] */
3908              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
3909              break;
3910 
3911           case 0x9E:
3912              /* LDR r6, [sp + imm] */
3913              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
3914              break;
3915 
3916           case 0x9F:
3917              /* LDR r7, [sp + imm] */
3918              thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
3919              break;
3920 
3921           case 0xA0:
3922              /* ADD r0, pc, +imm */
3923              thumb_add_noflags(imm, 0, (pc & ~2) + 4, (imm * 4));
3924              break;
3925 
3926           case 0xA1:
3927              /* ADD r1, pc, +imm */
3928              thumb_add_noflags(imm, 1, (pc & ~2) + 4, (imm * 4));
3929              break;
3930 
3931           case 0xA2:
3932              /* ADD r2, pc, +imm */
3933              thumb_add_noflags(imm, 2, (pc & ~2) + 4, (imm * 4));
3934              break;
3935 
3936           case 0xA3:
3937              /* ADD r3, pc, +imm */
3938              thumb_add_noflags(imm, 3, (pc & ~2) + 4, (imm * 4));
3939              break;
3940 
3941           case 0xA4:
3942              /* ADD r4, pc, +imm */
3943              thumb_add_noflags(imm, 4, (pc & ~2) + 4, (imm * 4));
3944              break;
3945 
3946           case 0xA5:
3947              /* ADD r5, pc, +imm */
3948              thumb_add_noflags(imm, 5, (pc & ~2) + 4, (imm * 4));
3949              break;
3950 
3951           case 0xA6:
3952              /* ADD r6, pc, +imm */
3953              thumb_add_noflags(imm, 6, (pc & ~2) + 4, (imm * 4));
3954              break;
3955 
3956           case 0xA7:
3957              /* ADD r7, pc, +imm */
3958              thumb_add_noflags(imm, 7, (pc & ~2) + 4, (imm * 4));
3959              break;
3960 
3961           case 0xA8:
3962              /* ADD r0, sp, +imm */
3963              thumb_add_noflags(imm, 0, reg[REG_SP], (imm * 4));
3964              break;
3965 
3966           case 0xA9:
3967              /* ADD r1, sp, +imm */
3968              thumb_add_noflags(imm, 1, reg[REG_SP], (imm * 4));
3969              break;
3970 
3971           case 0xAA:
3972              /* ADD r2, sp, +imm */
3973              thumb_add_noflags(imm, 2, reg[REG_SP], (imm * 4));
3974              break;
3975 
3976           case 0xAB:
3977              /* ADD r3, sp, +imm */
3978              thumb_add_noflags(imm, 3, reg[REG_SP], (imm * 4));
3979              break;
3980 
3981           case 0xAC:
3982              /* ADD r4, sp, +imm */
3983              thumb_add_noflags(imm, 4, reg[REG_SP], (imm * 4));
3984              break;
3985 
3986           case 0xAD:
3987              /* ADD r5, sp, +imm */
3988              thumb_add_noflags(imm, 5, reg[REG_SP], (imm * 4));
3989              break;
3990 
3991           case 0xAE:
3992              /* ADD r6, sp, +imm */
3993              thumb_add_noflags(imm, 6, reg[REG_SP], (imm * 4));
3994              break;
3995 
3996           case 0xAF:
3997              /* ADD r7, sp, +imm */
3998              thumb_add_noflags(imm, 7, reg[REG_SP], (imm * 4));
3999              break;
4000 
4001           case 0xB0:
4002           case 0xB1:
4003           case 0xB2:
4004           case 0xB3:
4005              if((opcode >> 7) & 0x01)
4006              {
4007                 /* ADD sp, -imm */
4008                 thumb_add_noflags(add_sp, 13, reg[REG_SP], -(imm * 4));
4009              }
4010              else
4011              {
4012                 /* ADD sp, +imm */
4013                 thumb_add_noflags(add_sp, 13, reg[REG_SP], (imm * 4));
4014              }
4015              break;
4016 
4017           case 0xB4:
4018              /* PUSH rlist */
4019              thumb_block_memory(store, down, no_op, 13);
4020              break;
4021 
4022           case 0xB5:
4023              /* PUSH rlist, lr */
4024              thumb_block_memory(store, push_lr, push_lr, 13);
4025              break;
4026 
4027           case 0xBC:
4028              /* POP rlist */
4029              thumb_block_memory(load, no_op, up, 13);
4030              break;
4031 
4032           case 0xBD:
4033              /* POP rlist, pc */
4034              thumb_block_memory(load, no_op, pop_pc, 13);
4035              break;
4036 
4037           case 0xC0:
4038              /* STMIA r0!, rlist */
4039              thumb_block_memory(store, no_op, up, 0);
4040              break;
4041 
4042           case 0xC1:
4043              /* STMIA r1!, rlist */
4044              thumb_block_memory(store, no_op, up, 1);
4045              break;
4046 
4047           case 0xC2:
4048              /* STMIA r2!, rlist */
4049              thumb_block_memory(store, no_op, up, 2);
4050              break;
4051 
4052           case 0xC3:
4053              /* STMIA r3!, rlist */
4054              thumb_block_memory(store, no_op, up, 3);
4055              break;
4056 
4057           case 0xC4:
4058              /* STMIA r4!, rlist */
4059              thumb_block_memory(store, no_op, up, 4);
4060              break;
4061 
4062           case 0xC5:
4063              /* STMIA r5!, rlist */
4064              thumb_block_memory(store, no_op, up, 5);
4065              break;
4066 
4067           case 0xC6:
4068              /* STMIA r6!, rlist */
4069              thumb_block_memory(store, no_op, up, 6);
4070              break;
4071 
4072           case 0xC7:
4073              /* STMIA r7!, rlist */
4074              thumb_block_memory(store, no_op, up, 7);
4075              break;
4076 
4077           case 0xC8:
4078              /* LDMIA r0!, rlist */
4079              thumb_block_memory(load, no_op, up, 0);
4080              break;
4081 
4082           case 0xC9:
4083              /* LDMIA r1!, rlist */
4084              thumb_block_memory(load, no_op, up, 1);
4085              break;
4086 
4087           case 0xCA:
4088              /* LDMIA r2!, rlist */
4089              thumb_block_memory(load, no_op, up, 2);
4090              break;
4091 
4092           case 0xCB:
4093              /* LDMIA r3!, rlist */
4094              thumb_block_memory(load, no_op, up, 3);
4095              break;
4096 
4097           case 0xCC:
4098              /* LDMIA r4!, rlist */
4099              thumb_block_memory(load, no_op, up, 4);
4100              break;
4101 
4102           case 0xCD:
4103              /* LDMIA r5!, rlist */
4104              thumb_block_memory(load, no_op, up, 5);
4105              break;
4106 
4107           case 0xCE:
4108              /* LDMIA r6!, rlist */
4109              thumb_block_memory(load, no_op, up, 6);
4110              break;
4111 
4112           case 0xCF:
4113              /* LDMIA r7!, rlist */
4114              thumb_block_memory(load, no_op, up, 7);
4115              break;
4116 
4117           case 0xD0:
4118              /* BEQ label */
4119              thumb_conditional_branch(z_flag == 1);
4120              break;
4121 
4122           case 0xD1:
4123              /* BNE label */
4124              thumb_conditional_branch(z_flag == 0);
4125              break;
4126 
4127           case 0xD2:
4128              /* BCS label */
4129              thumb_conditional_branch(c_flag == 1);
4130              break;
4131 
4132           case 0xD3:
4133              /* BCC label */
4134              thumb_conditional_branch(c_flag == 0);
4135              break;
4136 
4137           case 0xD4:
4138              /* BMI label */
4139              thumb_conditional_branch(n_flag == 1);
4140              break;
4141 
4142           case 0xD5:
4143              /* BPL label */
4144              thumb_conditional_branch(n_flag == 0);
4145              break;
4146 
4147           case 0xD6:
4148              /* BVS label */
4149              thumb_conditional_branch(v_flag == 1);
4150              break;
4151 
4152           case 0xD7:
4153              /* BVC label */
4154              thumb_conditional_branch(v_flag == 0);
4155              break;
4156 
4157           case 0xD8:
4158              /* BHI label */
4159              thumb_conditional_branch(c_flag & (z_flag ^ 1));
4160              break;
4161 
4162           case 0xD9:
4163              /* BLS label */
4164              thumb_conditional_branch((c_flag == 0) | z_flag);
4165              break;
4166 
4167           case 0xDA:
4168              /* BGE label */
4169              thumb_conditional_branch(n_flag == v_flag);
4170              break;
4171 
4172           case 0xDB:
4173              /* BLT label */
4174              thumb_conditional_branch(n_flag != v_flag);
4175              break;
4176 
4177           case 0xDC:
4178              /* BGT label */
4179              thumb_conditional_branch((z_flag == 0) & (n_flag == v_flag));
4180              break;
4181 
4182           case 0xDD:
4183              /* BLE label */
4184              thumb_conditional_branch(z_flag | (n_flag != v_flag));
4185              break;
4186 
4187           case 0xDF:
4188              {
4189                 /* SWI comment */
4190                 u32 swi_comment = opcode & 0xFF;
4191 
4192                 switch(swi_comment)
4193                 {
4194                    default:
4195                       reg_mode[MODE_SUPERVISOR][6] = pc + 2;
4196                       spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
4197                       reg[REG_PC] = 0x00000008;
4198                       thumb_update_pc();
4199                       reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13;
4200                       set_cpu_mode(MODE_SUPERVISOR);
4201                       collapse_flags();
4202                       goto arm_loop;
4203                 }
4204                 break;
4205              }
4206 
4207           case 0xE0:
4208           case 0xE1:
4209           case 0xE2:
4210           case 0xE3:
4211           case 0xE4:
4212           case 0xE5:
4213           case 0xE6:
4214           case 0xE7:
4215              {
4216                 /* B label */
4217                 thumb_decode_branch();
4218                 thumb_pc_offset_update(((s32)(offset << 21) >> 20) + 4);
4219                 break;
4220              }
4221 
4222           case 0xF0:
4223           case 0xF1:
4224           case 0xF2:
4225           case 0xF3:
4226           case 0xF4:
4227           case 0xF5:
4228           case 0xF6:
4229           case 0xF7:
4230              {
4231                 /* (low word) BL label */
4232                 thumb_decode_branch();
4233                 reg[REG_LR] = pc + 4 + ((s32)(offset << 21) >> 9);
4234                 thumb_pc_offset(2);
4235                 break;
4236              }
4237 
4238           case 0xF8:
4239           case 0xF9:
4240           case 0xFA:
4241           case 0xFB:
4242           case 0xFC:
4243           case 0xFD:
4244           case 0xFE:
4245           case 0xFF:
4246              {
4247                 /* (high word) BL label */
4248                 thumb_decode_branch();
4249                 u32 lr = (pc + 2) | 0x01;
4250                 pc = reg[REG_LR] + (offset * 2);
4251                 reg[REG_LR] = lr;
4252                 reg[REG_PC] = pc;
4253                 break;
4254              }
4255        }
4256 
4257        /* End of Execute THUMB instruction */
4258        cycles_remaining -= cycles_per_instruction;
4259 
4260        if (pc == idle_loop_target_pc && cycles_remaining > 0) cycles_remaining = 0;
4261     } while(cycles_remaining > 0);
4262 
4263     collapse_flags();
4264     cycles = update_gba();
4265     continue;
4266 
4267     alert:
4268 
4269     if(cpu_alert == CPU_ALERT_IRQ)
4270       cycles = cycles_remaining;
4271     else
4272     {
4273       collapse_flags();
4274 
4275       while(reg[CPU_HALT_STATE] != CPU_ACTIVE)
4276         cycles = update_gba();
4277     }
4278   }
4279 }
4280 
init_cpu(void)4281 void init_cpu(void)
4282 {
4283   u32 i;
4284 
4285   for(i = 0; i < 16; i++)
4286     reg[i] = 0;
4287 
4288   reg[REG_SP] = 0x03007F00;
4289   reg[REG_PC] = 0x08000000;
4290   reg[REG_CPSR] = 0x0000001F;
4291   reg[CPU_HALT_STATE] = CPU_ACTIVE;
4292   reg[CPU_MODE] = MODE_USER;
4293   reg[CHANGED_PC_STATUS] = 0;
4294 
4295   reg_mode[MODE_USER][5] = 0x03007F00;
4296   reg_mode[MODE_IRQ][5] = 0x03007FA0;
4297   reg_mode[MODE_FIQ][5] = 0x03007FA0;
4298   reg_mode[MODE_SUPERVISOR][5] = 0x03007FE0;
4299 }
4300 
move_reg(u32 * new_reg)4301 void move_reg(u32 *new_reg)
4302 {
4303   u32 i;
4304 
4305   for(i = 0; i < 32; i++)
4306     new_reg[i] = reg[i];
4307 
4308   reg = new_reg;
4309 }
4310 
4311 
4312 #define cpu_savestate_builder(type)   \
4313 void cpu_##type##_savestate(void)     \
4314 {                                     \
4315   state_mem_##type(reg, 0x100);       \
4316   state_mem_##type##_array(spsr);     \
4317   state_mem_##type##_array(reg_mode); \
4318 }
4319 
4320 cpu_savestate_builder(read)
4321 cpu_savestate_builder(write)
4322