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