1 // -*- C++ -*-
2 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
3 // Copyright (C) 1999-2003 Forgotten
4 // Copyright (C) 2004 Forgotten and the VBA development team
5 
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or(at your option)
9 // any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 #ifdef BKPT_SUPPORT
21 #define CONSOLE_OUTPUT(a,b) \
22     extern void (*dbgOutput)(char *, u32);\
23     if((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) {\
24       dbgOutput((a), (b));\
25     }
26 #else
27 #define CONSOLE_OUTPUT(a,b)
28 #endif
29 
30 #define OP_AND \
31       reg[dest].I = reg[(opcode>>16)&15].I & value;\
32       CONSOLE_OUTPUT(NULL,reg[2].I);
33 
34 #define OP_ANDS \
35       reg[dest].I = reg[(opcode>>16)&15].I & value;\
36       \
37       N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
38       Z_FLAG = (reg[dest].I) ? false : true;\
39       C_FLAG = C_OUT;
40 
41 #define OP_EOR \
42       reg[dest].I = reg[(opcode>>16)&15].I ^ value;
43 
44 #define OP_EORS \
45       reg[dest].I = reg[(opcode>>16)&15].I ^ value;\
46       \
47       N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
48       Z_FLAG = (reg[dest].I) ? false : true;\
49       C_FLAG = C_OUT;
50 #ifdef C_CORE
51 #define NEG(i) ((i) >> 31)
52 #define POS(i) ((~(i)) >> 31)
53 #define ADDCARRY(a, b, c) \
54   C_FLAG = ((NEG(a) & NEG(b)) |\
55             (NEG(a) & POS(c)) |\
56             (NEG(b) & POS(c))) ? true : false;
57 #define ADDOVERFLOW(a, b, c) \
58   V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
59             (POS(a) & POS(b) & NEG(c))) ? true : false;
60 #define SUBCARRY(a, b, c) \
61   C_FLAG = ((NEG(a) & POS(b)) |\
62             (NEG(a) & POS(c)) |\
63             (POS(b) & POS(c))) ? true : false;
64 #define SUBOVERFLOW(a, b, c)\
65   V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
66             (POS(a) & NEG(b) & NEG(c))) ? true : false;
67 #define OP_SUB \
68     {\
69       reg[dest].I = reg[base].I - value;\
70     }
71 #define OP_SUBS \
72    {\
73      u32 lhs = reg[base].I;\
74      u32 rhs = value;\
75      u32 res = lhs - rhs;\
76      reg[dest].I = res;\
77      Z_FLAG = (res == 0) ? true : false;\
78      N_FLAG = NEG(res) ? true : false;\
79      SUBCARRY(lhs, rhs, res);\
80      SUBOVERFLOW(lhs, rhs, res);\
81    }
82 #define OP_RSB \
83     {\
84       reg[dest].I = value - reg[base].I;\
85     }
86 #define OP_RSBS \
87    {\
88      u32 lhs = reg[base].I;\
89      u32 rhs = value;\
90      u32 res = rhs - lhs;\
91      reg[dest].I = res;\
92      Z_FLAG = (res == 0) ? true : false;\
93      N_FLAG = NEG(res) ? true : false;\
94      SUBCARRY(rhs, lhs, res);\
95      SUBOVERFLOW(rhs, lhs, res);\
96    }
97 #define OP_ADD \
98     {\
99       reg[dest].I = reg[base].I + value;\
100     }
101 #define OP_ADDS \
102    {\
103      u32 lhs = reg[base].I;\
104      u32 rhs = value;\
105      u32 res = lhs + rhs;\
106      reg[dest].I = res;\
107      Z_FLAG = (res == 0) ? true : false;\
108      N_FLAG = NEG(res) ? true : false;\
109      ADDCARRY(lhs, rhs, res);\
110      ADDOVERFLOW(lhs, rhs, res);\
111    }
112 #define OP_ADC \
113     {\
114       reg[dest].I = reg[base].I + value + (u32)C_FLAG;\
115     }
116 #define OP_ADCS \
117    {\
118      u32 lhs = reg[base].I;\
119      u32 rhs = value;\
120      u32 res = lhs + rhs + (u32)C_FLAG;\
121      reg[dest].I = res;\
122      Z_FLAG = (res == 0) ? true : false;\
123      N_FLAG = NEG(res) ? true : false;\
124      ADDCARRY(lhs, rhs, res);\
125      ADDOVERFLOW(lhs, rhs, res);\
126    }
127 #define OP_SBC \
128     {\
129       reg[dest].I = reg[base].I - value - !((u32)C_FLAG);\
130     }
131 #define OP_SBCS \
132    {\
133      u32 lhs = reg[base].I;\
134      u32 rhs = value;\
135      u32 res = lhs - rhs - !((u32)C_FLAG);\
136      reg[dest].I = res;\
137      Z_FLAG = (res == 0) ? true : false;\
138      N_FLAG = NEG(res) ? true : false;\
139      SUBCARRY(lhs, rhs, res);\
140      SUBOVERFLOW(lhs, rhs, res);\
141    }
142 #define OP_RSC \
143     {\
144       reg[dest].I = value - reg[base].I - !((u32)C_FLAG);\
145     }
146 #define OP_RSCS \
147    {\
148      u32 lhs = reg[base].I;\
149      u32 rhs = value;\
150      u32 res = rhs - lhs - !((u32)C_FLAG);\
151      reg[dest].I = res;\
152      Z_FLAG = (res == 0) ? true : false;\
153      N_FLAG = NEG(res) ? true : false;\
154      SUBCARRY(rhs, lhs, res);\
155      SUBOVERFLOW(rhs, lhs, res);\
156    }
157 #define OP_CMP \
158    {\
159      u32 lhs = reg[base].I;\
160      u32 rhs = value;\
161      u32 res = lhs - rhs;\
162      Z_FLAG = (res == 0) ? true : false;\
163      N_FLAG = NEG(res) ? true : false;\
164      SUBCARRY(lhs, rhs, res);\
165      SUBOVERFLOW(lhs, rhs, res);\
166    }
167 #define OP_CMN \
168    {\
169      u32 lhs = reg[base].I;\
170      u32 rhs = value;\
171      u32 res = lhs + rhs;\
172      Z_FLAG = (res == 0) ? true : false;\
173      N_FLAG = NEG(res) ? true : false;\
174      ADDCARRY(lhs, rhs, res);\
175      ADDOVERFLOW(lhs, rhs, res);\
176    }
177 
178 #define LOGICAL_LSL_REG \
179    {\
180      u32 v = reg[opcode & 0x0f].I;\
181      C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
182      value = v << shift;\
183    }
184 #define LOGICAL_LSR_REG \
185    {\
186      u32 v = reg[opcode & 0x0f].I;\
187      C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
188      value = v >> shift;\
189    }
190 #define LOGICAL_ASR_REG \
191    {\
192      u32 v = reg[opcode & 0x0f].I;\
193      C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false;\
194      value = (s32)v >> (int)shift;\
195    }
196 #define LOGICAL_ROR_REG \
197    {\
198      u32 v = reg[opcode & 0x0f].I;\
199      C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
200      value = ((v << (32 - shift)) |\
201               (v >> shift));\
202    }
203 #define LOGICAL_RRX_REG \
204    {\
205      u32 v = reg[opcode & 0x0f].I;\
206      shift = (int)C_FLAG;\
207      C_OUT = (v  & 1) ? true : false;\
208      value = ((v >> 1) |\
209               (shift << 31));\
210    }
211 #define LOGICAL_ROR_IMM \
212    {\
213      u32 v = opcode & 0xff;\
214      C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
215      value = ((v << (32 - shift)) |\
216               (v >> shift));\
217    }
218 #define ARITHMETIC_LSL_REG \
219    {\
220      u32 v = reg[opcode & 0x0f].I;\
221      value = v << shift;\
222    }
223 #define ARITHMETIC_LSR_REG \
224    {\
225      u32 v = reg[opcode & 0x0f].I;\
226      value = v >> shift;\
227    }
228 #define ARITHMETIC_ASR_REG \
229    {\
230      u32 v = reg[opcode & 0x0f].I;\
231      value = (s32)v >> (int)shift;\
232    }
233 #define ARITHMETIC_ROR_REG \
234    {\
235      u32 v = reg[opcode & 0x0f].I;\
236      value = ((v << (32 - shift)) |\
237               (v >> shift));\
238    }
239 #define ARITHMETIC_RRX_REG \
240    {\
241      u32 v = reg[opcode & 0x0f].I;\
242      shift = (int)C_FLAG;\
243      value = ((v >> 1) |\
244               (shift << 31));\
245    }
246 #define ARITHMETIC_ROR_IMM \
247    {\
248      u32 v = opcode & 0xff;\
249      value = ((v << (32 - shift)) |\
250               (v >> shift));\
251    }
252 #define ROR_IMM_MSR \
253    {\
254      u32 v = opcode & 0xff;\
255      value = ((v << (32 - shift)) |\
256               (v >> shift));\
257    }
258 #define ROR_VALUE \
259    {\
260      value = ((value << (32 - shift)) |\
261               (value >> shift));\
262    }
263 #define RCR_VALUE \
264    {\
265      shift = (int)C_FLAG;\
266      value = ((value >> 1) |\
267               (shift << 31));\
268    }
269 #else
270 #ifdef __GNUC__
271         #ifdef __POWERPC__
272             #define OP_SUB \
273                 {\
274                 reg[dest].I = reg[base].I - value;\
275                 }
276             #define OP_SUBS \
277             {\
278                 register int Flags;                             \
279                 register int Result;                            \
280                 asm volatile("subco. %0, %2, %3\n"              \
281                             "mcrxr cr1\n"                       \
282                             "mfcr %1\n"                         \
283                             : "=r" (Result),                    \
284                               "=r" (Flags)                      \
285                             : "r" (reg[base].I),                \
286                               "r" (value)                       \
287                             );                                  \
288                 reg[dest].I = Result;                           \
289                 Z_FLAG = (Flags >> 29) & 1;                     \
290                 N_FLAG = (Flags >> 31) & 1;                     \
291                 C_FLAG = (Flags >> 25) & 1;                     \
292                 V_FLAG = (Flags >> 26) & 1;                     \
293             }
294             #define OP_RSB \
295                 {\
296                 reg[dest].I = value - reg[base].I;\
297                 }
298             #define OP_RSBS \
299             {\
300                 register int Flags;                             \
301                 register int Result;                            \
302                 asm volatile("subfco. %0, %2, %3\n"             \
303                             "mcrxr cr1\n"                       \
304                             "mfcr %1\n"                         \
305                             : "=r" (Result),                    \
306                               "=r" (Flags)                      \
307                             : "r" (reg[base].I),                \
308                               "r" (value)                       \
309                             );                                  \
310                 reg[dest].I = Result;                           \
311                 Z_FLAG = (Flags >> 29) & 1;                     \
312                 N_FLAG = (Flags >> 31) & 1;                     \
313                 C_FLAG = (Flags >> 25) & 1;                     \
314                 V_FLAG = (Flags >> 26) & 1;                     \
315             }
316             #define OP_ADD \
317                 {\
318                 reg[dest].I = reg[base].I + value;\
319                 }
320 
321             #define OP_ADDS \
322             {\
323                 register int Flags;                             \
324                 register int Result;                            \
325                 asm volatile("addco. %0, %2, %3\n"              \
326                             "mcrxr cr1\n"                       \
327                             "mfcr %1\n"                         \
328                             : "=r" (Result),                    \
329                               "=r" (Flags)                      \
330                             : "r" (reg[base].I),                \
331                               "r" (value)                       \
332                             );                                  \
333                 reg[dest].I = Result;                           \
334                 Z_FLAG = (Flags >> 29) & 1;                     \
335                 N_FLAG = (Flags >> 31) & 1;                     \
336                 C_FLAG = (Flags >> 25) & 1;                     \
337                 V_FLAG = (Flags >> 26) & 1;                     \
338             }
339             #define OP_ADC \
340             {\
341                 reg[dest].I = reg[base].I + value + (u32)C_FLAG;\
342             }
343             #define OP_ADCS \
344             {\
345                 register int Flags;                             \
346                 register int Result;                            \
347                 asm volatile("mtspr xer, %4\n"                  \
348                              "addeo. %0, %2, %3\n"              \
349                              "mcrxr cr1\n"                      \
350                              "mfcr      %1\n"                   \
351                              : "=r" (Result),                   \
352                                "=r" (Flags)                     \
353                              : "r" (reg[base].I),               \
354                                "r" (value),                     \
355                                "r" (C_FLAG << 29)               \
356                              );                                 \
357                 reg[dest].I = Result;                           \
358                 Z_FLAG = (Flags >> 29) & 1;                     \
359                 N_FLAG = (Flags >> 31) & 1;                     \
360                 C_FLAG = (Flags >> 25) & 1;                     \
361                 V_FLAG = (Flags >> 26) & 1;                     \
362             }
363             #define OP_SBC \
364                 {\
365                 reg[dest].I = reg[base].I - value - (C_FLAG^1);\
366                 }
367             #define OP_SBCS \
368             {\
369                 register int Flags;                             \
370                 register int Result;                            \
371                 asm volatile("mtspr xer, %4\n"                  \
372                              "subfeo. %0, %3, %2\n"             \
373                              "mcrxr cr1\n"                      \
374                              "mfcr      %1\n"                   \
375                              : "=r" (Result),                   \
376                                "=r" (Flags)                     \
377                              : "r" (reg[base].I),               \
378                                "r" (value),                     \
379                                "r" (C_FLAG << 29)               \
380                              );                                 \
381                 reg[dest].I = Result;                           \
382                 Z_FLAG = (Flags >> 29) & 1;                     \
383                 N_FLAG = (Flags >> 31) & 1;                     \
384                 C_FLAG = (Flags >> 25) & 1;                     \
385                 V_FLAG = (Flags >> 26) & 1;                     \
386             }
387             #define OP_RSC \
388                 {\
389                 reg[dest].I = value - reg[base].I - (C_FLAG^1);\
390                 }
391             #define OP_RSCS \
392             {\
393                 register int Flags;                             \
394                 register int Result;                            \
395                 asm volatile("mtspr xer, %4\n"                  \
396                              "subfeo. %0, %2, %3\n"             \
397                              "mcrxr cr1\n"                      \
398                              "mfcr      %1\n"                   \
399                              : "=r" (Result),                   \
400                                "=r" (Flags)                     \
401                              : "r" (reg[base].I),               \
402                                "r" (value),                     \
403                                "r" (C_FLAG << 29)               \
404                              );                                 \
405                 reg[dest].I = Result;                           \
406                 Z_FLAG = (Flags >> 29) & 1;                     \
407                 N_FLAG = (Flags >> 31) & 1;                     \
408                 C_FLAG = (Flags >> 25) & 1;                     \
409                 V_FLAG = (Flags >> 26) & 1;                     \
410             }
411             #define OP_CMP \
412             {\
413                 register int Flags;                             \
414                 register int Result;                            \
415                 asm volatile("subco. %0, %2, %3\n"              \
416                             "mcrxr cr1\n"                       \
417                             "mfcr %1\n"                         \
418                             : "=r" (Result),                    \
419                               "=r" (Flags)                      \
420                             : "r" (reg[base].I),                \
421                               "r" (value)                       \
422                             );                                  \
423                 Z_FLAG = (Flags >> 29) & 1;                     \
424                 N_FLAG = (Flags >> 31) & 1;                     \
425                 C_FLAG = (Flags >> 25) & 1;                     \
426                 V_FLAG = (Flags >> 26) & 1;                     \
427             }
428             #define OP_CMN \
429             {\
430                 register int Flags;                             \
431                 register int Result;                            \
432                 asm volatile("addco. %0, %2, %3\n"              \
433                             "mcrxr cr1\n"                       \
434                             "mfcr %1\n"                         \
435                             : "=r" (Result),                    \
436                               "=r" (Flags)                      \
437                             : "r" (reg[base].I),                \
438                               "r" (value)                       \
439                             );                                  \
440                 Z_FLAG = (Flags >> 29) & 1;                     \
441                 N_FLAG = (Flags >> 31) & 1;                     \
442                 C_FLAG = (Flags >> 25) & 1;                     \
443                 V_FLAG = (Flags >> 26) & 1;                     \
444             }
445 
446             #define LOGICAL_LSL_REG \
447             {\
448                 u32 v = reg[opcode & 0x0f].I;\
449                 C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
450                 value = v << shift;\
451             }
452             #define LOGICAL_LSR_REG \
453             {\
454                 u32 v = reg[opcode & 0x0f].I;\
455                 C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
456                 value = v >> shift;\
457             }
458             #define LOGICAL_ASR_REG \
459             {\
460                 u32 v = reg[opcode & 0x0f].I;\
461                 C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false;\
462                 value = (s32)v >> (int)shift;\
463             }
464             #define LOGICAL_ROR_REG \
465             {\
466                 u32 v = reg[opcode & 0x0f].I;\
467                 C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
468                 value = ((v << (32 - shift)) |\
469                         (v >> shift));\
470             }
471             #define LOGICAL_RRX_REG \
472             {\
473                 u32 v = reg[opcode & 0x0f].I;\
474                 shift = (int)C_FLAG;\
475                 C_OUT = (v  & 1) ? true : false;\
476                 value = ((v >> 1) |\
477                         (shift << 31));\
478             }
479             #define LOGICAL_ROR_IMM \
480             {\
481                 u32 v = opcode & 0xff;\
482                 C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
483                 value = ((v << (32 - shift)) |\
484                         (v >> shift));\
485             }
486             #define ARITHMETIC_LSL_REG \
487             {\
488                 u32 v = reg[opcode & 0x0f].I;\
489                 value = v << shift;\
490             }
491             #define ARITHMETIC_LSR_REG \
492             {\
493                 u32 v = reg[opcode & 0x0f].I;\
494                 value = v >> shift;\
495             }
496             #define ARITHMETIC_ASR_REG \
497             {\
498                 u32 v = reg[opcode & 0x0f].I;\
499                 value = (s32)v >> (int)shift;\
500             }
501             #define ARITHMETIC_ROR_REG \
502             {\
503                 u32 v = reg[opcode & 0x0f].I;\
504                 value = ((v << (32 - shift)) |\
505                         (v >> shift));\
506             }
507             #define ARITHMETIC_RRX_REG \
508             {\
509                 u32 v = reg[opcode & 0x0f].I;\
510                 shift = (int)C_FLAG;\
511                 value = ((v >> 1) |\
512                         (shift << 31));\
513             }
514             #define ARITHMETIC_ROR_IMM \
515             {\
516                 u32 v = opcode & 0xff;\
517                 value = ((v << (32 - shift)) |\
518                         (v >> shift));\
519             }
520             #define ROR_IMM_MSR \
521             {\
522                 u32 v = opcode & 0xff;\
523                 value = ((v << (32 - shift)) |\
524                         (v >> shift));\
525             }
526             #define ROR_VALUE \
527             {\
528                 value = ((value << (32 - shift)) |\
529                         (value >> shift));\
530             }
531             #define RCR_VALUE \
532             {\
533                 shift = (int)C_FLAG;\
534                 value = ((value >> 1) |\
535                         (shift << 31));\
536             }
537 #else
538 #define OP_SUB \
539      asm ("sub %1, %%ebx;"\
540                   : "=b" (reg[dest].I)\
541                   : "r" (value), "b" (reg[base].I));
542 
543 #define OP_SUBS \
544      asm ("sub %1, %%ebx;"\
545           "setsb N_FLAG;"\
546           "setzb Z_FLAG;"\
547           "setncb C_FLAG;"\
548           "setob V_FLAG;"\
549                   : "=b" (reg[dest].I)\
550                   : "r" (value), "b" (reg[base].I));
551 
552 #define OP_RSB \
553             asm  ("sub %1, %%ebx;"\
554                  : "=b" (reg[dest].I)\
555                  : "r" (reg[base].I), "b" (value));
556 
557 #define OP_RSBS \
558             asm  ("sub %1, %%ebx;"\
559                   "setsb N_FLAG;"\
560                   "setzb Z_FLAG;"\
561                   "setncb C_FLAG;"\
562                   "setob V_FLAG;"\
563                  : "=b" (reg[dest].I)\
564                  : "r" (reg[base].I), "b" (value));
565 
566 #define OP_ADD \
567             asm  ("add %1, %%ebx;"\
568                  : "=b" (reg[dest].I)\
569                  : "r" (value), "b" (reg[base].I));
570 
571 #define OP_ADDS \
572             asm  ("add %1, %%ebx;"\
573                   "setsb N_FLAG;"\
574                   "setzb Z_FLAG;"\
575                   "setcb C_FLAG;"\
576                   "setob V_FLAG;"\
577                  : "=b" (reg[dest].I)\
578                  : "r" (value), "b" (reg[base].I));
579 
580 #define OP_ADC \
581             asm  ("bt $0, C_FLAG;"\
582                   "adc %1, %%ebx;"\
583                  : "=b" (reg[dest].I)\
584                  : "r" (value), "b" (reg[base].I));
585 
586 #define OP_ADCS \
587             asm  ("bt $0, C_FLAG;"\
588                   "adc %1, %%ebx;"\
589                   "setsb N_FLAG;"\
590                   "setzb Z_FLAG;"\
591                   "setcb C_FLAG;"\
592                   "setob V_FLAG;"\
593                  : "=b" (reg[dest].I)\
594                  : "r" (value), "b" (reg[base].I));
595 
596 #define OP_SBC \
597             asm  ("bt $0, C_FLAG;"\
598                   "cmc;"\
599                   "sbb %1, %%ebx;"\
600                  : "=b" (reg[dest].I)\
601                  : "r" (value), "b" (reg[base].I));
602 
603 #define OP_SBCS \
604             asm  ("bt $0, C_FLAG;"\
605                   "cmc;"\
606                   "sbb %1, %%ebx;"\
607                   "setsb N_FLAG;"\
608                   "setzb Z_FLAG;"\
609                   "setncb C_FLAG;"\
610                   "setob V_FLAG;"\
611                  : "=b" (reg[dest].I)\
612                  : "r" (value), "b" (reg[base].I));
613 #define OP_RSC \
614             asm  ("bt $0, C_FLAG;"\
615                   "cmc;"\
616                   "sbb %1, %%ebx;"\
617                  : "=b" (reg[dest].I)\
618                  : "r" (reg[base].I), "b" (value));
619 
620 #define OP_RSCS \
621             asm  ("bt $0, C_FLAG;"\
622                   "cmc;"\
623                   "sbb %1, %%ebx;"\
624                   "setsb N_FLAG;"\
625                   "setzb Z_FLAG;"\
626                   "setncb C_FLAG;"\
627                   "setob V_FLAG;"\
628                  : "=b" (reg[dest].I)\
629                  : "r" (reg[base].I), "b" (value));
630 #define OP_CMP \
631             asm  ("sub %0, %1;"\
632                   "setsb N_FLAG;"\
633                   "setzb Z_FLAG;"\
634                   "setncb C_FLAG;"\
635                   "setob V_FLAG;"\
636                  :\
637                  : "r" (value), "r" (reg[base].I));
638 
639 #define OP_CMN \
640             asm  ("add %0, %1;"\
641                   "setsb N_FLAG;"\
642                   "setzb Z_FLAG;"\
643                   "setcb C_FLAG;"\
644                   "setob V_FLAG;"\
645                  : \
646                  : "r" (value), "r" (reg[base].I));
647 #define LOGICAL_LSL_REG \
648        asm("shl %%cl, %%eax;"\
649            "setcb %%cl;"\
650            : "=a" (value), "=c" (C_OUT)\
651            : "a" (reg[opcode & 0x0f].I), "c" (shift));
652 
653 #define LOGICAL_LSR_REG \
654        asm("shr %%cl, %%eax;"\
655            "setcb %%cl;"\
656            : "=a" (value), "=c" (C_OUT)\
657            : "a" (reg[opcode & 0x0f].I), "c" (shift));
658 
659 #define LOGICAL_ASR_REG \
660        asm("sar %%cl, %%eax;"\
661            "setcb %%cl;"\
662            : "=a" (value), "=c" (C_OUT)\
663            : "a" (reg[opcode & 0x0f].I), "c" (shift));
664 
665 #define LOGICAL_ROR_REG \
666        asm("ror %%cl, %%eax;"\
667            "setcb %%cl;"\
668            : "=a" (value), "=c" (C_OUT)\
669            : "a" (reg[opcode & 0x0f].I), "c" (shift));
670 
671 #define LOGICAL_RRX_REG \
672        asm("bt $0, C_FLAG;"\
673            "rcr $1, %%eax;"\
674            "setcb %%cl;"\
675            : "=a" (value), "=c" (C_OUT)\
676            : "a" (reg[opcode & 0x0f].I));
677 
678 #define LOGICAL_ROR_IMM \
679        asm("ror %%cl, %%eax;"\
680            "setcb %%cl;"\
681            : "=a" (value), "=c" (C_OUT)\
682            : "a" (opcode & 0xff), "c" (shift));
683 #define ARITHMETIC_LSL_REG \
684        asm("\
685              shl %%cl, %%eax;"\
686            : "=a" (value)\
687            : "a" (reg[opcode & 0x0f].I), "c" (shift));
688 
689 #define ARITHMETIC_LSR_REG \
690        asm("\
691              shr %%cl, %%eax;"\
692            : "=a" (value)\
693            : "a" (reg[opcode & 0x0f].I), "c" (shift));
694 
695 #define ARITHMETIC_ASR_REG \
696        asm("\
697              sar %%cl, %%eax;"\
698            : "=a" (value)\
699            : "a" (reg[opcode & 0x0f].I), "c" (shift));
700 
701 #define ARITHMETIC_ROR_REG \
702        asm("\
703              ror %%cl, %%eax;"\
704            : "=a" (value)\
705            : "a" (reg[opcode & 0x0f].I), "c" (shift));
706 
707 #define ARITHMETIC_RRX_REG \
708        asm("\
709              bt $0, C_FLAG;\
710              rcr $1, %%eax;"\
711            : "=a" (value)\
712            : "a" (reg[opcode & 0x0f].I));
713 
714 #define ARITHMETIC_ROR_IMM \
715        asm("\
716              ror %%cl, %%eax;"\
717            : "=a" (value)\
718            : "a" (opcode & 0xff), "c" (shift));
719 #define ROR_IMM_MSR \
720       asm ("ror %%cl, %%eax;"\
721            : "=a" (value)\
722            : "a" (opcode & 0xFF), "c" (shift));
723 #define ROR_VALUE \
724       asm("ror %%cl, %0"\
725           : "=r" (value)\
726           : "r" (value), "c" (shift));
727 #define RCR_VALUE \
728       asm("bt $0, C_FLAG;"\
729           "rcr $1, %0"\
730           : "=r" (value)\
731           : "r" (value));
732 #endif
733 #else
734 #define OP_SUB \
735       {\
736         __asm mov ebx, base\
737         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
738         __asm sub ebx, value\
739         __asm mov eax, dest\
740         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
741       }
742 
743 #define OP_SUBS \
744       {\
745         __asm mov ebx, base\
746         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
747         __asm sub ebx, value\
748         __asm mov eax, dest\
749         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
750         __asm sets byte ptr N_FLAG\
751         __asm setz byte ptr Z_FLAG\
752         __asm setnc byte ptr C_FLAG\
753         __asm seto byte ptr V_FLAG\
754       }
755 
756 #define OP_RSB \
757       {\
758         __asm mov ebx, base\
759         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
760         __asm mov eax, value\
761         __asm sub eax, ebx\
762         __asm mov ebx, dest\
763         __asm mov dword ptr [OFFSET reg+4*ebx], eax\
764       }
765 
766 #define OP_RSBS \
767       {\
768         __asm mov ebx, base\
769         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
770         __asm mov eax, value\
771         __asm sub eax, ebx\
772         __asm mov ebx, dest\
773         __asm mov dword ptr [OFFSET reg+4*ebx], eax\
774         __asm sets byte ptr N_FLAG\
775         __asm setz byte ptr Z_FLAG\
776         __asm setnc byte ptr C_FLAG\
777         __asm seto byte ptr V_FLAG\
778       }
779 
780 #define OP_ADD \
781       {\
782         __asm mov ebx, base\
783         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
784         __asm add ebx, value\
785         __asm mov eax, dest\
786         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
787       }
788 
789 #define OP_ADDS \
790       {\
791         __asm mov ebx, base\
792         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
793         __asm add ebx, value\
794         __asm mov eax, dest\
795         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
796         __asm sets byte ptr N_FLAG\
797         __asm setz byte ptr Z_FLAG\
798         __asm setc byte ptr C_FLAG\
799         __asm seto byte ptr V_FLAG\
800       }
801 
802 #define OP_ADC \
803       {\
804         __asm mov ebx, base\
805         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
806         __asm bt word ptr C_FLAG, 0\
807         __asm adc ebx, value\
808         __asm mov eax, dest\
809         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
810       }
811 
812 #define OP_ADCS \
813       {\
814         __asm mov ebx, base\
815         __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
816         __asm bt word ptr C_FLAG, 0\
817         __asm adc ebx, value\
818         __asm mov eax, dest\
819         __asm mov dword ptr [OFFSET reg+4*eax], ebx\
820         __asm sets byte ptr N_FLAG\
821         __asm setz byte ptr Z_FLAG\
822         __asm setc byte ptr C_FLAG\
823         __asm seto byte ptr V_FLAG\
824       }
825 
826 #define OP_SBC \
827       {\
828         __asm mov ebx, base\
829         __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
830         __asm mov eax, value\
831         __asm bt word ptr C_FLAG, 0\
832         __asm cmc\
833         __asm sbb ebx, eax\
834         __asm mov eax, dest\
835         __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
836       }
837 
838 #define OP_SBCS \
839       {\
840         __asm mov ebx, base\
841         __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
842         __asm mov eax, value\
843         __asm bt word ptr C_FLAG, 0\
844         __asm cmc\
845         __asm sbb ebx, eax\
846         __asm mov eax, dest\
847         __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
848         __asm sets byte ptr N_FLAG\
849         __asm setz byte ptr Z_FLAG\
850         __asm setnc byte ptr C_FLAG\
851         __asm seto byte ptr V_FLAG\
852       }
853 #define OP_RSC \
854       {\
855         __asm mov ebx, value\
856         __asm mov eax, base\
857         __asm mov eax, dword ptr[OFFSET reg + 4*eax]\
858         __asm bt word ptr C_FLAG, 0\
859         __asm cmc\
860         __asm sbb ebx, eax\
861         __asm mov eax, dest\
862         __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
863       }
864 
865 #define OP_RSCS \
866       {\
867         __asm mov ebx, value\
868         __asm mov eax, base\
869         __asm mov eax, dword ptr[OFFSET reg + 4*eax]\
870         __asm bt word ptr C_FLAG, 0\
871         __asm cmc\
872         __asm sbb ebx, eax\
873         __asm mov eax, dest\
874         __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
875         __asm sets byte ptr N_FLAG\
876         __asm setz byte ptr Z_FLAG\
877         __asm setnc byte ptr C_FLAG\
878         __asm seto byte ptr V_FLAG\
879       }
880 #define OP_CMP \
881      {\
882        __asm mov eax, base\
883        __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
884        __asm sub ebx, value\
885        __asm sets byte ptr N_FLAG\
886        __asm setz byte ptr Z_FLAG\
887        __asm setnc byte ptr C_FLAG\
888        __asm seto byte ptr V_FLAG\
889      }
890 
891 #define OP_CMN \
892      {\
893        __asm mov eax, base\
894        __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
895        __asm add ebx, value\
896        __asm sets byte ptr N_FLAG\
897        __asm setz byte ptr Z_FLAG\
898        __asm setc byte ptr C_FLAG\
899        __asm seto byte ptr V_FLAG\
900      }
901 #define LOGICAL_LSL_REG \
902         __asm mov eax, opcode\
903         __asm and eax, 0x0f\
904         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
905         __asm mov cl, byte ptr shift\
906         __asm shl eax, cl\
907         __asm mov value, eax\
908         __asm setc byte ptr C_OUT
909 
910 #define LOGICAL_LSR_REG \
911         __asm mov eax, opcode\
912         __asm and eax, 0x0f\
913         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
914         __asm mov cl, byte ptr shift\
915         __asm shr eax, cl\
916         __asm mov value, eax\
917         __asm setc byte ptr C_OUT
918 
919 #define LOGICAL_ASR_REG \
920         __asm mov eax, opcode\
921         __asm and eax, 0x0f\
922         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
923         __asm mov cl, byte ptr shift\
924         __asm sar eax, cl\
925         __asm mov value, eax\
926         __asm setc byte ptr C_OUT
927 
928 #define LOGICAL_ROR_REG \
929         __asm mov eax, opcode\
930         __asm and eax, 0x0F\
931         __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
932         __asm mov cl, byte ptr shift\
933         __asm ror eax, cl\
934         __asm mov value, eax\
935         __asm setc byte ptr C_OUT
936 
937 #define LOGICAL_RRX_REG \
938         __asm mov eax, opcode\
939         __asm and eax, 0x0F\
940         __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
941         __asm bt word ptr C_OUT, 0\
942         __asm rcr eax, 1\
943         __asm mov value, eax\
944         __asm setc byte ptr C_OUT
945 
946 #define LOGICAL_ROR_IMM \
947         __asm mov eax, opcode\
948         __asm and eax, 0xff\
949         __asm mov cl, byte ptr shift\
950         __asm ror eax, cl\
951         __asm mov value, eax\
952         __asm setc byte ptr C_OUT
953 #define ARITHMETIC_LSL_REG \
954         __asm mov eax, opcode\
955         __asm and eax, 0x0f\
956         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
957         __asm mov cl, byte ptr shift\
958         __asm shl eax, cl\
959         __asm mov value, eax
960 
961 #define ARITHMETIC_LSR_REG \
962         __asm mov eax, opcode\
963         __asm and eax, 0x0f\
964         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
965         __asm mov cl, byte ptr shift\
966         __asm shr eax, cl\
967         __asm mov value, eax
968 
969 #define ARITHMETIC_ASR_REG \
970         __asm mov eax, opcode\
971         __asm and eax, 0x0f\
972         __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
973         __asm mov cl, byte ptr shift\
974         __asm sar eax, cl\
975         __asm mov value, eax
976 
977 #define ARITHMETIC_ROR_REG \
978         __asm mov eax, opcode\
979         __asm and eax, 0x0F\
980         __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
981         __asm mov cl, byte ptr shift\
982         __asm ror eax, cl\
983         __asm mov value, eax
984 
985 #define ARITHMETIC_RRX_REG \
986         __asm mov eax, opcode\
987         __asm and eax, 0x0F\
988         __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
989         __asm bt word ptr C_FLAG, 0\
990         __asm rcr eax, 1\
991         __asm mov value, eax
992 
993 #define ARITHMETIC_ROR_IMM \
994         __asm mov eax, opcode\
995         __asm and eax, 0xff\
996         __asm mov cl, byte ptr shift\
997         __asm ror eax, cl\
998         __asm mov value, eax
999 #define ROR_IMM_MSR \
1000       {\
1001         __asm mov eax, opcode\
1002         __asm and eax, 0xff\
1003         __asm mov cl, byte ptr shift\
1004         __asm ror eax, CL\
1005         __asm mov value, eax\
1006       }
1007 #define ROR_VALUE \
1008       {\
1009         __asm mov cl, byte ptr shift\
1010         __asm ror dword ptr value, cl\
1011       }
1012 #define RCR_VALUE \
1013       {\
1014         __asm mov cl, byte ptr shift\
1015         __asm bt word ptr C_FLAG, 0\
1016         __asm rcr dword ptr value, 1\
1017       }
1018 #endif
1019 #endif
1020 
1021 #define OP_TST \
1022       u32 res = reg[base].I & value;\
1023       N_FLAG = (res & 0x80000000) ? true : false;\
1024       Z_FLAG = (res) ? false : true;\
1025       C_FLAG = C_OUT;
1026 
1027 #define OP_TEQ \
1028       u32 res = reg[base].I ^ value;\
1029       N_FLAG = (res & 0x80000000) ? true : false;\
1030       Z_FLAG = (res) ? false : true;\
1031       C_FLAG = C_OUT;
1032 
1033 #define OP_ORR \
1034     reg[dest].I = reg[base].I | value;
1035 
1036 #define OP_ORRS \
1037     reg[dest].I = reg[base].I | value;\
1038     N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
1039     Z_FLAG = (reg[dest].I) ? false : true;\
1040     C_FLAG = C_OUT;
1041 
1042 #define OP_MOV \
1043     reg[dest].I = value;
1044 
1045 #define OP_MOVS \
1046     reg[dest].I = value;\
1047     N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
1048     Z_FLAG = (reg[dest].I) ? false : true;\
1049     C_FLAG = C_OUT;
1050 
1051 #define OP_BIC \
1052     reg[dest].I = reg[base].I & (~value);
1053 
1054 #define OP_BICS \
1055     reg[dest].I = reg[base].I & (~value);\
1056     N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
1057     Z_FLAG = (reg[dest].I) ? false : true;\
1058     C_FLAG = C_OUT;
1059 
1060 #define OP_MVN \
1061     reg[dest].I = ~value;
1062 
1063 #define OP_MVNS \
1064     reg[dest].I = ~value; \
1065     N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
1066     Z_FLAG = (reg[dest].I) ? false : true;\
1067     C_FLAG = C_OUT;
1068 
1069 #define CASE_16(BASE) \
1070   case BASE:\
1071   case BASE+1:\
1072   case BASE+2:\
1073   case BASE+3:\
1074   case BASE+4:\
1075   case BASE+5:\
1076   case BASE+6:\
1077   case BASE+7:\
1078   case BASE+8:\
1079   case BASE+9:\
1080   case BASE+10:\
1081   case BASE+11:\
1082   case BASE+12:\
1083   case BASE+13:\
1084   case BASE+14:\
1085   case BASE+15:
1086 
1087 #define CASE_256(BASE) \
1088   CASE_16(BASE)\
1089   CASE_16(BASE+0x10)\
1090   CASE_16(BASE+0x20)\
1091   CASE_16(BASE+0x30)\
1092   CASE_16(BASE+0x40)\
1093   CASE_16(BASE+0x50)\
1094   CASE_16(BASE+0x60)\
1095   CASE_16(BASE+0x70)\
1096   CASE_16(BASE+0x80)\
1097   CASE_16(BASE+0x90)\
1098   CASE_16(BASE+0xa0)\
1099   CASE_16(BASE+0xb0)\
1100   CASE_16(BASE+0xc0)\
1101   CASE_16(BASE+0xd0)\
1102   CASE_16(BASE+0xe0)\
1103   CASE_16(BASE+0xf0)
1104 
1105 #define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
1106   case BASE: \
1107   case BASE+8:\
1108     {\
1109       /* OP Rd,Rb,Rm LSL # */ \
1110       int base = (opcode >> 16) & 0x0F;\
1111       int shift = (opcode >> 7) & 0x1F;\
1112       int dest = (opcode>>12) & 15;\
1113       bool C_OUT = C_FLAG;\
1114       u32 value;\
1115       \
1116       if(shift) {\
1117         LOGICAL_LSL_REG\
1118       } else {\
1119         value = reg[opcode & 0x0F].I;\
1120       }\
1121       if(dest == 15) {\
1122         OPCODE2\
1123         /* todo */\
1124         if(opcode & 0x00100000) {\
1125           clockTicks++;\
1126           CPUSwitchMode(reg[17].I & 0x1f, false);\
1127         }\
1128         if(armState) {\
1129           reg[15].I &= 0xFFFFFFFC;\
1130           armNextPC = reg[15].I;\
1131           reg[15].I += 4;\
1132         } else {\
1133           reg[15].I &= 0xFFFFFFFE;\
1134           armNextPC = reg[15].I;\
1135           reg[15].I += 2;\
1136         }\
1137       } else {\
1138         OPCODE \
1139       }\
1140     }\
1141     break;\
1142   case BASE+2:\
1143   case BASE+10:\
1144     {\
1145        /* OP Rd,Rb,Rm LSR # */ \
1146       int base = (opcode >> 16) & 0x0F;\
1147       int shift = (opcode >> 7) & 0x1F;\
1148       int dest = (opcode>>12) & 15;\
1149       bool C_OUT = C_FLAG;\
1150       u32 value;\
1151       if(shift) {\
1152         LOGICAL_LSR_REG\
1153       } else {\
1154         value = 0;\
1155         C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
1156       }\
1157       \
1158       if(dest == 15) {\
1159         OPCODE2\
1160         /* todo */\
1161         if(opcode & 0x00100000) {\
1162           clockTicks++;\
1163           CPUSwitchMode(reg[17].I & 0x1f, false);\
1164         }\
1165         if(armState) {\
1166           reg[15].I &= 0xFFFFFFFC;\
1167           armNextPC = reg[15].I;\
1168           reg[15].I += 4;\
1169         } else {\
1170           reg[15].I &= 0xFFFFFFFE;\
1171           armNextPC = reg[15].I;\
1172           reg[15].I += 2;\
1173         }\
1174       } else {\
1175         OPCODE \
1176       }\
1177     }\
1178     break;\
1179   case BASE+4:\
1180   case BASE+12:\
1181     {\
1182        /* OP Rd,Rb,Rm ASR # */\
1183       int base = (opcode >> 16) & 0x0F;\
1184       int shift = (opcode >> 7) & 0x1F;\
1185       int dest = (opcode>>12) & 15;\
1186       bool C_OUT = C_FLAG;\
1187       u32 value;\
1188       if(shift) {\
1189         LOGICAL_ASR_REG\
1190       } else {\
1191         if(reg[opcode & 0x0F].I & 0x80000000){\
1192           value = 0xFFFFFFFF;\
1193           C_OUT = true;\
1194         } else {\
1195           value = 0;\
1196           C_OUT = false;\
1197         }                   \
1198       }\
1199       \
1200       if(dest == 15) {\
1201         OPCODE2\
1202         /* todo */\
1203         if(opcode & 0x00100000) {\
1204           clockTicks++;\
1205           CPUSwitchMode(reg[17].I & 0x1f, false);\
1206         }\
1207         if(armState) {\
1208           reg[15].I &= 0xFFFFFFFC;\
1209           armNextPC = reg[15].I;\
1210           reg[15].I += 4;\
1211         } else {\
1212           reg[15].I &= 0xFFFFFFFE;\
1213           armNextPC = reg[15].I;\
1214           reg[15].I += 2;\
1215         }\
1216       } else {\
1217         OPCODE \
1218       }\
1219     }\
1220     break;\
1221   case BASE+6:\
1222   case BASE+14:\
1223     {\
1224        /* OP Rd,Rb,Rm ROR # */\
1225       int base = (opcode >> 16) & 0x0F;\
1226       int shift = (opcode >> 7) & 0x1F;\
1227       int dest = (opcode>>12) & 15;\
1228       bool C_OUT = C_FLAG;\
1229       u32 value;\
1230       if(shift) {\
1231         LOGICAL_ROR_REG\
1232       } else {\
1233         LOGICAL_RRX_REG\
1234       }\
1235       if(dest == 15) {\
1236         OPCODE2\
1237         /* todo */\
1238         if(opcode & 0x00100000) {\
1239           clockTicks++;\
1240           CPUSwitchMode(reg[17].I & 0x1f, false);\
1241         }\
1242         if(armState) {\
1243           reg[15].I &= 0xFFFFFFFC;\
1244           armNextPC = reg[15].I;\
1245           reg[15].I += 4;\
1246         } else {\
1247           reg[15].I &= 0xFFFFFFFE;\
1248           armNextPC = reg[15].I;\
1249           reg[15].I += 2;\
1250         }\
1251       } else {\
1252         OPCODE \
1253       }\
1254     }\
1255     break;\
1256   case BASE+1:\
1257     {\
1258        /* OP Rd,Rb,Rm LSL Rs */\
1259       clockTicks++;\
1260       int base = (opcode >> 16) & 0x0F;\
1261       int shift = reg[(opcode >> 8)&15].B.B0;\
1262       int dest = (opcode>>12) & 15;\
1263       bool C_OUT = C_FLAG;\
1264       u32 value;\
1265       if(shift) {\
1266         if(shift == 32) {\
1267           value = 0;\
1268           C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
1269         } else if(shift < 32) {\
1270            LOGICAL_LSL_REG\
1271         } else {\
1272           value = 0;\
1273           C_OUT = false;\
1274         }\
1275       } else {\
1276         value = reg[opcode & 0x0F].I;\
1277       }\
1278       if(dest == 15) {\
1279         OPCODE2\
1280         /* todo */\
1281         if(opcode & 0x00100000) {\
1282           clockTicks++;\
1283           CPUSwitchMode(reg[17].I & 0x1f, false);\
1284         }\
1285         if(armState) {\
1286           reg[15].I &= 0xFFFFFFFC;\
1287           armNextPC = reg[15].I;\
1288           reg[15].I += 4;\
1289         } else {\
1290           reg[15].I &= 0xFFFFFFFE;\
1291           armNextPC = reg[15].I;\
1292           reg[15].I += 2;\
1293         }\
1294       } else {\
1295         OPCODE \
1296       }\
1297     }\
1298     break;\
1299   case BASE+3:\
1300     {\
1301        /* OP Rd,Rb,Rm LSR Rs */ \
1302       clockTicks++;\
1303       int base = (opcode >> 16) & 0x0F;\
1304       int shift = reg[(opcode >> 8)&15].B.B0;\
1305       int dest = (opcode>>12) & 15;\
1306       bool C_OUT = C_FLAG;\
1307       u32 value;\
1308       if(shift) {\
1309         if(shift == 32) {\
1310           value = 0;\
1311           C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
1312         } else if(shift < 32) {\
1313             LOGICAL_LSR_REG\
1314         } else {\
1315           value = 0;\
1316           C_OUT = false;\
1317         }\
1318       } else {\
1319         value = reg[opcode & 0x0F].I;\
1320       }\
1321       if(dest == 15) {\
1322         OPCODE2\
1323         /* todo */\
1324         if(opcode & 0x00100000) {\
1325           clockTicks++;\
1326           CPUSwitchMode(reg[17].I & 0x1f, false);\
1327         }\
1328         if(armState) {\
1329           reg[15].I &= 0xFFFFFFFC;\
1330           armNextPC = reg[15].I;\
1331           reg[15].I += 4;\
1332         } else {\
1333           reg[15].I &= 0xFFFFFFFE;\
1334           armNextPC = reg[15].I;\
1335           reg[15].I += 2;\
1336         }\
1337       } else {\
1338         OPCODE \
1339       }\
1340     }\
1341     break;\
1342   case BASE+5:\
1343     {\
1344        /* OP Rd,Rb,Rm ASR Rs */ \
1345       clockTicks++;\
1346       int base = (opcode >> 16) & 0x0F;\
1347       int shift = reg[(opcode >> 8)&15].B.B0;\
1348       int dest = (opcode>>12) & 15;\
1349       bool C_OUT = C_FLAG;\
1350       u32 value;\
1351       if(shift < 32) {\
1352         if(shift) {\
1353           LOGICAL_ASR_REG\
1354         } else {\
1355           value = reg[opcode & 0x0F].I;\
1356         }\
1357       } else {\
1358         if(reg[opcode & 0x0F].I & 0x80000000){\
1359           value = 0xFFFFFFFF;\
1360           C_OUT = true;\
1361         } else {\
1362           value = 0;\
1363           C_OUT = false;\
1364         }\
1365       }\
1366       if(dest == 15) {\
1367         OPCODE2\
1368         /* todo */\
1369         if(opcode & 0x00100000) {\
1370           clockTicks++;\
1371           CPUSwitchMode(reg[17].I & 0x1f, false);\
1372         }\
1373         if(armState) {\
1374           reg[15].I &= 0xFFFFFFFC;\
1375           armNextPC = reg[15].I;\
1376           reg[15].I += 4;\
1377         } else {\
1378           reg[15].I &= 0xFFFFFFFE;\
1379           armNextPC = reg[15].I;\
1380           reg[15].I += 2;\
1381         }\
1382       } else {\
1383         OPCODE \
1384       }\
1385     }\
1386     break;\
1387   case BASE+7:\
1388     {\
1389        /* OP Rd,Rb,Rm ROR Rs */\
1390       clockTicks++;\
1391       int base = (opcode >> 16) & 0x0F;\
1392       int shift = reg[(opcode >> 8)&15].B.B0;\
1393       int dest = (opcode>>12) & 15;\
1394       bool C_OUT = C_FLAG;\
1395       u32 value;\
1396       if(shift) {\
1397         shift &= 0x1f;\
1398         if(shift) {\
1399           LOGICAL_ROR_REG\
1400         } else {\
1401           value = reg[opcode & 0x0F].I;\
1402           C_OUT = (value & 0x80000000 ? true : false);\
1403         }\
1404       } else {\
1405         value = reg[opcode & 0x0F].I;\
1406         C_OUT = (value & 0x80000000 ? true : false);\
1407       }\
1408       if(dest == 15) {\
1409         OPCODE2\
1410         /* todo */\
1411         if(opcode & 0x00100000) {\
1412           clockTicks++;\
1413           CPUSwitchMode(reg[17].I & 0x1f, false);\
1414         }\
1415         if(armState) {\
1416           reg[15].I &= 0xFFFFFFFC;\
1417           armNextPC = reg[15].I;\
1418           reg[15].I += 4;\
1419         } else {\
1420           reg[15].I &= 0xFFFFFFFE;\
1421           armNextPC = reg[15].I;\
1422           reg[15].I += 2;\
1423         }\
1424       } else {\
1425         OPCODE \
1426       }\
1427     }\
1428     break;\
1429   case BASE+0x200:\
1430   case BASE+0x201:\
1431   case BASE+0x202:\
1432   case BASE+0x203:\
1433   case BASE+0x204:\
1434   case BASE+0x205:\
1435   case BASE+0x206:\
1436   case BASE+0x207:\
1437   case BASE+0x208:\
1438   case BASE+0x209:\
1439   case BASE+0x20a:\
1440   case BASE+0x20b:\
1441   case BASE+0x20c:\
1442   case BASE+0x20d:\
1443   case BASE+0x20e:\
1444   case BASE+0x20f:\
1445     {\
1446       int shift = (opcode & 0xF00) >> 7;\
1447       int base = (opcode >> 16) & 0x0F;\
1448       int dest = (opcode >> 12) & 0x0F;\
1449       bool C_OUT = C_FLAG;\
1450       u32 value;\
1451       if(shift) {\
1452         LOGICAL_ROR_IMM\
1453       } else {\
1454         value = opcode & 0xff;\
1455       }\
1456       if(dest == 15) {\
1457         OPCODE2\
1458         /* todo */\
1459         if(opcode & 0x00100000) {\
1460           clockTicks++;\
1461           CPUSwitchMode(reg[17].I & 0x1f, false);\
1462         }\
1463         if(armState) {\
1464           reg[15].I &= 0xFFFFFFFC;\
1465           armNextPC = reg[15].I;\
1466           reg[15].I += 4;\
1467         } else {\
1468           reg[15].I &= 0xFFFFFFFE;\
1469           armNextPC = reg[15].I;\
1470           reg[15].I += 2;\
1471         }\
1472       } else {\
1473         OPCODE \
1474       }\
1475     }\
1476     break;
1477 
1478 #define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \
1479   case BASE: \
1480   case BASE+8:\
1481     {\
1482       /* OP Rd,Rb,Rm LSL # */ \
1483       int shift = (opcode >> 7) & 0x1F;\
1484       int dest = (opcode>>12) & 15;\
1485       bool C_OUT = C_FLAG;\
1486       u32 value;\
1487       \
1488       if(shift) {\
1489         LOGICAL_LSL_REG\
1490       } else {\
1491         value = reg[opcode & 0x0F].I;\
1492       }\
1493       if(dest == 15) {\
1494         OPCODE2\
1495         /* todo */\
1496         if(opcode & 0x00100000) {\
1497           clockTicks++;\
1498           CPUSwitchMode(reg[17].I & 0x1f, false);\
1499         }\
1500         if(armState) {\
1501           reg[15].I &= 0xFFFFFFFC;\
1502           armNextPC = reg[15].I;\
1503           reg[15].I += 4;\
1504         } else {\
1505           reg[15].I &= 0xFFFFFFFE;\
1506           armNextPC = reg[15].I;\
1507           reg[15].I += 2;\
1508         }\
1509       } else {\
1510         OPCODE \
1511       }\
1512     }\
1513     break;\
1514   case BASE+2:\
1515   case BASE+10:\
1516     {\
1517        /* OP Rd,Rb,Rm LSR # */ \
1518       int shift = (opcode >> 7) & 0x1F;\
1519       int dest = (opcode>>12) & 15;\
1520       bool C_OUT = C_FLAG;\
1521       u32 value;\
1522       if(shift) {\
1523         LOGICAL_LSR_REG\
1524       } else {\
1525         value = 0;\
1526         C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
1527       }\
1528       \
1529       if(dest == 15) {\
1530         OPCODE2\
1531         /* todo */\
1532         if(opcode & 0x00100000) {\
1533           clockTicks++;\
1534           CPUSwitchMode(reg[17].I & 0x1f, false);\
1535         }\
1536         if(armState) {\
1537           reg[15].I &= 0xFFFFFFFC;\
1538           armNextPC = reg[15].I;\
1539           reg[15].I += 4;\
1540         } else {\
1541           reg[15].I &= 0xFFFFFFFE;\
1542           armNextPC = reg[15].I;\
1543           reg[15].I += 2;\
1544         }\
1545       } else {\
1546         OPCODE \
1547       }\
1548     }\
1549     break;\
1550   case BASE+4:\
1551   case BASE+12:\
1552     {\
1553        /* OP Rd,Rb,Rm ASR # */\
1554       int shift = (opcode >> 7) & 0x1F;\
1555       int dest = (opcode>>12) & 15;\
1556       bool C_OUT = C_FLAG;\
1557       u32 value;\
1558       if(shift) {\
1559         LOGICAL_ASR_REG\
1560       } else {\
1561         if(reg[opcode & 0x0F].I & 0x80000000){\
1562           value = 0xFFFFFFFF;\
1563           C_OUT = true;\
1564         } else {\
1565           value = 0;\
1566           C_OUT = false;\
1567         }                   \
1568       }\
1569       \
1570       if(dest == 15) {\
1571         OPCODE2\
1572         /* todo */\
1573         if(opcode & 0x00100000) {\
1574           clockTicks++;\
1575           CPUSwitchMode(reg[17].I & 0x1f, false);\
1576         }\
1577         if(armState) {\
1578           reg[15].I &= 0xFFFFFFFC;\
1579           armNextPC = reg[15].I;\
1580           reg[15].I += 4;\
1581         } else {\
1582           reg[15].I &= 0xFFFFFFFE;\
1583           armNextPC = reg[15].I;\
1584           reg[15].I += 2;\
1585         }\
1586       } else {\
1587         OPCODE \
1588       }\
1589     }\
1590     break;\
1591   case BASE+6:\
1592   case BASE+14:\
1593     {\
1594        /* OP Rd,Rb,Rm ROR # */\
1595       int shift = (opcode >> 7) & 0x1F;\
1596       int dest = (opcode>>12) & 15;\
1597       bool C_OUT = C_FLAG;\
1598       u32 value;\
1599       if(shift) {\
1600         LOGICAL_ROR_REG\
1601       } else {\
1602         LOGICAL_RRX_REG\
1603       }\
1604       if(dest == 15) {\
1605         OPCODE2\
1606         /* todo */\
1607         if(opcode & 0x00100000) {\
1608           clockTicks++;\
1609           CPUSwitchMode(reg[17].I & 0x1f, false);\
1610         }\
1611         if(armState) {\
1612           reg[15].I &= 0xFFFFFFFC;\
1613           armNextPC = reg[15].I;\
1614           reg[15].I += 4;\
1615         } else {\
1616           reg[15].I &= 0xFFFFFFFE;\
1617           armNextPC = reg[15].I;\
1618           reg[15].I += 2;\
1619         }\
1620       } else {\
1621         OPCODE \
1622       }\
1623     }\
1624     break;\
1625   case BASE+1:\
1626     {\
1627        /* OP Rd,Rb,Rm LSL Rs */\
1628       clockTicks++;\
1629       int shift = reg[(opcode >> 8)&15].B.B0;\
1630       int dest = (opcode>>12) & 15;\
1631       bool C_OUT = C_FLAG;\
1632       u32 value;\
1633       if(shift) {\
1634         if(shift == 32) {\
1635           value = 0;\
1636           C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
1637         } else if(shift < 32) {\
1638            LOGICAL_LSL_REG\
1639         } else {\
1640           value = 0;\
1641           C_OUT = false;\
1642         }\
1643       } else {\
1644         value = reg[opcode & 0x0F].I;\
1645       }\
1646       if(dest == 15) {\
1647         OPCODE2\
1648         /* todo */\
1649         if(opcode & 0x00100000) {\
1650           clockTicks++;\
1651           CPUSwitchMode(reg[17].I & 0x1f, false);\
1652         }\
1653         if(armState) {\
1654           reg[15].I &= 0xFFFFFFFC;\
1655           armNextPC = reg[15].I;\
1656           reg[15].I += 4;\
1657         } else {\
1658           reg[15].I &= 0xFFFFFFFE;\
1659           armNextPC = reg[15].I;\
1660           reg[15].I += 2;\
1661         }\
1662       } else {\
1663         OPCODE \
1664       }\
1665     }\
1666     break;\
1667   case BASE+3:\
1668     {\
1669        /* OP Rd,Rb,Rm LSR Rs */ \
1670       clockTicks++;\
1671       int shift = reg[(opcode >> 8)&15].B.B0;\
1672       int dest = (opcode>>12) & 15;\
1673       bool C_OUT = C_FLAG;\
1674       u32 value;\
1675       if(shift) {\
1676         if(shift == 32) {\
1677           value = 0;\
1678           C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
1679         } else if(shift < 32) {\
1680             LOGICAL_LSR_REG\
1681         } else {\
1682           value = 0;\
1683           C_OUT = false;\
1684         }\
1685       } else {\
1686         value = reg[opcode & 0x0F].I;\
1687       }\
1688       if(dest == 15) {\
1689         OPCODE2\
1690         /* todo */\
1691         if(opcode & 0x00100000) {\
1692           clockTicks++;\
1693           CPUSwitchMode(reg[17].I & 0x1f, false);\
1694         }\
1695         if(armState) {\
1696           reg[15].I &= 0xFFFFFFFC;\
1697           armNextPC = reg[15].I;\
1698           reg[15].I += 4;\
1699         } else {\
1700           reg[15].I &= 0xFFFFFFFE;\
1701           armNextPC = reg[15].I;\
1702           reg[15].I += 2;\
1703         }\
1704       } else {\
1705         OPCODE \
1706       }\
1707     }\
1708     break;\
1709   case BASE+5:\
1710     {\
1711        /* OP Rd,Rb,Rm ASR Rs */ \
1712       clockTicks++;\
1713       int shift = reg[(opcode >> 8)&15].B.B0;\
1714       int dest = (opcode>>12) & 15;\
1715       bool C_OUT = C_FLAG;\
1716       u32 value;\
1717       if(shift < 32) {\
1718         if(shift) {\
1719           LOGICAL_ASR_REG\
1720         } else {\
1721           value = reg[opcode & 0x0F].I;\
1722         }\
1723       } else {\
1724         if(reg[opcode & 0x0F].I & 0x80000000){\
1725           value = 0xFFFFFFFF;\
1726           C_OUT = true;\
1727         } else {\
1728           value = 0;\
1729           C_OUT = false;\
1730         }\
1731       }\
1732       if(dest == 15) {\
1733         OPCODE2\
1734         /* todo */\
1735         if(opcode & 0x00100000) {\
1736           clockTicks++;\
1737           CPUSwitchMode(reg[17].I & 0x1f, false);\
1738         }\
1739         if(armState) {\
1740           reg[15].I &= 0xFFFFFFFC;\
1741           armNextPC = reg[15].I;\
1742           reg[15].I += 4;\
1743         } else {\
1744           reg[15].I &= 0xFFFFFFFE;\
1745           armNextPC = reg[15].I;\
1746           reg[15].I += 2;\
1747         }\
1748       } else {\
1749         OPCODE \
1750       }\
1751     }\
1752     break;\
1753   case BASE+7:\
1754     {\
1755        /* OP Rd,Rb,Rm ROR Rs */\
1756       clockTicks++;\
1757       int shift = reg[(opcode >> 8)&15].B.B0;\
1758       int dest = (opcode>>12) & 15;\
1759       bool C_OUT = C_FLAG;\
1760       u32 value;\
1761       if(shift) {\
1762         shift &= 0x1f;\
1763         if(shift) {\
1764           LOGICAL_ROR_REG\
1765         } else {\
1766           value = reg[opcode & 0x0F].I;\
1767           C_OUT = (value & 0x80000000 ? true : false);\
1768         }\
1769       } else {\
1770         value = reg[opcode & 0x0F].I;\
1771         C_OUT = (value & 0x80000000 ? true : false);\
1772       }\
1773       if(dest == 15) {\
1774         OPCODE2\
1775         /* todo */\
1776         if(opcode & 0x00100000) {\
1777           clockTicks++;\
1778           CPUSwitchMode(reg[17].I & 0x1f, false);\
1779         }\
1780         if(armState) {\
1781           reg[15].I &= 0xFFFFFFFC;\
1782           armNextPC = reg[15].I;\
1783           reg[15].I += 4;\
1784         } else {\
1785           reg[15].I &= 0xFFFFFFFE;\
1786           armNextPC = reg[15].I;\
1787           reg[15].I += 2;\
1788         }\
1789       } else {\
1790         OPCODE \
1791       }\
1792     }\
1793     break;\
1794   case BASE+0x200:\
1795   case BASE+0x201:\
1796   case BASE+0x202:\
1797   case BASE+0x203:\
1798   case BASE+0x204:\
1799   case BASE+0x205:\
1800   case BASE+0x206:\
1801   case BASE+0x207:\
1802   case BASE+0x208:\
1803   case BASE+0x209:\
1804   case BASE+0x20a:\
1805   case BASE+0x20b:\
1806   case BASE+0x20c:\
1807   case BASE+0x20d:\
1808   case BASE+0x20e:\
1809   case BASE+0x20f:\
1810     {\
1811       int shift = (opcode & 0xF00) >> 7;\
1812       int dest = (opcode >> 12) & 0x0F;\
1813       bool C_OUT = C_FLAG;\
1814       u32 value;\
1815       if(shift) {\
1816         LOGICAL_ROR_IMM\
1817       } else {\
1818         value = opcode & 0xff;\
1819       }\
1820       if(dest == 15) {\
1821         OPCODE2\
1822         /* todo */\
1823         if(opcode & 0x00100000) {\
1824           clockTicks++;\
1825           CPUSwitchMode(reg[17].I & 0x1f, false);\
1826         }\
1827         if(armState) {\
1828           reg[15].I &= 0xFFFFFFFC;\
1829           armNextPC = reg[15].I;\
1830           reg[15].I += 4;\
1831         } else {\
1832           reg[15].I &= 0xFFFFFFFE;\
1833           armNextPC = reg[15].I;\
1834           reg[15].I += 2;\
1835         }\
1836       } else {\
1837         OPCODE \
1838       }\
1839     }\
1840     break;
1841 
1842 #define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
1843   case BASE:\
1844   case BASE+8:\
1845     {\
1846       /* OP Rd,Rb,Rm LSL # */\
1847       int base = (opcode >> 16) & 0x0F;\
1848       int shift = (opcode >> 7) & 0x1F;\
1849       int dest = (opcode>>12) & 15;\
1850       u32 value;\
1851       if(shift) {\
1852         ARITHMETIC_LSL_REG\
1853       } else {\
1854         value = reg[opcode & 0x0F].I;\
1855       }\
1856       if(dest == 15) {\
1857         OPCODE2\
1858         /* todo */\
1859         if(opcode & 0x00100000) {\
1860           clockTicks++;\
1861           CPUSwitchMode(reg[17].I & 0x1f, false);\
1862         }\
1863         if(armState) {\
1864           reg[15].I &= 0xFFFFFFFC;\
1865           armNextPC = reg[15].I;\
1866           reg[15].I += 4;\
1867         } else {\
1868           reg[15].I &= 0xFFFFFFFE;\
1869           armNextPC = reg[15].I;\
1870           reg[15].I += 2;\
1871         }\
1872       } else {\
1873         OPCODE \
1874       }\
1875     }\
1876     break;\
1877   case BASE+2:\
1878   case BASE+10:\
1879     {\
1880       /* OP Rd,Rb,Rm LSR # */\
1881       int base = (opcode >> 16) & 0x0F;\
1882       int shift = (opcode >> 7) & 0x1F;\
1883       int dest = (opcode>>12) & 15;\
1884       u32 value;\
1885       if(shift) {\
1886         ARITHMETIC_LSR_REG\
1887       } else {\
1888         value = 0;\
1889       }\
1890       if(dest == 15) {\
1891         OPCODE2\
1892         /* todo */\
1893         if(opcode & 0x00100000) {\
1894           clockTicks++;\
1895           CPUSwitchMode(reg[17].I & 0x1f, false);\
1896         }\
1897         if(armState) {\
1898           reg[15].I &= 0xFFFFFFFC;\
1899           armNextPC = reg[15].I;\
1900           reg[15].I += 4;\
1901         } else {\
1902           reg[15].I &= 0xFFFFFFFE;\
1903           armNextPC = reg[15].I;\
1904           reg[15].I += 2;\
1905         }\
1906       } else {\
1907         OPCODE \
1908       }\
1909     }\
1910     break;\
1911   case BASE+4:\
1912   case BASE+12:\
1913     {\
1914       /* OP Rd,Rb,Rm ASR # */\
1915       int base = (opcode >> 16) & 0x0F;\
1916       int shift = (opcode >> 7) & 0x1F;\
1917       int dest = (opcode>>12) & 15;\
1918       u32 value;\
1919       if(shift) {\
1920         ARITHMETIC_ASR_REG\
1921       } else {\
1922         if(reg[opcode & 0x0F].I & 0x80000000){\
1923           value = 0xFFFFFFFF;\
1924         } else value = 0;\
1925       }\
1926       if(dest == 15) {\
1927         OPCODE2\
1928         /* todo */\
1929         if(opcode & 0x00100000) {\
1930           clockTicks++;\
1931           CPUSwitchMode(reg[17].I & 0x1f, false);\
1932         }\
1933         if(armState) {\
1934           reg[15].I &= 0xFFFFFFFC;\
1935           armNextPC = reg[15].I;\
1936           reg[15].I += 4;\
1937         } else {\
1938           reg[15].I &= 0xFFFFFFFE;\
1939           armNextPC = reg[15].I;\
1940           reg[15].I += 2;\
1941         }\
1942       } else {\
1943         OPCODE \
1944       }\
1945     }\
1946     break;\
1947   case BASE+6:\
1948   case BASE+14:\
1949     {\
1950       /* OP Rd,Rb,Rm ROR # */\
1951       int base = (opcode >> 16) & 0x0F;\
1952       int shift = (opcode >> 7) & 0x1F;\
1953       int dest = (opcode>>12) & 15;\
1954       u32 value;\
1955       if(shift) {\
1956          ARITHMETIC_ROR_REG\
1957       } else {\
1958          ARITHMETIC_RRX_REG\
1959       }\
1960       if(dest == 15) {\
1961         OPCODE2\
1962         /* todo */\
1963         if(opcode & 0x00100000) {\
1964           clockTicks++;\
1965           CPUSwitchMode(reg[17].I & 0x1f, false);\
1966         }\
1967         if(armState) {\
1968           reg[15].I &= 0xFFFFFFFC;\
1969           armNextPC = reg[15].I;\
1970           reg[15].I += 4;\
1971         } else {\
1972           reg[15].I &= 0xFFFFFFFE;\
1973           armNextPC = reg[15].I;\
1974           reg[15].I += 2;\
1975         }\
1976       } else {\
1977         OPCODE \
1978       }\
1979     }\
1980     break;\
1981   case BASE+1:\
1982     {\
1983       /* OP Rd,Rb,Rm LSL Rs */\
1984       clockTicks++;\
1985       int base = (opcode >> 16) & 0x0F;\
1986       int shift = reg[(opcode >> 8)&15].B.B0;\
1987       int dest = (opcode>>12) & 15;\
1988       u32 value;\
1989       if(shift) {\
1990         if(shift == 32) {\
1991           value = 0;\
1992         } else if(shift < 32) {\
1993            ARITHMETIC_LSL_REG\
1994         } else value = 0;\
1995       } else {\
1996         value = reg[opcode & 0x0F].I;\
1997       }\
1998       if(dest == 15) {\
1999         OPCODE2\
2000         /* todo */\
2001         if(opcode & 0x00100000) {\
2002           clockTicks++;\
2003           CPUSwitchMode(reg[17].I & 0x1f, false);\
2004         }\
2005         if(armState) {\
2006           reg[15].I &= 0xFFFFFFFC;\
2007           armNextPC = reg[15].I;\
2008           reg[15].I += 4;\
2009         } else {\
2010           reg[15].I &= 0xFFFFFFFE;\
2011           armNextPC = reg[15].I;\
2012           reg[15].I += 2;\
2013         }\
2014       } else {\
2015         OPCODE \
2016       }\
2017     }\
2018     break;\
2019   case BASE+3:\
2020     {\
2021       /* OP Rd,Rb,Rm LSR Rs */\
2022       clockTicks++;\
2023       int base = (opcode >> 16) & 0x0F;\
2024       int shift = reg[(opcode >> 8)&15].B.B0;\
2025       int dest = (opcode>>12) & 15;\
2026       u32 value;\
2027       if(shift) {\
2028         if(shift == 32) {\
2029           value = 0;\
2030         } else if(shift < 32) {\
2031            ARITHMETIC_LSR_REG\
2032         } else value = 0;\
2033       } else {\
2034         value = reg[opcode & 0x0F].I;\
2035       }\
2036       if(dest == 15) {\
2037         OPCODE2\
2038         /* todo */\
2039         if(opcode & 0x00100000) {\
2040           clockTicks++;\
2041           CPUSwitchMode(reg[17].I & 0x1f, false);\
2042         }\
2043         if(armState) {\
2044           reg[15].I &= 0xFFFFFFFC;\
2045           armNextPC = reg[15].I;\
2046           reg[15].I += 4;\
2047         } else {\
2048           reg[15].I &= 0xFFFFFFFE;\
2049           armNextPC = reg[15].I;\
2050           reg[15].I += 2;\
2051         }\
2052       } else {\
2053         OPCODE \
2054       }\
2055     }\
2056     break;\
2057   case BASE+5:\
2058     {\
2059       /* OP Rd,Rb,Rm ASR Rs */\
2060       clockTicks++;\
2061       int base = (opcode >> 16) & 0x0F;\
2062       int shift = reg[(opcode >> 8)&15].B.B0;\
2063       int dest = (opcode>>12) & 15;\
2064       u32 value;\
2065       if(shift < 32) {\
2066         if(shift) {\
2067            ARITHMETIC_ASR_REG\
2068         } else {\
2069           value = reg[opcode & 0x0F].I;\
2070         }\
2071       } else {\
2072         if(reg[opcode & 0x0F].I & 0x80000000){\
2073           value = 0xFFFFFFFF;\
2074         } else value = 0;\
2075       }\
2076       if(dest == 15) {\
2077         OPCODE2\
2078         /* todo */\
2079         if(opcode & 0x00100000) {\
2080           clockTicks++;\
2081           CPUSwitchMode(reg[17].I & 0x1f, false);\
2082         }\
2083         if(armState) {\
2084           reg[15].I &= 0xFFFFFFFC;\
2085           armNextPC = reg[15].I;\
2086           reg[15].I += 4;\
2087         } else {\
2088           reg[15].I &= 0xFFFFFFFE;\
2089           armNextPC = reg[15].I;\
2090           reg[15].I += 2;\
2091         }\
2092       } else {\
2093         OPCODE \
2094       }\
2095     }\
2096     break;\
2097   case BASE+7:\
2098     {\
2099       /* OP Rd,Rb,Rm ROR Rs */\
2100       clockTicks++;\
2101       int base = (opcode >> 16) & 0x0F;\
2102       int shift = reg[(opcode >> 8)&15].B.B0;\
2103       int dest = (opcode>>12) & 15;\
2104       u32 value;\
2105       if(shift) {\
2106         shift &= 0x1f;\
2107         if(shift) {\
2108            ARITHMETIC_ROR_REG\
2109         } else {\
2110            value = reg[opcode & 0x0F].I;\
2111         }\
2112       } else {\
2113         value = reg[opcode & 0x0F].I;\
2114       }\
2115       if(dest == 15) {\
2116         OPCODE2\
2117         /* todo */\
2118         if(opcode & 0x00100000) {\
2119           clockTicks++;\
2120           CPUSwitchMode(reg[17].I & 0x1f, false);\
2121         }\
2122         if(armState) {\
2123           reg[15].I &= 0xFFFFFFFC;\
2124           armNextPC = reg[15].I;\
2125           reg[15].I += 4;\
2126         } else {\
2127           reg[15].I &= 0xFFFFFFFE;\
2128           armNextPC = reg[15].I;\
2129           reg[15].I += 2;\
2130         }\
2131       } else {\
2132         OPCODE \
2133       }\
2134     }\
2135     break;\
2136   case BASE+0x200:\
2137   case BASE+0x201:\
2138   case BASE+0x202:\
2139   case BASE+0x203:\
2140   case BASE+0x204:\
2141   case BASE+0x205:\
2142   case BASE+0x206:\
2143   case BASE+0x207:\
2144   case BASE+0x208:\
2145   case BASE+0x209:\
2146   case BASE+0x20a:\
2147   case BASE+0x20b:\
2148   case BASE+0x20c:\
2149   case BASE+0x20d:\
2150   case BASE+0x20e:\
2151   case BASE+0x20f:\
2152     {\
2153       int shift = (opcode & 0xF00) >> 7;\
2154       int base = (opcode >> 16) & 0x0F;\
2155       int dest = (opcode >> 12) & 0x0F;\
2156       u32 value;\
2157       {\
2158         ARITHMETIC_ROR_IMM\
2159       }\
2160       if(dest == 15) {\
2161         OPCODE2\
2162         /* todo */\
2163         if(opcode & 0x00100000) {\
2164           clockTicks++;\
2165           CPUSwitchMode(reg[17].I & 0x1f, false);\
2166         }\
2167         if(armState) {\
2168           reg[15].I &= 0xFFFFFFFC;\
2169           armNextPC = reg[15].I;\
2170           reg[15].I += 4;\
2171         } else {\
2172           reg[15].I &= 0xFFFFFFFE;\
2173           armNextPC = reg[15].I;\
2174           reg[15].I += 2;\
2175         }\
2176       } else {\
2177         OPCODE \
2178       }\
2179     }\
2180     break;
2181 
2182   u32 opcode = CPUReadMemoryQuick(armNextPC);
2183 
2184   clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15];
2185 
2186 #ifndef FINAL_VERSION
2187   if(armNextPC == stop) {
2188     armNextPC++;
2189   }
2190 #endif
2191 
2192   armNextPC = reg[15].I;
2193   reg[15].I += 4;
2194   int cond = opcode >> 28;
2195   // suggested optimization for frequent cases
2196   bool cond_res;
2197   if(cond == 0x0e) {
2198     cond_res = true;
2199   } else {
2200     switch(cond) {
2201     case 0x00: // EQ
2202       cond_res = Z_FLAG;
2203       break;
2204     case 0x01: // NE
2205       cond_res = !Z_FLAG;
2206       break;
2207     case 0x02: // CS
2208       cond_res = C_FLAG;
2209       break;
2210     case 0x03: // CC
2211       cond_res = !C_FLAG;
2212       break;
2213     case 0x04: // MI
2214       cond_res = N_FLAG;
2215       break;
2216     case 0x05: // PL
2217       cond_res = !N_FLAG;
2218       break;
2219     case 0x06: // VS
2220       cond_res = V_FLAG;
2221       break;
2222     case 0x07: // VC
2223       cond_res = !V_FLAG;
2224       break;
2225     case 0x08: // HI
2226       cond_res = C_FLAG && !Z_FLAG;
2227       break;
2228     case 0x09: // LS
2229       cond_res = !C_FLAG || Z_FLAG;
2230       break;
2231     case 0x0A: // GE
2232       cond_res = N_FLAG == V_FLAG;
2233       break;
2234     case 0x0B: // LT
2235       cond_res = N_FLAG != V_FLAG;
2236       break;
2237     case 0x0C: // GT
2238       cond_res = !Z_FLAG &&(N_FLAG == V_FLAG);
2239       break;
2240     case 0x0D: // LE
2241       cond_res = Z_FLAG || (N_FLAG != V_FLAG);
2242       break;
2243     case 0x0E:
2244       cond_res = true;
2245       break;
2246     case 0x0F:
2247     default:
2248       // ???
2249       cond_res = false;
2250       break;
2251     }
2252   }
2253 
2254 if(cond_res) {
2255   switch(((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F)) {
2256     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND,  OP_AND, 0x000);
2257     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010);
2258   case 0x009:
2259     {
2260       // MUL Rd, Rm, Rs
2261       int dest = (opcode >> 16) & 0x0F;
2262       int mult = (opcode & 0x0F);
2263       u32 rs = reg[(opcode >> 8) & 0x0F].I;
2264       reg[dest].I = reg[mult].I * rs;
2265       if(((s32)rs)<0)
2266         rs = ~rs;
2267       if((rs & 0xFFFFFF00) == 0)
2268         clockTicks += 2;
2269       else if ((rs & 0xFFFF0000) == 0)
2270         clockTicks += 3;
2271       else if ((rs & 0xFF000000) == 0)
2272         clockTicks += 4;
2273       else
2274         clockTicks += 5;
2275     }
2276     break;
2277   case 0x019:
2278     {
2279       // MULS Rd, Rm, Rs
2280       int dest = (opcode >> 16) & 0x0F;
2281       int mult = (opcode & 0x0F);
2282       u32 rs = reg[(opcode >> 8) & 0x0F].I;
2283       reg[dest].I = reg[mult].I * rs;
2284       N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
2285       Z_FLAG = (reg[dest].I) ? false : true;
2286       if(((s32)rs)<0)
2287         rs = ~rs;
2288       if((rs & 0xFFFFFF00) == 0)
2289         clockTicks += 2;
2290       else if ((rs & 0xFFFF0000) == 0)
2291         clockTicks += 3;
2292       else if ((rs & 0xFF000000) == 0)
2293         clockTicks += 4;
2294       else
2295         clockTicks += 5;
2296     }
2297     break;
2298   case 0x00b:
2299   case 0x02b:
2300     {
2301       // STRH Rd, [Rn], -Rm
2302       int base = (opcode >> 16) & 0x0F;
2303       int dest = (opcode >> 12) & 0x0F;
2304       u32 address = reg[base].I;
2305       int offset = reg[opcode & 0x0F].I;
2306       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2307       CPUWriteHalfWord(address, reg[dest].W.W0);
2308       address -= offset;
2309       reg[base].I = address;
2310     }
2311     break;
2312   case 0x04b:
2313   case 0x06b:
2314     {
2315       // STRH Rd, [Rn], #-offset
2316       int base = (opcode >> 16) & 0x0F;
2317       int dest = (opcode >> 12) & 0x0F;
2318       u32 address = reg[base].I;
2319       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2320       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2321       CPUWriteHalfWord(address, reg[dest].W.W0);
2322       address -= offset;
2323       reg[base].I = address;
2324     }
2325     break;
2326   case 0x08b:
2327   case 0x0ab:
2328     {
2329       // STRH Rd, [Rn], Rm
2330       int base = (opcode >> 16) & 0x0F;
2331       int dest = (opcode >> 12) & 0x0F;
2332       u32 address = reg[base].I;
2333       int offset = reg[opcode & 0x0F].I;
2334       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2335       CPUWriteHalfWord(address, reg[dest].W.W0);
2336       address += offset;
2337       reg[base].I = address;
2338     }
2339     break;
2340   case 0x0cb:
2341   case 0x0eb:
2342     {
2343       // STRH Rd, [Rn], #offset
2344       int base = (opcode >> 16) & 0x0F;
2345       int dest = (opcode >> 12) & 0x0F;
2346       u32 address = reg[base].I;
2347       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2348       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2349       CPUWriteHalfWord(address, reg[dest].W.W0);
2350       address += offset;
2351       reg[base].I = address;
2352     }
2353     break;
2354   case 0x10b:
2355     {
2356       // STRH Rd, [Rn, -Rm]
2357       int base = (opcode >> 16) & 0x0F;
2358       int dest = (opcode >> 12) & 0x0F;
2359       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2360       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2361       CPUWriteHalfWord(address, reg[dest].W.W0);
2362     }
2363     break;
2364   case 0x12b:
2365     {
2366       // STRH Rd, [Rn, -Rm]!
2367       int base = (opcode >> 16) & 0x0F;
2368       int dest = (opcode >> 12) & 0x0F;
2369       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2370       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2371       CPUWriteHalfWord(address, reg[dest].W.W0);
2372       reg[base].I = address;
2373     }
2374     break;
2375   case 0x14b:
2376     {
2377       // STRH Rd, [Rn, -#offset]
2378       int base = (opcode >> 16) & 0x0F;
2379       int dest = (opcode >> 12) & 0x0F;
2380       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2381       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2382       CPUWriteHalfWord(address, reg[dest].W.W0);
2383     }
2384     break;
2385   case 0x16b:
2386     {
2387       // STRH Rd, [Rn, -#offset]!
2388       int base = (opcode >> 16) & 0x0F;
2389       int dest = (opcode >> 12) & 0x0F;
2390       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2391       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2392       CPUWriteHalfWord(address, reg[dest].W.W0);
2393       reg[base].I = address;
2394     }
2395     break;
2396   case 0x18b:
2397     {
2398       // STRH Rd, [Rn, Rm]
2399       int base = (opcode >> 16) & 0x0F;
2400       int dest = (opcode >> 12) & 0x0F;
2401       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2402       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2403       CPUWriteHalfWord(address, reg[dest].W.W0);
2404     }
2405     break;
2406   case 0x1ab:
2407     {
2408       // STRH Rd, [Rn, Rm]!
2409       int base = (opcode >> 16) & 0x0F;
2410       int dest = (opcode >> 12) & 0x0F;
2411       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2412       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2413       CPUWriteHalfWord(address, reg[dest].W.W0);
2414       reg[base].I = address;
2415     }
2416     break;
2417   case 0x1cb:
2418     {
2419       // STRH Rd, [Rn, #offset]
2420       int base = (opcode >> 16) & 0x0F;
2421       int dest = (opcode >> 12) & 0x0F;
2422       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2423       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2424       CPUWriteHalfWord(address, reg[dest].W.W0);
2425     }
2426     break;
2427   case 0x1eb:
2428     {
2429       // STRH Rd, [Rn, #offset]!
2430       int base = (opcode >> 16) & 0x0F;
2431       int dest = (opcode >> 12) & 0x0F;
2432       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2433       clockTicks += 4 + CPUUpdateTicksAccess16(address);
2434       CPUWriteHalfWord(address, reg[dest].W.W0);
2435       reg[base].I = address;
2436     }
2437     break;
2438   case 0x01b:
2439   case 0x03b:
2440     {
2441       // LDRH Rd, [Rn], -Rm
2442       int base = (opcode >> 16) & 0x0F;
2443       int dest = (opcode >> 12) & 0x0F;
2444       u32 address = reg[base].I;
2445       int offset = reg[opcode & 0x0F].I;
2446       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2447       reg[dest].I = CPUReadHalfWord(address);
2448       if(dest != base) {
2449         address -= offset;
2450         reg[base].I = address;
2451       }
2452     }
2453     break;
2454   case 0x05b:
2455   case 0x07b:
2456     {
2457       // LDRH Rd, [Rn], #-offset
2458       int base = (opcode >> 16) & 0x0F;
2459       int dest = (opcode >> 12) & 0x0F;
2460       u32 address = reg[base].I;
2461       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2462       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2463       reg[dest].I = CPUReadHalfWord(address);
2464       if(dest != base) {
2465         address -= offset;
2466         reg[base].I = address;
2467       }
2468     }
2469     break;
2470   case 0x09b:
2471   case 0x0bb:
2472     {
2473       // LDRH Rd, [Rn], Rm
2474       int base = (opcode >> 16) & 0x0F;
2475       int dest = (opcode >> 12) & 0x0F;
2476       u32 address = reg[base].I;
2477       int offset = reg[opcode & 0x0F].I;
2478       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2479       reg[dest].I = CPUReadHalfWord(address);
2480       if(dest != base) {
2481         address += offset;
2482         reg[base].I = address;
2483       }
2484     }
2485     break;
2486   case 0x0db:
2487   case 0x0fb:
2488     {
2489       // LDRH Rd, [Rn], #offset
2490       int base = (opcode >> 16) & 0x0F;
2491       int dest = (opcode >> 12) & 0x0F;
2492       u32 address = reg[base].I;
2493       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2494       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2495       reg[dest].I = CPUReadHalfWord(address);
2496       if(dest != base) {
2497         address += offset;
2498         reg[base].I = address;
2499       }
2500     }
2501     break;
2502   case 0x11b:
2503     {
2504       // LDRH Rd, [Rn, -Rm]
2505       int base = (opcode >> 16) & 0x0F;
2506       int dest = (opcode >> 12) & 0x0F;
2507       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2508       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2509       reg[dest].I = CPUReadHalfWord(address);
2510     }
2511     break;
2512   case 0x13b:
2513     {
2514       // LDRH Rd, [Rn, -Rm]!
2515       int base = (opcode >> 16) & 0x0F;
2516       int dest = (opcode >> 12) & 0x0F;
2517       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2518       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2519       reg[dest].I = CPUReadHalfWord(address);
2520       if(dest != base)
2521         reg[base].I = address;
2522     }
2523     break;
2524   case 0x15b:
2525     {
2526       // LDRH Rd, [Rn, -#offset]
2527       int base = (opcode >> 16) & 0x0F;
2528       int dest = (opcode >> 12) & 0x0F;
2529       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2530       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2531       reg[dest].I = CPUReadHalfWord(address);
2532     }
2533     break;
2534   case 0x17b:
2535     {
2536       // LDRH Rd, [Rn, -#offset]!
2537       int base = (opcode >> 16) & 0x0F;
2538       int dest = (opcode >> 12) & 0x0F;
2539       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2540       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2541       reg[dest].I = CPUReadHalfWord(address);
2542       if(dest != base)
2543         reg[base].I = address;
2544     }
2545     break;
2546   case 0x19b:
2547     {
2548       // LDRH Rd, [Rn, Rm]
2549       int base = (opcode >> 16) & 0x0F;
2550       int dest = (opcode >> 12) & 0x0F;
2551       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2552       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2553       reg[dest].I = CPUReadHalfWord(address);
2554     }
2555     break;
2556   case 0x1bb:
2557     {
2558       // LDRH Rd, [Rn, Rm]!
2559       int base = (opcode >> 16) & 0x0F;
2560       int dest = (opcode >> 12) & 0x0F;
2561       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2562       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2563       reg[dest].I = CPUReadHalfWord(address);
2564       if(dest != base)
2565         reg[base].I = address;
2566     }
2567     break;
2568   case 0x1db:
2569     {
2570       // LDRH Rd, [Rn, #offset]
2571       int base = (opcode >> 16) & 0x0F;
2572       int dest = (opcode >> 12) & 0x0F;
2573       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2574       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2575       reg[dest].I = CPUReadHalfWord(address);
2576     }
2577     break;
2578   case 0x1fb:
2579     {
2580       // LDRH Rd, [Rn, #offset]!
2581       int base = (opcode >> 16) & 0x0F;
2582       int dest = (opcode >> 12) & 0x0F;
2583       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2584       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2585       reg[dest].I = CPUReadHalfWord(address);
2586       if(dest != base)
2587         reg[base].I = address;
2588     }
2589     break;
2590   case 0x01d:
2591   case 0x03d:
2592     {
2593       // LDRSB Rd, [Rn], -Rm
2594       int base = (opcode >> 16) & 0x0F;
2595       int dest = (opcode >> 12) & 0x0F;
2596       u32 address = reg[base].I;
2597       int offset = reg[opcode & 0x0F].I;
2598       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2599       reg[dest].I = (s8)CPUReadByte(address);
2600       if(dest != base) {
2601         address -= offset;
2602         reg[base].I = address;
2603       }
2604     }
2605     break;
2606   case 0x05d:
2607   case 0x07d:
2608     {
2609       // LDRSB Rd, [Rn], #-offset
2610       int base = (opcode >> 16) & 0x0F;
2611       int dest = (opcode >> 12) & 0x0F;
2612       u32 address = reg[base].I;
2613       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2614       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2615       reg[dest].I = (s8)CPUReadByte(address);
2616       if(dest != base) {
2617         address -= offset;
2618         reg[base].I = address;
2619       }
2620     }
2621     break;
2622   case 0x09d:
2623   case 0x0bd:
2624     {
2625       // LDRSB Rd, [Rn], Rm
2626       int base = (opcode >> 16) & 0x0F;
2627       int dest = (opcode >> 12) & 0x0F;
2628       u32 address = reg[base].I;
2629       int offset = reg[opcode & 0x0F].I;
2630       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2631       reg[dest].I = (s8)CPUReadByte(address);
2632       if(dest != base) {
2633         address += offset;
2634         reg[base].I = address;
2635       }
2636     }
2637     break;
2638   case 0x0dd:
2639   case 0x0fd:
2640     {
2641       // LDRSB Rd, [Rn], #offset
2642       int base = (opcode >> 16) & 0x0F;
2643       int dest = (opcode >> 12) & 0x0F;
2644       u32 address = reg[base].I;
2645       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2646       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2647       reg[dest].I = (s8)CPUReadByte(address);
2648       if(dest != base) {
2649         address += offset;
2650         reg[base].I = address;
2651       }
2652     }
2653     break;
2654   case 0x11d:
2655     {
2656       // LDRSB Rd, [Rn, -Rm]
2657       int base = (opcode >> 16) & 0x0F;
2658       int dest = (opcode >> 12) & 0x0F;
2659       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2660       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2661       reg[dest].I = (s8)CPUReadByte(address);
2662     }
2663     break;
2664   case 0x13d:
2665     {
2666       // LDRSB Rd, [Rn, -Rm]!
2667       int base = (opcode >> 16) & 0x0F;
2668       int dest = (opcode >> 12) & 0x0F;
2669       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2670       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2671       reg[dest].I = (s8)CPUReadByte(address);
2672       if(dest != base)
2673         reg[base].I = address;
2674     }
2675     break;
2676   case 0x15d:
2677     {
2678       // LDRSB Rd, [Rn, -#offset]
2679       int base = (opcode >> 16) & 0x0F;
2680       int dest = (opcode >> 12) & 0x0F;
2681       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2682       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2683       reg[dest].I = (s8)CPUReadByte(address);
2684     }
2685     break;
2686   case 0x17d:
2687     {
2688       // LDRSB Rd, [Rn, -#offset]!
2689       int base = (opcode >> 16) & 0x0F;
2690       int dest = (opcode >> 12) & 0x0F;
2691       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2692       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2693       reg[dest].I = (s8)CPUReadByte(address);
2694       if(dest != base)
2695         reg[base].I = address;
2696     }
2697     break;
2698   case 0x19d:
2699     {
2700       // LDRSB Rd, [Rn, Rm]
2701       int base = (opcode >> 16) & 0x0F;
2702       int dest = (opcode >> 12) & 0x0F;
2703       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2704       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2705       reg[dest].I = (s8)CPUReadByte(address);
2706     }
2707     break;
2708   case 0x1bd:
2709     {
2710       // LDRSB Rd, [Rn, Rm]!
2711       int base = (opcode >> 16) & 0x0F;
2712       int dest = (opcode >> 12) & 0x0F;
2713       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2714       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2715       reg[dest].I = (s8)CPUReadByte(address);
2716       if(dest != base)
2717         reg[base].I = address;
2718     }
2719     break;
2720   case 0x1dd:
2721     {
2722       // LDRSB Rd, [Rn, #offset]
2723       int base = (opcode >> 16) & 0x0F;
2724       int dest = (opcode >> 12) & 0x0F;
2725       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2726       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2727       reg[dest].I = (s8)CPUReadByte(address);
2728     }
2729     break;
2730   case 0x1fd:
2731     {
2732       // LDRSB Rd, [Rn, #offset]!
2733       int base = (opcode >> 16) & 0x0F;
2734       int dest = (opcode >> 12) & 0x0F;
2735       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2736       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2737       reg[dest].I = (s8)CPUReadByte(address);
2738       if(dest != base)
2739         reg[base].I = address;
2740     }
2741     break;
2742   case 0x01f:
2743   case 0x03f:
2744     {
2745       // LDRSH Rd, [Rn], -Rm
2746       int base = (opcode >> 16) & 0x0F;
2747       int dest = (opcode >> 12) & 0x0F;
2748       u32 address = reg[base].I;
2749       int offset = reg[opcode & 0x0F].I;
2750       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2751       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2752       if(dest != base) {
2753         address -= offset;
2754         reg[base].I = address;
2755       }
2756     }
2757     break;
2758   case 0x05f:
2759   case 0x07f:
2760     {
2761       // LDRSH Rd, [Rn], #-offset
2762       int base = (opcode >> 16) & 0x0F;
2763       int dest = (opcode >> 12) & 0x0F;
2764       u32 address = reg[base].I;
2765       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2766       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2767       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2768       if(dest != base) {
2769         address -= offset;
2770         reg[base].I = address;
2771       }
2772     }
2773     break;
2774   case 0x09f:
2775   case 0x0bf:
2776     {
2777       // LDRSH Rd, [Rn], Rm
2778       int base = (opcode >> 16) & 0x0F;
2779       int dest = (opcode >> 12) & 0x0F;
2780       u32 address = reg[base].I;
2781       int offset = reg[opcode & 0x0F].I;
2782       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2783       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2784       if(dest != base) {
2785         address += offset;
2786         reg[base].I = address;
2787       }
2788     }
2789     break;
2790   case 0x0df:
2791   case 0x0ff:
2792     {
2793       // LDRSH Rd, [Rn], #offset
2794       int base = (opcode >> 16) & 0x0F;
2795       int dest = (opcode >> 12) & 0x0F;
2796       u32 address = reg[base].I;
2797       int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
2798       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2799       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2800       if(dest != base) {
2801         address += offset;
2802         reg[base].I = address;
2803       }
2804     }
2805     break;
2806   case 0x11f:
2807     {
2808       // LDRSH Rd, [Rn, -Rm]
2809       int base = (opcode >> 16) & 0x0F;
2810       int dest = (opcode >> 12) & 0x0F;
2811       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2812       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2813       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2814     }
2815     break;
2816   case 0x13f:
2817     {
2818       // LDRSH Rd, [Rn, -Rm]!
2819       int base = (opcode >> 16) & 0x0F;
2820       int dest = (opcode >> 12) & 0x0F;
2821       u32 address = reg[base].I - reg[opcode & 0x0F].I;
2822       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2823       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2824       if(dest != base)
2825         reg[base].I = address;
2826     }
2827     break;
2828   case 0x15f:
2829     {
2830       // LDRSH Rd, [Rn, -#offset]
2831       int base = (opcode >> 16) & 0x0F;
2832       int dest = (opcode >> 12) & 0x0F;
2833       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2834       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2835       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2836     }
2837     break;
2838   case 0x17f:
2839     {
2840       // LDRSH Rd, [Rn, -#offset]!
2841       int base = (opcode >> 16) & 0x0F;
2842       int dest = (opcode >> 12) & 0x0F;
2843       u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
2844       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2845       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2846       if(dest != base)
2847         reg[base].I = address;
2848     }
2849     break;
2850   case 0x19f:
2851     {
2852       // LDRSH Rd, [Rn, Rm]
2853       int base = (opcode >> 16) & 0x0F;
2854       int dest = (opcode >> 12) & 0x0F;
2855       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2856       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2857       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2858     }
2859     break;
2860   case 0x1bf:
2861     {
2862       // LDRSH Rd, [Rn, Rm]!
2863       int base = (opcode >> 16) & 0x0F;
2864       int dest = (opcode >> 12) & 0x0F;
2865       u32 address = reg[base].I + reg[opcode & 0x0F].I;
2866       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2867       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2868       if(dest != base)
2869         reg[base].I = address;
2870     }
2871     break;
2872   case 0x1df:
2873     {
2874       // LDRSH Rd, [Rn, #offset]
2875       int base = (opcode >> 16) & 0x0F;
2876       int dest = (opcode >> 12) & 0x0F;
2877       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2878       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2879       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2880     }
2881     break;
2882   case 0x1ff:
2883     {
2884       // LDRSH Rd, [Rn, #offset]!
2885       int base = (opcode >> 16) & 0x0F;
2886       int dest = (opcode >> 12) & 0x0F;
2887       u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
2888       clockTicks += 3 + CPUUpdateTicksAccess16(address);
2889       reg[dest].I = (s16)CPUReadHalfWordSigned(address);
2890       if(dest != base)
2891         reg[base].I = address;
2892     }
2893     break;
2894     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR,  OP_EOR, 0x020);
2895     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030);
2896   case 0x029:
2897     {
2898       // MLA Rd, Rm, Rs, Rn
2899       int dest = (opcode >> 16) & 0x0F;
2900       int mult = (opcode & 0x0F);
2901       u32 rs = reg[(opcode >> 8) & 0x0F].I;
2902       reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I;
2903       if(((s32)rs)<0)
2904         rs = ~rs;
2905       if((rs & 0xFFFFFF00) == 0)
2906         clockTicks += 3;
2907       else if ((rs & 0xFFFF0000) == 0)
2908         clockTicks += 4;
2909       else if ((rs & 0xFF000000) == 0)
2910         clockTicks += 5;
2911       else
2912         clockTicks += 6;
2913     }
2914     break;
2915   case 0x039:
2916     {
2917       // MLAS Rd, Rm, Rs, Rn
2918       int dest = (opcode >> 16) & 0x0F;
2919       int mult = (opcode & 0x0F);
2920       u32 rs = reg[(opcode >> 8) & 0x0F].I;
2921       reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I;
2922       N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
2923       Z_FLAG = (reg[dest].I) ? false : true;
2924       if(((s32)rs)<0)
2925         rs = ~rs;
2926       if((rs & 0xFFFFFF00) == 0)
2927         clockTicks += 3;
2928       else if ((rs & 0xFFFF0000) == 0)
2929         clockTicks += 4;
2930       else if ((rs & 0xFF000000) == 0)
2931         clockTicks += 5;
2932       else
2933         clockTicks += 6;
2934     }
2935     break;
2936     ARITHMETIC_DATA_OPCODE(OP_SUB,  OP_SUB, 0x040);
2937     ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050);
2938     ARITHMETIC_DATA_OPCODE(OP_RSB,  OP_RSB, 0x060);
2939     ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070);
2940     ARITHMETIC_DATA_OPCODE(OP_ADD,  OP_ADD, 0x080);
2941     ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090);
2942   case 0x089:
2943     {
2944       // UMULL RdLo, RdHi, Rn, Rs
2945       u32 umult = reg[(opcode & 0x0F)].I;
2946       u32 usource = reg[(opcode >> 8) & 0x0F].I;
2947       int destLo = (opcode >> 12) & 0x0F;
2948       int destHi = (opcode >> 16) & 0x0F;
2949       u64 uTemp = ((u64)umult)*((u64)usource);
2950       reg[destLo].I = (u32)uTemp;
2951       reg[destHi].I = (u32)(uTemp >> 32);
2952       if ((usource & 0xFFFFFF00) == 0)
2953         clockTicks += 2;
2954       else if ((usource & 0xFFFF0000) == 0)
2955         clockTicks += 3;
2956       else if ((usource & 0xFF000000) == 0)
2957         clockTicks += 4;
2958       else
2959         clockTicks += 5;
2960     }
2961     break;
2962   case 0x099:
2963     {
2964       // UMULLS RdLo, RdHi, Rn, Rs
2965       u32 umult = reg[(opcode & 0x0F)].I;
2966       u32 usource = reg[(opcode >> 8) & 0x0F].I;
2967       int destLo = (opcode >> 12) & 0x0F;
2968       int destHi = (opcode >> 16) & 0x0F;
2969       u64 uTemp = ((u64)umult)*((u64)usource);
2970       reg[destLo].I = (u32)uTemp;
2971       reg[destHi].I = (u32)(uTemp >> 32);
2972       Z_FLAG = (uTemp) ? false : true;
2973       N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
2974       if ((usource & 0xFFFFFF00) == 0)
2975         clockTicks += 2;
2976       else if ((usource & 0xFFFF0000) == 0)
2977         clockTicks += 3;
2978       else if ((usource & 0xFF000000) == 0)
2979         clockTicks += 4;
2980       else
2981         clockTicks += 5;
2982     }
2983     break;
2984     ARITHMETIC_DATA_OPCODE(OP_ADC,  OP_ADC, 0x0a0);
2985     ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0);
2986   case 0x0a9:
2987     {
2988       // UMLAL RdLo, RdHi, Rn, Rs
2989       u32 umult = reg[(opcode & 0x0F)].I;
2990       u32 usource = reg[(opcode >> 8) & 0x0F].I;
2991       int destLo = (opcode >> 12) & 0x0F;
2992       int destHi = (opcode >> 16) & 0x0F;
2993       u64 uTemp = (u64)reg[destHi].I;
2994       uTemp <<= 32;
2995       uTemp |= (u64)reg[destLo].I;
2996       uTemp += ((u64)umult)*((u64)usource);
2997       reg[destLo].I = (u32)uTemp;
2998       reg[destHi].I = (u32)(uTemp >> 32);
2999       if ((usource & 0xFFFFFF00) == 0)
3000         clockTicks += 3;
3001       else if ((usource & 0xFFFF0000) == 0)
3002         clockTicks += 4;
3003       else if ((usource & 0xFF000000) == 0)
3004         clockTicks += 5;
3005       else
3006         clockTicks += 6;
3007     }
3008     break;
3009   case 0x0b9:
3010     {
3011       // UMLALS RdLo, RdHi, Rn, Rs
3012       u32 umult = reg[(opcode & 0x0F)].I;
3013       u32 usource = reg[(opcode >> 8) & 0x0F].I;
3014       int destLo = (opcode >> 12) & 0x0F;
3015       int destHi = (opcode >> 16) & 0x0F;
3016       u64 uTemp = (u64)reg[destHi].I;
3017       uTemp <<= 32;
3018       uTemp |= (u64)reg[destLo].I;
3019       uTemp += ((u64)umult)*((u64)usource);
3020       reg[destLo].I = (u32)uTemp;
3021       reg[destHi].I = (u32)(uTemp >> 32);
3022       Z_FLAG = (uTemp) ? false : true;
3023       N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
3024       if ((usource & 0xFFFFFF00) == 0)
3025         clockTicks += 3;
3026       else if ((usource & 0xFFFF0000) == 0)
3027         clockTicks += 4;
3028       else if ((usource & 0xFF000000) == 0)
3029         clockTicks += 5;
3030       else
3031         clockTicks += 6;
3032     }
3033     break;
3034     ARITHMETIC_DATA_OPCODE(OP_SBC,  OP_SBC, 0x0c0);
3035     ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0);
3036   case 0x0c9:
3037     {
3038       // SMULL RdLo, RdHi, Rm, Rs
3039       int destLo = (opcode >> 12) & 0x0F;
3040       int destHi = (opcode >> 16) & 0x0F;
3041       u32 rs = reg[(opcode >> 8) & 0x0F].I;
3042       s64 m = (s32)reg[(opcode & 0x0F)].I;
3043       s64 s = (s32)rs;
3044       s64 sTemp = m*s;
3045       reg[destLo].I = (u32)sTemp;
3046       reg[destHi].I = (u32)(sTemp >> 32);
3047       if(((s32)rs) < 0)
3048         rs = ~rs;
3049       if((rs & 0xFFFFFF00) == 0)
3050         clockTicks += 2;
3051       else if((rs & 0xFFFF0000) == 0)
3052         clockTicks += 3;
3053       else if((rs & 0xFF000000) == 0)
3054         clockTicks += 4;
3055       else
3056         clockTicks += 5;
3057     }
3058     break;
3059   case 0x0d9:
3060     {
3061       // SMULLS RdLo, RdHi, Rm, Rs
3062       int destLo = (opcode >> 12) & 0x0F;
3063       int destHi = (opcode >> 16) & 0x0F;
3064       u32 rs = reg[(opcode >> 8) & 0x0F].I;
3065       s64 m = (s32)reg[(opcode & 0x0F)].I;
3066       s64 s = (s32)rs;
3067       s64 sTemp = m*s;
3068       reg[destLo].I = (u32)sTemp;
3069       reg[destHi].I = (u32)(sTemp >> 32);
3070       Z_FLAG = (sTemp) ? false : true;
3071       N_FLAG = (sTemp < 0) ? true : false;
3072       if(((s32)rs) < 0)
3073         rs = ~rs;
3074       if((rs & 0xFFFFFF00) == 0)
3075         clockTicks += 2;
3076       else if((rs & 0xFFFF0000) == 0)
3077         clockTicks += 3;
3078       else if((rs & 0xFF000000) == 0)
3079         clockTicks += 4;
3080       else
3081         clockTicks += 5;
3082     }
3083     break;
3084     ARITHMETIC_DATA_OPCODE(OP_RSC,  OP_RSC, 0x0e0);
3085     ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0);
3086   case 0x0e9:
3087     {
3088       // SMLAL RdLo, RdHi, Rm, Rs
3089       int destLo = (opcode >> 12) & 0x0F;
3090       int destHi = (opcode >> 16) & 0x0F;
3091       u32 rs = reg[(opcode >> 8) & 0x0F].I;
3092       s64 m = (s32)reg[(opcode & 0x0F)].I;
3093       s64 s = (s32)rs;
3094       s64 sTemp = (u64)reg[destHi].I;
3095       sTemp <<= 32;
3096       sTemp |= (u64)reg[destLo].I;
3097       sTemp += m*s;
3098       reg[destLo].I = (u32)sTemp;
3099       reg[destHi].I = (u32)(sTemp >> 32);
3100       if(((s32)rs) < 0)
3101         rs = ~rs;
3102       if((rs & 0xFFFFFF00) == 0)
3103         clockTicks += 3;
3104       else if((rs & 0xFFFF0000) == 0)
3105         clockTicks += 4;
3106       else if((rs & 0xFF000000) == 0)
3107         clockTicks += 5;
3108       else
3109         clockTicks += 6;
3110     }
3111     break;
3112   case 0x0f9:
3113     {
3114       // SMLALS RdLo, RdHi, Rm, Rs
3115       int destLo = (opcode >> 12) & 0x0F;
3116       int destHi = (opcode >> 16) & 0x0F;
3117       u32 rs = reg[(opcode >> 8) & 0x0F].I;
3118       s64 m = (s32)reg[(opcode & 0x0F)].I;
3119       s64 s = (s32)rs;
3120       s64 sTemp = (u64)reg[destHi].I;
3121       sTemp <<= 32;
3122       sTemp |= (u64)reg[destLo].I;
3123       sTemp += m*s;
3124       reg[destLo].I = (u32)sTemp;
3125       reg[destHi].I = (u32)(sTemp >> 32);
3126       Z_FLAG = (sTemp) ? false : true;
3127       N_FLAG = (sTemp < 0) ? true : false;
3128       if(((s32)rs) < 0)
3129         rs = ~rs;
3130       if((rs & 0xFFFFFF00) == 0)
3131         clockTicks += 3;
3132       else if((rs & 0xFFFF0000) == 0)
3133         clockTicks += 4;
3134       else if((rs & 0xFF000000) == 0)
3135         clockTicks += 5;
3136       else
3137         clockTicks += 6;
3138     }
3139     break;
3140     LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110);
3141   case 0x100:
3142     // MRS Rd, CPSR
3143     // TODO: check if right instruction....
3144     CPUUpdateCPSR();
3145     reg[(opcode >> 12) & 0x0F].I = reg[16].I;
3146     break;
3147   case 0x109:
3148     {
3149       // SWP Rd, Rm, [Rn]
3150       u32 address = reg[(opcode >> 16) & 15].I;
3151       u32 temp = CPUReadMemory(address);
3152       CPUWriteMemory(address, reg[opcode&15].I);
3153       reg[(opcode >> 12) & 15].I = temp;
3154     }
3155     break;
3156     LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130);
3157   case 0x120:
3158     {
3159       // MSR CPSR_fields, Rm
3160       CPUUpdateCPSR();
3161       u32 value = reg[opcode & 15].I;
3162       u32 newValue = reg[16].I;
3163       if(armMode > 0x10) {
3164         if(opcode & 0x00010000)
3165           newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3166         if(opcode & 0x00020000)
3167           newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3168         if(opcode & 0x00040000)
3169           newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3170       }
3171       if(opcode & 0x00080000)
3172         newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3173       newValue |= 0x10;
3174       CPUSwitchMode(newValue & 0x1f, false);
3175       reg[16].I = newValue;
3176       CPUUpdateFlags();
3177     }
3178     break;
3179   case 0x121:
3180     {
3181       // BX Rm
3182       // TODO: check if right instruction...
3183       clockTicks += 3;
3184       int base = opcode & 0x0F;
3185       armState = reg[base].I & 1 ? false : true;
3186       if(armState) {
3187         reg[15].I = reg[base].I & 0xFFFFFFFC;
3188         armNextPC = reg[15].I;
3189         reg[15].I += 4;
3190       } else {
3191         reg[15].I = reg[base].I & 0xFFFFFFFE;
3192         armNextPC = reg[15].I;
3193         reg[15].I += 2;
3194       }
3195     }
3196     break;
3197     ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150);
3198   case 0x140:
3199     // MRS Rd, SPSR
3200     // TODO: check if right instruction...
3201     reg[(opcode >> 12) & 0x0F].I = reg[17].I;
3202     break;
3203   case 0x149:
3204     {
3205       // SWPB Rd, Rm, [Rn]
3206       u32 address = reg[(opcode >> 16) & 15].I;
3207       u32 temp = CPUReadByte(address);
3208       CPUWriteByte(address, reg[opcode&15].B.B0);
3209       reg[(opcode>>12)&15].I = temp;
3210     }
3211     break;
3212     ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170);
3213   case 0x160:
3214     {
3215       // MSR SPSR_fields, Rm
3216       u32 value = reg[opcode & 15].I;
3217       if(armMode > 0x10 && armMode < 0x1f) {
3218         if(opcode & 0x00010000)
3219           reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3220         if(opcode & 0x00020000)
3221           reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3222         if(opcode & 0x00040000)
3223           reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3224         if(opcode & 0x00080000)
3225           reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3226       }
3227     }
3228     break;
3229     LOGICAL_DATA_OPCODE             (OP_ORR,  OP_ORR, 0x180);
3230     LOGICAL_DATA_OPCODE             (OP_ORRS, OP_ORR, 0x190);
3231     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV,  OP_MOV, 0x1a0);
3232     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0);
3233     LOGICAL_DATA_OPCODE             (OP_BIC,  OP_BIC, 0x1c0);
3234     LOGICAL_DATA_OPCODE             (OP_BICS, OP_BIC, 0x1d0);
3235     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN,  OP_MVN, 0x1e0);
3236     LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0);
3237 #ifdef BKPT_SUPPORT
3238   case 0x127:
3239   case 0x7ff: // for GDB support
3240     extern void (*dbgSignal)(int,int);
3241     reg[15].I -= 4;
3242     armNextPC -= 4;
3243     dbgSignal(5, (opcode & 0x0f)|((opcode>>4) & 0xfff0));
3244     return;
3245 #endif
3246   case 0x320:
3247   case 0x321:
3248   case 0x322:
3249   case 0x323:
3250   case 0x324:
3251   case 0x325:
3252   case 0x326:
3253   case 0x327:
3254   case 0x328:
3255   case 0x329:
3256   case 0x32a:
3257   case 0x32b:
3258   case 0x32c:
3259   case 0x32d:
3260   case 0x32e:
3261   case 0x32f:
3262     {
3263       // MSR CPSR_fields, #
3264       CPUUpdateCPSR();
3265       u32 value = opcode & 0xFF;
3266       int shift = (opcode & 0xF00) >> 7;
3267       if(shift) {
3268         ROR_IMM_MSR;
3269       }
3270       u32 newValue = reg[16].I;
3271       if(armMode > 0x10) {
3272         if(opcode & 0x00010000)
3273           newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3274         if(opcode & 0x00020000)
3275           newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3276         if(opcode & 0x00040000)
3277           newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3278       }
3279       if(opcode & 0x00080000)
3280         newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3281 
3282       newValue |= 0x10;
3283 
3284       CPUSwitchMode(newValue & 0x1f, false);
3285       reg[16].I = newValue;
3286       CPUUpdateFlags();
3287     }
3288     break;
3289   case 0x360:
3290   case 0x361:
3291   case 0x362:
3292   case 0x363:
3293   case 0x364:
3294   case 0x365:
3295   case 0x366:
3296   case 0x367:
3297   case 0x368:
3298   case 0x369:
3299   case 0x36a:
3300   case 0x36b:
3301   case 0x36c:
3302   case 0x36d:
3303   case 0x36e:
3304   case 0x36f:
3305     {
3306       // MSR SPSR_fields, #
3307       if(armMode > 0x10 && armMode < 0x1f) {
3308         u32 value = opcode & 0xFF;
3309         int shift = (opcode & 0xF00) >> 7;
3310         if(shift) {
3311           ROR_IMM_MSR;
3312         }
3313         if(opcode & 0x00010000)
3314           reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3315         if(opcode & 0x00020000)
3316           reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3317         if(opcode & 0x00040000)
3318           reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3319         if(opcode & 0x00080000)
3320           reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3321       }
3322     }
3323   break;
3324   CASE_16(0x400)
3325   // T versions shouldn't be different on GBA
3326   CASE_16(0x420)
3327     {
3328       // STR Rd, [Rn], -#
3329       int offset = opcode & 0xFFF;
3330       int dest = (opcode >> 12) & 15;
3331       int base = (opcode >> 16) & 15;
3332       u32 address = reg[base].I;
3333       CPUWriteMemory(address, reg[dest].I);
3334       reg[base].I = address - offset;
3335       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3336     }
3337     break;
3338   CASE_16(0x480)
3339     // T versions shouldn't be different on GBA
3340   CASE_16(0x4a0)
3341     {
3342       // STR Rd, [Rn], #
3343       int offset = opcode & 0xFFF;
3344       int dest = (opcode >> 12) & 15;
3345       int base = (opcode >> 16) & 15;
3346       u32 address = reg[base].I;
3347       CPUWriteMemory(address, reg[dest].I);
3348       reg[base].I = address + offset;
3349       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3350     }
3351     break;
3352   CASE_16(0x500)
3353     {
3354       // STR Rd, [Rn, -#]
3355       int offset = opcode & 0xFFF;
3356       int dest = (opcode >> 12) & 15;
3357       int base = (opcode >> 16) & 15;
3358       u32 address = reg[base].I - offset;
3359       CPUWriteMemory(address, reg[dest].I);
3360       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3361     }
3362     break;
3363   CASE_16(0x520)
3364     {
3365       // STR Rd, [Rn, -#]!
3366       int offset = opcode & 0xFFF;
3367       int dest = (opcode >> 12) & 15;
3368       int base = (opcode >> 16) & 15;
3369       u32 address = reg[base].I - offset;
3370       reg[base].I = address;
3371       CPUWriteMemory(address, reg[dest].I);
3372       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3373     }
3374     break;
3375   CASE_16(0x580)
3376     {
3377       // STR Rd, [Rn, #]
3378       int offset = opcode & 0xFFF;
3379       int dest = (opcode >> 12) & 15;
3380       int base = (opcode >> 16) & 15;
3381       u32 address = reg[base].I + offset;
3382       CPUWriteMemory(address, reg[dest].I);
3383       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3384     }
3385     break;
3386   CASE_16(0x5a0)
3387     {
3388       // STR Rd, [Rn, #]!
3389       int offset = opcode & 0xFFF;
3390       int dest = (opcode >> 12) & 15;
3391       int base = (opcode >> 16) & 15;
3392       u32 address = reg[base].I + offset;
3393       reg[base].I = address;
3394       CPUWriteMemory(address, reg[dest].I);
3395       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3396     }
3397     break;
3398   CASE_16(0x410)
3399     {
3400       // LDR Rd, [Rn], -#
3401       int offset = opcode & 0xFFF;
3402       int dest = (opcode >> 12) & 15;
3403       int base = (opcode >> 16) & 15;
3404       u32 address = reg[base].I;
3405       reg[dest].I = CPUReadMemory(address);
3406       if(dest != base)
3407         reg[base].I -= offset;
3408       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3409       if(dest == 15) {
3410         clockTicks += 2;
3411         reg[15].I &= 0xFFFFFFFC;
3412         armNextPC = reg[15].I;
3413         reg[15].I += 4;
3414       }
3415     }
3416     break;
3417   CASE_16(0x430)
3418     {
3419       // LDRT Rd, [Rn], -#
3420       int offset = opcode & 0xFFF;
3421       int dest = (opcode >> 12) & 15;
3422       int base = (opcode >> 16) & 15;
3423       u32 address = reg[base].I;
3424       reg[dest].I = CPUReadMemory(address);
3425       if(dest != base)
3426         reg[base].I -= offset;
3427       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3428     }
3429     break;
3430   CASE_16(0x490)
3431     {
3432       // LDR Rd, [Rn], #
3433       int offset = opcode & 0xFFF;
3434       int dest = (opcode >> 12) & 15;
3435       int base = (opcode >> 16) & 15;
3436       u32 address = reg[base].I;
3437       reg[dest].I = CPUReadMemory(address);
3438       if(dest != base)
3439         reg[base].I += offset;
3440       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3441       if(dest == 15) {
3442         clockTicks += 2;
3443         reg[15].I &= 0xFFFFFFFC;
3444         armNextPC = reg[15].I;
3445         reg[15].I += 4;
3446       }
3447     }
3448     break;
3449   CASE_16(0x4b0)
3450     {
3451       // LDRT Rd, [Rn], #
3452       int offset = opcode & 0xFFF;
3453       int dest = (opcode >> 12) & 15;
3454       int base = (opcode >> 16) & 15;
3455       u32 address = reg[base].I;
3456       reg[dest].I = CPUReadMemory(address);
3457       if(dest != base)
3458         reg[base].I += offset;
3459       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3460     }
3461     break;
3462   CASE_16(0x510)
3463     {
3464       // LDR Rd, [Rn, -#]
3465       int offset = opcode & 0xFFF;
3466       int dest = (opcode >> 12) & 15;
3467       int base = (opcode >> 16) & 15;
3468       u32 address = reg[base].I - offset;
3469       reg[dest].I = CPUReadMemory(address);
3470       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3471       if(dest == 15) {
3472         clockTicks += 2;
3473         reg[15].I &= 0xFFFFFFFC;
3474         armNextPC = reg[15].I;
3475         reg[15].I += 4;
3476       }
3477     }
3478     break;
3479   CASE_16(0x530)
3480     {
3481       // LDR Rd, [Rn, -#]!
3482       int offset = opcode & 0xFFF;
3483       int dest = (opcode >> 12) & 15;
3484       int base = (opcode >> 16) & 15;
3485       u32 address = reg[base].I - offset;
3486       reg[dest].I = CPUReadMemory(address);
3487       if(dest != base)
3488         reg[base].I = address;
3489       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3490       if(dest == 15) {
3491         clockTicks += 2;
3492         reg[15].I &= 0xFFFFFFFC;
3493         armNextPC = reg[15].I;
3494         reg[15].I += 4;
3495       }
3496     }
3497     break;
3498   CASE_16(0x590)
3499     {
3500       // LDR Rd, [Rn, #]
3501       int offset = opcode & 0xFFF;
3502       int dest = (opcode >> 12) & 15;
3503       int base = (opcode >> 16) & 15;
3504       u32 address = reg[base].I + offset;
3505       reg[dest].I = CPUReadMemory(address);
3506       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3507       if(dest == 15) {
3508         clockTicks += 2;
3509         reg[15].I &= 0xFFFFFFFC;
3510         armNextPC = reg[15].I;
3511         reg[15].I += 4;
3512       }
3513     }
3514     break;
3515   CASE_16(0x5b0)
3516     {
3517       // LDR Rd, [Rn, #]!
3518       int offset = opcode & 0xFFF;
3519       int dest = (opcode >> 12) & 15;
3520       int base = (opcode >> 16) & 15;
3521       u32 address = reg[base].I + offset;
3522       reg[dest].I = CPUReadMemory(address);
3523       if(dest != base)
3524         reg[base].I = address;
3525       clockTicks += 3 + CPUUpdateTicksAccess32(address);
3526       if(dest == 15) {
3527         clockTicks += 2;
3528         reg[15].I &= 0xFFFFFFFC;
3529         armNextPC = reg[15].I;
3530         reg[15].I += 4;
3531       }
3532     }
3533     break;
3534   CASE_16(0x440)
3535     // T versions shouldn't be different on GBA
3536   CASE_16(0x460)
3537     {
3538       // STRB Rd, [Rn], -#
3539       int offset = opcode & 0xFFF;
3540       int dest = (opcode >> 12) & 15;
3541       int base = (opcode >> 16) & 15;
3542       u32 address = reg[base].I;
3543       CPUWriteByte(address, reg[dest].B.B0);
3544       reg[base].I = address - offset;
3545       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3546     }
3547     break;
3548   CASE_16(0x4c0)
3549     // T versions shouldn't be different on GBA
3550   CASE_16(0x4e0)
3551     // STRB Rd, [Rn], #
3552     {
3553       int offset = opcode & 0xFFF;
3554       int dest = (opcode >> 12) & 15;
3555       int base = (opcode >> 16) & 15;
3556       u32 address = reg[base].I;
3557       CPUWriteByte(address, reg[dest].B.B0);
3558       reg[base].I = address + offset;
3559       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3560     }
3561     break;
3562   CASE_16(0x540)
3563     {
3564       // STRB Rd, [Rn, -#]
3565       int offset = opcode & 0xFFF;
3566       int dest = (opcode >> 12) & 15;
3567       int base = (opcode >> 16) & 15;
3568       u32 address = reg[base].I - offset;
3569       CPUWriteByte(address, reg[dest].B.B0);
3570       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3571     }
3572     break;
3573   CASE_16(0x560)
3574     {
3575       // STRB Rd, [Rn, -#]!
3576       int offset = opcode & 0xFFF;
3577       int dest = (opcode >> 12) & 15;
3578       int base = (opcode >> 16) & 15;
3579       u32 address = reg[base].I - offset;
3580       reg[base].I = address;
3581       CPUWriteByte(address, reg[dest].B.B0);
3582       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3583     }
3584     break;
3585   CASE_16(0x5c0)
3586     {
3587       // STRB Rd, [Rn, #]
3588       int offset = opcode & 0xFFF;
3589       int dest = (opcode >> 12) & 15;
3590       int base = (opcode >> 16) & 15;
3591       u32 address = reg[base].I + offset;
3592       CPUWriteByte(address, reg[dest].B.B0);
3593       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3594     }
3595     break;
3596   CASE_16(0x5e0)
3597     {
3598       // STRB Rd, [Rn, #]!
3599       int offset = opcode & 0xFFF;
3600       int dest = (opcode >> 12) & 15;
3601       int base = (opcode >> 16) & 15;
3602       u32 address = reg[base].I + offset;
3603       reg[base].I = address;
3604       CPUWriteByte(address, reg[dest].I);
3605       clockTicks += 2 + CPUUpdateTicksAccess16(address);
3606     }
3607     break;
3608   CASE_16(0x450)
3609     // T versions shouldn't be different
3610   CASE_16(0x470)
3611     {
3612       // LDRB Rd, [Rn], -#
3613       int offset = opcode & 0xFFF;
3614       int dest = (opcode >> 12) & 15;
3615       int base = (opcode >> 16) & 15;
3616       u32 address = reg[base].I;
3617       reg[dest].I = CPUReadByte(address);
3618       if(dest != base)
3619         reg[base].I -= offset;
3620       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3621     }
3622     break;
3623   CASE_16(0x4d0)
3624   CASE_16(0x4f0) // T versions should not be different
3625     {
3626       // LDRB Rd, [Rn], #
3627       int offset = opcode & 0xFFF;
3628       int dest = (opcode >> 12) & 15;
3629       int base = (opcode >> 16) & 15;
3630       u32 address = reg[base].I;
3631       reg[dest].I = CPUReadByte(address);
3632       if(dest != base)
3633         reg[base].I += offset;
3634       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3635     }
3636     break;
3637   CASE_16(0x550)
3638     {
3639       // LDRB Rd, [Rn, -#]
3640       int offset = opcode & 0xFFF;
3641       int dest = (opcode >> 12) & 15;
3642       int base = (opcode >> 16) & 15;
3643       u32 address = reg[base].I - offset;
3644       reg[dest].I = CPUReadByte(address);
3645       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3646     }
3647     break;
3648   CASE_16(0x570)
3649     {
3650       // LDRB Rd, [Rn, -#]!
3651       int offset = opcode & 0xFFF;
3652       int dest = (opcode >> 12) & 15;
3653       int base = (opcode >> 16) & 15;
3654       u32 address = reg[base].I - offset;
3655       reg[dest].I = CPUReadByte(address);
3656       if(dest != base)
3657         reg[base].I = address;
3658       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3659     }
3660     break;
3661   CASE_16(0x5d0)
3662     {
3663       // LDRB Rd, [Rn, #]
3664       int offset = opcode & 0xFFF;
3665       int dest = (opcode >> 12) & 15;
3666       int base = (opcode >> 16) & 15;
3667       u32 address = reg[base].I + offset;
3668       reg[dest].I = CPUReadByte(address);
3669       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3670     }
3671     break;
3672   CASE_16(0x5f0)
3673     {
3674       // LDRB Rd, [Rn, #]!
3675       int offset = opcode & 0xFFF;
3676       int dest = (opcode >> 12) & 15;
3677       int base = (opcode >> 16) & 15;
3678       u32 address = reg[base].I + offset;
3679       reg[dest].I = CPUReadByte(address);
3680       if(dest != base)
3681         reg[base].I = address;
3682       clockTicks += 3 + CPUUpdateTicksAccess16(address);
3683     }
3684     break;
3685   case 0x600:
3686   case 0x608:
3687     // T versions are the same
3688   case 0x620:
3689   case 0x628:
3690     {
3691       // STR Rd, [Rn], -Rm, LSL #
3692       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
3693       int dest = (opcode >> 12) & 15;
3694       int base = (opcode >> 16) & 15;
3695       u32 address = reg[base].I;
3696       CPUWriteMemory(address, reg[dest].I);
3697       reg[base].I = address - offset;
3698       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3699     }
3700     break;
3701   case 0x602:
3702   case 0x60a:
3703     // T versions are the same
3704   case 0x622:
3705   case 0x62a:
3706     {
3707       // STR Rd, [Rn], -Rm, LSR #
3708       int shift = (opcode >> 7) & 31;
3709       int offset = shift ? reg[opcode & 15].I >> shift : 0;
3710       int dest = (opcode >> 12) & 15;
3711       int base = (opcode >> 16) & 15;
3712       u32 address = reg[base].I;
3713       CPUWriteMemory(address, reg[dest].I);
3714       reg[base].I = address - offset;
3715       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3716     }
3717     break;
3718   case 0x604:
3719   case 0x60c:
3720     // T versions are the same
3721   case 0x624:
3722   case 0x62c:
3723     {
3724       // STR Rd, [Rn], -Rm, ASR #
3725       int shift = (opcode >> 7) & 31;
3726       int offset;
3727       if(shift)
3728         offset = (int)((s32)reg[opcode & 15].I >> shift);
3729       else if(reg[opcode & 15].I & 0x80000000)
3730         offset = 0xFFFFFFFF;
3731       else
3732         offset = 0;
3733       int dest = (opcode >> 12) & 15;
3734       int base = (opcode >> 16) & 15;
3735       u32 address = reg[base].I;
3736       CPUWriteMemory(address, reg[dest].I);
3737       reg[base].I = address - offset;
3738       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3739     }
3740     break;
3741   case 0x606:
3742   case 0x60e:
3743     // T versions are the same
3744   case 0x626:
3745   case 0x62e:
3746     {
3747       // STR Rd, [Rn], -Rm, ROR #
3748       int shift = (opcode >> 7) & 31;
3749       u32 value = reg[opcode & 15].I;
3750       if(shift) {
3751         ROR_VALUE;
3752       } else {
3753         RCR_VALUE;
3754       }
3755       int dest = (opcode >> 12) & 15;
3756       int base = (opcode >> 16) & 15;
3757       u32 address = reg[base].I;
3758       CPUWriteMemory(address, reg[dest].I);
3759       reg[base].I = address - value;
3760       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3761     }
3762     break;
3763   case 0x680:
3764   case 0x688:
3765     // T versions are the same
3766   case 0x6a0:
3767   case 0x6a8:
3768     {
3769       // STR Rd, [Rn], Rm, LSL #
3770       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
3771       int dest = (opcode >> 12) & 15;
3772       int base = (opcode >> 16) & 15;
3773       u32 address = reg[base].I;
3774       CPUWriteMemory(address, reg[dest].I);
3775       reg[base].I = address + offset;
3776       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3777     }
3778     break;
3779   case 0x682:
3780   case 0x68a:
3781     // T versions are the same
3782   case 0x6a2:
3783   case 0x6aa:
3784     {
3785       // STR Rd, [Rn], Rm, LSR #
3786       int shift = (opcode >> 7) & 31;
3787       int offset = shift ? reg[opcode & 15].I >> shift : 0;
3788       int dest = (opcode >> 12) & 15;
3789       int base = (opcode >> 16) & 15;
3790       u32 address = reg[base].I;
3791       CPUWriteMemory(address, reg[dest].I);
3792       reg[base].I = address + offset;
3793       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3794     }
3795     break;
3796   case 0x684:
3797   case 0x68c:
3798     // T versions are the same
3799   case 0x6a4:
3800   case 0x6ac:
3801     {
3802       // STR Rd, [Rn], Rm, ASR #
3803       int shift = (opcode >> 7) & 31;
3804       int offset;
3805       if(shift)
3806         offset = (int)((s32)reg[opcode & 15].I >> shift);
3807       else if(reg[opcode & 15].I & 0x80000000)
3808         offset = 0xFFFFFFFF;
3809       else
3810         offset = 0;
3811       int dest = (opcode >> 12) & 15;
3812       int base = (opcode >> 16) & 15;
3813       u32 address = reg[base].I;
3814       CPUWriteMemory(address, reg[dest].I);
3815       reg[base].I = address + offset;
3816       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3817     }
3818     break;
3819   case 0x686:
3820   case 0x68e:
3821     // T versions are the same
3822   case 0x6a6:
3823   case 0x6ae:
3824     {
3825       // STR Rd, [Rn], Rm, ROR #
3826       int shift = (opcode >> 7) & 31;
3827       u32 value = reg[opcode & 15].I;
3828       if(shift) {
3829         ROR_VALUE;
3830       } else {
3831         RCR_VALUE;
3832       }
3833       int dest = (opcode >> 12) & 15;
3834       int base = (opcode >> 16) & 15;
3835       u32 address = reg[base].I;
3836       CPUWriteMemory(address, reg[dest].I);
3837       reg[base].I = address + value;
3838       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3839     }
3840     break;
3841   case 0x700:
3842   case 0x708:
3843     {
3844       // STR Rd, [Rn, -Rm, LSL #]
3845       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
3846       int dest = (opcode >> 12) & 15;
3847       int base = (opcode >> 16) & 15;
3848       u32 address = reg[base].I - offset;
3849       CPUWriteMemory(address, reg[dest].I);
3850       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3851     }
3852     break;
3853   case 0x702:
3854   case 0x70a:
3855     {
3856       // STR Rd, [Rn, -Rm, LSR #]
3857       int shift = (opcode >> 7) & 31;
3858       int offset = shift ? reg[opcode & 15].I >> shift : 0;
3859       int dest = (opcode >> 12) & 15;
3860       int base = (opcode >> 16) & 15;
3861       u32 address = reg[base].I - offset;
3862       CPUWriteMemory(address, reg[dest].I);
3863       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3864     }
3865     break;
3866   case 0x704:
3867   case 0x70c:
3868     {
3869       // STR Rd, [Rn, -Rm, ASR #]
3870       int shift = (opcode >> 7) & 31;
3871       int offset;
3872       if(shift)
3873         offset = (int)((s32)reg[opcode & 15].I >> shift);
3874       else if(reg[opcode & 15].I & 0x80000000)
3875         offset = 0xFFFFFFFF;
3876       else
3877         offset = 0;
3878       int dest = (opcode >> 12) & 15;
3879       int base = (opcode >> 16) & 15;
3880       u32 address = reg[base].I - offset;
3881       CPUWriteMemory(address, reg[dest].I);
3882       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3883     }
3884     break;
3885   case 0x706:
3886   case 0x70e:
3887     {
3888       // STR Rd, [Rn, -Rm, ROR #]
3889       int shift = (opcode >> 7) & 31;
3890       u32 value = reg[opcode & 15].I;
3891       if(shift) {
3892         ROR_VALUE;
3893       } else {
3894         RCR_VALUE;
3895       }
3896       int dest = (opcode >> 12) & 15;
3897       int base = (opcode >> 16) & 15;
3898       u32 address = reg[base].I - value;
3899       CPUWriteMemory(address, reg[dest].I);
3900       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3901     }
3902     break;
3903   case 0x720:
3904   case 0x728:
3905     {
3906       // STR Rd, [Rn, -Rm, LSL #]!
3907       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
3908       int dest = (opcode >> 12) & 15;
3909       int base = (opcode >> 16) & 15;
3910       u32 address = reg[base].I - offset;
3911       reg[base].I = address;
3912       CPUWriteMemory(address, reg[dest].I);
3913       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3914     }
3915     break;
3916   case 0x722:
3917   case 0x72a:
3918     {
3919       // STR Rd, [Rn, -Rm, LSR #]!
3920       int shift = (opcode >> 7) & 31;
3921       int offset = shift ? reg[opcode & 15].I >> shift : 0;
3922       int dest = (opcode >> 12) & 15;
3923       int base = (opcode >> 16) & 15;
3924       u32 address = reg[base].I - offset;
3925       reg[base].I = address;
3926       CPUWriteMemory(address, reg[dest].I);
3927       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3928     }
3929     break;
3930   case 0x724:
3931   case 0x72c:
3932     {
3933       // STR Rd, [Rn, -Rm, ASR #]!
3934       int shift = (opcode >> 7) & 31;
3935       int offset;
3936       if(shift)
3937         offset = (int)((s32)reg[opcode & 15].I >> shift);
3938       else if(reg[opcode & 15].I & 0x80000000)
3939         offset = 0xFFFFFFFF;
3940       else
3941         offset = 0;
3942       int dest = (opcode >> 12) & 15;
3943       int base = (opcode >> 16) & 15;
3944       u32 address = reg[base].I - offset;
3945       reg[base].I = address;
3946       CPUWriteMemory(address, reg[dest].I);
3947       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3948     }
3949     break;
3950   case 0x726:
3951   case 0x72e:
3952     {
3953       // STR Rd, [Rn, -Rm, ROR #]!
3954       int shift = (opcode >> 7) & 31;
3955       u32 value = reg[opcode & 15].I;
3956       if(shift) {
3957         ROR_VALUE;
3958       } else {
3959         RCR_VALUE;
3960       }
3961       int dest = (opcode >> 12) & 15;
3962       int base = (opcode >> 16) & 15;
3963       u32 address = reg[base].I - value;
3964       reg[base].I = address;
3965       CPUWriteMemory(address, reg[dest].I);
3966       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3967     }
3968     break;
3969   case 0x780:
3970   case 0x788:
3971     {
3972       // STR Rd, [Rn, Rm, LSL #]
3973       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
3974       int dest = (opcode >> 12) & 15;
3975       int base = (opcode >> 16) & 15;
3976       u32 address = reg[base].I + offset;
3977       CPUWriteMemory(address, reg[dest].I);
3978       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3979     }
3980     break;
3981   case 0x782:
3982   case 0x78a:
3983     {
3984       // STR Rd, [Rn, Rm, LSR #]
3985       int shift = (opcode >> 7) & 31;
3986       int offset = shift ? reg[opcode & 15].I >> shift : 0;
3987       int dest = (opcode >> 12) & 15;
3988       int base = (opcode >> 16) & 15;
3989       u32 address = reg[base].I + offset;
3990       CPUWriteMemory(address, reg[dest].I);
3991       clockTicks += 2 + CPUUpdateTicksAccess32(address);
3992     }
3993     break;
3994   case 0x784:
3995   case 0x78c:
3996     {
3997       // STR Rd, [Rn, Rm, ASR #]
3998       int shift = (opcode >> 7) & 31;
3999       int offset;
4000       if(shift)
4001         offset = (int)((s32)reg[opcode & 15].I >> shift);
4002       else if(reg[opcode & 15].I & 0x80000000)
4003         offset = 0xFFFFFFFF;
4004       else
4005         offset = 0;
4006       int dest = (opcode >> 12) & 15;
4007       int base = (opcode >> 16) & 15;
4008       u32 address = reg[base].I + offset;
4009       CPUWriteMemory(address, reg[dest].I);
4010       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4011     }
4012     break;
4013   case 0x786:
4014   case 0x78e:
4015     {
4016       // STR Rd, [Rn, Rm, ROR #]
4017       int shift = (opcode >> 7) & 31;
4018       u32 value = reg[opcode & 15].I;
4019       if(shift) {
4020         ROR_VALUE;
4021       } else {
4022         RCR_VALUE;
4023       }
4024       int dest = (opcode >> 12) & 15;
4025       int base = (opcode >> 16) & 15;
4026       u32 address = reg[base].I + value;
4027       CPUWriteMemory(address, reg[dest].I);
4028       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4029     }
4030     break;
4031   case 0x7a0:
4032   case 0x7a8:
4033     {
4034       // STR Rd, [Rn, Rm, LSL #]!
4035       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4036       int dest = (opcode >> 12) & 15;
4037       int base = (opcode >> 16) & 15;
4038       u32 address = reg[base].I + offset;
4039       reg[base].I = address;
4040       CPUWriteMemory(address, reg[dest].I);
4041       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4042     }
4043     break;
4044   case 0x7a2:
4045   case 0x7aa:
4046     {
4047       // STR Rd, [Rn, Rm, LSR #]!
4048       int shift = (opcode >> 7) & 31;
4049       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4050       int dest = (opcode >> 12) & 15;
4051       int base = (opcode >> 16) & 15;
4052       u32 address = reg[base].I + offset;
4053       reg[base].I = address;
4054       CPUWriteMemory(address, reg[dest].I);
4055       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4056     }
4057     break;
4058   case 0x7a4:
4059   case 0x7ac:
4060     {
4061       // STR Rd, [Rn, Rm, ASR #]!
4062       int shift = (opcode >> 7) & 31;
4063       int offset;
4064       if(shift)
4065         offset = (int)((s32)reg[opcode & 15].I >> shift);
4066       else if(reg[opcode & 15].I & 0x80000000)
4067         offset = 0xFFFFFFFF;
4068       else
4069         offset = 0;
4070       int dest = (opcode >> 12) & 15;
4071       int base = (opcode >> 16) & 15;
4072       u32 address = reg[base].I + offset;
4073       reg[base].I = address;
4074       CPUWriteMemory(address, reg[dest].I);
4075       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4076     }
4077     break;
4078   case 0x7a6:
4079   case 0x7ae:
4080     {
4081       // STR Rd, [Rn, Rm, ROR #]!
4082       int shift = (opcode >> 7) & 31;
4083       u32 value = reg[opcode & 15].I;
4084       if(shift) {
4085         ROR_VALUE;
4086       } else {
4087         RCR_VALUE;
4088       }
4089       int dest = (opcode >> 12) & 15;
4090       int base = (opcode >> 16) & 15;
4091       u32 address = reg[base].I + value;
4092       reg[base].I = address;
4093       CPUWriteMemory(address, reg[dest].I);
4094       clockTicks += 2 + CPUUpdateTicksAccess32(address);
4095     }
4096     break;
4097   case 0x610:
4098   case 0x618:
4099     // T versions are the same
4100   case 0x630:
4101   case 0x638:
4102     {
4103       // LDR Rd, [Rn], -Rm, LSL #
4104       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4105       int dest = (opcode >> 12) & 15;
4106       int base = (opcode >> 16) & 15;
4107       u32 address = reg[base].I;
4108       reg[dest].I = CPUReadMemory(address);
4109       if(dest != base)
4110         reg[base].I = address - offset;
4111       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4112       if(dest == 15) {
4113         clockTicks += 2;
4114         reg[15].I &= 0xFFFFFFFC;
4115         armNextPC = reg[15].I;
4116         reg[15].I += 4;
4117       }
4118     }
4119     break;
4120   case 0x612:
4121   case 0x61a:
4122     // T versions are the same
4123   case 0x632:
4124   case 0x63a:
4125     {
4126       // LDR Rd, [Rn], -Rm, LSR #
4127       int shift = (opcode >> 7) & 31;
4128       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4129       int dest = (opcode >> 12) & 15;
4130       int base = (opcode >> 16) & 15;
4131       u32 address = reg[base].I;
4132       reg[dest].I = CPUReadMemory(address);
4133       if(dest != base)
4134         reg[base].I = address - offset;
4135       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4136       if(dest == 15) {
4137         clockTicks += 2;
4138         reg[15].I &= 0xFFFFFFFC;
4139         armNextPC = reg[15].I;
4140         reg[15].I += 4;
4141       }
4142     }
4143     break;
4144   case 0x614:
4145   case 0x61c:
4146     // T versions are the same
4147   case 0x634:
4148   case 0x63c:
4149     {
4150       // LDR Rd, [Rn], -Rm, ASR #
4151       int shift = (opcode >> 7) & 31;
4152       int offset;
4153       if(shift)
4154         offset = (int)((s32)reg[opcode & 15].I >> shift);
4155       else if(reg[opcode & 15].I & 0x80000000)
4156         offset = 0xFFFFFFFF;
4157       else
4158         offset = 0;
4159       int dest = (opcode >> 12) & 15;
4160       int base = (opcode >> 16) & 15;
4161       u32 address = reg[base].I;
4162       reg[dest].I = CPUReadMemory(address);
4163       if(dest != base)
4164         reg[base].I = address - offset;
4165       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4166       if(dest == 15) {
4167         clockTicks += 2;
4168         reg[15].I &= 0xFFFFFFFC;
4169         armNextPC = reg[15].I;
4170         reg[15].I += 4;
4171       }
4172     }
4173     break;
4174   case 0x616:
4175   case 0x61e:
4176     // T versions are the same
4177   case 0x636:
4178   case 0x63e:
4179     {
4180       // LDR Rd, [Rn], -Rm, ROR #
4181       int shift = (opcode >> 7) & 31;
4182       u32 value = reg[opcode & 15].I;
4183       if(shift) {
4184         ROR_VALUE;
4185       } else {
4186         RCR_VALUE;
4187       }
4188       int dest = (opcode >> 12) & 15;
4189       int base = (opcode >> 16) & 15;
4190       u32 address = reg[base].I;
4191       reg[dest].I = CPUReadMemory(address);
4192       if(dest != base)
4193         reg[base].I = address - value;
4194       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4195       if(dest == 15) {
4196         clockTicks += 2;
4197         reg[15].I &= 0xFFFFFFFC;
4198         armNextPC = reg[15].I;
4199         reg[15].I += 4;
4200       }
4201     }
4202     break;
4203   case 0x690:
4204   case 0x698:
4205     // T versions are the same
4206   case 0x6b0:
4207   case 0x6b8:
4208     {
4209       // LDR Rd, [Rn], Rm, LSL #
4210       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4211       int dest = (opcode >> 12) & 15;
4212       int base = (opcode >> 16) & 15;
4213       u32 address = reg[base].I;
4214       reg[dest].I = CPUReadMemory(address);
4215       if(dest != base)
4216         reg[base].I = address + offset;
4217       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4218       if(dest == 15) {
4219         clockTicks += 2;
4220         reg[15].I &= 0xFFFFFFFC;
4221         armNextPC = reg[15].I;
4222         reg[15].I += 4;
4223       }
4224     }
4225     break;
4226   case 0x692:
4227   case 0x69a:
4228     // T versions are the same
4229   case 0x6b2:
4230   case 0x6ba:
4231     {
4232       // LDR Rd, [Rn], Rm, LSR #
4233       int shift = (opcode >> 7) & 31;
4234       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4235       int dest = (opcode >> 12) & 15;
4236       int base = (opcode >> 16) & 15;
4237       u32 address = reg[base].I;
4238       reg[dest].I = CPUReadMemory(address);
4239       if(dest != base)
4240         reg[base].I = address + offset;
4241       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4242       if(dest == 15) {
4243         clockTicks += 2;
4244         reg[15].I &= 0xFFFFFFFC;
4245         armNextPC = reg[15].I;
4246         reg[15].I += 4;
4247       }
4248     }
4249     break;
4250   case 0x694:
4251   case 0x69c:
4252     // T versions are the same
4253   case 0x6b4:
4254   case 0x6bc:
4255     {
4256       // LDR Rd, [Rn], Rm, ASR #
4257       int shift = (opcode >> 7) & 31;
4258       int offset;
4259       if(shift)
4260         offset = (int)((s32)reg[opcode & 15].I >> shift);
4261       else if(reg[opcode & 15].I & 0x80000000)
4262         offset = 0xFFFFFFFF;
4263       else
4264         offset = 0;
4265       int dest = (opcode >> 12) & 15;
4266       int base = (opcode >> 16) & 15;
4267       u32 address = reg[base].I;
4268       reg[dest].I = CPUReadMemory(address);
4269       if(dest != base)
4270         reg[base].I = address + offset;
4271       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4272       if(dest == 15) {
4273         clockTicks += 2;
4274         reg[15].I &= 0xFFFFFFFC;
4275         armNextPC = reg[15].I;
4276         reg[15].I += 4;
4277       }
4278     }
4279     break;
4280   case 0x696:
4281   case 0x69e:
4282     // T versions are the same
4283   case 0x6b6:
4284   case 0x6be:
4285     {
4286       // LDR Rd, [Rn], Rm, ROR #
4287       int shift = (opcode >> 7) & 31;
4288       u32 value = reg[opcode & 15].I;
4289       if(shift) {
4290         ROR_VALUE;
4291       } else {
4292         RCR_VALUE;
4293       }
4294       int dest = (opcode >> 12) & 15;
4295       int base = (opcode >> 16) & 15;
4296       u32 address = reg[base].I;
4297       reg[dest].I = CPUReadMemory(address);
4298       if(dest != base)
4299         reg[base].I = address + value;
4300       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4301       if(dest == 15) {
4302         clockTicks += 2;
4303         reg[15].I &= 0xFFFFFFFC;
4304         armNextPC = reg[15].I;
4305         reg[15].I += 4;
4306       }
4307     }
4308     break;
4309   case 0x710:
4310   case 0x718:
4311     {
4312       // LDR Rd, [Rn, -Rm, LSL #]
4313       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4314       int dest = (opcode >> 12) & 15;
4315       int base = (opcode >> 16) & 15;
4316       u32 address = reg[base].I - offset;
4317       reg[dest].I = CPUReadMemory(address);
4318       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4319       if(dest == 15) {
4320         clockTicks += 2;
4321         reg[15].I &= 0xFFFFFFFC;
4322         armNextPC = reg[15].I;
4323         reg[15].I += 4;
4324       }
4325     }
4326     break;
4327   case 0x712:
4328   case 0x71a:
4329     {
4330       // LDR Rd, [Rn, -Rm, LSR #]
4331       int shift = (opcode >> 7) & 31;
4332       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4333       int dest = (opcode >> 12) & 15;
4334       int base = (opcode >> 16) & 15;
4335       u32 address = reg[base].I - offset;
4336       reg[dest].I = CPUReadMemory(address);
4337       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4338       if(dest == 15) {
4339         clockTicks += 2;
4340         reg[15].I &= 0xFFFFFFFC;
4341         armNextPC = reg[15].I;
4342         reg[15].I += 4;
4343       }
4344     }
4345     break;
4346   case 0x714:
4347   case 0x71c:
4348     {
4349       // LDR Rd, [Rn, -Rm, ASR #]
4350       int shift = (opcode >> 7) & 31;
4351       int offset;
4352       if(shift)
4353         offset = (int)((s32)reg[opcode & 15].I >> shift);
4354       else if(reg[opcode & 15].I & 0x80000000)
4355         offset = 0xFFFFFFFF;
4356       else
4357         offset = 0;
4358       int dest = (opcode >> 12) & 15;
4359       int base = (opcode >> 16) & 15;
4360       u32 address = reg[base].I - offset;
4361       reg[dest].I = CPUReadMemory(address);
4362       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4363       if(dest == 15) {
4364         clockTicks += 2;
4365         reg[15].I &= 0xFFFFFFFC;
4366         armNextPC = reg[15].I;
4367         reg[15].I += 4;
4368       }
4369     }
4370     break;
4371   case 0x716:
4372   case 0x71e:
4373     {
4374       // LDR Rd, [Rn, -Rm, ROR #]
4375       int shift = (opcode >> 7) & 31;
4376       u32 value = reg[opcode & 15].I;
4377       if(shift) {
4378         ROR_VALUE;
4379       } else {
4380         RCR_VALUE;
4381       }
4382       int dest = (opcode >> 12) & 15;
4383       int base = (opcode >> 16) & 15;
4384       u32 address = reg[base].I - value;
4385       reg[dest].I = CPUReadMemory(address);
4386       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4387       if(dest == 15) {
4388         clockTicks += 2;
4389         reg[15].I &= 0xFFFFFFFC;
4390         armNextPC = reg[15].I;
4391         reg[15].I += 4;
4392       }
4393     }
4394     break;
4395   case 0x730:
4396   case 0x738:
4397     {
4398       // LDR Rd, [Rn, -Rm, LSL #]!
4399       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4400       int dest = (opcode >> 12) & 15;
4401       int base = (opcode >> 16) & 15;
4402       u32 address = reg[base].I - offset;
4403       reg[dest].I = CPUReadMemory(address);
4404       if(dest != base)
4405         reg[base].I = address;
4406       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4407       if(dest == 15) {
4408         clockTicks += 2;
4409         reg[15].I &= 0xFFFFFFFC;
4410         armNextPC = reg[15].I;
4411         reg[15].I += 4;
4412       }
4413     }
4414     break;
4415   case 0x732:
4416   case 0x73a:
4417     {
4418       // LDR Rd, [Rn, -Rm, LSR #]!
4419       int shift = (opcode >> 7) & 31;
4420       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4421       int dest = (opcode >> 12) & 15;
4422       int base = (opcode >> 16) & 15;
4423       u32 address = reg[base].I - offset;
4424       reg[dest].I = CPUReadMemory(address);
4425       if(dest != base)
4426         reg[base].I = address;
4427       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4428       if(dest == 15) {
4429         clockTicks += 2;
4430         reg[15].I &= 0xFFFFFFFC;
4431         armNextPC = reg[15].I;
4432         reg[15].I += 4;
4433       }
4434     }
4435     break;
4436   case 0x734:
4437   case 0x73c:
4438     {
4439       // LDR Rd, [Rn, -Rm, ASR #]!
4440       int shift = (opcode >> 7) & 31;
4441       int offset;
4442       if(shift)
4443         offset = (int)((s32)reg[opcode & 15].I >> shift);
4444       else if(reg[opcode & 15].I & 0x80000000)
4445         offset = 0xFFFFFFFF;
4446       else
4447         offset = 0;
4448       int dest = (opcode >> 12) & 15;
4449       int base = (opcode >> 16) & 15;
4450       u32 address = reg[base].I - offset;
4451       reg[dest].I = CPUReadMemory(address);
4452       if(dest != base)
4453         reg[base].I = address;
4454       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4455       if(dest == 15) {
4456         clockTicks += 2;
4457         reg[15].I &= 0xFFFFFFFC;
4458         armNextPC = reg[15].I;
4459         reg[15].I += 4;
4460       }
4461     }
4462     break;
4463   case 0x736:
4464   case 0x73e:
4465     {
4466       // LDR Rd, [Rn, -Rm, ROR #]!
4467       int shift = (opcode >> 7) & 31;
4468       u32 value = reg[opcode & 15].I;
4469       if(shift) {
4470         ROR_VALUE;
4471       } else {
4472         RCR_VALUE;
4473       }
4474       int dest = (opcode >> 12) & 15;
4475       int base = (opcode >> 16) & 15;
4476       u32 address = reg[base].I - value;
4477       reg[dest].I = CPUReadMemory(address);
4478       if(dest != base)
4479         reg[base].I = address;
4480       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4481       if(dest == 15) {
4482         clockTicks += 2;
4483         reg[15].I &= 0xFFFFFFFC;
4484         armNextPC = reg[15].I;
4485         reg[15].I += 4;
4486       }
4487     }
4488     break;
4489   case 0x790:
4490   case 0x798:
4491     {
4492       // LDR Rd, [Rn, Rm, LSL #]
4493       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4494       int dest = (opcode >> 12) & 15;
4495       int base = (opcode >> 16) & 15;
4496       u32 address = reg[base].I + offset;
4497       reg[dest].I = CPUReadMemory(address);
4498       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4499       if(dest == 15) {
4500         clockTicks += 2;
4501         reg[15].I &= 0xFFFFFFFC;
4502         armNextPC = reg[15].I;
4503         reg[15].I += 4;
4504       }
4505     }
4506     break;
4507   case 0x792:
4508   case 0x79a:
4509     {
4510       // LDR Rd, [Rn, Rm, LSR #]
4511       int shift = (opcode >> 7) & 31;
4512       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4513       int dest = (opcode >> 12) & 15;
4514       int base = (opcode >> 16) & 15;
4515       u32 address = reg[base].I + offset;
4516       reg[dest].I = CPUReadMemory(address);
4517       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4518       if(dest == 15) {
4519         clockTicks += 2;
4520         reg[15].I &= 0xFFFFFFFC;
4521         armNextPC = reg[15].I;
4522         reg[15].I += 4;
4523       }
4524     }
4525     break;
4526   case 0x794:
4527   case 0x79c:
4528     {
4529       // LDR Rd, [Rn, Rm, ASR #]
4530       int shift = (opcode >> 7) & 31;
4531       int offset;
4532       if(shift)
4533         offset = (int)((s32)reg[opcode & 15].I >> shift);
4534       else if(reg[opcode & 15].I & 0x80000000)
4535         offset = 0xFFFFFFFF;
4536       else
4537         offset = 0;
4538       int dest = (opcode >> 12) & 15;
4539       int base = (opcode >> 16) & 15;
4540       u32 address = reg[base].I + offset;
4541       reg[dest].I = CPUReadMemory(address);
4542       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4543       if(dest == 15) {
4544         clockTicks += 2;
4545         reg[15].I &= 0xFFFFFFFC;
4546         armNextPC = reg[15].I;
4547         reg[15].I += 4;
4548       }
4549     }
4550     break;
4551   case 0x796:
4552   case 0x79e:
4553     {
4554       // LDR Rd, [Rn, Rm, ROR #]
4555       int shift = (opcode >> 7) & 31;
4556       u32 value = reg[opcode & 15].I;
4557       if(shift) {
4558         ROR_VALUE;
4559       } else {
4560         RCR_VALUE;
4561       }
4562       int dest = (opcode >> 12) & 15;
4563       int base = (opcode >> 16) & 15;
4564       u32 address = reg[base].I + value;
4565       reg[dest].I = CPUReadMemory(address);
4566       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4567       if(dest == 15) {
4568         clockTicks += 2;
4569         reg[15].I &= 0xFFFFFFFC;
4570         armNextPC = reg[15].I;
4571         reg[15].I += 4;
4572       }
4573     }
4574     break;
4575   case 0x7b0:
4576   case 0x7b8:
4577     {
4578       // LDR Rd, [Rn, Rm, LSL #]!
4579       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4580       int dest = (opcode >> 12) & 15;
4581       int base = (opcode >> 16) & 15;
4582       u32 address = reg[base].I + offset;
4583       reg[dest].I = CPUReadMemory(address);
4584       if(dest != base)
4585         reg[base].I = address;
4586       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4587       if(dest == 15) {
4588         clockTicks += 2;
4589         reg[15].I &= 0xFFFFFFFC;
4590         armNextPC = reg[15].I;
4591         reg[15].I += 4;
4592       }
4593     }
4594     break;
4595   case 0x7b2:
4596   case 0x7ba:
4597     {
4598       // LDR Rd, [Rn, Rm, LSR #]!
4599       int shift = (opcode >> 7) & 31;
4600       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4601       int dest = (opcode >> 12) & 15;
4602       int base = (opcode >> 16) & 15;
4603       u32 address = reg[base].I + offset;
4604       reg[dest].I = CPUReadMemory(address);
4605       if(dest != base)
4606         reg[base].I = address;
4607       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4608       if(dest == 15) {
4609         clockTicks += 2;
4610         reg[15].I &= 0xFFFFFFFC;
4611         armNextPC = reg[15].I;
4612         reg[15].I += 4;
4613       }
4614     }
4615     break;
4616   case 0x7b4:
4617   case 0x7bc:
4618     {
4619       // LDR Rd, [Rn, Rm, ASR #]!
4620       int shift = (opcode >> 7) & 31;
4621       int offset;
4622       if(shift)
4623         offset = (int)((s32)reg[opcode & 15].I >> shift);
4624       else if(reg[opcode & 15].I & 0x80000000)
4625         offset = 0xFFFFFFFF;
4626       else
4627         offset = 0;
4628       int dest = (opcode >> 12) & 15;
4629       int base = (opcode >> 16) & 15;
4630       u32 address = reg[base].I + offset;
4631       reg[dest].I = CPUReadMemory(address);
4632       if(dest != base)
4633         reg[base].I = address;
4634       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4635       if(dest == 15) {
4636         clockTicks += 2;
4637         reg[15].I &= 0xFFFFFFFC;
4638         armNextPC = reg[15].I;
4639         reg[15].I += 4;
4640       }
4641     }
4642     break;
4643   case 0x7b6:
4644   case 0x7be:
4645     {
4646       // LDR Rd, [Rn, Rm, ROR #]!
4647       int shift = (opcode >> 7) & 31;
4648       u32 value = reg[opcode & 15].I;
4649       if(shift) {
4650         ROR_VALUE;
4651       } else {
4652         RCR_VALUE;
4653       }
4654       int dest = (opcode >> 12) & 15;
4655       int base = (opcode >> 16) & 15;
4656       u32 address = reg[base].I + value;
4657       reg[dest].I = CPUReadMemory(address);
4658       if(dest != base)
4659         reg[base].I = address;
4660       clockTicks += 3 + CPUUpdateTicksAccess32(address);
4661       if(dest == 15) {
4662         clockTicks += 2;
4663         reg[15].I &= 0xFFFFFFFC;
4664         armNextPC = reg[15].I;
4665         reg[15].I += 4;
4666       }
4667     }
4668     break;
4669   case 0x640:
4670   case 0x648:
4671     // T versions are the same
4672   case 0x660:
4673   case 0x668:
4674     {
4675       // STRB Rd, [Rn], -Rm, LSL #
4676       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4677       int dest = (opcode >> 12) & 15;
4678       int base = (opcode >> 16) & 15;
4679       u32 address = reg[base].I;
4680       CPUWriteByte(address, reg[dest].B.B0);
4681       reg[base].I = address - offset;
4682       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4683     }
4684     break;
4685   case 0x642:
4686   case 0x64a:
4687     // T versions are the same
4688   case 0x662:
4689   case 0x66a:
4690     {
4691       // STRB Rd, [Rn], -Rm, LSR #
4692       int shift = (opcode >> 7) & 31;
4693       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4694       int dest = (opcode >> 12) & 15;
4695       int base = (opcode >> 16) & 15;
4696       u32 address = reg[base].I;
4697       CPUWriteByte(address, reg[dest].B.B0);
4698       reg[base].I = address - offset;
4699       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4700     }
4701     break;
4702   case 0x644:
4703   case 0x64c:
4704     // T versions are the same
4705   case 0x664:
4706   case 0x66c:
4707     {
4708       // STRB Rd, [Rn], -Rm, ASR #
4709       int shift = (opcode >> 7) & 31;
4710       int offset;
4711       if(shift)
4712         offset = (int)((s32)reg[opcode & 15].I >> shift);
4713       else if(reg[opcode & 15].I & 0x80000000)
4714         offset = 0xFFFFFFFF;
4715       else
4716         offset = 0;
4717       int dest = (opcode >> 12) & 15;
4718       int base = (opcode >> 16) & 15;
4719       u32 address = reg[base].I;
4720       CPUWriteByte(address, reg[dest].B.B0);
4721       reg[base].I = address - offset;
4722       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4723     }
4724     break;
4725   case 0x646:
4726   case 0x64e:
4727     // T versions are the same
4728   case 0x666:
4729   case 0x66e:
4730     {
4731       // STRB Rd, [Rn], -Rm, ROR #
4732       int shift = (opcode >> 7) & 31;
4733       u32 value = reg[opcode & 15].I;
4734       if(shift) {
4735         ROR_VALUE;
4736       } else {
4737         RCR_VALUE;
4738       }
4739       int dest = (opcode >> 12) & 15;
4740       int base = (opcode >> 16) & 15;
4741       u32 address = reg[base].I;
4742       CPUWriteByte(address, reg[dest].B.B0);
4743       reg[base].I = address - value;
4744       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4745     }
4746     break;
4747   case 0x6c0:
4748   case 0x6c8:
4749     // T versions are the same
4750   case 0x6e0:
4751   case 0x6e8:
4752     {
4753       // STRB Rd, [Rn], Rm, LSL #
4754       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4755       int dest = (opcode >> 12) & 15;
4756       int base = (opcode >> 16) & 15;
4757       u32 address = reg[base].I;
4758       CPUWriteByte(address, reg[dest].B.B0);
4759       reg[base].I = address + offset;
4760       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4761     }
4762     break;
4763   case 0x6c2:
4764   case 0x6ca:
4765     // T versions are the same
4766   case 0x6e2:
4767   case 0x6ea:
4768     {
4769       // STRB Rd, [Rn], Rm, LSR #
4770       int shift = (opcode >> 7) & 31;
4771       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4772       int dest = (opcode >> 12) & 15;
4773       int base = (opcode >> 16) & 15;
4774       u32 address = reg[base].I;
4775       CPUWriteByte(address, reg[dest].B.B0);
4776       reg[base].I = address + offset;
4777       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4778     }
4779     break;
4780   case 0x6c4:
4781   case 0x6cc:
4782     // T versions are the same
4783   case 0x6e4:
4784   case 0x6ec:
4785     {
4786       // STR Rd, [Rn], Rm, ASR #
4787       int shift = (opcode >> 7) & 31;
4788       int offset;
4789       if(shift)
4790         offset = (int)((s32)reg[opcode & 15].I >> shift);
4791       else if(reg[opcode & 15].I & 0x80000000)
4792         offset = 0xFFFFFFFF;
4793       else
4794         offset = 0;
4795       int dest = (opcode >> 12) & 15;
4796       int base = (opcode >> 16) & 15;
4797       u32 address = reg[base].I;
4798       CPUWriteByte(address, reg[dest].B.B0);
4799       reg[base].I = address + offset;
4800       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4801     }
4802     break;
4803   case 0x6c6:
4804   case 0x6ce:
4805     // T versions are the same
4806   case 0x6e6:
4807   case 0x6ee:
4808     {
4809       // STRB Rd, [Rn], Rm, ROR #
4810       int shift = (opcode >> 7) & 31;
4811       u32 value = reg[opcode & 15].I;
4812       if(shift) {
4813         ROR_VALUE;
4814       } else {
4815         RCR_VALUE;
4816       }
4817       int dest = (opcode >> 12) & 15;
4818       int base = (opcode >> 16) & 15;
4819       u32 address = reg[base].I;
4820       CPUWriteByte(address, reg[dest].B.B0);
4821       reg[base].I = address + value;
4822       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4823     }
4824     break;
4825   case 0x740:
4826   case 0x748:
4827     {
4828       // STRB Rd, [Rn, -Rm, LSL #]
4829       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4830       int dest = (opcode >> 12) & 15;
4831       int base = (opcode >> 16) & 15;
4832       u32 address = reg[base].I - offset;
4833       CPUWriteByte(address, reg[dest].B.B0);
4834       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4835     }
4836     break;
4837   case 0x742:
4838   case 0x74a:
4839     {
4840       // STRB Rd, [Rn, -Rm, LSR #]
4841       int shift = (opcode >> 7) & 31;
4842       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4843       int dest = (opcode >> 12) & 15;
4844       int base = (opcode >> 16) & 15;
4845       u32 address = reg[base].I - offset;
4846       CPUWriteByte(address, reg[dest].B.B0);
4847       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4848     }
4849     break;
4850   case 0x744:
4851   case 0x74c:
4852     {
4853       // STRB Rd, [Rn, -Rm, ASR #]
4854       int shift = (opcode >> 7) & 31;
4855       int offset;
4856       if(shift)
4857         offset = (int)((s32)reg[opcode & 15].I >> shift);
4858       else if(reg[opcode & 15].I & 0x80000000)
4859         offset = 0xFFFFFFFF;
4860       else
4861         offset = 0;
4862       int dest = (opcode >> 12) & 15;
4863       int base = (opcode >> 16) & 15;
4864       u32 address = reg[base].I - offset;
4865       CPUWriteByte(address, reg[dest].B.B0);
4866       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4867     }
4868     break;
4869   case 0x746:
4870   case 0x74e:
4871     {
4872       // STRB Rd, [Rn, -Rm, ROR #]
4873       int shift = (opcode >> 7) & 31;
4874       u32 value = reg[opcode & 15].I;
4875       if(shift) {
4876         ROR_VALUE;
4877       } else {
4878         RCR_VALUE;
4879       }
4880       int dest = (opcode >> 12) & 15;
4881       int base = (opcode >> 16) & 15;
4882       u32 address = reg[base].I - value;
4883       CPUWriteByte(address, reg[dest].B.B0);
4884       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4885     }
4886     break;
4887   case 0x760:
4888   case 0x768:
4889     {
4890       // STRB Rd, [Rn, -Rm, LSL #]!
4891       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4892       int dest = (opcode >> 12) & 15;
4893       int base = (opcode >> 16) & 15;
4894       u32 address = reg[base].I - offset;
4895       reg[base].I = address;
4896       CPUWriteByte(address, reg[dest].B.B0);
4897       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4898     }
4899     break;
4900   case 0x762:
4901   case 0x76a:
4902     {
4903       // STRB Rd, [Rn, -Rm, LSR #]!
4904       int shift = (opcode >> 7) & 31;
4905       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4906       int dest = (opcode >> 12) & 15;
4907       int base = (opcode >> 16) & 15;
4908       u32 address = reg[base].I - offset;
4909       reg[base].I = address;
4910       CPUWriteByte(address, reg[dest].B.B0);
4911       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4912     }
4913     break;
4914   case 0x764:
4915   case 0x76c:
4916     {
4917       // STRB Rd, [Rn, -Rm, ASR #]!
4918       int shift = (opcode >> 7) & 31;
4919       int offset;
4920       if(shift)
4921         offset = (int)((s32)reg[opcode & 15].I >> shift);
4922       else if(reg[opcode & 15].I & 0x80000000)
4923         offset = 0xFFFFFFFF;
4924       else
4925         offset = 0;
4926       int dest = (opcode >> 12) & 15;
4927       int base = (opcode >> 16) & 15;
4928       u32 address = reg[base].I - offset;
4929       reg[base].I = address;
4930       CPUWriteByte(address, reg[dest].B.B0);
4931       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4932     }
4933     break;
4934   case 0x766:
4935   case 0x76e:
4936     {
4937       // STRB Rd, [Rn, -Rm, ROR #]!
4938       int shift = (opcode >> 7) & 31;
4939       u32 value = reg[opcode & 15].I;
4940       if(shift) {
4941         ROR_VALUE;
4942       } else {
4943         RCR_VALUE;
4944       }
4945       int dest = (opcode >> 12) & 15;
4946       int base = (opcode >> 16) & 15;
4947       u32 address = reg[base].I - value;
4948       reg[base].I = address;
4949       CPUWriteByte(address, reg[dest].B.B0);
4950       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4951     }
4952     break;
4953   case 0x7c0:
4954   case 0x7c8:
4955     {
4956       // STRB Rd, [Rn, Rm, LSL #]
4957       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
4958       int dest = (opcode >> 12) & 15;
4959       int base = (opcode >> 16) & 15;
4960       u32 address = reg[base].I + offset;
4961       CPUWriteByte(address, reg[dest].B.B0);
4962       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4963     }
4964     break;
4965   case 0x7c2:
4966   case 0x7ca:
4967     {
4968       // STRB Rd, [Rn, Rm, LSR #]
4969       int shift = (opcode >> 7) & 31;
4970       int offset = shift ? reg[opcode & 15].I >> shift : 0;
4971       int dest = (opcode >> 12) & 15;
4972       int base = (opcode >> 16) & 15;
4973       u32 address = reg[base].I + offset;
4974       CPUWriteByte(address, reg[dest].B.B0);
4975       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4976     }
4977     break;
4978   case 0x7c4:
4979   case 0x7cc:
4980     {
4981       // STRB Rd, [Rn, Rm, ASR #]
4982       int shift = (opcode >> 7) & 31;
4983       int offset;
4984       if(shift)
4985         offset = (int)((s32)reg[opcode & 15].I >> shift);
4986       else if(reg[opcode & 15].I & 0x80000000)
4987         offset = 0xFFFFFFFF;
4988       else
4989         offset = 0;
4990       int dest = (opcode >> 12) & 15;
4991       int base = (opcode >> 16) & 15;
4992       u32 address = reg[base].I + offset;
4993       CPUWriteByte(address, reg[dest].B.B0);
4994       clockTicks += 2 + CPUUpdateTicksAccess16(address);
4995     }
4996     break;
4997   case 0x7c6:
4998   case 0x7ce:
4999     {
5000       // STRB Rd, [Rn, Rm, ROR #]
5001       int shift = (opcode >> 7) & 31;
5002       u32 value = reg[opcode & 15].I;
5003       if(shift) {
5004         ROR_VALUE;
5005       } else {
5006         RCR_VALUE;
5007       }
5008       int dest = (opcode >> 12) & 15;
5009       int base = (opcode >> 16) & 15;
5010       u32 address = reg[base].I + value;
5011       CPUWriteByte(address, reg[dest].B.B0);
5012       clockTicks += 2 + CPUUpdateTicksAccess16(address);
5013     }
5014     break;
5015   case 0x7e0:
5016   case 0x7e8:
5017     {
5018       // STRB Rd, [Rn, Rm, LSL #]!
5019       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5020       int dest = (opcode >> 12) & 15;
5021       int base = (opcode >> 16) & 15;
5022       u32 address = reg[base].I + offset;
5023       reg[base].I = address;
5024       CPUWriteByte(address, reg[dest].B.B0);
5025       clockTicks += 2 + CPUUpdateTicksAccess16(address);
5026     }
5027     break;
5028   case 0x7e2:
5029   case 0x7ea:
5030     {
5031       // STRB Rd, [Rn, Rm, LSR #]!
5032       int shift = (opcode >> 7) & 31;
5033       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5034       int dest = (opcode >> 12) & 15;
5035       int base = (opcode >> 16) & 15;
5036       u32 address = reg[base].I + offset;
5037       reg[base].I = address;
5038       CPUWriteByte(address, reg[dest].B.B0);
5039       clockTicks += 2 + CPUUpdateTicksAccess16(address);
5040     }
5041     break;
5042   case 0x7e4:
5043   case 0x7ec:
5044     {
5045       // STRB Rd, [Rn, Rm, ASR #]!
5046       int shift = (opcode >> 7) & 31;
5047       int offset;
5048       if(shift)
5049         offset = (int)((s32)reg[opcode & 15].I >> shift);
5050       else if(reg[opcode & 15].I & 0x80000000)
5051         offset = 0xFFFFFFFF;
5052       else
5053         offset = 0;
5054       int dest = (opcode >> 12) & 15;
5055       int base = (opcode >> 16) & 15;
5056       u32 address = reg[base].I + offset;
5057       reg[base].I = address;
5058       CPUWriteByte(address, reg[dest].B.B0);
5059       clockTicks += 2 + CPUUpdateTicksAccess16(address);
5060     }
5061     break;
5062   case 0x7e6:
5063   case 0x7ee:
5064     {
5065       // STRB Rd, [Rn, Rm, ROR #]!
5066       int shift = (opcode >> 7) & 31;
5067       u32 value = reg[opcode & 15].I;
5068       if(shift) {
5069         ROR_VALUE;
5070       } else {
5071         RCR_VALUE;
5072       }
5073       int dest = (opcode >> 12) & 15;
5074       int base = (opcode >> 16) & 15;
5075       u32 address = reg[base].I + value;
5076       reg[base].I = address;
5077       CPUWriteByte(address, reg[dest].B.B0);
5078       clockTicks += 2 + CPUUpdateTicksAccess16(address);
5079     }
5080     break;
5081   case 0x650:
5082   case 0x658:
5083     // T versions are the same
5084   case 0x670:
5085   case 0x678:
5086     {
5087       // LDRB Rd, [Rn], -Rm, LSL #
5088       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5089       int dest = (opcode >> 12) & 15;
5090       int base = (opcode >> 16) & 15;
5091       u32 address = reg[base].I;
5092       reg[dest].I = CPUReadByte(address);
5093       if(dest != base)
5094         reg[base].I = address - offset;
5095       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5096     }
5097     break;
5098   case 0x652:
5099   case 0x65a:
5100     // T versions are the same
5101   case 0x672:
5102   case 0x67a:
5103     {
5104       // LDRB Rd, [Rn], -Rm, LSR #
5105       int shift = (opcode >> 7) & 31;
5106       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5107       int dest = (opcode >> 12) & 15;
5108       int base = (opcode >> 16) & 15;
5109       u32 address = reg[base].I;
5110       reg[dest].I = CPUReadByte(address);
5111       if(dest != base)
5112         reg[base].I = address - offset;
5113       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5114     }
5115     break;
5116   case 0x654:
5117   case 0x65c:
5118     // T versions are the same
5119   case 0x674:
5120   case 0x67c:
5121     {
5122       // LDRB Rd, [Rn], -Rm, ASR #
5123       int shift = (opcode >> 7) & 31;
5124       int offset;
5125       if(shift)
5126         offset = (int)((s32)reg[opcode & 15].I >> shift);
5127       else if(reg[opcode & 15].I & 0x80000000)
5128         offset = 0xFFFFFFFF;
5129       else
5130         offset = 0;
5131       int dest = (opcode >> 12) & 15;
5132       int base = (opcode >> 16) & 15;
5133       u32 address = reg[base].I;
5134       reg[dest].I = CPUReadByte(address);
5135       if(dest != base)
5136         reg[base].I = address - offset;
5137       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5138     }
5139     break;
5140   case 0x656:
5141   case 0x65e:
5142     // T versions are the same
5143   case 0x676:
5144   case 0x67e:
5145     {
5146       // LDRB Rd, [Rn], -Rm, ROR #
5147       int shift = (opcode >> 7) & 31;
5148       u32 value = reg[opcode & 15].I;
5149       if(shift) {
5150         ROR_VALUE;
5151       } else {
5152         RCR_VALUE;
5153       }
5154       int dest = (opcode >> 12) & 15;
5155       int base = (opcode >> 16) & 15;
5156       u32 address = reg[base].I;
5157       reg[dest].I = CPUReadByte(address);
5158       if(dest != base)
5159         reg[base].I = address - value;
5160       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5161     }
5162     break;
5163   case 0x6d0:
5164   case 0x6d8:
5165     // T versions are the same
5166   case 0x6f0:
5167   case 0x6f8:
5168     {
5169       // LDRB Rd, [Rn], Rm, LSL #
5170       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5171       int dest = (opcode >> 12) & 15;
5172       int base = (opcode >> 16) & 15;
5173       u32 address = reg[base].I;
5174       reg[dest].I = CPUReadByte(address);
5175       if(dest != base)
5176         reg[base].I = address + offset;
5177       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5178     }
5179     break;
5180   case 0x6d2:
5181   case 0x6da:
5182     // T versions are the same
5183   case 0x6f2:
5184   case 0x6fa:
5185     {
5186       // LDRB Rd, [Rn], Rm, LSR #
5187       int shift = (opcode >> 7) & 31;
5188       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5189       int dest = (opcode >> 12) & 15;
5190       int base = (opcode >> 16) & 15;
5191       u32 address = reg[base].I;
5192       reg[dest].I = CPUReadByte(address);
5193       if(dest != base)
5194         reg[base].I = address + offset;
5195       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5196     }
5197     break;
5198   case 0x6d4:
5199   case 0x6dc:
5200     // T versions are the same
5201   case 0x6f4:
5202   case 0x6fc:
5203     {
5204       // LDRB Rd, [Rn], Rm, ASR #
5205       int shift = (opcode >> 7) & 31;
5206       int offset;
5207       if(shift)
5208         offset = (int)((s32)reg[opcode & 15].I >> shift);
5209       else if(reg[opcode & 15].I & 0x80000000)
5210         offset = 0xFFFFFFFF;
5211       else
5212         offset = 0;
5213       int dest = (opcode >> 12) & 15;
5214       int base = (opcode >> 16) & 15;
5215       u32 address = reg[base].I;
5216       reg[dest].I = CPUReadByte(address);
5217       if(dest != base)
5218         reg[base].I = address + offset;
5219       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5220     }
5221     break;
5222   case 0x6d6:
5223   case 0x6de:
5224     // T versions are the same
5225   case 0x6f6:
5226   case 0x6fe:
5227     {
5228       // LDRB Rd, [Rn], Rm, ROR #
5229       int shift = (opcode >> 7) & 31;
5230       u32 value = reg[opcode & 15].I;
5231       if(shift) {
5232         ROR_VALUE;
5233       } else {
5234         RCR_VALUE;
5235       }
5236       int dest = (opcode >> 12) & 15;
5237       int base = (opcode >> 16) & 15;
5238       u32 address = reg[base].I;
5239       reg[dest].I = CPUReadByte(address);
5240       if(dest != base)
5241         reg[base].I = address + value;
5242       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5243     }
5244     break;
5245   case 0x750:
5246   case 0x758:
5247     {
5248       // LDRB Rd, [Rn, -Rm, LSL #]
5249       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5250       int dest = (opcode >> 12) & 15;
5251       int base = (opcode >> 16) & 15;
5252       u32 address = reg[base].I - offset;
5253       reg[dest].I = CPUReadByte(address);
5254       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5255     }
5256     break;
5257   case 0x752:
5258   case 0x75a:
5259     {
5260       // LDRB Rd, [Rn, -Rm, LSR #]
5261       int shift = (opcode >> 7) & 31;
5262       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5263       int dest = (opcode >> 12) & 15;
5264       int base = (opcode >> 16) & 15;
5265       u32 address = reg[base].I - offset;
5266       reg[dest].I = CPUReadByte(address);
5267       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5268     }
5269     break;
5270   case 0x754:
5271   case 0x75c:
5272     {
5273       // LDRB Rd, [Rn, -Rm, ASR #]
5274       int shift = (opcode >> 7) & 31;
5275       int offset;
5276       if(shift)
5277         offset = (int)((s32)reg[opcode & 15].I >> shift);
5278       else if(reg[opcode & 15].I & 0x80000000)
5279         offset = 0xFFFFFFFF;
5280       else
5281         offset = 0;
5282       int dest = (opcode >> 12) & 15;
5283       int base = (opcode >> 16) & 15;
5284       u32 address = reg[base].I - offset;
5285       reg[dest].I = CPUReadByte(address);
5286       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5287     }
5288     break;
5289   case 0x756:
5290   case 0x75e:
5291     {
5292       // LDRB Rd, [Rn, -Rm, ROR #]
5293       int shift = (opcode >> 7) & 31;
5294       u32 value = reg[opcode & 15].I;
5295       if(shift) {
5296         ROR_VALUE;
5297       } else {
5298         RCR_VALUE;
5299       }
5300       int dest = (opcode >> 12) & 15;
5301       int base = (opcode >> 16) & 15;
5302       u32 address = reg[base].I - value;
5303       reg[dest].I = CPUReadByte(address);
5304       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5305     }
5306     break;
5307   case 0x770:
5308   case 0x778:
5309     {
5310       // LDRB Rd, [Rn, -Rm, LSL #]!
5311       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5312       int dest = (opcode >> 12) & 15;
5313       int base = (opcode >> 16) & 15;
5314       u32 address = reg[base].I - offset;
5315       reg[dest].I = CPUReadByte(address);
5316       if(dest != base)
5317         reg[base].I = address;
5318       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5319     }
5320     break;
5321   case 0x772:
5322   case 0x77a:
5323     {
5324       // LDRB Rd, [Rn, -Rm, LSR #]!
5325       int shift = (opcode >> 7) & 31;
5326       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5327       int dest = (opcode >> 12) & 15;
5328       int base = (opcode >> 16) & 15;
5329       u32 address = reg[base].I - offset;
5330       reg[dest].I = CPUReadByte(address);
5331       if(dest != base)
5332         reg[base].I = address;
5333       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5334     }
5335     break;
5336   case 0x774:
5337   case 0x77c:
5338     {
5339       // LDRB Rd, [Rn, -Rm, ASR #]!
5340       int shift = (opcode >> 7) & 31;
5341       int offset;
5342       if(shift)
5343         offset = (int)((s32)reg[opcode & 15].I >> shift);
5344       else if(reg[opcode & 15].I & 0x80000000)
5345         offset = 0xFFFFFFFF;
5346       else
5347         offset = 0;
5348       int dest = (opcode >> 12) & 15;
5349       int base = (opcode >> 16) & 15;
5350       u32 address = reg[base].I - offset;
5351       reg[dest].I = CPUReadByte(address);
5352       if(dest != base)
5353         reg[base].I = address;
5354       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5355     }
5356     break;
5357   case 0x776:
5358   case 0x77e:
5359     {
5360       // LDRB Rd, [Rn, -Rm, ROR #]!
5361       int shift = (opcode >> 7) & 31;
5362       u32 value = reg[opcode & 15].I;
5363       if(shift) {
5364         ROR_VALUE;
5365       } else {
5366         RCR_VALUE;
5367       }
5368       int dest = (opcode >> 12) & 15;
5369       int base = (opcode >> 16) & 15;
5370       u32 address = reg[base].I - value;
5371       reg[dest].I = CPUReadByte(address);
5372       if(dest != base)
5373         reg[base].I = address;
5374       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5375     }
5376     break;
5377   case 0x7d0:
5378   case 0x7d8:
5379     {
5380       // LDRB Rd, [Rn, Rm, LSL #]
5381       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5382       int dest = (opcode >> 12) & 15;
5383       int base = (opcode >> 16) & 15;
5384       u32 address = reg[base].I + offset;
5385       reg[dest].I = CPUReadByte(address);
5386       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5387     }
5388     break;
5389   case 0x7d2:
5390   case 0x7da:
5391     {
5392       // LDRB Rd, [Rn, Rm, LSR #]
5393       int shift = (opcode >> 7) & 31;
5394       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5395       int dest = (opcode >> 12) & 15;
5396       int base = (opcode >> 16) & 15;
5397       u32 address = reg[base].I + offset;
5398       reg[dest].I = CPUReadByte(address);
5399       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5400     }
5401     break;
5402   case 0x7d4:
5403   case 0x7dc:
5404     {
5405       // LDRB Rd, [Rn, Rm, ASR #]
5406       int shift = (opcode >> 7) & 31;
5407       int offset;
5408       if(shift)
5409         offset = (int)((s32)reg[opcode & 15].I >> shift);
5410       else if(reg[opcode & 15].I & 0x80000000)
5411         offset = 0xFFFFFFFF;
5412       else
5413         offset = 0;
5414       int dest = (opcode >> 12) & 15;
5415       int base = (opcode >> 16) & 15;
5416       u32 address = reg[base].I + offset;
5417       reg[dest].I = CPUReadByte(address);
5418       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5419     }
5420     break;
5421   case 0x7d6:
5422   case 0x7de:
5423     {
5424       // LDRB Rd, [Rn, Rm, ROR #]
5425       int shift = (opcode >> 7) & 31;
5426       u32 value = reg[opcode & 15].I;
5427       if(shift) {
5428         ROR_VALUE;
5429       } else {
5430         RCR_VALUE;
5431       }
5432       int dest = (opcode >> 12) & 15;
5433       int base = (opcode >> 16) & 15;
5434       u32 address = reg[base].I + value;
5435       reg[dest].I = CPUReadByte(address);
5436       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5437     }
5438     break;
5439   case 0x7f0:
5440   case 0x7f8:
5441     {
5442       // LDRB Rd, [Rn, Rm, LSL #]!
5443       int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
5444       int dest = (opcode >> 12) & 15;
5445       int base = (opcode >> 16) & 15;
5446       u32 address = reg[base].I + offset;
5447       reg[dest].I = CPUReadByte(address);
5448       if(dest != base)
5449         reg[base].I = address;
5450       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5451     }
5452     break;
5453   case 0x7f2:
5454   case 0x7fa:
5455     {
5456       // LDRB Rd, [Rn, Rm, LSR #]!
5457       int shift = (opcode >> 7) & 31;
5458       int offset = shift ? reg[opcode & 15].I >> shift : 0;
5459       int dest = (opcode >> 12) & 15;
5460       int base = (opcode >> 16) & 15;
5461       u32 address = reg[base].I + offset;
5462       reg[dest].I = CPUReadByte(address);
5463       if(dest != base)
5464         reg[base].I = address;
5465       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5466     }
5467     break;
5468   case 0x7f4:
5469   case 0x7fc:
5470     {
5471       // LDRB Rd, [Rn, Rm, ASR #]!
5472       int shift = (opcode >> 7) & 31;
5473       int offset;
5474       if(shift)
5475         offset = (int)((s32)reg[opcode & 15].I >> shift);
5476       else if(reg[opcode & 15].I & 0x80000000)
5477         offset = 0xFFFFFFFF;
5478       else
5479         offset = 0;
5480       int dest = (opcode >> 12) & 15;
5481       int base = (opcode >> 16) & 15;
5482       u32 address = reg[base].I + offset;
5483       reg[dest].I = CPUReadByte(address);
5484       if(dest != base)
5485         reg[base].I = address;
5486       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5487     }
5488     break;
5489   case 0x7f6:
5490   case 0x7fe:
5491     {
5492       // LDRB Rd, [Rn, Rm, ROR #]!
5493       int shift = (opcode >> 7) & 31;
5494       u32 value = reg[opcode & 15].I;
5495       if(shift) {
5496         ROR_VALUE;
5497       } else {
5498         RCR_VALUE;
5499       }
5500       int dest = (opcode >> 12) & 15;
5501       int base = (opcode >> 16) & 15;
5502       u32 address = reg[base].I + value;
5503       reg[dest].I = CPUReadByte(address);
5504       if(dest != base)
5505         reg[base].I = address;
5506       clockTicks += 3 + CPUUpdateTicksAccess16(address);
5507     }
5508     break;
5509 #define STMW_REG(val,num) \
5510   if(opcode & (val)) {\
5511     CPUWriteMemory(address, reg[(num)].I);\
5512     if(!offset) {\
5513       reg[base].I = temp;\
5514       clockTicks += 1 + CPUUpdateTicksAccess32(address);\
5515       offset = 1;\
5516     } else {\
5517       clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
5518     }\
5519     address += 4;\
5520   }
5521 #define STM_REG(val,num) \
5522   if(opcode & (val)) {\
5523     CPUWriteMemory(address, reg[(num)].I);\
5524     if(!offset) {\
5525       clockTicks += 1 + CPUUpdateTicksAccess32(address);\
5526       offset = 1;\
5527     } else {\
5528       clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
5529     }\
5530     address += 4;\
5531   }
5532 
5533   CASE_16(0x800)
5534     // STMDA Rn, {Rlist}
5535     {
5536       int base = (opcode & 0x000F0000) >> 16;
5537       u32 temp = reg[base].I -
5538         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5539       u32 address = (temp + 4) & 0xFFFFFFFC;
5540       clockTicks += 2;
5541       int offset = 0;
5542       STM_REG(1, 0);
5543       STM_REG(2, 1);
5544       STM_REG(4, 2);
5545       STM_REG(8, 3);
5546       STM_REG(16, 4);
5547       STM_REG(32, 5);
5548       STM_REG(64, 6);
5549       STM_REG(128, 7);
5550       STM_REG(256, 8);
5551       STM_REG(512, 9);
5552       STM_REG(1024, 10);
5553       STM_REG(2048, 11);
5554       STM_REG(4096, 12);
5555       STM_REG(8192, 13);
5556       STM_REG(16384, 14);
5557       if(opcode & 32768) {
5558         CPUWriteMemory(address, reg[15].I+4);
5559         if(!offset)
5560           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5561         else
5562           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5563       }
5564     }
5565     break;
5566   CASE_16(0x820)
5567     {
5568       // STMDA Rn!, {Rlist}
5569       int base = (opcode & 0x000F0000) >> 16;
5570       u32 temp = reg[base].I -
5571         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5572       u32 address = (temp+4) & 0xFFFFFFFC;
5573       clockTicks += 2;
5574       int offset = 0;
5575 
5576       STMW_REG(1, 0);
5577       STMW_REG(2, 1);
5578       STMW_REG(4, 2);
5579       STMW_REG(8, 3);
5580       STMW_REG(16, 4);
5581       STMW_REG(32, 5);
5582       STMW_REG(64, 6);
5583       STMW_REG(128, 7);
5584       STMW_REG(256, 8);
5585       STMW_REG(512, 9);
5586       STMW_REG(1024, 10);
5587       STMW_REG(2048, 11);
5588       STMW_REG(4096, 12);
5589       STMW_REG(8192, 13);
5590       STMW_REG(16384, 14);
5591       if(opcode & 32768) {
5592         CPUWriteMemory(address, reg[15].I+4);
5593         if(!offset)
5594           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5595         else
5596           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5597         reg[base].I = temp;
5598       }
5599     }
5600   break;
5601   CASE_16(0x840)
5602     {
5603       // STMDA Rn, {Rlist}^
5604       int base = (opcode & 0x000F0000) >> 16;
5605       u32 temp = reg[base].I -
5606         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5607       u32 address = (temp+4) & 0xFFFFFFFC;
5608       clockTicks += 2;
5609       int offset = 0;
5610 
5611       STM_REG(1, 0);
5612       STM_REG(2, 1);
5613       STM_REG(4, 2);
5614       STM_REG(8, 3);
5615       STM_REG(16, 4);
5616       STM_REG(32, 5);
5617       STM_REG(64, 6);
5618       STM_REG(128, 7);
5619 
5620       if(armMode == 0x11) {
5621         STM_REG(256, R8_FIQ);
5622         STM_REG(512, R9_FIQ);
5623         STM_REG(1024, R10_FIQ);
5624         STM_REG(2048, R11_FIQ);
5625         STM_REG(4096, R12_FIQ);
5626       } else {
5627         STM_REG(256, 8);
5628         STM_REG(512, 9);
5629         STM_REG(1024, 10);
5630         STM_REG(2048, 11);
5631         STM_REG(4096, 12);
5632       }
5633 
5634       if(armMode != 0x10 && armMode != 0x1f) {
5635         STM_REG(8192, R13_USR);
5636         STM_REG(16384, R14_USR);
5637       } else {
5638         STM_REG(8192, 13);
5639         STM_REG(16384, 14);
5640       }
5641 
5642       if(opcode & 32768) {
5643         CPUWriteMemory(address, reg[15].I+4);
5644         if(!offset)
5645           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5646         else
5647           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5648       }
5649     }
5650     break;
5651   CASE_16(0x860)
5652     {
5653       // STMDA Rn!, {Rlist}^
5654       int base = (opcode & 0x000F0000) >> 16;
5655       u32 temp = reg[base].I -
5656         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5657       u32 address = (temp+4) & 0xFFFFFFFC;
5658       clockTicks += 2;
5659       int offset = 0;
5660 
5661       STMW_REG(1, 0);
5662       STMW_REG(2, 1);
5663       STMW_REG(4, 2);
5664       STMW_REG(8, 3);
5665       STMW_REG(16, 4);
5666       STMW_REG(32, 5);
5667       STMW_REG(64, 6);
5668       STMW_REG(128, 7);
5669 
5670       if(armMode == 0x11) {
5671         STMW_REG(256, R8_FIQ);
5672         STMW_REG(512, R9_FIQ);
5673         STMW_REG(1024, R10_FIQ);
5674         STMW_REG(2048, R11_FIQ);
5675         STMW_REG(4096, R12_FIQ);
5676       } else {
5677         STMW_REG(256, 8);
5678         STMW_REG(512, 9);
5679         STMW_REG(1024, 10);
5680         STMW_REG(2048, 11);
5681         STMW_REG(4096, 12);
5682       }
5683 
5684       if(armMode != 0x10 && armMode != 0x1f) {
5685         STMW_REG(8192, R13_USR);
5686         STMW_REG(16384, R14_USR);
5687       } else {
5688         STMW_REG(8192, 13);
5689         STMW_REG(16384, 14);
5690       }
5691 
5692       if(opcode & 32768) {
5693         CPUWriteMemory(address, reg[15].I+4);
5694         if(!offset)
5695           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5696         else
5697           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5698         reg[base].I = temp;
5699       }
5700     }
5701     break;
5702 
5703   CASE_16(0x880)
5704     {
5705       // STMIA Rn, {Rlist}
5706       int base = (opcode & 0x000F0000) >> 16;
5707       u32 address = reg[base].I & 0xFFFFFFFC;
5708       clockTicks += 2;
5709       int offset = 0;
5710       STM_REG(1, 0);
5711       STM_REG(2, 1);
5712       STM_REG(4, 2);
5713       STM_REG(8, 3);
5714       STM_REG(16, 4);
5715       STM_REG(32, 5);
5716       STM_REG(64, 6);
5717       STM_REG(128, 7);
5718       STM_REG(256, 8);
5719       STM_REG(512, 9);
5720       STM_REG(1024, 10);
5721       STM_REG(2048, 11);
5722       STM_REG(4096, 12);
5723       STM_REG(8192, 13);
5724       STM_REG(16384, 14);
5725       if(opcode & 32768) {
5726         CPUWriteMemory(address, reg[15].I+4);
5727         if(!offset)
5728           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5729         else
5730           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5731       }
5732     }
5733   break;
5734   CASE_16(0x8a0)
5735     {
5736       // STMIA Rn!, {Rlist}
5737       int base = (opcode & 0x000F0000) >> 16;
5738       u32 address = reg[base].I & 0xFFFFFFFC;
5739       clockTicks += 2;
5740       int offset = 0;
5741       u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
5742                                   cpuBitsSet[(opcode >> 8) & 255]);
5743       STMW_REG(1, 0);
5744       STMW_REG(2, 1);
5745       STMW_REG(4, 2);
5746       STMW_REG(8, 3);
5747       STMW_REG(16, 4);
5748       STMW_REG(32, 5);
5749       STMW_REG(64, 6);
5750       STMW_REG(128, 7);
5751       STMW_REG(256, 8);
5752       STMW_REG(512, 9);
5753       STMW_REG(1024, 10);
5754       STMW_REG(2048, 11);
5755       STMW_REG(4096, 12);
5756       STMW_REG(8192, 13);
5757       STMW_REG(16384, 14);
5758       if(opcode & 32768) {
5759         CPUWriteMemory(address, reg[15].I+4);
5760         if(!offset) {
5761           reg[base].I = temp;
5762           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5763         } else
5764           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5765       }
5766     }
5767   break;
5768   CASE_16(0x8c0)
5769     {
5770       // STMIA Rn, {Rlist}^
5771       int base = (opcode & 0x000F0000) >> 16;
5772       u32 address = reg[base].I & 0xFFFFFFFC;
5773       clockTicks += 2;
5774       int offset = 0;
5775       STM_REG(1, 0);
5776       STM_REG(2, 1);
5777       STM_REG(4, 2);
5778       STM_REG(8, 3);
5779       STM_REG(16, 4);
5780       STM_REG(32, 5);
5781       STM_REG(64, 6);
5782       STM_REG(128, 7);
5783       if(armMode == 0x11) {
5784         STM_REG(256, R8_FIQ);
5785         STM_REG(512, R9_FIQ);
5786         STM_REG(1024, R10_FIQ);
5787         STM_REG(2048, R11_FIQ);
5788         STM_REG(4096, R12_FIQ);
5789       } else {
5790         STM_REG(256, 8);
5791         STM_REG(512, 9);
5792         STM_REG(1024, 10);
5793         STM_REG(2048, 11);
5794         STM_REG(4096, 12);
5795       }
5796       if(armMode != 0x10 && armMode != 0x1f) {
5797         STM_REG(8192, R13_USR);
5798         STM_REG(16384, R14_USR);
5799       } else {
5800         STM_REG(8192, 13);
5801         STM_REG(16384, 14);
5802       }
5803       if(opcode & 32768) {
5804         CPUWriteMemory(address, reg[15].I+4);
5805         if(!offset)
5806           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5807         else
5808           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5809       }
5810     }
5811     break;
5812   CASE_16(0x8e0)
5813     {
5814       // STMIA Rn!, {Rlist}^
5815       int base = (opcode & 0x000F0000) >> 16;
5816       u32 address = reg[base].I & 0xFFFFFFFC;
5817       clockTicks += 2;
5818       int offset = 0;
5819       u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
5820                                   cpuBitsSet[(opcode >> 8) & 255]);
5821       STMW_REG(1, 0);
5822       STMW_REG(2, 1);
5823       STMW_REG(4, 2);
5824       STMW_REG(8, 3);
5825       STMW_REG(16, 4);
5826       STMW_REG(32, 5);
5827       STMW_REG(64, 6);
5828       STMW_REG(128, 7);
5829       if(armMode == 0x11) {
5830         STMW_REG(256, R8_FIQ);
5831         STMW_REG(512, R9_FIQ);
5832         STMW_REG(1024, R10_FIQ);
5833         STMW_REG(2048, R11_FIQ);
5834         STMW_REG(4096, R12_FIQ);
5835       } else {
5836         STMW_REG(256, 8);
5837         STMW_REG(512, 9);
5838         STMW_REG(1024, 10);
5839         STMW_REG(2048, 11);
5840         STMW_REG(4096, 12);
5841       }
5842       if(armMode != 0x10 && armMode != 0x1f) {
5843         STMW_REG(8192, R13_USR);
5844         STMW_REG(16384, R14_USR);
5845       } else {
5846         STMW_REG(8192, 13);
5847         STMW_REG(16384, 14);
5848       }
5849       if(opcode & 32768) {
5850         CPUWriteMemory(address, reg[15].I+4);
5851         if(!offset) {
5852           reg[base].I = temp;
5853           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5854         } else
5855           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5856       }
5857     }
5858     break;
5859 
5860   CASE_16(0x900)
5861     {
5862       // STMDB Rn, {Rlist}
5863       int base = (opcode & 0x000F0000) >> 16;
5864       u32 temp = reg[base].I -
5865         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5866       u32 address = temp & 0xFFFFFFFC;
5867       clockTicks += 2;
5868       int offset = 0;
5869       STM_REG(1, 0);
5870       STM_REG(2, 1);
5871       STM_REG(4, 2);
5872       STM_REG(8, 3);
5873       STM_REG(16, 4);
5874       STM_REG(32, 5);
5875       STM_REG(64, 6);
5876       STM_REG(128, 7);
5877       STM_REG(256, 8);
5878       STM_REG(512, 9);
5879       STM_REG(1024, 10);
5880       STM_REG(2048, 11);
5881       STM_REG(4096, 12);
5882       STM_REG(8192, 13);
5883       STM_REG(16384, 14);
5884       if(opcode & 32768) {
5885         CPUWriteMemory(address, reg[15].I+4);
5886         if(!offset)
5887           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5888         else
5889           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5890       }
5891     }
5892     break;
5893   CASE_16(0x920)
5894     {
5895       // STMDB Rn!, {Rlist}
5896       int base = (opcode & 0x000F0000) >> 16;
5897       u32 temp = reg[base].I -
5898         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5899       u32 address = temp & 0xFFFFFFFC;
5900       clockTicks += 2;
5901       int offset = 0;
5902 
5903       STMW_REG(1, 0);
5904       STMW_REG(2, 1);
5905       STMW_REG(4, 2);
5906       STMW_REG(8, 3);
5907       STMW_REG(16, 4);
5908       STMW_REG(32, 5);
5909       STMW_REG(64, 6);
5910       STMW_REG(128, 7);
5911       STMW_REG(256, 8);
5912       STMW_REG(512, 9);
5913       STMW_REG(1024, 10);
5914       STMW_REG(2048, 11);
5915       STMW_REG(4096, 12);
5916       STMW_REG(8192, 13);
5917       STMW_REG(16384, 14);
5918       if(opcode & 32768) {
5919         CPUWriteMemory(address, reg[15].I+4);
5920         if(!offset)
5921           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5922         else
5923           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5924         reg[base].I = temp;
5925       }
5926     }
5927   break;
5928   CASE_16(0x940)
5929     {
5930       // STMDB Rn, {Rlist}^
5931       int base = (opcode & 0x000F0000) >> 16;
5932       u32 temp = reg[base].I -
5933         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5934       u32 address = temp & 0xFFFFFFFC;
5935       clockTicks += 2;
5936       int offset = 0;
5937 
5938       STM_REG(1, 0);
5939       STM_REG(2, 1);
5940       STM_REG(4, 2);
5941       STM_REG(8, 3);
5942       STM_REG(16, 4);
5943       STM_REG(32, 5);
5944       STM_REG(64, 6);
5945       STM_REG(128, 7);
5946 
5947       if(armMode == 0x11) {
5948         STM_REG(256, R8_FIQ);
5949         STM_REG(512, R9_FIQ);
5950         STM_REG(1024, R10_FIQ);
5951         STM_REG(2048, R11_FIQ);
5952         STM_REG(4096, R12_FIQ);
5953       } else {
5954         STM_REG(256, 8);
5955         STM_REG(512, 9);
5956         STM_REG(1024, 10);
5957         STM_REG(2048, 11);
5958         STM_REG(4096, 12);
5959       }
5960 
5961       if(armMode != 0x10 && armMode != 0x1f) {
5962         STM_REG(8192, R13_USR);
5963         STM_REG(16384, R14_USR);
5964       } else {
5965         STM_REG(8192, 13);
5966         STM_REG(16384, 14);
5967       }
5968 
5969       if(opcode & 32768) {
5970         CPUWriteMemory(address, reg[15].I+4);
5971         if(!offset)
5972           clockTicks += 1 + CPUUpdateTicksAccess32(address);
5973         else
5974           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
5975       }
5976     }
5977     break;
5978   CASE_16(0x960)
5979     {
5980       // STMDB Rn!, {Rlist}^
5981       int base = (opcode & 0x000F0000) >> 16;
5982       u32 temp = reg[base].I -
5983         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5984       u32 address = temp & 0xFFFFFFFC;
5985       clockTicks += 2;
5986       int offset = 0;
5987 
5988       STMW_REG(1, 0);
5989       STMW_REG(2, 1);
5990       STMW_REG(4, 2);
5991       STMW_REG(8, 3);
5992       STMW_REG(16, 4);
5993       STMW_REG(32, 5);
5994       STMW_REG(64, 6);
5995       STMW_REG(128, 7);
5996 
5997       if(armMode == 0x11) {
5998         STMW_REG(256, R8_FIQ);
5999         STMW_REG(512, R9_FIQ);
6000         STMW_REG(1024, R10_FIQ);
6001         STMW_REG(2048, R11_FIQ);
6002         STMW_REG(4096, R12_FIQ);
6003       } else {
6004         STMW_REG(256, 8);
6005         STMW_REG(512, 9);
6006         STMW_REG(1024, 10);
6007         STMW_REG(2048, 11);
6008         STMW_REG(4096, 12);
6009       }
6010 
6011       if(armMode != 0x10 && armMode != 0x1f) {
6012         STMW_REG(8192, R13_USR);
6013         STMW_REG(16384, R14_USR);
6014       } else {
6015         STMW_REG(8192, 13);
6016         STMW_REG(16384, 14);
6017       }
6018 
6019       if(opcode & 32768) {
6020         CPUWriteMemory(address, reg[15].I+4);
6021         if(!offset)
6022           clockTicks += 1 + CPUUpdateTicksAccess32(address);
6023         else
6024           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6025         reg[base].I = temp;
6026       }
6027     }
6028     break;
6029 
6030   CASE_16(0x980)
6031     // STMIB Rn, {Rlist}
6032     {
6033       int base = (opcode & 0x000F0000) >> 16;
6034       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6035       clockTicks += 2;
6036       int offset = 0;
6037       STM_REG(1, 0);
6038       STM_REG(2, 1);
6039       STM_REG(4, 2);
6040       STM_REG(8, 3);
6041       STM_REG(16, 4);
6042       STM_REG(32, 5);
6043       STM_REG(64, 6);
6044       STM_REG(128, 7);
6045       STM_REG(256, 8);
6046       STM_REG(512, 9);
6047       STM_REG(1024, 10);
6048       STM_REG(2048, 11);
6049       STM_REG(4096, 12);
6050       STM_REG(8192, 13);
6051       STM_REG(16384, 14);
6052       if(opcode & 32768) {
6053         CPUWriteMemory(address, reg[15].I+4);
6054         if(!offset)
6055           clockTicks += 1 + CPUUpdateTicksAccess32(address);
6056         else
6057           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6058       }
6059     }
6060     break;
6061   CASE_16(0x9a0)
6062     {
6063       // STMIB Rn!, {Rlist}
6064       int base = (opcode & 0x000F0000) >> 16;
6065       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6066       clockTicks += 2;
6067       int offset = 0;
6068       u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
6069                                   cpuBitsSet[(opcode >> 8) & 255]);
6070       STMW_REG(1, 0);
6071       STMW_REG(2, 1);
6072       STMW_REG(4, 2);
6073       STMW_REG(8, 3);
6074       STMW_REG(16, 4);
6075       STMW_REG(32, 5);
6076       STMW_REG(64, 6);
6077       STMW_REG(128, 7);
6078       STMW_REG(256, 8);
6079       STMW_REG(512, 9);
6080       STMW_REG(1024, 10);
6081       STMW_REG(2048, 11);
6082       STMW_REG(4096, 12);
6083       STMW_REG(8192, 13);
6084       STMW_REG(16384, 14);
6085       if(opcode & 32768) {
6086         CPUWriteMemory(address, reg[15].I+4);
6087         if(!offset) {
6088           reg[base].I = temp;
6089           clockTicks += 1 + CPUUpdateTicksAccess32(address);
6090         } else
6091           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6092       }
6093     }
6094     break;
6095   CASE_16(0x9c0)
6096     {
6097       // STMIB Rn, {Rlist}^
6098       int base = (opcode & 0x000F0000) >> 16;
6099       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6100       clockTicks += 2;
6101       int offset = 0;
6102       STM_REG(1, 0);
6103       STM_REG(2, 1);
6104       STM_REG(4, 2);
6105       STM_REG(8, 3);
6106       STM_REG(16, 4);
6107       STM_REG(32, 5);
6108       STM_REG(64, 6);
6109       STM_REG(128, 7);
6110       if(armMode == 0x11) {
6111         STM_REG(256, R8_FIQ);
6112         STM_REG(512, R9_FIQ);
6113         STM_REG(1024, R10_FIQ);
6114         STM_REG(2048, R11_FIQ);
6115         STM_REG(4096, R12_FIQ);
6116       } else {
6117         STM_REG(256, 8);
6118         STM_REG(512, 9);
6119         STM_REG(1024, 10);
6120         STM_REG(2048, 11);
6121         STM_REG(4096, 12);
6122       }
6123       if(armMode != 0x10 && armMode != 0x1f) {
6124         STM_REG(8192, R13_USR);
6125         STM_REG(16384, R14_USR);
6126       } else {
6127         STM_REG(8192, 13);
6128         STM_REG(16384, 14);
6129       }
6130       if(opcode & 32768) {
6131         CPUWriteMemory(address, reg[15].I+4);
6132         if(!offset)
6133           clockTicks += 1 + CPUUpdateTicksAccess32(address);
6134         else
6135           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6136       }
6137     }
6138     break;
6139   CASE_16(0x9e0)
6140     {
6141       // STMIB Rn!, {Rlist}^
6142       int base = (opcode & 0x000F0000) >> 16;
6143       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6144       clockTicks += 2;
6145       int offset = 0;
6146       u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
6147                                   cpuBitsSet[(opcode >> 8) & 255]);
6148       STMW_REG(1, 0);
6149       STMW_REG(2, 1);
6150       STMW_REG(4, 2);
6151       STMW_REG(8, 3);
6152       STMW_REG(16, 4);
6153       STMW_REG(32, 5);
6154       STMW_REG(64, 6);
6155       STMW_REG(128, 7);
6156       if(armMode == 0x11) {
6157         STMW_REG(256, R8_FIQ);
6158         STMW_REG(512, R9_FIQ);
6159         STMW_REG(1024, R10_FIQ);
6160         STMW_REG(2048, R11_FIQ);
6161         STMW_REG(4096, R12_FIQ);
6162       } else {
6163         STMW_REG(256, 8);
6164         STMW_REG(512, 9);
6165         STMW_REG(1024, 10);
6166         STMW_REG(2048, 11);
6167         STMW_REG(4096, 12);
6168       }
6169       if(armMode != 0x10 && armMode != 0x1f) {
6170         STMW_REG(8192, R13_USR);
6171         STMW_REG(16384, R14_USR);
6172       } else {
6173         STMW_REG(8192, 13);
6174         STMW_REG(16384, 14);
6175       }
6176       if(opcode & 32768) {
6177         CPUWriteMemory(address, reg[15].I+4);
6178         if(!offset) {
6179           reg[base].I = temp;
6180           clockTicks += 1 + CPUUpdateTicksAccess32(address);
6181         } else
6182           clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
6183       }
6184     }
6185     break;
6186 
6187 #define LDM_REG(val,num) \
6188   if(opcode & (val)) {\
6189     reg[(num)].I = CPUReadMemory(address);\
6190     if(offset)\
6191       clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
6192     else {\
6193       clockTicks += 1 + CPUUpdateTicksAccess32(address);\
6194       offset = 1;\
6195     }\
6196     address += 4;\
6197   }
6198 
6199   CASE_16(0x810)
6200     {
6201       // LDMDA Rn, {Rlist}
6202       int base = (opcode & 0x000F0000) >> 16;
6203       u32 temp = reg[base].I -
6204         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6205       u32 address = (temp + 4) & 0xFFFFFFFC;
6206       clockTicks += 2;
6207       int offset = 0;
6208       LDM_REG(1, 0);
6209       LDM_REG(2, 1);
6210       LDM_REG(4, 2);
6211       LDM_REG(8, 3);
6212       LDM_REG(16, 4);
6213       LDM_REG(32, 5);
6214       LDM_REG(64, 6);
6215       LDM_REG(128, 7);
6216       LDM_REG(256, 8);
6217       LDM_REG(512, 9);
6218       LDM_REG(1024, 10);
6219       LDM_REG(2048, 11);
6220       LDM_REG(4096, 12);
6221       LDM_REG(8192, 13);
6222       LDM_REG(16384, 14);
6223       if(opcode & 32768) {
6224         reg[15].I = CPUReadMemory(address);
6225         if (!offset)
6226           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6227         else
6228           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6229         armNextPC = reg[15].I;
6230         reg[15].I += 4;
6231       }
6232     }
6233     break;
6234   CASE_16(0x830)
6235     {
6236       // LDMDA Rn!, {Rlist}
6237       int base = (opcode & 0x000F0000) >> 16;
6238       u32 temp = reg[base].I -
6239         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6240       u32 address = (temp + 4) & 0xFFFFFFFC;
6241       clockTicks += 2;
6242       int offset = 0;
6243       LDM_REG(1, 0);
6244       LDM_REG(2, 1);
6245       LDM_REG(4, 2);
6246       LDM_REG(8, 3);
6247       LDM_REG(16, 4);
6248       LDM_REG(32, 5);
6249       LDM_REG(64, 6);
6250       LDM_REG(128, 7);
6251       LDM_REG(256, 8);
6252       LDM_REG(512, 9);
6253       LDM_REG(1024, 10);
6254       LDM_REG(2048, 11);
6255       LDM_REG(4096, 12);
6256       LDM_REG(8192, 13);
6257       LDM_REG(16384, 14);
6258       if(opcode & 32768) {
6259         reg[15].I = CPUReadMemory(address);
6260         if (!offset)
6261           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6262         else
6263           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6264         armNextPC = reg[15].I;
6265         reg[15].I += 4;
6266       }
6267       if(!(opcode & (1 << base)))
6268         reg[base].I = temp;
6269     }
6270     break;
6271   CASE_16(0x850)
6272     {
6273       // LDMDA Rn, {Rlist}^
6274       int base = (opcode & 0x000F0000) >> 16;
6275       u32 temp = reg[base].I -
6276         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6277       u32 address = (temp + 4) & 0xFFFFFFFC;
6278       clockTicks += 2;
6279       int offset = 0;
6280       if(opcode & 0x8000) {
6281         LDM_REG(1, 0);
6282         LDM_REG(2, 1);
6283         LDM_REG(4, 2);
6284         LDM_REG(8, 3);
6285         LDM_REG(16, 4);
6286         LDM_REG(32, 5);
6287         LDM_REG(64, 6);
6288         LDM_REG(128, 7);
6289         LDM_REG(256, 8);
6290         LDM_REG(512, 9);
6291         LDM_REG(1024, 10);
6292         LDM_REG(2048, 11);
6293         LDM_REG(4096, 12);
6294         LDM_REG(8192, 13);
6295         LDM_REG(16384, 14);
6296 
6297         reg[15].I = CPUReadMemory(address);
6298         if (!offset)
6299           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6300         else
6301           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6302 
6303         CPUSwitchMode(reg[17].I & 0x1f, false);
6304         if(armState) {
6305           armNextPC = reg[15].I & 0xFFFFFFFC;
6306           reg[15].I = armNextPC + 4;
6307         } else {
6308           armNextPC = reg[15].I & 0xFFFFFFFE;
6309           reg[15].I = armNextPC + 2;
6310         }
6311       } else {
6312         LDM_REG(1, 0);
6313         LDM_REG(2, 1);
6314         LDM_REG(4, 2);
6315         LDM_REG(8, 3);
6316         LDM_REG(16, 4);
6317         LDM_REG(32, 5);
6318         LDM_REG(64, 6);
6319         LDM_REG(128, 7);
6320 
6321         if(armMode == 0x11) {
6322           LDM_REG(256, R8_FIQ);
6323           LDM_REG(512, R9_FIQ);
6324           LDM_REG(1024, R10_FIQ);
6325           LDM_REG(2048, R11_FIQ);
6326           LDM_REG(4096, R12_FIQ);
6327         } else {
6328           LDM_REG(256, 8);
6329           LDM_REG(512, 9);
6330           LDM_REG(1024, 10);
6331           LDM_REG(2048, 11);
6332           LDM_REG(4096, 12);
6333         }
6334 
6335         if(armMode != 0x10 && armMode != 0x1f) {
6336           LDM_REG(8192, R13_USR);
6337           LDM_REG(16384, R14_USR);
6338         } else {
6339           LDM_REG(8192, 13);
6340           LDM_REG(16384, 14);
6341         }
6342       }
6343     }
6344     break;
6345   CASE_16(0x870)
6346     {
6347       // LDMDA Rn!, {Rlist}^
6348       int base = (opcode & 0x000F0000) >> 16;
6349       u32 temp = reg[base].I -
6350         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6351       u32 address = (temp + 4) & 0xFFFFFFFC;
6352       clockTicks += 2;
6353       int offset = 0;
6354       if(opcode & 0x8000) {
6355         LDM_REG(1, 0);
6356         LDM_REG(2, 1);
6357         LDM_REG(4, 2);
6358         LDM_REG(8, 3);
6359         LDM_REG(16, 4);
6360         LDM_REG(32, 5);
6361         LDM_REG(64, 6);
6362         LDM_REG(128, 7);
6363         LDM_REG(256, 8);
6364         LDM_REG(512, 9);
6365         LDM_REG(1024, 10);
6366         LDM_REG(2048, 11);
6367         LDM_REG(4096, 12);
6368         LDM_REG(8192, 13);
6369         LDM_REG(16384, 14);
6370 
6371         reg[15].I = CPUReadMemory(address);
6372         if(!offset)
6373           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6374         else
6375           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6376 
6377         if(!(opcode & (1 << base)))
6378           reg[base].I = temp;
6379 
6380         CPUSwitchMode(reg[17].I & 0x1f, false);
6381         if(armState) {
6382           armNextPC = reg[15].I & 0xFFFFFFFC;
6383           reg[15].I = armNextPC + 4;
6384         } else {
6385           armNextPC = reg[15].I & 0xFFFFFFFE;
6386           reg[15].I = armNextPC + 2;
6387         }
6388       } else {
6389         LDM_REG(1, 0);
6390         LDM_REG(2, 1);
6391         LDM_REG(4, 2);
6392         LDM_REG(8, 3);
6393         LDM_REG(16, 4);
6394         LDM_REG(32, 5);
6395         LDM_REG(64, 6);
6396         LDM_REG(128, 7);
6397 
6398         if(armMode == 0x11) {
6399           LDM_REG(256, R8_FIQ);
6400           LDM_REG(512, R9_FIQ);
6401           LDM_REG(1024, R10_FIQ);
6402           LDM_REG(2048, R11_FIQ);
6403           LDM_REG(4096, R12_FIQ);
6404         } else {
6405           LDM_REG(256, 8);
6406           LDM_REG(512, 9);
6407           LDM_REG(1024, 10);
6408           LDM_REG(2048, 11);
6409           LDM_REG(4096, 12);
6410         }
6411 
6412         if(armMode != 0x10 && armMode != 0x1f) {
6413           LDM_REG(8192, R13_USR);
6414           LDM_REG(16384, R14_USR);
6415         } else {
6416           LDM_REG(8192, 13);
6417           LDM_REG(16384, 14);
6418         }
6419 
6420         if(!(opcode & (1 << base)))
6421           reg[base].I = temp;
6422       }
6423     }
6424     break;
6425 
6426   CASE_16(0x890)
6427     {
6428       // LDMIA Rn, {Rlist}
6429       int base = (opcode & 0x000F0000) >> 16;
6430       u32 address = reg[base].I & 0xFFFFFFFC;
6431       clockTicks += 2;
6432       int offset = 0;
6433       LDM_REG(1, 0);
6434       LDM_REG(2, 1);
6435       LDM_REG(4, 2);
6436       LDM_REG(8, 3);
6437       LDM_REG(16, 4);
6438       LDM_REG(32, 5);
6439       LDM_REG(64, 6);
6440       LDM_REG(128, 7);
6441       LDM_REG(256, 8);
6442       LDM_REG(512, 9);
6443       LDM_REG(1024, 10);
6444       LDM_REG(2048, 11);
6445       LDM_REG(4096, 12);
6446       LDM_REG(8192, 13);
6447       LDM_REG(16384, 14);
6448       if(opcode & 32768) {
6449         reg[15].I = CPUReadMemory(address);
6450         if (!offset)
6451           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6452         else
6453           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6454         armNextPC = reg[15].I;
6455         reg[15].I += 4;
6456       }
6457     }
6458   break;
6459   CASE_16(0x8b0)
6460     {
6461       // LDMIA Rn!, {Rlist}
6462       int base = (opcode & 0x000F0000) >> 16;
6463       u32 temp = reg[base].I +
6464         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6465       u32 address = reg[base].I & 0xFFFFFFFC;
6466       clockTicks += 2;
6467       int offset = 0;
6468       LDM_REG(1, 0);
6469       LDM_REG(2, 1);
6470       LDM_REG(4, 2);
6471       LDM_REG(8, 3);
6472       LDM_REG(16, 4);
6473       LDM_REG(32, 5);
6474       LDM_REG(64, 6);
6475       LDM_REG(128, 7);
6476       LDM_REG(256, 8);
6477       LDM_REG(512, 9);
6478       LDM_REG(1024, 10);
6479       LDM_REG(2048, 11);
6480       LDM_REG(4096, 12);
6481       LDM_REG(8192, 13);
6482       LDM_REG(16384, 14);
6483       if(opcode & 32768) {
6484         reg[15].I = CPUReadMemory(address);
6485         if (!offset)
6486           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6487         else
6488           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6489         armNextPC = reg[15].I;
6490         reg[15].I += 4;
6491       }
6492       if(!(opcode & (1 << base)))
6493         reg[base].I = temp;
6494     }
6495     break;
6496   CASE_16(0x8d0)
6497     {
6498       // LDMIA Rn, {Rlist}^
6499       int base = (opcode & 0x000F0000) >> 16;
6500       u32 address = reg[base].I & 0xFFFFFFFC;
6501       clockTicks += 2;
6502       int offset = 0;
6503       if(opcode & 0x8000) {
6504         LDM_REG(1, 0);
6505         LDM_REG(2, 1);
6506         LDM_REG(4, 2);
6507         LDM_REG(8, 3);
6508         LDM_REG(16, 4);
6509         LDM_REG(32, 5);
6510         LDM_REG(64, 6);
6511         LDM_REG(128, 7);
6512         LDM_REG(256, 8);
6513         LDM_REG(512, 9);
6514         LDM_REG(1024, 10);
6515         LDM_REG(2048, 11);
6516         LDM_REG(4096, 12);
6517         LDM_REG(8192, 13);
6518         LDM_REG(16384, 14);
6519 
6520         reg[15].I = CPUReadMemory(address);
6521         if (!offset)
6522           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6523         else
6524           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6525 
6526         CPUSwitchMode(reg[17].I & 0x1f, false);
6527         if(armState) {
6528           armNextPC = reg[15].I & 0xFFFFFFFC;
6529           reg[15].I = armNextPC + 4;
6530         } else {
6531           armNextPC = reg[15].I & 0xFFFFFFFE;
6532           reg[15].I = armNextPC + 2;
6533         }
6534       } else {
6535         LDM_REG(1, 0);
6536         LDM_REG(2, 1);
6537         LDM_REG(4, 2);
6538         LDM_REG(8, 3);
6539         LDM_REG(16, 4);
6540         LDM_REG(32, 5);
6541         LDM_REG(64, 6);
6542         LDM_REG(128, 7);
6543 
6544         if(armMode == 0x11) {
6545           LDM_REG(256, R8_FIQ);
6546           LDM_REG(512, R9_FIQ);
6547           LDM_REG(1024, R10_FIQ);
6548           LDM_REG(2048, R11_FIQ);
6549           LDM_REG(4096, R12_FIQ);
6550         } else {
6551           LDM_REG(256, 8);
6552           LDM_REG(512, 9);
6553           LDM_REG(1024, 10);
6554           LDM_REG(2048, 11);
6555           LDM_REG(4096, 12);
6556         }
6557 
6558         if(armMode != 0x10 && armMode != 0x1f) {
6559           LDM_REG(8192, R13_USR);
6560           LDM_REG(16384, R14_USR);
6561         } else {
6562           LDM_REG(8192, 13);
6563           LDM_REG(16384, 14);
6564         }
6565       }
6566     }
6567   break;
6568   CASE_16(0x8f0)
6569     {
6570       // LDMIA Rn!, {Rlist}^
6571       int base = (opcode & 0x000F0000) >> 16;
6572       u32 temp = reg[base].I +
6573         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6574       u32 address = reg[base].I & 0xFFFFFFFC;
6575       clockTicks += 2;
6576       int offset = 0;
6577       if(opcode & 0x8000) {
6578         LDM_REG(1, 0);
6579         LDM_REG(2, 1);
6580         LDM_REG(4, 2);
6581         LDM_REG(8, 3);
6582         LDM_REG(16, 4);
6583         LDM_REG(32, 5);
6584         LDM_REG(64, 6);
6585         LDM_REG(128, 7);
6586         LDM_REG(256, 8);
6587         LDM_REG(512, 9);
6588         LDM_REG(1024, 10);
6589         LDM_REG(2048, 11);
6590         LDM_REG(4096, 12);
6591         LDM_REG(8192, 13);
6592         LDM_REG(16384, 14);
6593 
6594         reg[15].I = CPUReadMemory(address);
6595         if(!offset)
6596           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6597         else
6598           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6599 
6600         if(!(opcode & (1 << base)))
6601           reg[base].I = temp;
6602 
6603         CPUSwitchMode(reg[17].I & 0x1f, false);
6604         if(armState) {
6605           armNextPC = reg[15].I & 0xFFFFFFFC;
6606           reg[15].I = armNextPC + 4;
6607         } else {
6608           armNextPC = reg[15].I & 0xFFFFFFFE;
6609           reg[15].I = armNextPC + 2;
6610         }
6611       } else {
6612         LDM_REG(1, 0);
6613         LDM_REG(2, 1);
6614         LDM_REG(4, 2);
6615         LDM_REG(8, 3);
6616         LDM_REG(16, 4);
6617         LDM_REG(32, 5);
6618         LDM_REG(64, 6);
6619         LDM_REG(128, 7);
6620 
6621         if(armMode == 0x11) {
6622           LDM_REG(256, R8_FIQ);
6623           LDM_REG(512, R9_FIQ);
6624           LDM_REG(1024, R10_FIQ);
6625           LDM_REG(2048, R11_FIQ);
6626           LDM_REG(4096, R12_FIQ);
6627         } else {
6628           LDM_REG(256, 8);
6629           LDM_REG(512, 9);
6630           LDM_REG(1024, 10);
6631           LDM_REG(2048, 11);
6632           LDM_REG(4096, 12);
6633         }
6634 
6635         if(armMode != 0x10 && armMode != 0x1f) {
6636           LDM_REG(8192, R13_USR);
6637           LDM_REG(16384, R14_USR);
6638         } else {
6639           LDM_REG(8192, 13);
6640           LDM_REG(16384, 14);
6641         }
6642 
6643         if(!(opcode & (1 << base)))
6644           reg[base].I = temp;
6645       }
6646     }
6647     break;
6648 
6649   CASE_16(0x910)
6650     {
6651       // LDMDB Rn, {Rlist}
6652       int base = (opcode & 0x000F0000) >> 16;
6653       u32 temp = reg[base].I -
6654         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6655       u32 address = temp & 0xFFFFFFFC;
6656       clockTicks += 2;
6657       int offset = 0;
6658       LDM_REG(1, 0);
6659       LDM_REG(2, 1);
6660       LDM_REG(4, 2);
6661       LDM_REG(8, 3);
6662       LDM_REG(16, 4);
6663       LDM_REG(32, 5);
6664       LDM_REG(64, 6);
6665       LDM_REG(128, 7);
6666       LDM_REG(256, 8);
6667       LDM_REG(512, 9);
6668       LDM_REG(1024, 10);
6669       LDM_REG(2048, 11);
6670       LDM_REG(4096, 12);
6671       LDM_REG(8192, 13);
6672       LDM_REG(16384, 14);
6673       if(opcode & 32768) {
6674         reg[15].I = CPUReadMemory(address);
6675         if (!offset)
6676           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6677         else
6678           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6679         armNextPC = reg[15].I;
6680         reg[15].I += 4;
6681       }
6682     }
6683     break;
6684   CASE_16(0x930)
6685     {
6686       // LDMDB Rn!, {Rlist}
6687       int base = (opcode & 0x000F0000) >> 16;
6688       u32 temp = reg[base].I -
6689         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6690       u32 address = temp & 0xFFFFFFFC;
6691       clockTicks += 2;
6692       int offset = 0;
6693       LDM_REG(1, 0);
6694       LDM_REG(2, 1);
6695       LDM_REG(4, 2);
6696       LDM_REG(8, 3);
6697       LDM_REG(16, 4);
6698       LDM_REG(32, 5);
6699       LDM_REG(64, 6);
6700       LDM_REG(128, 7);
6701       LDM_REG(256, 8);
6702       LDM_REG(512, 9);
6703       LDM_REG(1024, 10);
6704       LDM_REG(2048, 11);
6705       LDM_REG(4096, 12);
6706       LDM_REG(8192, 13);
6707       LDM_REG(16384, 14);
6708       if(opcode & 32768) {
6709         reg[15].I = CPUReadMemory(address);
6710         if (!offset)
6711           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6712         else
6713           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6714         armNextPC = reg[15].I;
6715         reg[15].I += 4;
6716       }
6717       if(!(opcode & (1 << base)))
6718         reg[base].I = temp;
6719     }
6720     break;
6721   CASE_16(0x950)
6722     {
6723       // LDMDB Rn, {Rlist}^
6724       int base = (opcode & 0x000F0000) >> 16;
6725       u32 temp = reg[base].I -
6726         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6727       u32 address = temp & 0xFFFFFFFC;
6728       clockTicks += 2;
6729       int offset = 0;
6730       if(opcode & 0x8000) {
6731         LDM_REG(1, 0);
6732         LDM_REG(2, 1);
6733         LDM_REG(4, 2);
6734         LDM_REG(8, 3);
6735         LDM_REG(16, 4);
6736         LDM_REG(32, 5);
6737         LDM_REG(64, 6);
6738         LDM_REG(128, 7);
6739         LDM_REG(256, 8);
6740         LDM_REG(512, 9);
6741         LDM_REG(1024, 10);
6742         LDM_REG(2048, 11);
6743         LDM_REG(4096, 12);
6744         LDM_REG(8192, 13);
6745         LDM_REG(16384, 14);
6746 
6747         reg[15].I = CPUReadMemory(address);
6748         if (!offset)
6749           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6750         else
6751           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6752 
6753         CPUSwitchMode(reg[17].I & 0x1f, false);
6754         if(armState) {
6755           armNextPC = reg[15].I & 0xFFFFFFFC;
6756           reg[15].I = armNextPC + 4;
6757         } else {
6758           armNextPC = reg[15].I & 0xFFFFFFFE;
6759           reg[15].I = armNextPC + 2;
6760         }
6761       } else {
6762         LDM_REG(1, 0);
6763         LDM_REG(2, 1);
6764         LDM_REG(4, 2);
6765         LDM_REG(8, 3);
6766         LDM_REG(16, 4);
6767         LDM_REG(32, 5);
6768         LDM_REG(64, 6);
6769         LDM_REG(128, 7);
6770 
6771         if(armMode == 0x11) {
6772           LDM_REG(256, R8_FIQ);
6773           LDM_REG(512, R9_FIQ);
6774           LDM_REG(1024, R10_FIQ);
6775           LDM_REG(2048, R11_FIQ);
6776           LDM_REG(4096, R12_FIQ);
6777         } else {
6778           LDM_REG(256, 8);
6779           LDM_REG(512, 9);
6780           LDM_REG(1024, 10);
6781           LDM_REG(2048, 11);
6782           LDM_REG(4096, 12);
6783         }
6784 
6785         if(armMode != 0x10 && armMode != 0x1f) {
6786           LDM_REG(8192, R13_USR);
6787           LDM_REG(16384, R14_USR);
6788         } else {
6789           LDM_REG(8192, 13);
6790           LDM_REG(16384, 14);
6791         }
6792       }
6793     }
6794     break;
6795   CASE_16(0x970)
6796     {
6797       // LDMDB Rn!, {Rlist}^
6798       int base = (opcode & 0x000F0000) >> 16;
6799       u32 temp = reg[base].I -
6800         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6801       u32 address = temp & 0xFFFFFFFC;
6802       clockTicks += 2;
6803       int offset = 0;
6804       if(opcode & 0x8000) {
6805         LDM_REG(1, 0);
6806         LDM_REG(2, 1);
6807         LDM_REG(4, 2);
6808         LDM_REG(8, 3);
6809         LDM_REG(16, 4);
6810         LDM_REG(32, 5);
6811         LDM_REG(64, 6);
6812         LDM_REG(128, 7);
6813         LDM_REG(256, 8);
6814         LDM_REG(512, 9);
6815         LDM_REG(1024, 10);
6816         LDM_REG(2048, 11);
6817         LDM_REG(4096, 12);
6818         LDM_REG(8192, 13);
6819         LDM_REG(16384, 14);
6820 
6821         reg[15].I = CPUReadMemory(address);
6822         if(!offset)
6823           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6824         else
6825           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6826 
6827         if(!(opcode & (1 << base)))
6828           reg[base].I = temp;
6829 
6830         CPUSwitchMode(reg[17].I & 0x1f, false);
6831         if(armState) {
6832           armNextPC = reg[15].I & 0xFFFFFFFC;
6833           reg[15].I = armNextPC + 4;
6834         } else {
6835           armNextPC = reg[15].I & 0xFFFFFFFE;
6836           reg[15].I = armNextPC + 2;
6837         }
6838       } else {
6839         LDM_REG(1, 0);
6840         LDM_REG(2, 1);
6841         LDM_REG(4, 2);
6842         LDM_REG(8, 3);
6843         LDM_REG(16, 4);
6844         LDM_REG(32, 5);
6845         LDM_REG(64, 6);
6846         LDM_REG(128, 7);
6847 
6848         if(armMode == 0x11) {
6849           LDM_REG(256, R8_FIQ);
6850           LDM_REG(512, R9_FIQ);
6851           LDM_REG(1024, R10_FIQ);
6852           LDM_REG(2048, R11_FIQ);
6853           LDM_REG(4096, R12_FIQ);
6854         } else {
6855           LDM_REG(256, 8);
6856           LDM_REG(512, 9);
6857           LDM_REG(1024, 10);
6858           LDM_REG(2048, 11);
6859           LDM_REG(4096, 12);
6860         }
6861 
6862         if(armMode != 0x10 && armMode != 0x1f) {
6863           LDM_REG(8192, R13_USR);
6864           LDM_REG(16384, R14_USR);
6865         } else {
6866           LDM_REG(8192, 13);
6867           LDM_REG(16384, 14);
6868         }
6869 
6870         if(!(opcode & (1 << base)))
6871           reg[base].I = temp;
6872       }
6873     }
6874     break;
6875 
6876   CASE_16(0x990)
6877     {
6878       // LDMIB Rn, {Rlist}
6879       int base = (opcode & 0x000F0000) >> 16;
6880       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6881       clockTicks += 2;
6882       int offset = 0;
6883       LDM_REG(1, 0);
6884       LDM_REG(2, 1);
6885       LDM_REG(4, 2);
6886       LDM_REG(8, 3);
6887       LDM_REG(16, 4);
6888       LDM_REG(32, 5);
6889       LDM_REG(64, 6);
6890       LDM_REG(128, 7);
6891       LDM_REG(256, 8);
6892       LDM_REG(512, 9);
6893       LDM_REG(1024, 10);
6894       LDM_REG(2048, 11);
6895       LDM_REG(4096, 12);
6896       LDM_REG(8192, 13);
6897       LDM_REG(16384, 14);
6898       if(opcode & 32768) {
6899         reg[15].I = CPUReadMemory(address);
6900         if (!offset)
6901           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6902         else
6903           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6904         armNextPC = reg[15].I;
6905         reg[15].I += 4;
6906       }
6907     }
6908     break;
6909   CASE_16(0x9b0)
6910     {
6911       // LDMIB Rn!, {Rlist}
6912       int base = (opcode & 0x000F0000) >> 16;
6913       u32 temp = reg[base].I +
6914         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
6915       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6916       clockTicks += 2;
6917       int offset = 0;
6918       LDM_REG(1, 0);
6919       LDM_REG(2, 1);
6920       LDM_REG(4, 2);
6921       LDM_REG(8, 3);
6922       LDM_REG(16, 4);
6923       LDM_REG(32, 5);
6924       LDM_REG(64, 6);
6925       LDM_REG(128, 7);
6926       LDM_REG(256, 8);
6927       LDM_REG(512, 9);
6928       LDM_REG(1024, 10);
6929       LDM_REG(2048, 11);
6930       LDM_REG(4096, 12);
6931       LDM_REG(8192, 13);
6932       LDM_REG(16384, 14);
6933       if(opcode & 32768) {
6934         reg[15].I = CPUReadMemory(address);
6935         if (!offset)
6936           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6937         else
6938           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6939         armNextPC = reg[15].I;
6940         reg[15].I += 4;
6941       }
6942       if(!(opcode & (1 << base)))
6943         reg[base].I = temp;
6944     }
6945     break;
6946   CASE_16(0x9d0)
6947     {
6948       // LDMIB Rn, {Rlist}^
6949       int base = (opcode & 0x000F0000) >> 16;
6950       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
6951       clockTicks += 2;
6952       int offset = 0;
6953       if(opcode & 0x8000) {
6954         LDM_REG(1, 0);
6955         LDM_REG(2, 1);
6956         LDM_REG(4, 2);
6957         LDM_REG(8, 3);
6958         LDM_REG(16, 4);
6959         LDM_REG(32, 5);
6960         LDM_REG(64, 6);
6961         LDM_REG(128, 7);
6962         LDM_REG(256, 8);
6963         LDM_REG(512, 9);
6964         LDM_REG(1024, 10);
6965         LDM_REG(2048, 11);
6966         LDM_REG(4096, 12);
6967         LDM_REG(8192, 13);
6968         LDM_REG(16384, 14);
6969 
6970         reg[15].I = CPUReadMemory(address);
6971         if (!offset)
6972           clockTicks += 2 + CPUUpdateTicksAccess32(address);
6973         else
6974           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
6975 
6976         CPUSwitchMode(reg[17].I & 0x1f, false);
6977         if(armState) {
6978           armNextPC = reg[15].I & 0xFFFFFFFC;
6979           reg[15].I = armNextPC + 4;
6980         } else {
6981           armNextPC = reg[15].I & 0xFFFFFFFE;
6982           reg[15].I = armNextPC + 2;
6983         }
6984       } else {
6985         LDM_REG(1, 0);
6986         LDM_REG(2, 1);
6987         LDM_REG(4, 2);
6988         LDM_REG(8, 3);
6989         LDM_REG(16, 4);
6990         LDM_REG(32, 5);
6991         LDM_REG(64, 6);
6992         LDM_REG(128, 7);
6993 
6994         if(armMode == 0x11) {
6995           LDM_REG(256, R8_FIQ);
6996           LDM_REG(512, R9_FIQ);
6997           LDM_REG(1024, R10_FIQ);
6998           LDM_REG(2048, R11_FIQ);
6999           LDM_REG(4096, R12_FIQ);
7000         } else {
7001           LDM_REG(256, 8);
7002           LDM_REG(512, 9);
7003           LDM_REG(1024, 10);
7004           LDM_REG(2048, 11);
7005           LDM_REG(4096, 12);
7006         }
7007 
7008         if(armMode != 0x10 && armMode != 0x1f) {
7009           LDM_REG(8192, R13_USR);
7010           LDM_REG(16384, R14_USR);
7011         } else {
7012           LDM_REG(8192, 13);
7013           LDM_REG(16384, 14);
7014         }
7015       }
7016     }
7017     break;
7018   CASE_16(0x9f0)
7019     {
7020       // LDMIB Rn!, {Rlist}^
7021       int base = (opcode & 0x000F0000) >> 16;
7022       u32 temp = reg[base].I +
7023         4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
7024       u32 address = (reg[base].I+4) & 0xFFFFFFFC;
7025       clockTicks += 2;
7026       int offset = 0;
7027       if(opcode & 0x8000) {
7028         LDM_REG(1, 0);
7029         LDM_REG(2, 1);
7030         LDM_REG(4, 2);
7031         LDM_REG(8, 3);
7032         LDM_REG(16, 4);
7033         LDM_REG(32, 5);
7034         LDM_REG(64, 6);
7035         LDM_REG(128, 7);
7036         LDM_REG(256, 8);
7037         LDM_REG(512, 9);
7038         LDM_REG(1024, 10);
7039         LDM_REG(2048, 11);
7040         LDM_REG(4096, 12);
7041         LDM_REG(8192, 13);
7042         LDM_REG(16384, 14);
7043 
7044         reg[15].I = CPUReadMemory(address);
7045         if(!offset)
7046           clockTicks += 2 + CPUUpdateTicksAccess32(address);
7047         else
7048           clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
7049 
7050         if(!(opcode & (1 << base)))
7051           reg[base].I = temp;
7052 
7053         CPUSwitchMode(reg[17].I & 0x1f, false);
7054         if(armState) {
7055           armNextPC = reg[15].I & 0xFFFFFFFC;
7056           reg[15].I = armNextPC + 4;
7057         } else {
7058           armNextPC = reg[15].I & 0xFFFFFFFE;
7059           reg[15].I = armNextPC + 2;
7060         }
7061       } else {
7062         LDM_REG(1, 0);
7063         LDM_REG(2, 1);
7064         LDM_REG(4, 2);
7065         LDM_REG(8, 3);
7066         LDM_REG(16, 4);
7067         LDM_REG(32, 5);
7068         LDM_REG(64, 6);
7069         LDM_REG(128, 7);
7070 
7071         if(armMode == 0x11) {
7072           LDM_REG(256, R8_FIQ);
7073           LDM_REG(512, R9_FIQ);
7074           LDM_REG(1024, R10_FIQ);
7075           LDM_REG(2048, R11_FIQ);
7076           LDM_REG(4096, R12_FIQ);
7077         } else {
7078           LDM_REG(256, 8);
7079           LDM_REG(512, 9);
7080           LDM_REG(1024, 10);
7081           LDM_REG(2048, 11);
7082           LDM_REG(4096, 12);
7083         }
7084 
7085         if(armMode != 0x10 && armMode != 0x1f) {
7086           LDM_REG(8192, R13_USR);
7087           LDM_REG(16384, R14_USR);
7088         } else {
7089           LDM_REG(8192, 13);
7090           LDM_REG(16384, 14);
7091         }
7092 
7093         if(!(opcode & (1 << base)))
7094           reg[base].I = temp;
7095       }
7096     }
7097     break;
7098   CASE_256(0xa00)
7099     {
7100       // B <offset>
7101       clockTicks += 3;
7102       int offset = opcode & 0x00FFFFFF;
7103       if(offset & 0x00800000) {
7104         offset |= 0xFF000000;
7105       }
7106       offset <<= 2;
7107       reg[15].I += offset;
7108       armNextPC = reg[15].I;
7109       reg[15].I += 4;
7110     }
7111     break;
7112   CASE_256(0xb00)
7113     {
7114       // BL <offset>
7115       clockTicks += 3;
7116       int offset = opcode & 0x00FFFFFF;
7117       if(offset & 0x00800000) {
7118         offset |= 0xFF000000;
7119       }
7120       offset <<= 2;
7121       reg[14].I = reg[15].I - 4;
7122       reg[15].I += offset;
7123       armNextPC = reg[15].I;
7124       reg[15].I += 4;
7125     }
7126     break;
7127   CASE_256(0xf00)
7128     // SWI <comment>
7129     clockTicks += 3;
7130     CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
7131     break;
7132 #ifdef GP_SUPPORT
7133   case 0xe11:
7134   case 0xe13:
7135   case 0xe15:
7136   case 0xe17:
7137   case 0xe19:
7138   case 0xe1b:
7139   case 0xe1d:
7140   case 0xe1f:
7141     // MRC
7142     break;
7143   case 0xe01:
7144   case 0xe03:
7145   case 0xe05:
7146   case 0xe07:
7147   case 0xe09:
7148   case 0xe0b:
7149   case 0xe0d:
7150   case 0xe0f:
7151     // MRC
7152     break;
7153 #endif
7154   default:
7155 #ifdef DEV_VERSION
7156     if(systemVerbose & VERBOSE_UNDEFINED)
7157       log("Undefined ARM instruction %08x at %08x\n", opcode,
7158           armNextPC-4);
7159 #endif
7160     CPUUndefinedException();
7161     break;
7162     // END
7163   }
7164 }
7165