Add copyright message to gles_video
[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 = 0;                                                             \
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 = 0;                                                             \
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 = 0;                                                         \
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   u32 _address = address;                                                     \
1020   u8 *map = memory_map_read[_address >> 15];                                  \
1021   if(_address < 0x10000000)                                                   \
1022   {                                                                           \
1023     memory_region_access_read_u32[_address >> 24]++;                          \
1024     memory_reads_u32++;                                                       \
1025   }                                                                           \
1026   if(map)                                                                     \
1027   {                                                                           \
1028     dest = address32(map, _address & 0x7FFF);                                 \
1029   }                                                                           \
1030   else                                                                        \
1031   {                                                                           \
1032     dest = read_memory32(_address);                                           \
1033   }                                                                           \
1034 }                                                                             \
1035
1036 #define store_aligned32(address, value)                                       \
1037 {                                                                             \
1038   u32 _address = address;                                                     \
1039   u8 *map = memory_map_write[_address >> 15];                                 \
1040   if(_address < 0x10000000)                                                   \
1041   {                                                                           \
1042     memory_region_access_write_u32[_address >> 24]++;                         \
1043     memory_writes_u32++;                                                      \
1044   }                                                                           \
1045   if(map)                                                                     \
1046   {                                                                           \
1047     address32(map, _address & 0x7FFF) = value;                                \
1048   }                                                                           \
1049   else                                                                        \
1050   {                                                                           \
1051     cpu_alert = write_memory32(_address, value);                              \
1052     if(cpu_alert)                                                             \
1053       goto alert;                                                             \
1054   }                                                                           \
1055 }                                                                             \
1056
1057 #define load_memory_u8(address, dest)                                         \
1058   fast_read_memory(8, u8, address, dest)                                      \
1059
1060 #define load_memory_u16(address, dest)                                        \
1061   fast_read_memory(16, u16, address, dest)                                    \
1062
1063 #define load_memory_u32(address, dest)                                        \
1064   fast_read_memory(32, u32, address, dest)                                    \
1065
1066 #define load_memory_s8(address, dest)                                         \
1067   fast_read_memory(8, s8, address, dest)                                      \
1068
1069 #define load_memory_s16(address, dest)                                        \
1070   fast_read_memory_s16(address, dest)                                         \
1071
1072 #define store_memory_u8(address, value)                                       \
1073   fast_write_memory(8, u8, address, value)                                    \
1074
1075 #define store_memory_u16(address, value)                                      \
1076   fast_write_memory(16, u16, address, value)                                  \
1077
1078 #define store_memory_u32(address, value)                                      \
1079   fast_write_memory(32, u32, address, value)                                  \
1080
1081 #define no_op                                                                 \
1082
1083 #define arm_access_memory_writeback_yes(off_op)                               \
1084   reg[rn] = address off_op                                                    \
1085
1086 #define arm_access_memory_writeback_no(off_op)                                \
1087
1088 #define arm_access_memory_pc_preadjust_load()                                 \
1089
1090 #define arm_access_memory_pc_preadjust_store()                                \
1091   u32 reg_op = reg[rd];                                                       \
1092   if(rd == 15)                                                                \
1093     reg_op += 4                                                               \
1094
1095 #define arm_access_memory_pc_postadjust_load()                                \
1096   arm_update_pc()                                                             \
1097
1098 #define arm_access_memory_pc_postadjust_store()                               \
1099
1100 #define load_reg_op reg[rd]                                                   \
1101
1102 #define store_reg_op reg_op                                                   \
1103
1104 #define arm_access_memory(access_type, off_op, off_type, mem_type,            \
1105  wb, wb_off_op)                                                               \
1106 {                                                                             \
1107   arm_pc_offset(8);                                                           \
1108   arm_data_trans_##off_type();                                                \
1109   u32 address = reg[rn] off_op;                                               \
1110   arm_access_memory_pc_preadjust_##access_type();                             \
1111                                                                               \
1112   arm_pc_offset(-4);                                                          \
1113   arm_access_memory_writeback_##wb(wb_off_op);                                \
1114   access_type##_memory_##mem_type(address, access_type##_reg_op);             \
1115   arm_access_memory_pc_postadjust_##access_type();                            \
1116 }                                                                             \
1117
1118 #define word_bit_count(word)                                                  \
1119   (bit_count[word >> 8] + bit_count[word & 0xFF])                             \
1120
1121 #define sprint_no(access_type, offset_type, writeback_type)                   \
1122
1123 #define sprint_yes(access_type, offset_type, writeback_type)                  \
1124   printf("sbit on %s %s %s\n", #access_type, #offset_type, #writeback_type)   \
1125
1126 #define arm_block_writeback_load()                                            \
1127   if(!((reg_list >> rn) & 0x01))                                              \
1128   {                                                                           \
1129     reg[rn] = address;                                                        \
1130   }                                                                           \
1131
1132 #define arm_block_writeback_store()                                           \
1133   reg[rn] = address                                                           \
1134
1135 #define arm_block_writeback_yes(access_type)                                  \
1136   arm_block_writeback_##access_type()                                         \
1137
1138 #define arm_block_writeback_no(access_type)                                   \
1139
1140 #define load_block_memory(address, dest)                                      \
1141   dest = address32(address_region, (address + offset) & 0x7FFF)               \
1142
1143 #define store_block_memory(address, dest)                                     \
1144   address32(address_region, (address + offset) & 0x7FFF) = dest               \
1145
1146 #define arm_block_memory_offset_down_a()                                      \
1147   (base - (word_bit_count(reg_list) * 4) + 4)                                 \
1148
1149 #define arm_block_memory_offset_down_b()                                      \
1150   (base - (word_bit_count(reg_list) * 4))                                     \
1151
1152 #define arm_block_memory_offset_no()                                          \
1153   (base)                                                                      \
1154
1155 #define arm_block_memory_offset_up()                                          \
1156   (base + 4)                                                                  \
1157
1158 #define arm_block_memory_writeback_down()                                     \
1159   reg[rn] = base - (word_bit_count(reg_list) * 4)                             \
1160
1161 #define arm_block_memory_writeback_up()                                       \
1162   reg[rn] = base + (word_bit_count(reg_list) * 4)                             \
1163
1164 #define arm_block_memory_writeback_no()                                       \
1165
1166 #define arm_block_memory_load_pc()                                            \
1167   load_aligned32(address, pc);                                                \
1168   reg[REG_PC] = pc                                                            \
1169
1170 #define arm_block_memory_store_pc()                                           \
1171   store_aligned32(address, pc + 4)                                            \
1172
1173 #define arm_block_memory(access_type, offset_type, writeback_type, s_bit)     \
1174 {                                                                             \
1175   arm_decode_block_trans();                                                   \
1176   u32 base = reg[rn];                                                         \
1177   u32 address = arm_block_memory_offset_##offset_type() & 0xFFFFFFFC;         \
1178   u32 i;                                                                      \
1179                                                                               \
1180   arm_block_memory_writeback_##writeback_type();                              \
1181                                                                               \
1182   for(i = 0; i < 15; i++)                                                     \
1183   {                                                                           \
1184     if((reg_list >> i) & 0x01)                                                \
1185     {                                                                         \
1186       access_type##_aligned32(address, reg[i]);                               \
1187       address += 4;                                                           \
1188     }                                                                         \
1189   }                                                                           \
1190                                                                               \
1191   arm_pc_offset(4);                                                           \
1192   if(reg_list & 0x8000)                                                       \
1193   {                                                                           \
1194     arm_block_memory_##access_type##_pc();                                    \
1195   }                                                                           \
1196 }                                                                             \
1197
1198 #define arm_swap(type)                                                        \
1199 {                                                                             \
1200   arm_decode_swap();                                                          \
1201   u32 temp;                                                                   \
1202   load_memory_##type(reg[rn], temp);                                          \
1203   store_memory_##type(reg[rn], reg[rm]);                                      \
1204   reg[rd] = temp;                                                             \
1205   arm_pc_offset(4);                                                           \
1206 }                                                                             \
1207
1208 #define arm_next_instruction()                                                \
1209 {                                                                             \
1210   arm_pc_offset(4);                                                           \
1211   goto skip_instruction;                                                      \
1212 }                                                                             \
1213
1214 #define thumb_update_pc()                                                     \
1215   pc = reg[REG_PC]                                                            \
1216
1217 #define thumb_pc_offset(val)                                                  \
1218   pc += val;                                                                  \
1219   reg[REG_PC] = pc                                                            \
1220
1221 #define thumb_pc_offset_update(val)                                           \
1222   pc += val;                                                                  \
1223   reg[REG_PC] = pc                                                            \
1224
1225 #define thumb_pc_offset_update_direct(val)                                    \
1226   pc = val;                                                                   \
1227   reg[REG_PC] = pc                                                            \
1228
1229 // Types: add_sub, add_sub_imm, alu_op, imm
1230 // Affects N/Z/C/V flags
1231
1232 #define thumb_add(type, dest_reg, src_a, src_b)                               \
1233 {                                                                             \
1234   thumb_decode_##type();                                                      \
1235   const u32 _sa = src_a;                                                      \
1236   const u32 _sb = src_b;                                                      \
1237   u32 dest = _sa + _sb;                                                       \
1238   calculate_flags_add(dest, _sa, _sb);                                        \
1239   reg[dest_reg] = dest;                                                       \
1240   thumb_pc_offset(2);                                                         \
1241 }                                                                             \
1242
1243 #define thumb_add_noflags(type, dest_reg, src_a, src_b)                       \
1244 {                                                                             \
1245   thumb_decode_##type();                                                      \
1246   u32 dest = (src_a) + (src_b);                                               \
1247   reg[dest_reg] = dest;                                                       \
1248   thumb_pc_offset(2);                                                         \
1249 }                                                                             \
1250
1251 #define thumb_sub(type, dest_reg, src_a, src_b)                               \
1252 {                                                                             \
1253   thumb_decode_##type();                                                      \
1254   const u32 _sa = src_a;                                                      \
1255   const u32 _sb = src_b;                                                      \
1256   u32 dest = _sa - _sb;                                                       \
1257   calculate_flags_sub(dest, _sa, _sb);                                        \
1258   reg[dest_reg] = dest;                                                       \
1259   thumb_pc_offset(2);                                                         \
1260 }                                                                             \
1261
1262 // Affects N/Z flags
1263
1264 #define thumb_logic(type, dest_reg, expr)                                     \
1265 {                                                                             \
1266   thumb_decode_##type();                                                      \
1267   u32 dest = expr;                                                            \
1268   calculate_flags_logic(dest);                                                \
1269   reg[dest_reg] = dest;                                                       \
1270   thumb_pc_offset(2);                                                         \
1271 }                                                                             \
1272
1273 // Decode types: shift, alu_op
1274 // Operation types: lsl, lsr, asr, ror
1275 // Affects N/Z/C flags
1276
1277 #define thumb_shift_lsl_reg()                                                 \
1278   u32 shift = reg[rs];                                                        \
1279   u32 dest = reg[rd];                                                         \
1280   if(shift != 0)                                                              \
1281   {                                                                           \
1282     if(shift > 31)                                                            \
1283     {                                                                         \
1284       if(shift == 32)                                                         \
1285         c_flag = dest & 0x01;                                                 \
1286       else                                                                    \
1287         c_flag = 0;                                                           \
1288       dest = 0;                                                               \
1289     }                                                                         \
1290     else                                                                      \
1291     {                                                                         \
1292       c_flag = (dest >> (32 - shift)) & 0x01;                                 \
1293       dest <<= shift;                                                         \
1294     }                                                                         \
1295   }                                                                           \
1296
1297 #define thumb_shift_lsr_reg()                                                 \
1298   u32 shift = reg[rs];                                                        \
1299   u32 dest = reg[rd];                                                         \
1300   if(shift != 0)                                                              \
1301   {                                                                           \
1302     if(shift > 31)                                                            \
1303     {                                                                         \
1304       if(shift == 32)                                                         \
1305         c_flag = dest >> 31;                                                  \
1306       else                                                                    \
1307         c_flag = 0;                                                           \
1308       dest = 0;                                                               \
1309     }                                                                         \
1310     else                                                                      \
1311     {                                                                         \
1312       c_flag = (dest >> (shift - 1)) & 0x01;                                  \
1313       dest >>= shift;                                                         \
1314     }                                                                         \
1315   }                                                                           \
1316
1317 #define thumb_shift_asr_reg()                                                 \
1318   u32 shift = reg[rs];                                                        \
1319   u32 dest = reg[rd];                                                         \
1320   if(shift != 0)                                                              \
1321   {                                                                           \
1322     if(shift > 31)                                                            \
1323     {                                                                         \
1324       dest = (s32)dest >> 31;                                                 \
1325       c_flag = dest & 0x01;                                                   \
1326     }                                                                         \
1327     else                                                                      \
1328     {                                                                         \
1329       c_flag = (dest >> (shift - 1)) & 0x01;                                  \
1330       dest = (s32)dest >> shift;                                              \
1331     }                                                                         \
1332   }                                                                           \
1333
1334 #define thumb_shift_ror_reg()                                                 \
1335   u32 shift = reg[rs];                                                        \
1336   u32 dest = reg[rd];                                                         \
1337   if(shift != 0)                                                              \
1338   {                                                                           \
1339     c_flag = (dest >> (shift - 1)) & 0x01;                                    \
1340     ror(dest, dest, shift);                                                   \
1341   }                                                                           \
1342
1343 #define thumb_shift_lsl_imm()                                                 \
1344   u32 dest = reg[rs];                                                         \
1345   if(imm != 0)                                                                \
1346   {                                                                           \
1347     c_flag = (dest >> (32 - imm)) & 0x01;                                     \
1348     dest <<= imm;                                                             \
1349   }                                                                           \
1350
1351 #define thumb_shift_lsr_imm()                                                 \
1352   u32 dest;                                                                   \
1353   if(imm == 0)                                                                \
1354   {                                                                           \
1355     dest = 0;                                                                 \
1356     c_flag = reg[rs] >> 31;                                                   \
1357   }                                                                           \
1358   else                                                                        \
1359   {                                                                           \
1360     dest = reg[rs];                                                           \
1361     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1362     dest >>= imm;                                                             \
1363   }                                                                           \
1364
1365 #define thumb_shift_asr_imm()                                                 \
1366   u32 dest;                                                                   \
1367   if(imm == 0)                                                                \
1368   {                                                                           \
1369     dest = (s32)reg[rs] >> 31;                                                \
1370     c_flag = dest & 0x01;                                                     \
1371   }                                                                           \
1372   else                                                                        \
1373   {                                                                           \
1374     dest = reg[rs];                                                           \
1375     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1376     dest = (s32)dest >> imm;                                                  \
1377   }                                                                           \
1378
1379 #define thumb_shift_ror_imm()                                                 \
1380   u32 dest = reg[rs];                                                         \
1381   if(imm == 0)                                                                \
1382   {                                                                           \
1383     u32 old_c_flag = c_flag;                                                  \
1384     c_flag = dest & 0x01;                                                     \
1385     dest = (dest >> 1) | (old_c_flag << 31);                                  \
1386   }                                                                           \
1387   else                                                                        \
1388   {                                                                           \
1389     c_flag = (dest >> (imm - 1)) & 0x01;                                      \
1390     ror(dest, dest, imm);                                                     \
1391   }                                                                           \
1392
1393 #define thumb_shift(decode_type, op_type, value_type)                         \
1394 {                                                                             \
1395   thumb_decode_##decode_type();                                               \
1396   thumb_shift_##op_type##_##value_type();                                     \
1397   calculate_flags_logic(dest);                                                \
1398   reg[rd] = dest;                                                             \
1399   thumb_pc_offset(2);                                                         \
1400 }                                                                             \
1401
1402 #define thumb_test_add(type, src_a, src_b)                                    \
1403 {                                                                             \
1404   thumb_decode_##type();                                                      \
1405   const u32 _sa = src_a;                                                      \
1406   const u32 _sb = src_b;                                                      \
1407   u32 dest = _sa + _sb;                                                       \
1408   calculate_flags_add(dest, src_a, src_b);                                    \
1409   thumb_pc_offset(2);                                                         \
1410 }                                                                             \
1411
1412 #define thumb_test_sub(type, src_a, src_b)                                    \
1413 {                                                                             \
1414   thumb_decode_##type();                                                      \
1415   const u32 _sa = src_a;                                                      \
1416   const u32 _sb = src_b;                                                      \
1417   u32 dest = _sa - _sb;                                                       \
1418   calculate_flags_sub(dest, src_a, src_b);                                    \
1419   thumb_pc_offset(2);                                                         \
1420 }                                                                             \
1421
1422 #define thumb_test_logic(type, expr)                                          \
1423 {                                                                             \
1424   thumb_decode_##type();                                                      \
1425   u32 dest = expr;                                                            \
1426   calculate_flags_logic(dest);                                                \
1427   thumb_pc_offset(2);                                                         \
1428 }
1429
1430 #define thumb_hireg_op(expr)                                                  \
1431 {                                                                             \
1432   thumb_pc_offset(4);                                                         \
1433   thumb_decode_hireg_op();                                                    \
1434   u32 dest = expr;                                                            \
1435   thumb_pc_offset(-2);                                                        \
1436   if(rd == 15)                                                                \
1437   {                                                                           \
1438     reg[REG_PC] = dest & ~0x01;                                               \
1439     thumb_update_pc();                                                        \
1440   }                                                                           \
1441   else                                                                        \
1442   {                                                                           \
1443     reg[rd] = dest;                                                           \
1444   }                                                                           \
1445 }                                                                             \
1446
1447 // Operation types: imm, mem_reg, mem_imm
1448
1449 #define thumb_access_memory(access_type, op_type, address, reg_op,            \
1450  mem_type)                                                                    \
1451 {                                                                             \
1452   thumb_decode_##op_type();                                                   \
1453   access_type##_memory_##mem_type(address, reg_op);                           \
1454   thumb_pc_offset(2);                                                         \
1455 }                                                                             \
1456
1457 #define thumb_block_address_preadjust_no_op()                                 \
1458
1459 #define thumb_block_address_preadjust_up()                                    \
1460   address += bit_count[reg_list] * 4                                          \
1461
1462 #define thumb_block_address_preadjust_down()                                  \
1463   address -= bit_count[reg_list] * 4                                          \
1464
1465 #define thumb_block_address_preadjust_push_lr()                               \
1466   address -= (bit_count[reg_list] + 1) * 4                                    \
1467
1468 #define thumb_block_address_postadjust_no_op()                                \
1469
1470 #define thumb_block_address_postadjust_up()                                   \
1471   address += offset                                                           \
1472
1473 #define thumb_block_address_postadjust_down()                                 \
1474   address -= offset                                                           \
1475
1476 #define thumb_block_address_postadjust_pop_pc()                               \
1477   load_memory_u32(address + offset, pc);                                      \
1478   pc &= ~0x01;                                                                \
1479   reg[REG_PC] = pc;                                                           \
1480   address += offset + 4                                                       \
1481
1482 #define thumb_block_address_postadjust_push_lr()                              \
1483   store_memory_u32(address + offset, reg[REG_LR]);                            \
1484
1485 #define thumb_block_memory_wb_load(base_reg)                                  \
1486   if(!((reg_list >> base_reg) & 0x01))                                        \
1487   {                                                                           \
1488     reg[base_reg] = address;                                                  \
1489   }                                                                           \
1490
1491 #define thumb_block_memory_wb_store(base_reg)                                 \
1492   reg[base_reg] = address                                                     \
1493
1494 #define thumb_block_memory(access_type, pre_op, post_op, base_reg)            \
1495 {                                                                             \
1496   u32 i;                                                                      \
1497   u32 offset = 0;                                                             \
1498   thumb_decode_rlist();                                                       \
1499   using_register(thumb, base_reg, memory_base);                               \
1500   u32 address = reg[base_reg] & ~0x03;                                        \
1501   thumb_block_address_preadjust_##pre_op();                                   \
1502                                                                               \
1503   for(i = 0; i < 8; i++)                                                      \
1504   {                                                                           \
1505     if((reg_list >> i) & 1)                                                   \
1506     {                                                                         \
1507       access_type##_aligned32(address + offset, reg[i]);                      \
1508       offset += 4;                                                            \
1509     }                                                                         \
1510   }                                                                           \
1511                                                                               \
1512   thumb_pc_offset(2);                                                         \
1513                                                                               \
1514   thumb_block_address_postadjust_##post_op();                                 \
1515   thumb_block_memory_wb_##access_type(base_reg);                              \
1516 }                                                                             \
1517
1518 #define thumb_conditional_branch(condition)                                   \
1519 {                                                                             \
1520   thumb_decode_branch_cond();                                                 \
1521   if(condition)                                                               \
1522   {                                                                           \
1523     thumb_pc_offset((offset * 2) + 4);                                        \
1524   }                                                                           \
1525   else                                                                        \
1526   {                                                                           \
1527     thumb_pc_offset(2);                                                       \
1528   }                                                                           \
1529 }                                                                             \
1530
1531 // When a mode change occurs from non-FIQ to non-FIQ retire the current
1532 // reg[13] and reg[14] into reg_mode[cpu_mode][5] and reg_mode[cpu_mode][6]
1533 // respectively and load into reg[13] and reg[14] reg_mode[new_mode][5] and
1534 // reg_mode[new_mode][6]. When swapping to/from FIQ retire/load reg[8]
1535 // through reg[14] to/from reg_mode[MODE_FIQ][0] through reg_mode[MODE_FIQ][6].
1536
1537 u32 reg_mode[7][7];
1538
1539 u32 cpu_modes[32] =
1540 {
1541   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1542   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1543   MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1544   MODE_INVALID, MODE_USER, MODE_FIQ, MODE_IRQ, MODE_SUPERVISOR, MODE_INVALID,
1545   MODE_INVALID, MODE_INVALID, MODE_ABORT, MODE_INVALID, MODE_INVALID,
1546   MODE_INVALID, MODE_INVALID, MODE_UNDEFINED, MODE_INVALID, MODE_INVALID,
1547   MODE_USER
1548 };
1549
1550 u32 cpu_modes_cpsr[7] = { 0x10, 0x11, 0x12, 0x13, 0x17, 0x1B, 0x1F };
1551
1552 // When switching modes set spsr[new_mode] to cpsr. Modifying PC as the
1553 // target of a data proc instruction will set cpsr to spsr[cpu_mode].
1554
1555 u32 initial_reg[64];
1556 u32 *reg = initial_reg;
1557 u32 spsr[6];
1558
1559 // ARM/Thumb mode is stored in the flags directly, this is simpler than
1560 // shadowing it since it has a constant 1bit represenation.
1561
1562 char *reg_names[16] =
1563 {
1564   " r0", " r1", " r2", " r3", " r4", " r5", " r6", " r7",
1565   " r8", " r9", "r10", " fp", " ip", " sp", " lr", " pc"
1566 };
1567
1568 char *cpu_mode_names[] =
1569 {
1570   "user", "irq", "fiq", "svsr", "abrt", "undf", "invd"
1571 };
1572
1573
1574 #define execute_arm_instruction()                                             \
1575   using_instruction(arm);                                                     \
1576   check_pc_region();                                                          \
1577   pc &= ~0x03;                                                                \
1578   opcode = address32(pc_address_block, (pc & 0x7FFF));                        \
1579   condition = opcode >> 28;                                                   \
1580                                                                               \
1581   switch(condition)                                                           \
1582   {                                                                           \
1583     case 0x0:                                                                 \
1584       /* EQ */                                                                \
1585       if(!z_flag)                                                             \
1586         arm_next_instruction();                                               \
1587       break;                                                                  \
1588                                                                               \
1589     case 0x1:                                                                 \
1590       /* NE      */                                                           \
1591       if(z_flag)                                                              \
1592         arm_next_instruction();                                               \
1593       break;                                                                  \
1594                                                                               \
1595     case 0x2:                                                                 \
1596       /* CS       */                                                          \
1597       if(!c_flag)                                                             \
1598         arm_next_instruction();                                               \
1599       break;                                                                  \
1600                                                                               \
1601     case 0x3:                                                                 \
1602       /* CC       */                                                          \
1603       if(c_flag)                                                              \
1604         arm_next_instruction();                                               \
1605       break;                                                                  \
1606                                                                               \
1607     case 0x4:                                                                 \
1608       /* MI       */                                                          \
1609       if(!n_flag)                                                             \
1610         arm_next_instruction();                                               \
1611       break;                                                                  \
1612                                                                               \
1613     case 0x5:                                                                 \
1614       /* PL       */                                                          \
1615       if(n_flag)                                                              \
1616         arm_next_instruction();                                               \
1617       break;                                                                  \
1618                                                                               \
1619     case 0x6:                                                                 \
1620       /* VS       */                                                          \
1621       if(!v_flag)                                                             \
1622         arm_next_instruction();                                               \
1623       break;                                                                  \
1624                                                                               \
1625     case 0x7:                                                                 \
1626       /* VC       */                                                          \
1627       if(v_flag)                                                              \
1628         arm_next_instruction();                                               \
1629       break;                                                                  \
1630                                                                               \
1631     case 0x8:                                                                 \
1632       /* HI       */                                                          \
1633       if((c_flag == 0) | z_flag)                                              \
1634         arm_next_instruction();                                               \
1635       break;                                                                  \
1636                                                                               \
1637     case 0x9:                                                                 \
1638       /* LS       */                                                          \
1639       if(c_flag & (z_flag ^ 1))                                               \
1640         arm_next_instruction();                                               \
1641       break;                                                                  \
1642                                                                               \
1643     case 0xA:                                                                 \
1644       /* GE       */                                                          \
1645       if(n_flag != v_flag)                                                    \
1646         arm_next_instruction();                                               \
1647       break;                                                                  \
1648                                                                               \
1649     case 0xB:                                                                 \
1650       /* LT       */                                                          \
1651       if(n_flag == v_flag)                                                    \
1652         arm_next_instruction();                                               \
1653       break;                                                                  \
1654                                                                               \
1655     case 0xC:                                                                 \
1656       /* GT       */                                                          \
1657       if(z_flag | (n_flag != v_flag))                                         \
1658         arm_next_instruction();                                               \
1659       break;                                                                  \
1660                                                                               \
1661     case 0xD:                                                                 \
1662       /* LE       */                                                          \
1663       if((z_flag == 0) & (n_flag == v_flag))                                  \
1664         arm_next_instruction();                                               \
1665       break;                                                                  \
1666                                                                               \
1667     case 0xE:                                                                 \
1668       /* AL       */                                                          \
1669       break;                                                                  \
1670                                                                               \
1671     case 0xF:                                                                 \
1672       /* Reserved - treat as "never" */                                       \
1673       quit();                                                                 \
1674       arm_next_instruction();                                                 \
1675       break;                                                                  \
1676   }                                                                           \
1677                                                                               \
1678   switch((opcode >> 20) & 0xFF)                                               \
1679   {                                                                           \
1680     case 0x00:                                                                \
1681       if((opcode & 0x90) == 0x90)                                             \
1682       {                                                                       \
1683         if(opcode & 0x20)                                                     \
1684         {                                                                     \
1685           /* STRH rd, [rn], -rm */                                            \
1686           arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);     \
1687         }                                                                     \
1688         else                                                                  \
1689         {                                                                     \
1690           /* MUL rd, rm, rs */                                                \
1691           arm_multiply(no_op, no);                                            \
1692         }                                                                     \
1693       }                                                                       \
1694       else                                                                    \
1695       {                                                                       \
1696         /* AND rd, rn, reg_op */                                              \
1697         arm_data_proc(reg[rn] & reg_sh, reg);                                 \
1698       }                                                                       \
1699       break;                                                                  \
1700                                                                               \
1701     case 0x01:                                                                \
1702       if((opcode & 0x90) == 0x90)                                             \
1703       {                                                                       \
1704         switch((opcode >> 5) & 0x03)                                          \
1705         {                                                                     \
1706           case 0:                                                             \
1707             /* MULS rd, rm, rs */                                             \
1708             arm_multiply(no_op, yes);                                         \
1709             break;                                                            \
1710                                                                               \
1711           case 1:                                                             \
1712             /* LDRH rd, [rn], -rm */                                          \
1713             arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);    \
1714             break;                                                            \
1715                                                                               \
1716           case 2:                                                             \
1717             /* LDRSB rd, [rn], -rm */                                         \
1718             arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);     \
1719             break;                                                            \
1720                                                                               \
1721           case 3:                                                             \
1722             /* LDRSH rd, [rn], -rm */                                         \
1723             arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);    \
1724             break;                                                            \
1725         }                                                                     \
1726       }                                                                       \
1727       else                                                                    \
1728       {                                                                       \
1729         /* ANDS rd, rn, reg_op */                                             \
1730         arm_data_proc_logic_flags(reg[rn] & reg_sh, reg);                     \
1731       }                                                                       \
1732       break;                                                                  \
1733                                                                               \
1734     case 0x02:                                                                \
1735       if((opcode & 0x90) == 0x90)                                             \
1736       {                                                                       \
1737         if(opcode & 0x20)                                                     \
1738         {                                                                     \
1739           /* STRH rd, [rn], -rm */                                            \
1740           arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);     \
1741         }                                                                     \
1742         else                                                                  \
1743         {                                                                     \
1744           /* MLA rd, rm, rs, rn */                                            \
1745           arm_multiply(+ reg[rn], no);                                        \
1746         }                                                                     \
1747       }                                                                       \
1748       else                                                                    \
1749       {                                                                       \
1750         /* EOR rd, rn, reg_op */                                              \
1751         arm_data_proc(reg[rn] ^ reg_sh, reg);                                 \
1752       }                                                                       \
1753       break;                                                                  \
1754                                                                               \
1755     case 0x03:                                                                \
1756       if((opcode & 0x90) == 0x90)                                             \
1757       {                                                                       \
1758         switch((opcode >> 5) & 0x03)                                          \
1759         {                                                                     \
1760           case 0:                                                             \
1761             /* MLAS rd, rm, rs, rn */                                         \
1762             arm_multiply(+ reg[rn], yes);                                     \
1763             break;                                                            \
1764                                                                               \
1765           case 1:                                                             \
1766             /* LDRH rd, [rn], -rm */                                          \
1767             arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);    \
1768             break;                                                            \
1769                                                                               \
1770           case 2:                                                             \
1771             /* LDRSB rd, [rn], -rm */                                         \
1772             arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);     \
1773             break;                                                            \
1774                                                                               \
1775           case 3:                                                             \
1776             /* LDRSH rd, [rn], -rm */                                         \
1777             arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);    \
1778             break;                                                            \
1779         }                                                                     \
1780       }                                                                       \
1781       else                                                                    \
1782       {                                                                       \
1783         /* EORS rd, rn, reg_op */                                             \
1784         arm_data_proc_logic_flags(reg[rn] ^ reg_sh, reg);                     \
1785       }                                                                       \
1786       break;                                                                  \
1787                                                                               \
1788     case 0x04:                                                                \
1789       if((opcode & 0x90) == 0x90)                                             \
1790       {                                                                       \
1791         /* STRH rd, [rn], -imm */                                             \
1792         arm_access_memory(store, no_op, half_imm, u16, yes, - offset);        \
1793       }                                                                       \
1794       else                                                                    \
1795       {                                                                       \
1796         /* SUB rd, rn, reg_op */                                              \
1797         arm_data_proc(reg[rn] - reg_sh, reg);                                 \
1798       }                                                                       \
1799       break;                                                                  \
1800                                                                               \
1801     case 0x05:                                                                \
1802       if((opcode & 0x90) == 0x90)                                             \
1803       {                                                                       \
1804         switch((opcode >> 5) & 0x03)                                          \
1805         {                                                                     \
1806           case 1:                                                             \
1807             /* LDRH rd, [rn], -imm */                                         \
1808             arm_access_memory(load, no_op, half_imm, u16, yes, - offset);     \
1809             break;                                                            \
1810                                                                               \
1811           case 2:                                                             \
1812             /* LDRSB rd, [rn], -imm */                                        \
1813             arm_access_memory(load, no_op, half_imm, s8, yes, - offset);      \
1814             break;                                                            \
1815                                                                               \
1816           case 3:                                                             \
1817             /* LDRSH rd, [rn], -imm */                                        \
1818             arm_access_memory(load, no_op, half_imm, s16, yes, - offset);     \
1819             break;                                                            \
1820         }                                                                     \
1821       }                                                                       \
1822       else                                                                    \
1823       {                                                                       \
1824         /* SUBS rd, rn, reg_op */                                             \
1825         arm_data_proc_sub_flags(reg[rn], reg_sh, reg);                        \
1826       }                                                                       \
1827       break;                                                                  \
1828                                                                               \
1829     case 0x06:                                                                \
1830       if((opcode & 0x90) == 0x90)                                             \
1831       {                                                                       \
1832         /* STRH rd, [rn], -imm */                                             \
1833         arm_access_memory(store, no_op, half_imm, u16, yes, - offset);        \
1834       }                                                                       \
1835       else                                                                    \
1836       {                                                                       \
1837         /* RSB rd, rn, reg_op */                                              \
1838         arm_data_proc(reg_sh - reg[rn], reg);                                 \
1839       }                                                                       \
1840       break;                                                                  \
1841                                                                               \
1842     case 0x07:                                                                \
1843       if((opcode & 0x90) == 0x90)                                             \
1844       {                                                                       \
1845         switch((opcode >> 5) & 0x03)                                          \
1846         {                                                                     \
1847           case 1:                                                             \
1848             /* LDRH rd, [rn], -imm */                                         \
1849             arm_access_memory(load, no_op, half_imm, u16, yes, - offset);     \
1850             break;                                                            \
1851                                                                               \
1852           case 2:                                                             \
1853             /* LDRSB rd, [rn], -imm */                                        \
1854             arm_access_memory(load, no_op, half_imm, s8, yes, - offset);      \
1855             break;                                                            \
1856                                                                               \
1857           case 3:                                                             \
1858             /* LDRSH rd, [rn], -imm */                                        \
1859             arm_access_memory(load, no_op, half_imm, s16, yes, - offset);     \
1860             break;                                                            \
1861         }                                                                     \
1862       }                                                                       \
1863       else                                                                    \
1864       {                                                                       \
1865         /* RSBS rd, rn, reg_op */                                             \
1866         arm_data_proc_sub_flags(reg_sh, reg[rn], reg);                        \
1867       }                                                                       \
1868       break;                                                                  \
1869                                                                               \
1870     case 0x08:                                                                \
1871       if((opcode & 0x90) == 0x90)                                             \
1872       {                                                                       \
1873         if(opcode & 0x20)                                                     \
1874         {                                                                     \
1875           /* STRH rd, [rn], +rm */                                            \
1876           arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);     \
1877         }                                                                     \
1878         else                                                                  \
1879         {                                                                     \
1880           /* UMULL rd, rm, rs */                                              \
1881           arm_multiply_long(no_op, no, u);                                    \
1882         }                                                                     \
1883       }                                                                       \
1884       else                                                                    \
1885       {                                                                       \
1886         /* ADD rd, rn, reg_op */                                              \
1887         arm_data_proc(reg[rn] + reg_sh, reg);                                 \
1888       }                                                                       \
1889       break;                                                                  \
1890                                                                               \
1891     case 0x09:                                                                \
1892       if((opcode & 0x90) == 0x90)                                             \
1893       {                                                                       \
1894         switch((opcode >> 5) & 0x03)                                          \
1895         {                                                                     \
1896           case 0:                                                             \
1897             /* UMULLS rdlo, rdhi, rm, rs */                                   \
1898             arm_multiply_long(no_op, yes, u);                                 \
1899             break;                                                            \
1900                                                                               \
1901           case 1:                                                             \
1902             /* LDRH rd, [rn], +rm */                                          \
1903             arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);    \
1904             break;                                                            \
1905                                                                               \
1906           case 2:                                                             \
1907             /* LDRSB rd, [rn], +rm */                                         \
1908             arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);     \
1909             break;                                                            \
1910                                                                               \
1911           case 3:                                                             \
1912             /* LDRSH rd, [rn], +rm */                                         \
1913             arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);    \
1914             break;                                                            \
1915         }                                                                     \
1916       }                                                                       \
1917       else                                                                    \
1918       {                                                                       \
1919         /* ADDS rd, rn, reg_op */                                             \
1920         arm_data_proc_add_flags(reg[rn], reg_sh, reg);                        \
1921       }                                                                       \
1922       break;                                                                  \
1923                                                                               \
1924     case 0x0A:                                                                \
1925       if((opcode & 0x90) == 0x90)                                             \
1926       {                                                                       \
1927         if(opcode & 0x20)                                                     \
1928         {                                                                     \
1929           /* STRH rd, [rn], +rm */                                            \
1930           arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);     \
1931         }                                                                     \
1932         else                                                                  \
1933         {                                                                     \
1934           /* UMLAL rd, rm, rs */                                              \
1935           arm_multiply_long(arm_multiply_long_addop(u), no, u);               \
1936         }                                                                     \
1937       }                                                                       \
1938       else                                                                    \
1939       {                                                                       \
1940         /* ADC rd, rn, reg_op */                                              \
1941         arm_data_proc(reg[rn] + reg_sh + c_flag, reg);                        \
1942       }                                                                       \
1943       break;                                                                  \
1944                                                                               \
1945     case 0x0B:                                                                \
1946       if((opcode & 0x90) == 0x90)                                             \
1947       {                                                                       \
1948         switch((opcode >> 5) & 0x03)                                          \
1949         {                                                                     \
1950           case 0:                                                             \
1951             /* UMLALS rdlo, rdhi, rm, rs */                                   \
1952             arm_multiply_long(arm_multiply_long_addop(u), yes, u);            \
1953             break;                                                            \
1954                                                                               \
1955           case 1:                                                             \
1956             /* LDRH rd, [rn], +rm */                                          \
1957             arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);    \
1958             break;                                                            \
1959                                                                               \
1960           case 2:                                                             \
1961             /* LDRSB rd, [rn], +rm */                                         \
1962             arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);     \
1963             break;                                                            \
1964                                                                               \
1965           case 3:                                                             \
1966             /* LDRSH rd, [rn], +rm */                                         \
1967             arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);    \
1968             break;                                                            \
1969         }                                                                     \
1970       }                                                                       \
1971       else                                                                    \
1972       {                                                                       \
1973         /* ADCS rd, rn, reg_op */                                             \
1974         arm_data_proc_add_flags(reg[rn], reg_sh + c_flag, reg);               \
1975       }                                                                       \
1976       break;                                                                  \
1977                                                                               \
1978     case 0x0C:                                                                \
1979       if((opcode & 0x90) == 0x90)                                             \
1980       {                                                                       \
1981         if(opcode & 0x20)                                                     \
1982         {                                                                     \
1983           /* STRH rd, [rn], +imm */                                           \
1984           arm_access_memory(store, no_op, half_imm, u16, yes, + offset);      \
1985         }                                                                     \
1986         else                                                                  \
1987         {                                                                     \
1988           /* SMULL rd, rm, rs */                                              \
1989           arm_multiply_long(no_op, no, s);                                    \
1990         }                                                                     \
1991       }                                                                       \
1992       else                                                                    \
1993       {                                                                       \
1994         /* SBC rd, rn, reg_op */                                              \
1995         arm_data_proc(reg[rn] - (reg_sh + (c_flag ^ 1)), reg);                \
1996       }                                                                       \
1997       break;                                                                  \
1998                                                                               \
1999     case 0x0D:                                                                \
2000       if((opcode & 0x90) == 0x90)                                             \
2001       {                                                                       \
2002         switch((opcode >> 5) & 0x03)                                          \
2003         {                                                                     \
2004           case 0:                                                             \
2005             /* SMULLS rdlo, rdhi, rm, rs */                                   \
2006             arm_multiply_long(no_op, yes, s);                                 \
2007             break;                                                            \
2008                                                                               \
2009           case 1:                                                             \
2010             /* LDRH rd, [rn], +imm */                                         \
2011             arm_access_memory(load, no_op, half_imm, u16, yes, + offset);     \
2012             break;                                                            \
2013                                                                               \
2014           case 2:                                                             \
2015             /* LDRSB rd, [rn], +imm */                                        \
2016             arm_access_memory(load, no_op, half_imm, s8, yes, + offset);      \
2017             break;                                                            \
2018                                                                               \
2019           case 3:                                                             \
2020             /* LDRSH rd, [rn], +imm */                                        \
2021             arm_access_memory(load, no_op, half_imm, s16, yes, + offset);     \
2022             break;                                                            \
2023         }                                                                     \
2024       }                                                                       \
2025       else                                                                    \
2026       {                                                                       \
2027         /* SBCS rd, rn, reg_op */                                             \
2028         arm_data_proc_sub_flags(reg[rn], (reg_sh + (c_flag ^ 1)), reg);       \
2029       }                                                                       \
2030       break;                                                                  \
2031                                                                               \
2032     case 0x0E:                                                                \
2033       if((opcode & 0x90) == 0x90)                                             \
2034       {                                                                       \
2035         if(opcode & 0x20)                                                     \
2036         {                                                                     \
2037           /* STRH rd, [rn], +imm */                                           \
2038           arm_access_memory(store, no_op, half_imm, u16, yes, + offset);      \
2039         }                                                                     \
2040         else                                                                  \
2041         {                                                                     \
2042           /* SMLAL rd, rm, rs */                                              \
2043           arm_multiply_long(arm_multiply_long_addop(s), no, s);               \
2044         }                                                                     \
2045       }                                                                       \
2046       else                                                                    \
2047       {                                                                       \
2048         /* RSC rd, rn, reg_op */                                              \
2049         arm_data_proc(reg_sh - reg[rn] + c_flag - 1, reg);                    \
2050       }                                                                       \
2051       break;                                                                  \
2052                                                                               \
2053     case 0x0F:                                                                \
2054       if((opcode & 0x90) == 0x90)                                             \
2055       {                                                                       \
2056         switch((opcode >> 5) & 0x03)                                          \
2057         {                                                                     \
2058           case 0:                                                             \
2059             /* SMLALS rdlo, rdhi, rm, rs */                                   \
2060             arm_multiply_long(arm_multiply_long_addop(s), yes, s);            \
2061             break;                                                            \
2062                                                                               \
2063           case 1:                                                             \
2064             /* LDRH rd, [rn], +imm */                                         \
2065             arm_access_memory(load, no_op, half_imm, u16, yes, + offset);     \
2066             break;                                                            \
2067                                                                               \
2068           case 2:                                                             \
2069             /* LDRSB rd, [rn], +imm */                                        \
2070             arm_access_memory(load, no_op, half_imm, s8, yes, + offset);      \
2071             break;                                                            \
2072                                                                               \
2073           case 3:                                                             \
2074             /* LDRSH rd, [rn], +imm */                                        \
2075             arm_access_memory(load, no_op, half_imm, s16, yes, + offset);     \
2076             break;                                                            \
2077         }                                                                     \
2078       }                                                                       \
2079       else                                                                    \
2080       {                                                                       \
2081         /* RSCS rd, rn, reg_op */                                             \
2082         arm_data_proc_sub_flags((reg_sh + c_flag - 1), reg[rn], reg);         \
2083       }                                                                       \
2084       break;                                                                  \
2085                                                                               \
2086     case 0x10:                                                                \
2087       if((opcode & 0x90) == 0x90)                                             \
2088       {                                                                       \
2089         if(opcode & 0x20)                                                     \
2090         {                                                                     \
2091           /* STRH rd, [rn - rm] */                                            \
2092           arm_access_memory(store, - reg[rm], half_reg, u16, no, no_op);      \
2093         }                                                                     \
2094         else                                                                  \
2095         {                                                                     \
2096           /* SWP rd, rm, [rn] */                                              \
2097           arm_swap(u32);                                                      \
2098         }                                                                     \
2099       }                                                                       \
2100       else                                                                    \
2101       {                                                                       \
2102         /* MRS rd, cpsr */                                                    \
2103         arm_psr(reg, read, reg[REG_CPSR]);                                    \
2104       }                                                                       \
2105       break;                                                                  \
2106                                                                               \
2107     case 0x11:                                                                \
2108       if((opcode & 0x90) == 0x90)                                             \
2109       {                                                                       \
2110         switch((opcode >> 5) & 0x03)                                          \
2111         {                                                                     \
2112           case 1:                                                             \
2113             /* LDRH rd, [rn - rm] */                                          \
2114             arm_access_memory(load, - reg[rm], half_reg, u16, no, no_op);     \
2115             break;                                                            \
2116                                                                               \
2117           case 2:                                                             \
2118             /* LDRSB rd, [rn - rm] */                                         \
2119             arm_access_memory(load, - reg[rm], half_reg, s8, no, no_op);      \
2120             break;                                                            \
2121                                                                               \
2122           case 3:                                                             \
2123             /* LDRSH rd, [rn - rm] */                                         \
2124             arm_access_memory(load, - reg[rm], half_reg, s16, no, no_op);     \
2125             break;                                                            \
2126         }                                                                     \
2127       }                                                                       \
2128       else                                                                    \
2129       {                                                                       \
2130         /* TST rd, rn, reg_op */                                              \
2131         arm_data_proc_test_logic(reg[rn] & reg_sh, reg);                      \
2132       }                                                                       \
2133       break;                                                                  \
2134                                                                               \
2135     case 0x12:                                                                \
2136       if((opcode & 0x90) == 0x90)                                             \
2137       {                                                                       \
2138         /* STRH rd, [rn - rm]! */                                             \
2139         arm_access_memory(store, - reg[rm], half_reg, u16, yes, no_op);       \
2140       }                                                                       \
2141       else                                                                    \
2142       {                                                                       \
2143         if(opcode & 0x10)                                                     \
2144         {                                                                     \
2145           /* BX rn */                                                         \
2146           arm_decode_branchx();                                               \
2147           u32 src = reg[rn];                                                  \
2148           if(src & 0x01)                                                      \
2149           {                                                                   \
2150             src -= 1;                                                         \
2151             arm_pc_offset_update_direct(src);                                 \
2152             reg[REG_CPSR] |= 0x20;                                            \
2153             goto thumb_loop;                                                  \
2154           }                                                                   \
2155           else                                                                \
2156           {                                                                   \
2157             arm_pc_offset_update_direct(src);                                 \
2158           }                                                                   \
2159         }                                                                     \
2160         else                                                                  \
2161         {                                                                     \
2162           /* MSR cpsr, rm */                                                  \
2163           arm_psr(reg, store, cpsr);                                          \
2164         }                                                                     \
2165       }                                                                       \
2166       break;                                                                  \
2167                                                                               \
2168     case 0x13:                                                                \
2169       if((opcode & 0x90) == 0x90)                                             \
2170       {                                                                       \
2171         switch((opcode >> 5) & 0x03)                                          \
2172         {                                                                     \
2173           case 1:                                                             \
2174             /* LDRH rd, [rn - rm]! */                                         \
2175             arm_access_memory(load, - reg[rm], half_reg, u16, yes, no_op);    \
2176             break;                                                            \
2177                                                                               \
2178           case 2:                                                             \
2179             /* LDRSB rd, [rn - rm]! */                                        \
2180             arm_access_memory(load, - reg[rm], half_reg, s8, yes, no_op);     \
2181             break;                                                            \
2182                                                                               \
2183           case 3:                                                             \
2184             /* LDRSH rd, [rn - rm]! */                                        \
2185             arm_access_memory(load, - reg[rm], half_reg, s16, yes, no_op);    \
2186             break;                                                            \
2187         }                                                                     \
2188       }                                                                       \
2189       else                                                                    \
2190       {                                                                       \
2191         /* TEQ rd, rn, reg_op */                                              \
2192         arm_data_proc_test_logic(reg[rn] ^ reg_sh, reg);                      \
2193       }                                                                       \
2194       break;                                                                  \
2195                                                                               \
2196     case 0x14:                                                                \
2197       if((opcode & 0x90) == 0x90)                                             \
2198       {                                                                       \
2199         if(opcode & 0x20)                                                     \
2200         {                                                                     \
2201           /* STRH rd, [rn - imm] */                                           \
2202           arm_access_memory(store, - offset, half_imm, u16, no, no_op);       \
2203         }                                                                     \
2204         else                                                                  \
2205         {                                                                     \
2206           /* SWPB rd, rm, [rn] */                                             \
2207           arm_swap(u8);                                                       \
2208         }                                                                     \
2209       }                                                                       \
2210       else                                                                    \
2211       {                                                                       \
2212         /* MRS rd, spsr */                                                    \
2213         arm_psr(reg, read, spsr[reg[CPU_MODE]]);                              \
2214       }                                                                       \
2215       break;                                                                  \
2216                                                                               \
2217     case 0x15:                                                                \
2218       if((opcode & 0x90) == 0x90)                                             \
2219       {                                                                       \
2220         switch((opcode >> 5) & 0x03)                                          \
2221         {                                                                     \
2222           case 1:                                                             \
2223             /* LDRH rd, [rn - imm] */                                         \
2224             arm_access_memory(load, - offset, half_imm, u16, no, no_op);      \
2225             break;                                                            \
2226                                                                               \
2227           case 2:                                                             \
2228             /* LDRSB rd, [rn - imm] */                                        \
2229             arm_access_memory(load, - offset, half_imm, s8, no, no_op);       \
2230             break;                                                            \
2231                                                                               \
2232           case 3:                                                             \
2233             /* LDRSH rd, [rn - imm] */                                        \
2234             arm_access_memory(load, - offset, half_imm, s16, no, no_op);      \
2235             break;                                                            \
2236         }                                                                     \
2237       }                                                                       \
2238       else                                                                    \
2239       {                                                                       \
2240         /* CMP rn, reg_op */                                                  \
2241         arm_data_proc_test_sub(reg[rn], reg_sh, reg);                         \
2242       }                                                                       \
2243       break;                                                                  \
2244                                                                               \
2245     case 0x16:                                                                \
2246       if((opcode & 0x90) == 0x90)                                             \
2247       {                                                                       \
2248         /* STRH rd, [rn - imm]! */                                            \
2249         arm_access_memory(store, - offset, half_imm, u16, yes, no_op);        \
2250       }                                                                       \
2251       else                                                                    \
2252       {                                                                       \
2253         /* MSR spsr, rm */                                                    \
2254         arm_psr(reg, store, spsr);                                            \
2255       }                                                                       \
2256       break;                                                                  \
2257                                                                               \
2258     case 0x17:                                                                \
2259       if((opcode & 0x90) == 0x90)                                             \
2260       {                                                                       \
2261         switch((opcode >> 5) & 0x03)                                          \
2262         {                                                                     \
2263           case 1:                                                             \
2264             /* LDRH rd, [rn - imm]! */                                        \
2265             arm_access_memory(load, - offset, half_imm, u16, yes, no_op);     \
2266             break;                                                            \
2267                                                                               \
2268           case 2:                                                             \
2269             /* LDRSB rd, [rn - imm]! */                                       \
2270             arm_access_memory(load, - offset, half_imm, s8, yes, no_op);      \
2271             break;                                                            \
2272                                                                               \
2273           case 3:                                                             \
2274             /* LDRSH rd, [rn - imm]! */                                       \
2275             arm_access_memory(load, - offset, half_imm, s16, yes, no_op);     \
2276             break;                                                            \
2277         }                                                                     \
2278       }                                                                       \
2279       else                                                                    \
2280       {                                                                       \
2281         /* CMN rd, rn, reg_op */                                              \
2282         arm_data_proc_test_add(reg[rn], reg_sh, reg);                         \
2283       }                                                                       \
2284       break;                                                                  \
2285                                                                               \
2286     case 0x18:                                                                \
2287       if((opcode & 0x90) == 0x90)                                             \
2288       {                                                                       \
2289         /* STRH rd, [rn + rm] */                                              \
2290         arm_access_memory(store, + reg[rm], half_reg, u16, no, no_op);        \
2291       }                                                                       \
2292       else                                                                    \
2293       {                                                                       \
2294         /* ORR rd, rn, reg_op */                                              \
2295         arm_data_proc(reg[rn] | reg_sh, reg);                                 \
2296       }                                                                       \
2297       break;                                                                  \
2298                                                                               \
2299     case 0x19:                                                                \
2300       if((opcode & 0x90) == 0x90)                                             \
2301       {                                                                       \
2302         switch((opcode >> 5) & 0x03)                                          \
2303         {                                                                     \
2304           case 1:                                                             \
2305             /* LDRH rd, [rn + rm] */                                          \
2306             arm_access_memory(load, + reg[rm], half_reg, u16, no, no_op);     \
2307             break;                                                            \
2308                                                                               \
2309           case 2:                                                             \
2310             /* LDRSB rd, [rn + rm] */                                         \
2311             arm_access_memory(load, + reg[rm], half_reg, s8, no, no_op);      \
2312             break;                                                            \
2313                                                                               \
2314           case 3:                                                             \
2315             /* LDRSH rd, [rn + rm] */                                         \
2316             arm_access_memory(load, + reg[rm], half_reg, s16, no, no_op);     \
2317             break;                                                            \
2318         }                                                                     \
2319       }                                                                       \
2320       else                                                                    \
2321       {                                                                       \
2322         /* ORRS rd, rn, reg_op */                                             \
2323         arm_data_proc_logic_flags(reg[rn] | reg_sh, reg);                     \
2324       }                                                                       \
2325       break;                                                                  \
2326                                                                               \
2327     case 0x1A:                                                                \
2328       if((opcode & 0x90) == 0x90)                                             \
2329       {                                                                       \
2330         /* STRH rd, [rn + rm]! */                                             \
2331         arm_access_memory(store, + reg[rm], half_reg, u16, yes, no_op);       \
2332       }                                                                       \
2333       else                                                                    \
2334       {                                                                       \
2335         /* MOV rd, reg_op */                                                  \
2336         arm_data_proc(reg_sh, reg);                                           \
2337       }                                                                       \
2338       break;                                                                  \
2339                                                                               \
2340     case 0x1B:                                                                \
2341       if((opcode & 0x90) == 0x90)                                             \
2342       {                                                                       \
2343         switch((opcode >> 5) & 0x03)                                          \
2344         {                                                                     \
2345           case 1:                                                             \
2346             /* LDRH rd, [rn + rm]! */                                         \
2347             arm_access_memory(load, + reg[rm], half_reg, u16, yes, no_op);    \
2348             break;                                                            \
2349                                                                               \
2350           case 2:                                                             \
2351             /* LDRSB rd, [rn + rm]! */                                        \
2352             arm_access_memory(load, + reg[rm], half_reg, s8, yes, no_op);     \
2353             break;                                                            \
2354                                                                               \
2355           case 3:                                                             \
2356             /* LDRSH rd, [rn + rm]! */                                        \
2357             arm_access_memory(load, + reg[rm], half_reg, s16, yes, no_op);    \
2358             break;                                                            \
2359         }                                                                     \
2360       }                                                                       \
2361       else                                                                    \
2362       {                                                                       \
2363         /* MOVS rd, reg_op */                                                 \
2364         arm_data_proc_logic_flags(reg_sh, reg);                               \
2365       }                                                                       \
2366       break;                                                                  \
2367                                                                               \
2368     case 0x1C:                                                                \
2369       if((opcode & 0x90) == 0x90)                                             \
2370       {                                                                       \
2371         /* STRH rd, [rn + imm] */                                             \
2372         arm_access_memory(store, + offset, half_imm, u16, no, no_op);         \
2373       }                                                                       \
2374       else                                                                    \
2375       {                                                                       \
2376         /* BIC rd, rn, reg_op */                                              \
2377         arm_data_proc(reg[rn] & (~reg_sh), reg);                              \
2378       }                                                                       \
2379       break;                                                                  \
2380                                                                               \
2381     case 0x1D:                                                                \
2382       if((opcode & 0x90) == 0x90)                                             \
2383       {                                                                       \
2384         switch((opcode >> 5) & 0x03)                                          \
2385         {                                                                     \
2386           case 1:                                                             \
2387             /* LDRH rd, [rn + imm] */                                         \
2388             arm_access_memory(load, + offset, half_imm, u16, no, no_op);      \
2389             break;                                                            \
2390                                                                               \
2391           case 2:                                                             \
2392             /* LDRSB rd, [rn + imm] */                                        \
2393             arm_access_memory(load, + offset, half_imm, s8, no, no_op);       \
2394             break;                                                            \
2395                                                                               \
2396           case 3:                                                             \
2397             /* LDRSH rd, [rn + imm] */                                        \
2398             arm_access_memory(load, + offset, half_imm, s16, no, no_op);      \
2399             break;                                                            \
2400         }                                                                     \
2401       }                                                                       \
2402       else                                                                    \
2403       {                                                                       \
2404         /* BICS rd, rn, reg_op */                                             \
2405         arm_data_proc_logic_flags(reg[rn] & (~reg_sh), reg);                  \
2406       }                                                                       \
2407       break;                                                                  \
2408                                                                               \
2409     case 0x1E:                                                                \
2410       if((opcode & 0x90) == 0x90)                                             \
2411       {                                                                       \
2412         /* STRH rd, [rn + imm]! */                                            \
2413         arm_access_memory(store, + offset, half_imm, u16, yes, no_op);        \
2414       }                                                                       \
2415       else                                                                    \
2416       {                                                                       \
2417         /* MVN rd, reg_op */                                                  \
2418         arm_data_proc(~reg_sh, reg);                                          \
2419       }                                                                       \
2420       break;                                                                  \
2421                                                                               \
2422     case 0x1F:                                                                \
2423       if((opcode & 0x90) == 0x90)                                             \
2424       {                                                                       \
2425         switch((opcode >> 5) & 0x03)                                          \
2426         {                                                                     \
2427           case 1:                                                             \
2428             /* LDRH rd, [rn + imm]! */                                        \
2429             arm_access_memory(load, + offset, half_imm, u16, yes, no_op);     \
2430             break;                                                            \
2431                                                                               \
2432           case 2:                                                             \
2433             /* LDRSB rd, [rn + imm]! */                                       \
2434             arm_access_memory(load, + offset, half_imm, s8, yes, no_op);      \
2435             break;                                                            \
2436                                                                               \
2437           case 3:                                                             \
2438             /* LDRSH rd, [rn + imm]! */                                       \
2439             arm_access_memory(load, + offset, half_imm, s16, yes, no_op);     \
2440             break;                                                            \
2441         }                                                                     \
2442       }                                                                       \
2443       else                                                                    \
2444       {                                                                       \
2445         /* MVNS rd, rn, reg_op */                                             \
2446         arm_data_proc_logic_flags(~reg_sh, reg);                              \
2447       }                                                                       \
2448       break;                                                                  \
2449                                                                               \
2450     case 0x20:                                                                \
2451       /* AND rd, rn, imm */                                                   \
2452       arm_data_proc(reg[rn] & imm, imm);                                      \
2453       break;                                                                  \
2454                                                                               \
2455     case 0x21:                                                                \
2456       /* ANDS rd, rn, imm */                                                  \
2457       arm_data_proc_logic_flags(reg[rn] & imm, imm);                          \
2458       break;                                                                  \
2459                                                                               \
2460     case 0x22:                                                                \
2461       /* EOR rd, rn, imm */                                                   \
2462       arm_data_proc(reg[rn] ^ imm, imm);                                      \
2463       break;                                                                  \
2464                                                                               \
2465     case 0x23:                                                                \
2466       /* EORS rd, rn, imm */                                                  \
2467       arm_data_proc_logic_flags(reg[rn] ^ imm, imm);                          \
2468       break;                                                                  \
2469                                                                               \
2470     case 0x24:                                                                \
2471       /* SUB rd, rn, imm */                                                   \
2472       arm_data_proc(reg[rn] - imm, imm);                                      \
2473       break;                                                                  \
2474                                                                               \
2475     case 0x25:                                                                \
2476       /* SUBS rd, rn, imm */                                                  \
2477       arm_data_proc_sub_flags(reg[rn], imm, imm);                             \
2478       break;                                                                  \
2479                                                                               \
2480     case 0x26:                                                                \
2481       /* RSB rd, rn, imm */                                                   \
2482       arm_data_proc(imm - reg[rn], imm);                                      \
2483       break;                                                                  \
2484                                                                               \
2485     case 0x27:                                                                \
2486       /* RSBS rd, rn, imm */                                                  \
2487       arm_data_proc_sub_flags(imm, reg[rn], imm);                             \
2488       break;                                                                  \
2489                                                                               \
2490     case 0x28:                                                                \
2491       /* ADD rd, rn, imm */                                                   \
2492       arm_data_proc(reg[rn] + imm, imm);                                      \
2493       break;                                                                  \
2494                                                                               \
2495     case 0x29:                                                                \
2496       /* ADDS rd, rn, imm */                                                  \
2497       arm_data_proc_add_flags(reg[rn], imm, imm);                             \
2498       break;                                                                  \
2499                                                                               \
2500     case 0x2A:                                                                \
2501       /* ADC rd, rn, imm */                                                   \
2502       arm_data_proc(reg[rn] + imm + c_flag, imm);                             \
2503       break;                                                                  \
2504                                                                               \
2505     case 0x2B:                                                                \
2506       /* ADCS rd, rn, imm */                                                  \
2507       arm_data_proc_add_flags(reg[rn] + imm, c_flag, imm);                    \
2508       break;                                                                  \
2509                                                                               \
2510     case 0x2C:                                                                \
2511       /* SBC rd, rn, imm */                                                   \
2512       arm_data_proc(reg[rn] - imm + c_flag - 1, imm);                         \
2513       break;                                                                  \
2514                                                                               \
2515     case 0x2D:                                                                \
2516       /* SBCS rd, rn, imm */                                                  \
2517       arm_data_proc_sub_flags(reg[rn], (imm + (c_flag ^ 1)), imm);            \
2518       break;                                                                  \
2519                                                                               \
2520     case 0x2E:                                                                \
2521       /* RSC rd, rn, imm */                                                   \
2522       arm_data_proc(imm - reg[rn] + c_flag - 1, imm);                         \
2523       break;                                                                  \
2524                                                                               \
2525     case 0x2F:                                                                \
2526       /* RSCS rd, rn, imm */                                                  \
2527       arm_data_proc_sub_flags((imm + c_flag - 1), reg[rn], imm);              \
2528       break;                                                                  \
2529                                                                               \
2530     case 0x30 ... 0x31:                                                       \
2531       /* TST rn, imm */                                                       \
2532       arm_data_proc_test_logic(reg[rn] & imm, imm);                           \
2533       break;                                                                  \
2534                                                                               \
2535     case 0x32:                                                                \
2536       /* MSR cpsr, imm */                                                     \
2537       arm_psr(imm, store, cpsr);                                              \
2538       break;                                                                  \
2539                                                                               \
2540     case 0x33:                                                                \
2541       /* TEQ rn, imm */                                                       \
2542       arm_data_proc_test_logic(reg[rn] ^ imm, imm);                           \
2543       break;                                                                  \
2544                                                                               \
2545     case 0x34 ... 0x35:                                                       \
2546       /* CMP rn, imm */                                                       \
2547       arm_data_proc_test_sub(reg[rn], imm, imm);                              \
2548       break;                                                                  \
2549                                                                               \
2550     case 0x36:                                                                \
2551       /* MSR spsr, imm */                                                     \
2552       arm_psr(imm, store, spsr);                                              \
2553       break;                                                                  \
2554                                                                               \
2555     case 0x37:                                                                \
2556       /* CMN rn, imm */                                                       \
2557       arm_data_proc_test_add(reg[rn], imm, imm);                              \
2558       break;                                                                  \
2559                                                                               \
2560     case 0x38:                                                                \
2561       /* ORR rd, rn, imm */                                                   \
2562       arm_data_proc(reg[rn] | imm, imm);                                      \
2563       break;                                                                  \
2564                                                                               \
2565     case 0x39:                                                                \
2566       /* ORRS rd, rn, imm */                                                  \
2567       arm_data_proc_logic_flags(reg[rn] | imm, imm);                          \
2568       break;                                                                  \
2569                                                                               \
2570     case 0x3A:                                                                \
2571       /* MOV rd, imm */                                                       \
2572       arm_data_proc(imm, imm);                                                \
2573       break;                                                                  \
2574                                                                               \
2575     case 0x3B:                                                                \
2576       /* MOVS rd, imm */                                                      \
2577       arm_data_proc_logic_flags(imm, imm);                                    \
2578       break;                                                                  \
2579                                                                               \
2580     case 0x3C:                                                                \
2581       /* BIC rd, rn, imm */                                                   \
2582       arm_data_proc(reg[rn] & (~imm), imm);                                   \
2583       break;                                                                  \
2584                                                                               \
2585     case 0x3D:                                                                \
2586       /* BICS rd, rn, imm */                                                  \
2587       arm_data_proc_logic_flags(reg[rn] & (~imm), imm);                       \
2588       break;                                                                  \
2589                                                                               \
2590     case 0x3E:                                                                \
2591       /* MVN rd, imm */                                                       \
2592       arm_data_proc(~imm, imm);                                               \
2593       break;                                                                  \
2594                                                                               \
2595     case 0x3F:                                                                \
2596       /* MVNS rd, imm */                                                      \
2597       arm_data_proc_logic_flags(~imm, imm);                                   \
2598       break;                                                                  \
2599                                                                               \
2600     case 0x40:                                                                \
2601       /* STR rd, [rn], -imm */                                                \
2602       arm_access_memory(store, no_op, imm, u32, yes, - offset);               \
2603       break;                                                                  \
2604                                                                               \
2605     case 0x41:                                                                \
2606       /* LDR rd, [rn], -imm */                                                \
2607       arm_access_memory(load, no_op, imm, u32, yes, - offset);                \
2608       break;                                                                  \
2609                                                                               \
2610     case 0x42:                                                                \
2611       /* STRT rd, [rn], -imm */                                               \
2612       arm_access_memory(store, no_op, imm, u32, yes, - offset);               \
2613       break;                                                                  \
2614                                                                               \
2615     case 0x43:                                                                \
2616       /* LDRT rd, [rn], -imm */                                               \
2617       arm_access_memory(load, no_op, imm, u32, yes, - offset);                \
2618       break;                                                                  \
2619                                                                               \
2620     case 0x44:                                                                \
2621       /* STRB rd, [rn], -imm */                                               \
2622       arm_access_memory(store, no_op, imm, u8, yes, - offset);                \
2623       break;                                                                  \
2624                                                                               \
2625     case 0x45:                                                                \
2626       /* LDRB rd, [rn], -imm */                                               \
2627       arm_access_memory(load, no_op, imm, u8, yes, - offset);                 \
2628       break;                                                                  \
2629                                                                               \
2630     case 0x46:                                                                \
2631       /* STRBT rd, [rn], -imm */                                              \
2632       arm_access_memory(store, no_op, imm, u8, yes, - offset);                \
2633       break;                                                                  \
2634                                                                               \
2635     case 0x47:                                                                \
2636       /* LDRBT rd, [rn], -imm */                                              \
2637       arm_access_memory(load, no_op, imm, u8, yes, - offset);                 \
2638       break;                                                                  \
2639                                                                               \
2640     case 0x48:                                                                \
2641       /* STR rd, [rn], +imm */                                                \
2642       arm_access_memory(store, no_op, imm, u32, yes, + offset);               \
2643       break;                                                                  \
2644                                                                               \
2645     case 0x49:                                                                \
2646       /* LDR rd, [rn], +imm */                                                \
2647       arm_access_memory(load, no_op, imm, u32, yes, + offset);                \
2648       break;                                                                  \
2649                                                                               \
2650     case 0x4A:                                                                \
2651       /* STRT rd, [rn], +imm */                                               \
2652       arm_access_memory(store, no_op, imm, u32, yes, + offset);               \
2653       break;                                                                  \
2654                                                                               \
2655     case 0x4B:                                                                \
2656       /* LDRT rd, [rn], +imm */                                               \
2657       arm_access_memory(load, no_op, imm, u32, yes, + offset);                \
2658       break;                                                                  \
2659                                                                               \
2660     case 0x4C:                                                                \
2661       /* STRB rd, [rn], +imm */                                               \
2662       arm_access_memory(store, no_op, imm, u8, yes, + offset);                \
2663       break;                                                                  \
2664                                                                               \
2665     case 0x4D:                                                                \
2666       /* LDRB rd, [rn], +imm */                                               \
2667       arm_access_memory(load, no_op, imm, u8, yes, + offset);                 \
2668       break;                                                                  \
2669                                                                               \
2670     case 0x4E:                                                                \
2671       /* STRBT rd, [rn], +imm */                                              \
2672       arm_access_memory(store, no_op, imm, u8, yes, + offset);                \
2673       break;                                                                  \
2674                                                                               \
2675     case 0x4F:                                                                \
2676       /* LDRBT rd, [rn], +imm */                                              \
2677       arm_access_memory(load, no_op, imm, u8, yes, + offset);                 \
2678       break;                                                                  \
2679                                                                               \
2680     case 0x50:                                                                \
2681       /* STR rd, [rn - imm] */                                                \
2682       arm_access_memory(store, - offset, imm, u32, no, no_op);                \
2683       break;                                                                  \
2684                                                                               \
2685     case 0x51:                                                                \
2686       /* LDR rd, [rn - imm] */                                                \
2687       arm_access_memory(load, - offset, imm, u32, no, no_op);                 \
2688       break;                                                                  \
2689                                                                               \
2690     case 0x52:                                                                \
2691       /* STR rd, [rn - imm]! */                                               \
2692       arm_access_memory(store, - offset, imm, u32, yes, no_op);               \
2693       break;                                                                  \
2694                                                                               \
2695     case 0x53:                                                                \
2696       /* LDR rd, [rn - imm]! */                                               \
2697       arm_access_memory(load, - offset, imm, u32, yes, no_op);                \
2698       break;                                                                  \
2699                                                                               \
2700     case 0x54:                                                                \
2701       /* STRB rd, [rn - imm] */                                               \
2702       arm_access_memory(store, - offset, imm, u8, no, no_op);                 \
2703       break;                                                                  \
2704                                                                               \
2705     case 0x55:                                                                \
2706       /* LDRB rd, [rn - imm] */                                               \
2707       arm_access_memory(load, - offset, imm, u8, no, no_op);                  \
2708       break;                                                                  \
2709                                                                               \
2710     case 0x56:                                                                \
2711       /* STRB rd, [rn - imm]! */                                              \
2712       arm_access_memory(store, - offset, imm, u8, yes, no_op);                \
2713       break;                                                                  \
2714                                                                               \
2715     case 0x57:                                                                \
2716       /* LDRB rd, [rn - imm]! */                                              \
2717       arm_access_memory(load, - offset, imm, u8, yes, no_op);                 \
2718       break;                                                                  \
2719                                                                               \
2720     case 0x58:                                                                \
2721       /* STR rd, [rn + imm] */                                                \
2722       arm_access_memory(store, + offset, imm, u32, no, no_op);                \
2723       break;                                                                  \
2724                                                                               \
2725     case 0x59:                                                                \
2726       /* LDR rd, [rn + imm] */                                                \
2727       arm_access_memory(load, + offset, imm, u32, no, no_op);                 \
2728       break;                                                                  \
2729                                                                               \
2730     case 0x5A:                                                                \
2731       /* STR rd, [rn + imm]! */                                               \
2732       arm_access_memory(store, + offset, imm, u32, yes, no_op);               \
2733       break;                                                                  \
2734                                                                               \
2735     case 0x5B:                                                                \
2736       /* LDR rd, [rn + imm]! */                                               \
2737       arm_access_memory(load, + offset, imm, u32, yes, no_op);                \
2738       break;                                                                  \
2739                                                                               \
2740     case 0x5C:                                                                \
2741       /* STRB rd, [rn + imm] */                                               \
2742       arm_access_memory(store, + offset, imm, u8, no, no_op);                 \
2743       break;                                                                  \
2744                                                                               \
2745     case 0x5D:                                                                \
2746       /* LDRB rd, [rn + imm] */                                               \
2747       arm_access_memory(load, + offset, imm, u8, no, no_op);                  \
2748       break;                                                                  \
2749                                                                               \
2750     case 0x5E:                                                                \
2751       /* STRB rd, [rn + imm]! */                                              \
2752       arm_access_memory(store, + offset, imm, u8, yes, no_op);                \
2753       break;                                                                  \
2754                                                                               \
2755     case 0x5F:                                                                \
2756       /* LDRBT rd, [rn + imm]! */                                             \
2757       arm_access_memory(load, + offset, imm, u8, yes, no_op);                 \
2758       break;                                                                  \
2759                                                                               \
2760     case 0x60:                                                                \
2761       /* STR rd, [rn], -reg_op */                                             \
2762       arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);           \
2763       break;                                                                  \
2764                                                                               \
2765     case 0x61:                                                                \
2766       /* LDR rd, [rn], -reg_op */                                             \
2767       arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);            \
2768       break;                                                                  \
2769                                                                               \
2770     case 0x62:                                                                \
2771       /* STRT rd, [rn], -reg_op */                                            \
2772       arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);           \
2773       break;                                                                  \
2774                                                                               \
2775     case 0x63:                                                                \
2776       /* LDRT rd, [rn], -reg_op */                                            \
2777       arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);            \
2778       break;                                                                  \
2779                                                                               \
2780     case 0x64:                                                                \
2781       /* STRB rd, [rn], -reg_op */                                            \
2782       arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);            \
2783       break;                                                                  \
2784                                                                               \
2785     case 0x65:                                                                \
2786       /* LDRB rd, [rn], -reg_op */                                            \
2787       arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);             \
2788       break;                                                                  \
2789                                                                               \
2790     case 0x66:                                                                \
2791       /* STRBT rd, [rn], -reg_op */                                           \
2792       arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);            \
2793       break;                                                                  \
2794                                                                               \
2795     case 0x67:                                                                \
2796       /* LDRBT rd, [rn], -reg_op */                                           \
2797       arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);             \
2798       break;                                                                  \
2799                                                                               \
2800     case 0x68:                                                                \
2801       /* STR rd, [rn], +reg_op */                                             \
2802       arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);           \
2803       break;                                                                  \
2804                                                                               \
2805     case 0x69:                                                                \
2806       /* LDR rd, [rn], +reg_op */                                             \
2807       arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);            \
2808       break;                                                                  \
2809                                                                               \
2810     case 0x6A:                                                                \
2811       /* STRT rd, [rn], +reg_op */                                            \
2812       arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);           \
2813       break;                                                                  \
2814                                                                               \
2815     case 0x6B:                                                                \
2816       /* LDRT rd, [rn], +reg_op */                                            \
2817       arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);            \
2818       break;                                                                  \
2819                                                                               \
2820     case 0x6C:                                                                \
2821       /* STRB rd, [rn], +reg_op */                                            \
2822       arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);            \
2823       break;                                                                  \
2824                                                                               \
2825     case 0x6D:                                                                \
2826       /* LDRB rd, [rn], +reg_op */                                            \
2827       arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);             \
2828       break;                                                                  \
2829                                                                               \
2830     case 0x6E:                                                                \
2831       /* STRBT rd, [rn], +reg_op */                                           \
2832       arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);            \
2833       break;                                                                  \
2834                                                                               \
2835     case 0x6F:                                                                \
2836       /* LDRBT rd, [rn], +reg_op */                                           \
2837       arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);             \
2838       break;                                                                  \
2839                                                                               \
2840     case 0x70:                                                                \
2841       /* STR rd, [rn - reg_op] */                                             \
2842       arm_access_memory(store, - reg_offset, reg, u32, no, no_op);            \
2843       break;                                                                  \
2844                                                                               \
2845     case 0x71:                                                                \
2846       /* LDR rd, [rn - reg_op] */                                             \
2847       arm_access_memory(load, - reg_offset, reg, u32, no, no_op);             \
2848       break;                                                                  \
2849                                                                               \
2850     case 0x72:                                                                \
2851       /* STR rd, [rn - reg_op]! */                                            \
2852       arm_access_memory(store, - reg_offset, reg, u32, yes, no_op);           \
2853       break;                                                                  \
2854                                                                               \
2855     case 0x73:                                                                \
2856       /* LDR rd, [rn - reg_op]! */                                            \
2857       arm_access_memory(load, - reg_offset, reg, u32, yes, no_op);            \
2858       break;                                                                  \
2859                                                                               \
2860     case 0x74:                                                                \
2861       /* STRB rd, [rn - reg_op] */                                            \
2862       arm_access_memory(store, - reg_offset, reg, u8, no, no_op);             \
2863       break;                                                                  \
2864                                                                               \
2865     case 0x75:                                                                \
2866       /* LDRB rd, [rn - reg_op] */                                            \
2867       arm_access_memory(load, - reg_offset, reg, u8, no, no_op);              \
2868       break;                                                                  \
2869                                                                               \
2870     case 0x76:                                                                \
2871       /* STRB rd, [rn - reg_op]! */                                           \
2872       arm_access_memory(store, - reg_offset, reg, u8, yes, no_op);            \
2873       break;                                                                  \
2874                                                                               \
2875     case 0x77:                                                                \
2876       /* LDRB rd, [rn - reg_op]! */                                           \
2877       arm_access_memory(load, - reg_offset, reg, u8, yes, no_op);             \
2878       break;                                                                  \
2879                                                                               \
2880     case 0x78:                                                                \
2881       /* STR rd, [rn + reg_op] */                                             \
2882       arm_access_memory(store, + reg_offset, reg, u32, no, no_op);            \
2883       break;                                                                  \
2884                                                                               \
2885     case 0x79:                                                                \
2886       /* LDR rd, [rn + reg_op] */                                             \
2887       arm_access_memory(load, + reg_offset, reg, u32, no, no_op);             \
2888       break;                                                                  \
2889                                                                               \
2890     case 0x7A:                                                                \
2891       /* STR rd, [rn + reg_op]! */                                            \
2892       arm_access_memory(store, + reg_offset, reg, u32, yes, no_op);           \
2893       break;                                                                  \
2894                                                                               \
2895     case 0x7B:                                                                \
2896       /* LDR rd, [rn + reg_op]! */                                            \
2897       arm_access_memory(load, + reg_offset, reg, u32, yes, no_op);            \
2898       break;                                                                  \
2899                                                                               \
2900     case 0x7C:                                                                \
2901       /* STRB rd, [rn + reg_op] */                                            \
2902       arm_access_memory(store, + reg_offset, reg, u8, no, no_op);             \
2903       break;                                                                  \
2904                                                                               \
2905     case 0x7D:                                                                \
2906       /* LDRB rd, [rn + reg_op] */                                            \
2907       arm_access_memory(load, + reg_offset, reg, u8, no, no_op);              \
2908       break;                                                                  \
2909                                                                               \
2910     case 0x7E:                                                                \
2911       /* STRB rd, [rn + reg_op]! */                                           \
2912       arm_access_memory(store, + reg_offset, reg, u8, yes, no_op);            \
2913       break;                                                                  \
2914                                                                               \
2915     case 0x7F:                                                                \
2916       /* LDRBT rd, [rn + reg_op]! */                                          \
2917       arm_access_memory(load, + reg_offset, reg, u8, yes, no_op);             \
2918       break;                                                                  \
2919                                                                               \
2920     case 0x80:                                                                \
2921       /* STMDA rn, rlist */                                                   \
2922       arm_block_memory(store, down_a, no, no);                                \
2923       break;                                                                  \
2924                                                                               \
2925     case 0x81:                                                                \
2926       /* LDMDA rn, rlist */                                                   \
2927       arm_block_memory(load, down_a, no, no);                                 \
2928       break;                                                                  \
2929                                                                               \
2930     case 0x82:                                                                \
2931       /* STMDA rn!, rlist */                                                  \
2932       arm_block_memory(store, down_a, down, no);                              \
2933       break;                                                                  \
2934                                                                               \
2935     case 0x83:                                                                \
2936       /* LDMDA rn!, rlist */                                                  \
2937       arm_block_memory(load, down_a, down, no);                               \
2938       break;                                                                  \
2939                                                                               \
2940     case 0x84:                                                                \
2941       /* STMDA rn, rlist^ */                                                  \
2942       arm_block_memory(store, down_a, no, yes);                               \
2943       break;                                                                  \
2944                                                                               \
2945     case 0x85:                                                                \
2946       /* LDMDA rn, rlist^ */                                                  \
2947       arm_block_memory(load, down_a, no, yes);                                \
2948       break;                                                                  \
2949                                                                               \
2950     case 0x86:                                                                \
2951       /* STMDA rn!, rlist^ */                                                 \
2952       arm_block_memory(store, down_a, down, yes);                             \
2953       break;                                                                  \
2954                                                                               \
2955     case 0x87:                                                                \
2956       /* LDMDA rn!, rlist^ */                                                 \
2957       arm_block_memory(load, down_a, down, yes);                              \
2958       break;                                                                  \
2959                                                                               \
2960     case 0x88:                                                                \
2961       /* STMIA rn, rlist */                                                   \
2962       arm_block_memory(store, no, no, no);                                    \
2963       break;                                                                  \
2964                                                                               \
2965     case 0x89:                                                                \
2966       /* LDMIA rn, rlist */                                                   \
2967       arm_block_memory(load, no, no, no);                                     \
2968       break;                                                                  \
2969                                                                               \
2970     case 0x8A:                                                                \
2971       /* STMIA rn!, rlist */                                                  \
2972       arm_block_memory(store, no, up, no);                                    \
2973       break;                                                                  \
2974                                                                               \
2975     case 0x8B:                                                                \
2976       /* LDMIA rn!, rlist */                                                  \
2977       arm_block_memory(load, no, up, no);                                     \
2978       break;                                                                  \
2979                                                                               \
2980     case 0x8C:                                                                \
2981       /* STMIA rn, rlist^ */                                                  \
2982       arm_block_memory(store, no, no, yes);                                   \
2983       break;                                                                  \
2984                                                                               \
2985     case 0x8D:                                                                \
2986       /* LDMIA rn, rlist^ */                                                  \
2987       arm_block_memory(load, no, no, yes);                                    \
2988       break;                                                                  \
2989                                                                               \
2990     case 0x8E:                                                                \
2991       /* STMIA rn!, rlist^ */                                                 \
2992       arm_block_memory(store, no, up, yes);                                   \
2993       break;                                                                  \
2994                                                                               \
2995     case 0x8F:                                                                \
2996       /* LDMIA rn!, rlist^ */                                                 \
2997       arm_block_memory(load, no, up, yes);                                    \
2998       break;                                                                  \
2999                                                                               \
3000     case 0x90:                                                                \
3001       /* STMDB rn, rlist */                                                   \
3002       arm_block_memory(store, down_b, no, no);                                \
3003       break;                                                                  \
3004                                                                               \
3005     case 0x91:                                                                \
3006       /* LDMDB rn, rlist */                                                   \
3007       arm_block_memory(load, down_b, no, no);                                 \
3008       break;                                                                  \
3009                                                                               \
3010     case 0x92:                                                                \
3011       /* STMDB rn!, rlist */                                                  \
3012       arm_block_memory(store, down_b, down, no);                              \
3013       break;                                                                  \
3014                                                                               \
3015     case 0x93:                                                                \
3016       /* LDMDB rn!, rlist */                                                  \
3017       arm_block_memory(load, down_b, down, no);                               \
3018       break;                                                                  \
3019                                                                               \
3020     case 0x94:                                                                \
3021       /* STMDB rn, rlist^ */                                                  \
3022       arm_block_memory(store, down_b, no, yes);                               \
3023       break;                                                                  \
3024                                                                               \
3025     case 0x95:                                                                \
3026       /* LDMDB rn, rlist^ */                                                  \
3027       arm_block_memory(load, down_b, no, yes);                                \
3028       break;                                                                  \
3029                                                                               \
3030     case 0x96:                                                                \
3031       /* STMDB rn!, rlist^ */                                                 \
3032       arm_block_memory(store, down_b, down, yes);                             \
3033       break;                                                                  \
3034                                                                               \
3035     case 0x97:                                                                \
3036       /* LDMDB rn!, rlist^ */                                                 \
3037       arm_block_memory(load, down_b, down, yes);                              \
3038       break;                                                                  \
3039                                                                               \
3040     case 0x98:                                                                \
3041       /* STMIB rn, rlist */                                                   \
3042       arm_block_memory(store, up, no, no);                                    \
3043       break;                                                                  \
3044                                                                               \
3045     case 0x99:                                                                \
3046       /* LDMIB rn, rlist */                                                   \
3047       arm_block_memory(load, up, no, no);                                     \
3048       break;                                                                  \
3049                                                                               \
3050     case 0x9A:                                                                \
3051       /* STMIB rn!, rlist */                                                  \
3052       arm_block_memory(store, up, up, no);                                    \
3053       break;                                                                  \
3054                                                                               \
3055     case 0x9B:                                                                \
3056       /* LDMIB rn!, rlist */                                                  \
3057       arm_block_memory(load, up, up, no);                                     \
3058       break;                                                                  \
3059                                                                               \
3060     case 0x9C:                                                                \
3061       /* STMIB rn, rlist^ */                                                  \
3062       arm_block_memory(store, up, no, yes);                                   \
3063       break;                                                                  \
3064                                                                               \
3065     case 0x9D:                                                                \
3066       /* LDMIB rn, rlist^ */                                                  \
3067       arm_block_memory(load, up, no, yes);                                    \
3068       break;                                                                  \
3069                                                                               \
3070     case 0x9E:                                                                \
3071       /* STMIB rn!, rlist^ */                                                 \
3072       arm_block_memory(store, up, up, yes);                                   \
3073       break;                                                                  \
3074                                                                               \
3075     case 0x9F:                                                                \
3076       /* LDMIB rn!, rlist^ */                                                 \
3077       arm_block_memory(load, up, up, yes);                                    \
3078       break;                                                                  \
3079                                                                               \
3080     case 0xA0:                                                                \
3081     case 0xA1:                                                                \
3082     case 0xA2:                                                                \
3083     case 0xA3:                                                                \
3084     case 0xA4:                                                                \
3085     case 0xA5:                                                                \
3086     case 0xA6:                                                                \
3087     case 0xA7:                                                                \
3088     case 0xA8:                                                                \
3089     case 0xA9:                                                                \
3090     case 0xAA:                                                                \
3091     case 0xAB:                                                                \
3092     case 0xAC:                                                                \
3093     case 0xAD:                                                                \
3094     case 0xAE:                                                                \
3095     case 0xAF:                                                                \
3096     {                                                                         \
3097       /* B offset */                                                          \
3098       arm_decode_branch();                                                    \
3099       arm_pc_offset_update(offset + 8);                                       \
3100       break;                                                                  \
3101     }                                                                         \
3102                                                                               \
3103     case 0xB0 ... 0xBF:                                                       \
3104     {                                                                         \
3105       /* BL offset */                                                         \
3106       arm_decode_branch();                                                    \
3107       reg[REG_LR] = pc + 4;                                                   \
3108       arm_pc_offset_update(offset + 8);                                       \
3109       break;                                                                  \
3110     }                                                                         \
3111                                                                               \
3112     case 0xC0 ... 0xEF:                                                       \
3113       /* coprocessor instructions, reserved on GBA */                         \
3114       break;                                                                  \
3115                                                                               \
3116     case 0xF0 ... 0xFF:                                                       \
3117     {                                                                         \
3118       /* SWI comment */                                                       \
3119       u32 swi_comment = opcode & 0x00FFFFFF;                                  \
3120                                                                               \
3121       switch(swi_comment >> 16)                                               \
3122       {                                                                       \
3123         /* Jump to BIOS SWI handler */                                        \
3124         default:                                                              \
3125           reg_mode[MODE_SUPERVISOR][6] = pc + 4;                              \
3126           collapse_flags();                                                   \
3127           spsr[MODE_SUPERVISOR] = reg[REG_CPSR];                              \
3128           reg[REG_PC] = 0x00000008;                                           \
3129           arm_update_pc();                                                    \
3130           reg[REG_CPSR] = (reg[REG_CPSR] & ~0x1F) | 0x13;                     \
3131           set_cpu_mode(MODE_SUPERVISOR);                                      \
3132           break;                                                              \
3133       }                                                                       \
3134       break;                                                                  \
3135     }                                                                         \
3136   }                                                                           \
3137                                                                               \
3138   skip_instruction:                                                           \
3139
3140 #define execute_thumb_instruction()                                           \
3141   using_instruction(thumb);                                                   \
3142   check_pc_region();                                                          \
3143   pc &= ~0x01;                                                                \
3144   opcode = address16(pc_address_block, (pc & 0x7FFF));                        \
3145                                                                               \
3146   switch((opcode >> 8) & 0xFF)                                                \
3147   {                                                                           \
3148     case 0x00 ... 0x07:                                                       \
3149       /* LSL rd, rs, offset */                                                \
3150       thumb_shift(shift, lsl, imm);                                           \
3151       break;                                                                  \
3152                                                                               \
3153     case 0x08 ... 0x0F:                                                       \
3154       /* LSR rd, rs, offset */                                                \
3155       thumb_shift(shift, lsr, imm);                                           \
3156       break;                                                                  \
3157                                                                               \
3158     case 0x10 ... 0x17:                                                       \
3159       /* ASR rd, rs, offset */                                                \
3160       thumb_shift(shift, asr, imm);                                           \
3161       break;                                                                  \
3162                                                                               \
3163     case 0x18 ... 0x19:                                                       \
3164       /* ADD rd, rs, rn */                                                    \
3165       thumb_add(add_sub, rd, reg[rs], reg[rn]);                               \
3166       break;                                                                  \
3167                                                                               \
3168     case 0x1A ... 0x1B:                                                       \
3169       /* SUB rd, rs, rn */                                                    \
3170       thumb_sub(add_sub, rd, reg[rs], reg[rn]);                               \
3171       break;                                                                  \
3172                                                                               \
3173     case 0x1C ... 0x1D:                                                       \
3174       /* ADD rd, rs, imm */                                                   \
3175       thumb_add(add_sub_imm, rd, reg[rs], imm);                               \
3176       break;                                                                  \
3177                                                                               \
3178     case 0x1E ... 0x1F:                                                       \
3179       /* SUB rd, rs, imm */                                                   \
3180       thumb_sub(add_sub_imm, rd, reg[rs], imm);                               \
3181       break;                                                                  \
3182                                                                               \
3183     case 0x20:                                                                \
3184       /* MOV r0, imm */                                                       \
3185       thumb_logic(imm, 0, imm);                                               \
3186       break;                                                                  \
3187                                                                               \
3188     case 0x21:                                                                \
3189       /* MOV r1, imm */                                                       \
3190       thumb_logic(imm, 1, imm);                                               \
3191       break;                                                                  \
3192                                                                               \
3193     case 0x22:                                                                \
3194       /* MOV r2, imm */                                                       \
3195       thumb_logic(imm, 2, imm);                                               \
3196       break;                                                                  \
3197                                                                               \
3198     case 0x23:                                                                \
3199       /* MOV r3, imm */                                                       \
3200       thumb_logic(imm, 3, imm);                                               \
3201       break;                                                                  \
3202                                                                               \
3203     case 0x24:                                                                \
3204       /* MOV r4, imm */                                                       \
3205       thumb_logic(imm, 4, imm);                                               \
3206       break;                                                                  \
3207                                                                               \
3208     case 0x25:                                                                \
3209       /* MOV r5, imm */                                                       \
3210       thumb_logic(imm, 5, imm);                                               \
3211       break;                                                                  \
3212                                                                               \
3213     case 0x26:                                                                \
3214       /* MOV r6, imm */                                                       \
3215       thumb_logic(imm, 6, imm);                                               \
3216       break;                                                                  \
3217                                                                               \
3218     case 0x27:                                                                \
3219       /* MOV r7, imm */                                                       \
3220       thumb_logic(imm, 7, imm);                                               \
3221       break;                                                                  \
3222                                                                               \
3223     case 0x28:                                                                \
3224       /* CMP r0, imm */                                                       \
3225       thumb_test_sub(imm, reg[0], imm);                                       \
3226       break;                                                                  \
3227                                                                               \
3228     case 0x29:                                                                \
3229       /* CMP r1, imm */                                                       \
3230       thumb_test_sub(imm, reg[1], imm);                                       \
3231       break;                                                                  \
3232                                                                               \
3233     case 0x2A:                                                                \
3234       /* CMP r2, imm */                                                       \
3235       thumb_test_sub(imm, reg[2], imm);                                       \
3236       break;                                                                  \
3237                                                                               \
3238     case 0x2B:                                                                \
3239       /* CMP r3, imm */                                                       \
3240       thumb_test_sub(imm, reg[3], imm);                                       \
3241       break;                                                                  \
3242                                                                               \
3243     case 0x2C:                                                                \
3244       /* CMP r4, imm */                                                       \
3245       thumb_test_sub(imm, reg[4], imm);                                       \
3246       break;                                                                  \
3247                                                                               \
3248     case 0x2D:                                                                \
3249       /* CMP r5, imm */                                                       \
3250       thumb_test_sub(imm, reg[5], imm);                                       \
3251       break;                                                                  \
3252                                                                               \
3253     case 0x2E:                                                                \
3254       /* CMP r6, imm */                                                       \
3255       thumb_test_sub(imm, reg[6], imm);                                       \
3256       break;                                                                  \
3257                                                                               \
3258     case 0x2F:                                                                \
3259       /* CMP r7, imm */                                                       \
3260       thumb_test_sub(imm, reg[7], imm);                                       \
3261       break;                                                                  \
3262                                                                               \
3263     case 0x30:                                                                \
3264       /* ADD r0, imm */                                                       \
3265       thumb_add(imm, 0, reg[0], imm);                                         \
3266       break;                                                                  \
3267                                                                               \
3268     case 0x31:                                                                \
3269       /* ADD r1, imm */                                                       \
3270       thumb_add(imm, 1, reg[1], imm);                                         \
3271       break;                                                                  \
3272                                                                               \
3273     case 0x32:                                                                \
3274       /* ADD r2, imm */                                                       \
3275       thumb_add(imm, 2, reg[2], imm);                                         \
3276       break;                                                                  \
3277                                                                               \
3278     case 0x33:                                                                \
3279       /* ADD r3, imm */                                                       \
3280       thumb_add(imm, 3, reg[3], imm);                                         \
3281       break;                                                                  \
3282                                                                               \
3283     case 0x34:                                                                \
3284       /* ADD r4, imm */                                                       \
3285       thumb_add(imm, 4, reg[4], imm);                                         \
3286       break;                                                                  \
3287                                                                               \
3288     case 0x35:                                                                \
3289       /* ADD r5, imm */                                                       \
3290       thumb_add(imm, 5, reg[5], imm);                                         \
3291       break;                                                                  \
3292                                                                               \
3293     case 0x36:                                                                \
3294       /* ADD r6, imm */                                                       \
3295       thumb_add(imm, 6, reg[6], imm);                                         \
3296       break;                                                                  \
3297                                                                               \
3298     case 0x37:                                                                \
3299       /* ADD r7, imm */                                                       \
3300       thumb_add(imm, 7, reg[7], imm);                                         \
3301       break;                                                                  \
3302                                                                               \
3303     case 0x38:                                                                \
3304       /* SUB r0, imm */                                                       \
3305       thumb_sub(imm, 0, reg[0], imm);                                         \
3306       break;                                                                  \
3307                                                                               \
3308     case 0x39:                                                                \
3309       /* SUB r1, imm */                                                       \
3310       thumb_sub(imm, 1, reg[1], imm);                                         \
3311       break;                                                                  \
3312                                                                               \
3313     case 0x3A:                                                                \
3314       /* SUB r2, imm */                                                       \
3315       thumb_sub(imm, 2, reg[2], imm);                                         \
3316       break;                                                                  \
3317                                                                               \
3318     case 0x3B:                                                                \
3319       /* SUB r3, imm */                                                       \
3320       thumb_sub(imm, 3, reg[3], imm);                                         \
3321       break;                                                                  \
3322                                                                               \
3323     case 0x3C:                                                                \
3324       /* SUB r4, imm */                                                       \
3325       thumb_sub(imm, 4, reg[4], imm);                                         \
3326       break;                                                                  \
3327                                                                               \
3328     case 0x3D:                                                                \
3329       /* SUB r5, imm */                                                       \
3330       thumb_sub(imm, 5, reg[5], imm);                                         \
3331       break;                                                                  \
3332                                                                               \
3333     case 0x3E:                                                                \
3334       /* SUB r6, imm */                                                       \
3335       thumb_sub(imm, 6, reg[6], imm);                                         \
3336       break;                                                                  \
3337                                                                               \
3338     case 0x3F:                                                                \
3339       /* SUB r7, imm */                                                       \
3340       thumb_sub(imm, 7, reg[7], imm);                                         \
3341       break;                                                                  \
3342                                                                               \
3343     case 0x40:                                                                \
3344       switch((opcode >> 6) & 0x03)                                            \
3345       {                                                                       \
3346         case 0x00:                                                            \
3347           /* AND rd, rs */                                                    \
3348           thumb_logic(alu_op, rd, reg[rd] & reg[rs]);                         \
3349           break;                                                              \
3350                                                                               \
3351         case 0x01:                                                            \
3352           /* EOR rd, rs */                                                    \
3353           thumb_logic(alu_op, rd, reg[rd] ^ reg[rs]);                         \
3354           break;                                                              \
3355                                                                               \
3356         case 0x02:                                                            \
3357           /* LSL rd, rs */                                                    \
3358           thumb_shift(alu_op, lsl, reg);                                      \
3359           break;                                                              \
3360                                                                               \
3361         case 0x03:                                                            \
3362           /* LSR rd, rs */                                                    \
3363           thumb_shift(alu_op, lsr, reg);                                      \
3364           break;                                                              \
3365       }                                                                       \
3366       break;                                                                  \
3367                                                                               \
3368     case 0x41:                                                                \
3369       switch((opcode >> 6) & 0x03)                                            \
3370       {                                                                       \
3371         case 0x00:                                                            \
3372           /* ASR rd, rs */                                                    \
3373           thumb_shift(alu_op, asr, reg);                                      \
3374           break;                                                              \
3375                                                                               \
3376         case 0x01:                                                            \
3377           /* ADC rd, rs */                                                    \
3378           thumb_add(alu_op, rd, reg[rd] + reg[rs], c_flag);                   \
3379           break;                                                              \
3380                                                                               \
3381         case 0x02:                                                            \
3382           /* SBC rd, rs */                                                    \
3383           thumb_sub(alu_op, rd, reg[rd] - reg[rs], (c_flag ^ 1));             \
3384           break;                                                              \
3385                                                                               \
3386         case 0x03:                                                            \
3387           /* ROR rd, rs */                                                    \
3388           thumb_shift(alu_op, ror, reg);                                      \
3389           break;                                                              \
3390       }                                                                       \
3391       break;                                                                  \
3392                                                                               \
3393     case 0x42:                                                                \
3394       switch((opcode >> 6) & 0x03)                                            \
3395       {                                                                       \
3396         case 0x00:                                                            \
3397           /* TST rd, rs */                                                    \
3398           thumb_test_logic(alu_op, reg[rd] & reg[rs]);                        \
3399           break;                                                              \
3400                                                                               \
3401         case 0x01:                                                            \
3402           /* NEG rd, rs */                                                    \
3403           thumb_sub(alu_op, rd, 0, reg[rs]);                                  \
3404           break;                                                              \
3405                                                                               \
3406         case 0x02:                                                            \
3407           /* CMP rd, rs */                                                    \
3408           thumb_test_sub(alu_op, reg[rd], reg[rs]);                           \
3409           break;                                                              \
3410                                                                               \
3411         case 0x03:                                                            \
3412           /* CMN rd, rs */                                                    \
3413           thumb_test_add(alu_op, reg[rd], reg[rs]);                           \
3414           break;                                                              \
3415       }                                                                       \
3416       break;                                                                  \
3417                                                                               \
3418     case 0x43:                                                                \
3419       switch((opcode >> 6) & 0x03)                                            \
3420       {                                                                       \
3421         case 0x00:                                                            \
3422           /* ORR rd, rs */                                                    \
3423           thumb_logic(alu_op, rd, reg[rd] | reg[rs]);                         \
3424           break;                                                              \
3425                                                                               \
3426         case 0x01:                                                            \
3427           /* MUL rd, rs */                                                    \
3428           thumb_logic(alu_op, rd, reg[rd] * reg[rs]);                         \
3429           break;                                                              \
3430                                                                               \
3431         case 0x02:                                                            \
3432           /* BIC rd, rs */                                                    \
3433           thumb_logic(alu_op, rd, reg[rd] & (~reg[rs]));                      \
3434           break;                                                              \
3435                                                                               \
3436         case 0x03:                                                            \
3437           /* MVN rd, rs */                                                    \
3438           thumb_logic(alu_op, rd, ~reg[rs]);                                  \
3439           break;                                                              \
3440       }                                                                       \
3441       break;                                                                  \
3442                                                                               \
3443     case 0x44:                                                                \
3444       /* ADD rd, rs */                                                        \
3445       thumb_hireg_op(reg[rd] + reg[rs]);                                      \
3446       break;                                                                  \
3447                                                                               \
3448     case 0x45:                                                                \
3449       /* CMP rd, rs */                                                        \
3450       {                                                                       \
3451         thumb_pc_offset(4);                                                   \
3452         thumb_decode_hireg_op();                                              \
3453         u32 _sa = reg[rd];                                                    \
3454         u32 _sb = reg[rs];                                                    \
3455         u32 dest = _sa - _sb;                                                 \
3456         thumb_pc_offset(-2);                                                  \
3457         calculate_flags_sub(dest, _sa, _sb);                                  \
3458       }                                                                       \
3459       break;                                                                  \
3460                                                                               \
3461     case 0x46:                                                                \
3462       /* MOV rd, rs */                                                        \
3463       thumb_hireg_op(reg[rs]);                                                \
3464       break;                                                                  \
3465                                                                               \
3466     case 0x47:                                                                \
3467       /* BX rs */                                                             \
3468       {                                                                       \
3469         thumb_decode_hireg_op();                                              \
3470         u32 src;                                                              \
3471         thumb_pc_offset(4);                                                   \
3472         src = reg[rs];                                                        \
3473         if(src & 0x01)                                                        \
3474         {                                                                     \
3475           src -= 1;                                                           \
3476           thumb_pc_offset_update_direct(src);                                 \
3477         }                                                                     \
3478         else                                                                  \
3479         {                                                                     \
3480           /* Switch to ARM mode */                                            \
3481           thumb_pc_offset_update_direct(src);                                 \
3482           reg[REG_CPSR] &= ~0x20;                                             \
3483           collapse_flags();                                                   \
3484           goto arm_loop;                                                      \
3485         }                                                                     \
3486       }                                                                       \
3487       break;                                                                  \
3488                                                                               \
3489     case 0x48:                                                                \
3490       /* LDR r0, [pc + imm] */                                                \
3491       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[0], u32); \
3492       break;                                                                  \
3493                                                                               \
3494     case 0x49:                                                                \
3495       /* LDR r1, [pc + imm] */                                                \
3496       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[1], u32); \
3497       break;                                                                  \
3498                                                                               \
3499     case 0x4A:                                                                \
3500       /* LDR r2, [pc + imm] */                                                \
3501       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[2], u32); \
3502       break;                                                                  \
3503                                                                               \
3504     case 0x4B:                                                                \
3505       /* LDR r3, [pc + imm] */                                                \
3506       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[3], u32); \
3507       break;                                                                  \
3508                                                                               \
3509     case 0x4C:                                                                \
3510       /* LDR r4, [pc + imm] */                                                \
3511       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[4], u32); \
3512       break;                                                                  \
3513                                                                               \
3514     case 0x4D:                                                                \
3515       /* LDR r5, [pc + imm] */                                                \
3516       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[5], u32); \
3517       break;                                                                  \
3518                                                                               \
3519     case 0x4E:                                                                \
3520       /* LDR r6, [pc + imm] */                                                \
3521       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[6], u32); \
3522       break;                                                                  \
3523                                                                               \
3524     case 0x4F:                                                                \
3525       /* LDR r7, [pc + imm] */                                                \
3526       thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[7], u32); \
3527       break;                                                                  \
3528                                                                               \
3529     case 0x50 ... 0x51:                                                       \
3530       /* STR rd, [rb + ro] */                                                 \
3531       thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u32);   \
3532       break;                                                                  \
3533                                                                               \
3534     case 0x52 ... 0x53:                                                       \
3535       /* STRH rd, [rb + ro] */                                                \
3536       thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u16);   \
3537       break;                                                                  \
3538                                                                               \
3539     case 0x54 ... 0x55:                                                       \
3540       /* STRB rd, [rb + ro] */                                                \
3541       thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u8);    \
3542       break;                                                                  \
3543                                                                               \
3544     case 0x56 ... 0x57:                                                       \
3545       /* LDSB rd, [rb + ro] */                                                \
3546       thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s8);     \
3547       break;                                                                  \
3548                                                                               \
3549     case 0x58 ... 0x59:                                                       \
3550       /* LDR rd, [rb + ro] */                                                 \
3551       thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u32);    \
3552       break;                                                                  \
3553                                                                               \
3554     case 0x5A ... 0x5B:                                                       \
3555       /* LDRH rd, [rb + ro] */                                                \
3556       thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u16);    \
3557       break;                                                                  \
3558                                                                               \
3559     case 0x5C ... 0x5D:                                                       \
3560       /* LDRB rd, [rb + ro] */                                                \
3561       thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u8);     \
3562       break;                                                                  \
3563                                                                               \
3564     case 0x5E ... 0x5F:                                                       \
3565       /* LDSH rd, [rb + ro] */                                                \
3566       thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s16);    \
3567       break;                                                                  \
3568                                                                               \
3569     case 0x60 ... 0x67:                                                       \
3570       /* STR rd, [rb + imm] */                                                \
3571       thumb_access_memory(store, mem_imm, reg[rb] + (imm * 4), reg[rd], u32); \
3572       break;                                                                  \
3573                                                                               \
3574     case 0x68 ... 0x6F:                                                       \
3575       /* LDR rd, [rb + imm] */                                                \
3576       thumb_access_memory(load, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);  \
3577       break;                                                                  \
3578                                                                               \
3579     case 0x70 ... 0x77:                                                       \
3580       /* STRB rd, [rb + imm] */                                               \
3581       thumb_access_memory(store, mem_imm, reg[rb] + imm, reg[rd], u8);        \
3582       break;                                                                  \
3583                                                                               \
3584     case 0x78 ... 0x7F:                                                       \
3585       /* LDRB rd, [rb + imm] */                                               \
3586       thumb_access_memory(load, mem_imm, reg[rb] + imm, reg[rd], u8);         \
3587       break;                                                                  \
3588                                                                               \
3589     case 0x80 ... 0x87:                                                       \
3590       /* STRH rd, [rb + imm] */                                               \
3591       thumb_access_memory(store, mem_imm, reg[rb] + (imm * 2), reg[rd], u16); \
3592       break;                                                                  \
3593                                                                               \
3594     case 0x88 ... 0x8F:                                                       \
3595       /* LDRH rd, [rb + imm] */                                               \
3596       thumb_access_memory(load, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);  \
3597       break;                                                                  \
3598                                                                               \
3599     case 0x90:                                                                \
3600       /* STR r0, [sp + imm] */                                                \
3601       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[0], u32);  \
3602       break;                                                                  \
3603                                                                               \
3604     case 0x91:                                                                \
3605       /* STR r1, [sp + imm] */                                                \
3606       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[1], u32);  \
3607       break;                                                                  \
3608                                                                               \
3609     case 0x92:                                                                \
3610       /* STR r2, [sp + imm] */                                                \
3611       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[2], u32);  \
3612       break;                                                                  \
3613                                                                               \
3614     case 0x93:                                                                \
3615       /* STR r3, [sp + imm] */                                                \
3616       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[3], u32);  \
3617       break;                                                                  \
3618                                                                               \
3619     case 0x94:                                                                \
3620       /* STR r4, [sp + imm] */                                                \
3621       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[4], u32);  \
3622       break;                                                                  \
3623                                                                               \
3624     case 0x95:                                                                \
3625       /* STR r5, [sp + imm] */                                                \
3626       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[5], u32);  \
3627       break;                                                                  \
3628                                                                               \
3629     case 0x96:                                                                \
3630       /* STR r6, [sp + imm] */                                                \
3631       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[6], u32);  \
3632       break;                                                                  \
3633                                                                               \
3634     case 0x97:                                                                \
3635       /* STR r7, [sp + imm] */                                                \
3636       thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[7], u32);  \
3637       break;                                                                  \
3638                                                                               \
3639     case 0x98:                                                                \
3640       /* LDR r0, [sp + imm] */                                                \
3641       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[0], u32);   \
3642       break;                                                                  \
3643                                                                               \
3644     case 0x99:                                                                \
3645       /* LDR r1, [sp + imm] */                                                \
3646       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[1], u32);   \
3647       break;                                                                  \
3648                                                                               \
3649     case 0x9A:                                                                \
3650       /* LDR r2, [sp + imm] */                                                \
3651       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[2], u32);   \
3652       break;                                                                  \
3653                                                                               \
3654     case 0x9B:                                                                \
3655       /* LDR r3, [sp + imm] */                                                \
3656       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[3], u32);   \
3657       break;                                                                  \
3658                                                                               \
3659     case 0x9C:                                                                \
3660       /* LDR r4, [sp + imm] */                                                \
3661       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[4], u32);   \
3662       break;                                                                  \
3663                                                                               \
3664     case 0x9D:                                                                \
3665       /* LDR r5, [sp + imm] */                                                \
3666       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[5], u32);   \
3667       break;                                                                  \
3668                                                                               \
3669     case 0x9E:                                                                \
3670       /* LDR r6, [sp + imm] */                                                \
3671       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[6], u32);   \
3672       break;                                                                  \
3673                                                                               \
3674     case 0x9F:                                                                \
3675       /* LDR r7, [sp + imm] */                                                \
3676       thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[7], u32);   \
3677       break;                                                                  \
3678                                                                               \
3679     case 0xA0:                                                                \
3680       /* ADD r0, pc, +imm */                                                  \
3681       thumb_add_noflags(imm, 0, (pc & ~2) + 4, (imm * 4));                    \
3682       break;                                                                  \
3683                                                                               \
3684     case 0xA1:                                                                \
3685       /* ADD r1, pc, +imm */                                                  \
3686       thumb_add_noflags(imm, 1, (pc & ~2) + 4, (imm * 4));                    \
3687       break;                                                                  \
3688                                                                               \
3689     case 0xA2:                                                                \
3690       /* ADD r2, pc, +imm */                                                  \
3691       thumb_add_noflags(imm, 2, (pc & ~2) + 4, (imm * 4));                    \
3692       break;                                                                  \
3693                                                                               \
3694     case 0xA3:                                                                \
3695       /* ADD r3, pc, +imm */                                                  \
3696       thumb_add_noflags(imm, 3, (pc & ~2) + 4, (imm * 4));                    \
3697       break;                                                                  \
3698                                                                               \
3699     case 0xA4:                                                                \
3700       /* ADD r4, pc, +imm */                                                  \
3701       thumb_add_noflags(imm, 4, (pc & ~2) + 4, (imm * 4));                    \
3702       break;                                                                  \
3703                                                                               \
3704     case 0xA5:                                                                \
3705       /* ADD r5, pc, +imm */                                                  \
3706       thumb_add_noflags(imm, 5, (pc & ~2) + 4, (imm * 4));                    \
3707       break;                                                                  \
3708                                                                               \
3709     case 0xA6:                                                                \
3710       /* ADD r6, pc, +imm */                                                  \
3711       thumb_add_noflags(imm, 6, (pc & ~2) + 4, (imm * 4));                    \
3712       break;                                                                  \
3713                                                                               \
3714     case 0xA7:                                                                \
3715       /* ADD r7, pc, +imm */                                                  \
3716       thumb_add_noflags(imm, 7, (pc & ~2) + 4, (imm * 4));                    \
3717       break;                                                                  \
3718                                                                               \
3719     case 0xA8:                                                                \
3720       /* ADD r0, sp, +imm */                                                  \
3721       thumb_add_noflags(imm, 0, reg[REG_SP], (imm * 4));                      \
3722       break;                                                                  \
3723                                                                               \
3724     case 0xA9:                                                                \
3725       /* ADD r1, sp, +imm */                                                  \
3726       thumb_add_noflags(imm, 1, reg[REG_SP], (imm * 4));                      \
3727       break;                                                                  \
3728                                                                               \
3729     case 0xAA:                                                                \
3730       /* ADD r2, sp, +imm */                                                  \
3731       thumb_add_noflags(imm, 2, reg[REG_SP], (imm * 4));                      \
3732       break;                                                                  \
3733                                                                               \
3734     case 0xAB:                                                                \
3735       /* ADD r3, sp, +imm */                                                  \
3736       thumb_add_noflags(imm, 3, reg[REG_SP], (imm * 4));                      \
3737       break;                                                                  \
3738                                                                               \
3739     case 0xAC:                                                                \
3740       /* ADD r4, sp, +imm */                                                  \
3741       thumb_add_noflags(imm, 4, reg[REG_SP], (imm * 4));                      \
3742       break;                                                                  \
3743                                                                               \
3744     case 0xAD:                                                                \
3745       /* ADD r5, sp, +imm */                                                  \
3746       thumb_add_noflags(imm, 5, reg[REG_SP], (imm * 4));                      \
3747       break;                                                                  \
3748                                                                               \
3749     case 0xAE:                                                                \
3750       /* ADD r6, sp, +imm */                                                  \
3751       thumb_add_noflags(imm, 6, reg[REG_SP], (imm * 4));                      \
3752       break;                                                                  \
3753                                                                               \
3754     case 0xAF:                                                                \
3755       /* ADD r7, sp, +imm */                                                  \
3756       thumb_add_noflags(imm, 7, reg[REG_SP], (imm * 4));                      \
3757       break;                                                                  \
3758                                                                               \
3759     case 0xB0 ... 0xB3:                                                       \
3760       if((opcode >> 7) & 0x01)                                                \
3761       {                                                                       \
3762         /* ADD sp, -imm */                                                    \
3763         thumb_add_noflags(add_sp, 13, reg[REG_SP], -(imm * 4));               \
3764       }                                                                       \
3765       else                                                                    \
3766       {                                                                       \
3767         /* ADD sp, +imm */                                                    \
3768         thumb_add_noflags(add_sp, 13, reg[REG_SP], (imm * 4));                \
3769       }                                                                       \
3770       break;                                                                  \
3771                                                                               \
3772     case 0xB4:                                                                \
3773       /* PUSH rlist */                                                        \
3774       thumb_block_memory(store, down, no_op, 13);                             \
3775       break;                                                                  \
3776                                                                               \
3777     case 0xB5:                                                                \
3778       /* PUSH rlist, lr */                                                    \
3779       thumb_block_memory(store, push_lr, push_lr, 13);                        \
3780       break;                                                                  \
3781                                                                               \
3782     case 0xBC:                                                                \
3783       /* POP rlist */                                                         \
3784       thumb_block_memory(load, no_op, up, 13);                                \
3785       break;                                                                  \
3786                                                                               \
3787     case 0xBD:                                                                \
3788       /* POP rlist, pc */                                                     \
3789       thumb_block_memory(load, no_op, pop_pc, 13);                            \
3790       break;                                                                  \
3791                                                                               \
3792     case 0xC0:                                                                \
3793       /* STMIA r0!, rlist */                                                  \
3794       thumb_block_memory(store, no_op, up, 0);                                \
3795       break;                                                                  \
3796                                                                               \
3797     case 0xC1:                                                                \
3798       /* STMIA r1!, rlist */                                                  \
3799       thumb_block_memory(store, no_op, up, 1);                                \
3800       break;                                                                  \
3801                                                                               \
3802     case 0xC2:                                                                \
3803       /* STMIA r2!, rlist */                                                  \
3804       thumb_block_memory(store, no_op, up, 2);                                \
3805       break;                                                                  \
3806                                                                               \
3807     case 0xC3:                                                                \
3808       /* STMIA r3!, rlist */                                                  \
3809       thumb_block_memory(store, no_op, up, 3);                                \
3810       break;                                                                  \
3811                                                                               \
3812     case 0xC4:                                                                \
3813       /* STMIA r4!, rlist */                                                  \
3814       thumb_block_memory(store, no_op, up, 4);                                \
3815       break;                                                                  \
3816                                                                               \
3817     case 0xC5:                                                                \
3818       /* STMIA r5!, rlist */                                                  \
3819       thumb_block_memory(store, no_op, up, 5);                                \
3820       break;                                                                  \
3821                                                                               \
3822     case 0xC6:                                                                \
3823       /* STMIA r6!, rlist */                                                  \
3824       thumb_block_memory(store, no_op, up, 6);                                \
3825       break;                                                                  \
3826                                                                               \
3827     case 0xC7:                                                                \
3828       /* STMIA r7!, rlist */                                                  \
3829       thumb_block_memory(store, no_op, up, 7);                                \
3830       break;                                                                  \
3831                                                                               \
3832     case 0xC8:                                                                \
3833       /* LDMIA r0!, rlist */                                                  \
3834       thumb_block_memory(load, no_op, up, 0);                                 \
3835       break;                                                                  \
3836                                                                               \
3837     case 0xC9:                                                                \
3838       /* LDMIA r1!, rlist */                                                  \
3839       thumb_block_memory(load, no_op, up, 1);                                 \
3840       break;                                                                  \
3841                                                                               \
3842     case 0xCA:                                                                \
3843       /* LDMIA r2!, rlist */                                                  \
3844       thumb_block_memory(load, no_op, up, 2);                                 \
3845       break;                                                                  \
3846                                                                               \
3847     case 0xCB:                                                                \
3848       /* LDMIA r3!, rlist */                                                  \
3849       thumb_block_memory(load, no_op, up, 3);                                 \
3850       break;                                                                  \
3851                                                                               \
3852     case 0xCC:                                                                \
3853       /* LDMIA r4!, rlist */                                                  \
3854       thumb_block_memory(load, no_op, up, 4);                                 \
3855       break;                                                                  \
3856                                                                               \
3857     case 0xCD:                                                                \
3858       /* LDMIA r5!, rlist */                                                  \
3859       thumb_block_memory(load, no_op, up, 5);                                 \
3860       break;                                                                  \
3861                                                                               \
3862     case 0xCE:                                                                \
3863       /* LDMIA r6!, rlist */                                                  \
3864       thumb_block_memory(load, no_op, up, 6);                                 \
3865       break;                                                                  \
3866                                                                               \
3867     case 0xCF:                                                                \
3868       /* LDMIA r7!, rlist */                                                  \
3869       thumb_block_memory(load, no_op, up, 7);                                 \
3870       break;                                                                  \
3871                                                                               \
3872     case 0xD0:                                                                \
3873       /* BEQ label */                                                         \
3874       thumb_conditional_branch(z_flag == 1);                                  \
3875       break;                                                                  \
3876                                                                               \
3877     case 0xD1:                                                                \
3878       /* BNE label */                                                         \
3879       thumb_conditional_branch(z_flag == 0);                                  \
3880       break;                                                                  \
3881                                                                               \
3882     case 0xD2:                                                                \
3883       /* BCS label */                                                         \
3884       thumb_conditional_branch(c_flag == 1);                                  \
3885       break;                                                                  \
3886                                                                               \
3887     case 0xD3:                                                                \
3888       /* BCC label */                                                         \
3889       thumb_conditional_branch(c_flag == 0);                                  \
3890       break;                                                                  \
3891                                                                               \
3892     case 0xD4:                                                                \
3893       /* BMI label */                                                         \
3894       thumb_conditional_branch(n_flag == 1);                                  \
3895       break;                                                                  \
3896                                                                               \
3897     case 0xD5:                                                                \
3898       /* BPL label */                                                         \
3899       thumb_conditional_branch(n_flag == 0);                                  \
3900       break;                                                                  \
3901                                                                               \
3902     case 0xD6:                                                                \
3903       /* BVS label */                                                         \
3904       thumb_conditional_branch(v_flag == 1);                                  \
3905       break;                                                                  \
3906                                                                               \
3907     case 0xD7:                                                                \
3908       /* BVC label */                                                         \
3909       thumb_conditional_branch(v_flag == 0);                                  \
3910       break;                                                                  \
3911                                                                               \
3912     case 0xD8:                                                                \
3913       /* BHI label */                                                         \
3914       thumb_conditional_branch(c_flag & (z_flag ^ 1));                        \
3915       break;                                                                  \
3916                                                                               \
3917     case 0xD9:                                                                \
3918       /* BLS label */                                                         \
3919       thumb_conditional_branch((c_flag == 0) | z_flag);                       \
3920       break;                                                                  \
3921                                                                               \
3922     case 0xDA:                                                                \
3923       /* BGE label */                                                         \
3924       thumb_conditional_branch(n_flag == v_flag);                             \
3925       break;                                                                  \
3926                                                                               \
3927     case 0xDB:                                                                \
3928       /* BLT label */                                                         \
3929       thumb_conditional_branch(n_flag != v_flag);                             \
3930       break;                                                                  \
3931                                                                               \
3932     case 0xDC:                                                                \
3933       /* BGT label */                                                         \
3934       thumb_conditional_branch((z_flag == 0) & (n_flag == v_flag));           \
3935       break;                                                                  \
3936                                                                               \
3937     case 0xDD:                                                                \
3938       /* BLE label */                                                         \
3939       thumb_conditional_branch(z_flag | (n_flag != v_flag));                  \
3940       break;                                                                  \
3941                                                                               \
3942     case 0xDF:                                                                \
3943     {                                                                         \
3944       /* SWI comment */                                                       \
3945       u32 swi_comment = opcode & 0xFF;                                        \
3946                                                                               \
3947       switch(swi_comment)                                                     \
3948       {                                                                       \
3949         default:                                                              \
3950           reg_mode[MODE_SUPERVISOR][6] = pc + 2;                              \
3951           spsr[MODE_SUPERVISOR] = reg[REG_CPSR];                              \
3952           reg[REG_PC] = 0x00000008;                                           \
3953           thumb_update_pc();                                                  \
3954           reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13;                     \
3955           set_cpu_mode(MODE_SUPERVISOR);                                      \
3956           collapse_flags();                                                   \
3957           goto arm_loop;                                                      \
3958       }                                                                       \
3959       break;                                                                  \
3960     }                                                                         \
3961                                                                               \
3962     case 0xE0 ... 0xE7:                                                       \
3963     {                                                                         \
3964       /* B label */                                                           \
3965       thumb_decode_branch();                                                  \
3966       thumb_pc_offset_update(((s32)(offset << 21) >> 20) + 4);                \
3967       break;                                                                  \
3968     }                                                                         \
3969                                                                               \
3970     case 0xF0 ... 0xF7:                                                       \
3971     {                                                                         \
3972       /* (low word) BL label */                                               \
3973       thumb_decode_branch();                                                  \
3974       reg[REG_LR] = pc + 4 + ((s32)(offset << 21) >> 9);                      \
3975       thumb_pc_offset(2);                                                     \
3976       break;                                                                  \
3977     }                                                                         \
3978                                                                               \
3979     case 0xF8 ... 0xFF:                                                       \
3980     {                                                                         \
3981       /* (high word) BL label */                                              \
3982       thumb_decode_branch();                                                  \
3983       u32 lr = (pc + 2) | 0x01;                                               \
3984       pc = reg[REG_LR] + (offset * 2);                                        \
3985       reg[REG_LR] = lr;                                                       \
3986       reg[REG_PC] = pc;                                                       \
3987       break;                                                                  \
3988     }                                                                         \
3989   }                                                                           \
3990
3991 void print_arm_registers()
3992 {
3993   u32 i, i2, i3;
3994
3995   for(i = 0, i3 = 0; i < 4; i++)
3996   {
3997     debug_screen_printf(" ");
3998     for(i2 = 0; i2 < 4; i2++, i3++)
3999     {
4000       debug_screen_printf("R%02d %08x ", i3, reg[i3]);
4001     }
4002     debug_screen_newline(1);
4003   }
4004 }
4005
4006 void print_thumb_instruction()
4007 {
4008   debug_screen_printf("Thumb instruction at PC: %04x",
4009    read_memory16(reg[REG_PC]));
4010   debug_screen_newline(1);
4011 }
4012
4013 void print_arm_instruction()
4014 {
4015   debug_screen_printf("ARM instruction at PC: %08x",
4016    read_memory32(reg[REG_PC]));
4017   debug_screen_newline(1);
4018 }
4019
4020 void print_flags()
4021 {
4022   u32 cpsr = reg[REG_CPSR];
4023   debug_screen_newline(1);
4024   debug_screen_printf(
4025    " N: %d  Z: %d  C: %d  V: %d  CPSR: %08x  SPSR: %08x  mode: %s",
4026    (cpsr >> 31) & 0x01, (cpsr >> 30) & 0x01, (cpsr >> 29) & 0x01,
4027    (cpsr >> 28) & 0x01, cpsr, spsr[reg[CPU_MODE]],
4028    cpu_mode_names[reg[CPU_MODE]]);
4029   debug_screen_newline(2);
4030 }
4031
4032 const u32 stack_print_lines = 2;
4033
4034 void print_stack()
4035 {
4036   u32 i, i2, i3;
4037
4038   debug_screen_printf("Stack:");
4039   debug_screen_newline(1);
4040
4041   for(i = 0, i3 = reg[REG_SP]; i < stack_print_lines; i++)
4042   {
4043     for(i2 = 0; i2 < 5; i2++, i3 += 4)
4044     {
4045       debug_screen_printf(" %08x", read_memory32(i3));
4046     }
4047     if(i != stack_print_lines)
4048       debug_screen_newline(1);
4049   }
4050
4051   debug_screen_newline(1);
4052 }
4053
4054 u32 instruction_count = 0;
4055
4056 u32 output_field = 0;
4057 const u32 num_output_fields = 2;
4058
4059 u32 last_instruction = 0;
4060
4061 u32 in_interrupt = 0;
4062
4063 void debug_on()
4064 {
4065   current_debug_state = STEP;
4066   debug_screen_start();
4067 }
4068
4069 void debug_off(debug_state new_debug_state)
4070 {
4071   current_debug_state = new_debug_state;
4072   debug_screen_end();
4073 }
4074
4075 void function_cc step_debug(u32 pc, u32 cycles)
4076 {
4077   u32 thumb = 0;
4078
4079   reg[REG_PC] = pc;
4080
4081   if(reg[REG_CPSR] & 0x20)
4082     thumb = 1;
4083
4084   instruction_count++;
4085
4086   switch(current_debug_state)
4087   {
4088     case PC_BREAKPOINT:
4089       if(reg[REG_PC] == breakpoint_value)
4090         debug_on();
4091
4092       break;
4093
4094     case Z_BREAKPOINT:
4095       if(reg[REG_Z_FLAG] == 1)
4096         debug_on();
4097
4098       break;
4099
4100     case VCOUNT_BREAKPOINT:
4101       if(io_registers[REG_VCOUNT] == breakpoint_value)
4102         debug_on();
4103
4104       break;
4105
4106     case COUNTDOWN_BREAKPOINT:
4107       if(breakpoint_value == 0)
4108         debug_on();
4109       else
4110         breakpoint_value--;
4111
4112       break;
4113
4114     case COUNTDOWN_BREAKPOINT_B:
4115       if(breakpoint_value == instruction_count)
4116         debug_on();
4117
4118       break;
4119
4120     case COUNTDOWN_BREAKPOINT_C:
4121     {
4122       if(pc == 0x18)
4123         in_interrupt++;
4124
4125       if((breakpoint_value == 0) && (in_interrupt == 0))
4126       {
4127         debug_on();
4128       }
4129       else
4130
4131       if(in_interrupt == 0)
4132         breakpoint_value--;
4133
4134       if(in_interrupt && (pc == 0x13c))
4135         in_interrupt--;
4136
4137       break;
4138     }
4139
4140     default:
4141       break;
4142   }
4143
4144   if((current_debug_state == STEP) ||
4145    (current_debug_state == STEP_RUN))
4146   {
4147     u32 key = 0;
4148
4149     SDL_LockMutex(sound_mutex);
4150     SDL_PauseAudio(1);
4151
4152     if(output_field >= num_output_fields)
4153     {
4154       output_field = 0;
4155       debug_screen_clear();
4156     }
4157
4158     if(thumb)
4159       print_thumb_instruction(cycles);
4160     else
4161       print_arm_instruction(cycles);
4162
4163     print_arm_registers();
4164     print_flags();
4165     print_stack();
4166
4167
4168     printf("%x instructions in, VCOUNT %d, cycles remaining: %d \n",
4169      instruction_count, io_registers[REG_VCOUNT], cycles);
4170
4171     debug_screen_update();
4172     output_field++;
4173
4174     if(current_debug_state != STEP_RUN)
4175     {
4176
4177 #ifdef STDIO_DEBUG
4178       key = getchar();
4179 #else
4180
4181       gui_action_type next_input = CURSOR_NONE;
4182       while(next_input == CURSOR_NONE)
4183       {
4184         next_input = get_gui_input();
4185
4186         switch(next_input)
4187         {
4188           case CURSOR_BACK:
4189             key = 'b';
4190             break;
4191
4192           case CURSOR_UP:
4193             key = 'r';
4194             break;
4195
4196           case CURSOR_EXIT:
4197             key = 'q';
4198             break;
4199
4200           default:
4201             key = 'n';
4202             break;
4203         }
4204       }
4205 #endif
4206     }
4207
4208     switch(key)
4209     {
4210       case 'd':
4211         dump_translation_cache();
4212         break;
4213
4214       case 'z':
4215         debug_off(Z_BREAKPOINT);
4216         break;
4217
4218 #ifdef STDIO_DEBUG
4219       case 'x':
4220         printf("break at PC (hex): ");
4221         scanf("%08x", &breakpoint_value);
4222         debug_off(PC_BREAKPOINT);
4223         break;
4224
4225       case 'c':
4226         printf("break after N instructions (hex): ");
4227         scanf("%08x", &breakpoint_value);
4228         breakpoint_value -= 1;
4229         debug_off(COUNTDOWN_BREAKPOINT);
4230         break;
4231
4232       case 'f':
4233         printf("break after N instructions, skip in IRQ (hex): ");
4234         scanf("%08x", &breakpoint_value);
4235         breakpoint_value -= 1;
4236         debug_off(COUNTDOWN_BREAKPOINT_C);
4237         break;
4238
4239       case 'g':
4240         printf("break after N instructions (since start): ");
4241         scanf("%d", &breakpoint_value);
4242         debug_off(COUNTDOWN_BREAKPOINT_B);
4243         break;
4244
4245       case 'v':
4246         printf("break at VCOUNT: ");
4247         scanf("%d", &breakpoint_value);
4248         debug_off(VCOUNT_BREAKPOINT);
4249         break;
4250 #endif
4251
4252       case 's':
4253         current_debug_state = STEP_RUN;
4254         break;
4255
4256       case 'r':
4257         debug_off(RUN);
4258         break;
4259
4260       case 'b':
4261         debug_off(PC_BREAKPOINT);
4262         break;
4263
4264       case 't':
4265         global_cycles_per_instruction = 0;
4266         debug_off(RUN);
4267         break;
4268
4269       case 'a':
4270       {
4271         char current_savestate_filename[512];
4272         u16 *current_screen = copy_screen();
4273         get_savestate_filename_noshot(savestate_slot,
4274          current_savestate_filename);
4275         save_state(current_savestate_filename, current_screen);
4276         free(current_screen);
4277         break;
4278       }
4279
4280       case 'q':
4281         quit();
4282     }
4283
4284     SDL_PauseAudio(0);
4285     SDL_UnlockMutex(sound_mutex);
4286   }
4287
4288   last_instruction = reg[REG_PC];
4289
4290   if(thumb)
4291     reg[REG_PC] = pc + 2;
4292   else
4293     reg[REG_PC] = pc + 4;
4294 }
4295
4296 void set_cpu_mode(cpu_mode_type new_mode)
4297 {
4298   u32 i;
4299   cpu_mode_type cpu_mode = reg[CPU_MODE];
4300
4301   if(cpu_mode != new_mode)
4302   {
4303     if(new_mode == MODE_FIQ)
4304     {
4305       for(i = 8; i < 15; i++)
4306       {
4307         reg_mode[cpu_mode][i - 8] = reg[i];
4308       }
4309     }
4310     else
4311     {
4312       reg_mode[cpu_mode][5] = reg[REG_SP];
4313       reg_mode[cpu_mode][6] = reg[REG_LR];
4314     }
4315
4316     if(cpu_mode == MODE_FIQ)
4317     {
4318       for(i = 8; i < 15; i++)
4319       {
4320         reg[i] = reg_mode[new_mode][i - 8];
4321       }
4322     }
4323     else
4324     {
4325       reg[REG_SP] = reg_mode[new_mode][5];
4326       reg[REG_LR] = reg_mode[new_mode][6];
4327     }
4328
4329     reg[CPU_MODE] = new_mode;
4330   }
4331 }
4332
4333 void raise_interrupt(irq_type irq_raised)
4334 {
4335   // The specific IRQ must be enabled in IE, master IRQ enable must be on,
4336   // and it must be on in the flags.
4337   io_registers[REG_IF] |= irq_raised;
4338
4339   if((io_registers[REG_IE] & irq_raised) && io_registers[REG_IME] &&
4340    ((reg[REG_CPSR] & 0x80) == 0))
4341   {
4342     bios_read_protect = 0xe55ec002;
4343
4344     // Interrupt handler in BIOS
4345     reg_mode[MODE_IRQ][6] = reg[REG_PC] + 4;
4346     spsr[MODE_IRQ] = reg[REG_CPSR];
4347     reg[REG_CPSR] = 0xD2;
4348     reg[REG_PC] = 0x00000018;
4349
4350     bios_region_read_allow();
4351
4352     set_cpu_mode(MODE_IRQ);
4353     reg[CPU_HALT_STATE] = CPU_ACTIVE;
4354     reg[CHANGED_PC_STATUS] = 1;
4355   }
4356 }
4357
4358 void execute_arm(u32 cycles)
4359 {
4360   u32 pc = reg[REG_PC];
4361   u32 opcode;
4362   u32 condition;
4363   u32 n_flag, z_flag, c_flag, v_flag;
4364   u32 pc_region = (pc >> 15);
4365   u8 *pc_address_block = memory_map_read[pc_region];
4366   u32 new_pc_region;
4367   s32 cycles_remaining;
4368   u32 cycles_per_instruction = global_cycles_per_instruction;
4369   cpu_alert_type cpu_alert;
4370
4371   u32 old_pc;
4372
4373   if(pc_address_block == NULL)
4374     pc_address_block = load_gamepak_page(pc_region & 0x3FF);
4375
4376   while(1)
4377   {
4378     cycles_remaining = cycles;
4379     pc = reg[REG_PC];
4380     extract_flags();
4381
4382     if(reg[REG_CPSR] & 0x20)
4383       goto thumb_loop;
4384
4385     do
4386     {
4387       arm_loop:
4388
4389       collapse_flags();
4390       step_debug(pc, cycles_remaining);
4391       cycles_per_instruction = global_cycles_per_instruction;
4392
4393       old_pc = pc;
4394       execute_arm_instruction();
4395       cycles_remaining -= cycles_per_instruction;
4396     } while(cycles_remaining > 0);
4397
4398     collapse_flags();
4399     cycles = update_gba();
4400     continue;
4401
4402     do
4403     {
4404       thumb_loop:
4405
4406       collapse_flags();
4407       step_debug(pc, cycles_remaining);
4408
4409       old_pc = pc;
4410       execute_thumb_instruction();
4411       cycles_remaining -= cycles_per_instruction;
4412     } while(cycles_remaining > 0);
4413
4414     collapse_flags();
4415     cycles = update_gba();
4416     continue;
4417
4418     alert:
4419
4420     if(cpu_alert == CPU_ALERT_IRQ)
4421     {
4422       cycles = cycles_remaining;
4423     }
4424     else
4425     {
4426       collapse_flags();
4427
4428       while(reg[CPU_HALT_STATE] != CPU_ACTIVE)
4429       {
4430         cycles = update_gba();
4431       }
4432     }
4433   }
4434 }
4435
4436 void init_cpu()
4437 {
4438   u32 i;
4439
4440   for(i = 0; i < 16; i++)
4441   {
4442     reg[i] = 0;
4443   }
4444
4445   reg[REG_SP] = 0x03007F00;
4446   reg[REG_PC] = 0x08000000;
4447   reg[REG_CPSR] = 0x0000001F;
4448   reg[CPU_HALT_STATE] = CPU_ACTIVE;
4449   reg[CPU_MODE] = MODE_USER;
4450   reg[CHANGED_PC_STATUS] = 0;
4451
4452   reg_mode[MODE_USER][5] = 0x03007F00;
4453   reg_mode[MODE_IRQ][5] = 0x03007FA0;
4454   reg_mode[MODE_FIQ][5] = 0x03007FA0;
4455   reg_mode[MODE_SUPERVISOR][5] = 0x03007FE0;
4456 }
4457
4458 void move_reg(u32 *new_reg)
4459 {
4460   u32 i;
4461
4462   for(i = 0; i < 32; i++)
4463   {
4464     new_reg[i] = reg[i];
4465   }
4466
4467   reg = new_reg;
4468 }
4469
4470
4471 #define cpu_savestate_builder(type)                                           \
4472 void cpu_##type##_savestate(file_tag_type savestate_file)                     \
4473 {                                                                             \
4474   file_##type(savestate_file, reg, 0x100);                                    \
4475   file_##type##_array(savestate_file, spsr);                                  \
4476   file_##type##_array(savestate_file, reg_mode);                              \
4477 }                                                                             \
4478
4479 cpu_savestate_builder(read);
4480 cpu_savestate_builder(write_mem);
4481