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