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 C_CORE
21 #define NEG(i) ((i) >> 31)
22 #define POS(i) ((~(i)) >> 31)
23 #define ADDCARRY(a, b, c) \
24   C_FLAG = ((NEG(a) & NEG(b)) |\
25             (NEG(a) & POS(c)) |\
26             (NEG(b) & POS(c))) ? true : false;
27 #define ADDOVERFLOW(a, b, c) \
28   V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
29             (POS(a) & POS(b) & NEG(c))) ? true : false;
30 #define SUBCARRY(a, b, c) \
31   C_FLAG = ((NEG(a) & POS(b)) |\
32             (NEG(a) & POS(c)) |\
33             (POS(b) & POS(c))) ? true : false;
34 #define SUBOVERFLOW(a, b, c)\
35   V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
36             (POS(a) & NEG(b) & NEG(c))) ? true : false;
37 #define ADD_RD_RS_RN \
38    {\
39      u32 lhs = reg[source].I;\
40      u32 rhs = value;\
41      u32 res = lhs + rhs;\
42      reg[dest].I = res;\
43      Z_FLAG = (res == 0) ? true : false;\
44      N_FLAG = NEG(res) ? true : false;\
45      ADDCARRY(lhs, rhs, res);\
46      ADDOVERFLOW(lhs, rhs, res);\
47    }
48 #define ADD_RD_RS_O3 \
49    {\
50      u32 lhs = reg[source].I;\
51      u32 rhs = value;\
52      u32 res = lhs + rhs;\
53      reg[dest].I = res;\
54      Z_FLAG = (res == 0) ? true : false;\
55      N_FLAG = NEG(res) ? true : false;\
56      ADDCARRY(lhs, rhs, res);\
57      ADDOVERFLOW(lhs, rhs, res);\
58    }
59 #define ADD_RN_O8(d) \
60    {\
61      u32 lhs = reg[(d)].I;\
62      u32 rhs = (opcode & 255);\
63      u32 res = lhs + rhs;\
64      reg[(d)].I = res;\
65      Z_FLAG = (res == 0) ? true : false;\
66      N_FLAG = NEG(res) ? true : false;\
67      ADDCARRY(lhs, rhs, res);\
68      ADDOVERFLOW(lhs, rhs, res);\
69    }
70 #define CMN_RD_RS \
71    {\
72      u32 lhs = reg[dest].I;\
73      u32 rhs = value;\
74      u32 res = lhs + rhs;\
75      Z_FLAG = (res == 0) ? true : false;\
76      N_FLAG = NEG(res) ? true : false;\
77      ADDCARRY(lhs, rhs, res);\
78      ADDOVERFLOW(lhs, rhs, res);\
79    }
80 #define ADC_RD_RS \
81    {\
82      u32 lhs = reg[dest].I;\
83      u32 rhs = value;\
84      u32 res = lhs + rhs + (u32)C_FLAG;\
85      reg[dest].I = res;\
86      Z_FLAG = (res == 0) ? true : false;\
87      N_FLAG = NEG(res) ? true : false;\
88      ADDCARRY(lhs, rhs, res);\
89      ADDOVERFLOW(lhs, rhs, res);\
90    }
91 #define SUB_RD_RS_RN \
92    {\
93      u32 lhs = reg[source].I;\
94      u32 rhs = value;\
95      u32 res = lhs - rhs;\
96      reg[dest].I = res;\
97      Z_FLAG = (res == 0) ? true : false;\
98      N_FLAG = NEG(res) ? true : false;\
99      SUBCARRY(lhs, rhs, res);\
100      SUBOVERFLOW(lhs, rhs, res);\
101    }
102 #define SUB_RD_RS_O3 \
103    {\
104      u32 lhs = reg[source].I;\
105      u32 rhs = value;\
106      u32 res = lhs - rhs;\
107      reg[dest].I = res;\
108      Z_FLAG = (res == 0) ? true : false;\
109      N_FLAG = NEG(res) ? true : false;\
110      SUBCARRY(lhs, rhs, res);\
111      SUBOVERFLOW(lhs, rhs, res);\
112    }
113 #define SUB_RN_O8(d) \
114    {\
115      u32 lhs = reg[(d)].I;\
116      u32 rhs = (opcode & 255);\
117      u32 res = lhs - rhs;\
118      reg[(d)].I = res;\
119      Z_FLAG = (res == 0) ? true : false;\
120      N_FLAG = NEG(res) ? true : false;\
121      SUBCARRY(lhs, rhs, res);\
122      SUBOVERFLOW(lhs, rhs, res);\
123    }
124 #define CMP_RN_O8(d) \
125    {\
126      u32 lhs = reg[(d)].I;\
127      u32 rhs = (opcode & 255);\
128      u32 res = lhs - rhs;\
129      Z_FLAG = (res == 0) ? true : false;\
130      N_FLAG = NEG(res) ? true : false;\
131      SUBCARRY(lhs, rhs, res);\
132      SUBOVERFLOW(lhs, rhs, res);\
133    }
134 #define SBC_RD_RS \
135    {\
136      u32 lhs = reg[dest].I;\
137      u32 rhs = value;\
138      u32 res = lhs - rhs - !((u32)C_FLAG);\
139      reg[dest].I = res;\
140      Z_FLAG = (res == 0) ? true : false;\
141      N_FLAG = NEG(res) ? true : false;\
142      SUBCARRY(lhs, rhs, res);\
143      SUBOVERFLOW(lhs, rhs, res);\
144    }
145 #define LSL_RD_RM_I5 \
146    {\
147      C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\
148      value = reg[source].I << shift;\
149    }
150 #define LSL_RD_RS \
151    {\
152      C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\
153      value = reg[dest].I << value;\
154    }
155 #define LSR_RD_RM_I5 \
156    {\
157      C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\
158      value = reg[source].I >> shift;\
159    }
160 #define LSR_RD_RS \
161    {\
162      C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
163      value = reg[dest].I >> value;\
164    }
165 #define ASR_RD_RM_I5 \
166    {\
167      C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
168      value = (s32)reg[source].I >> (int)shift;\
169    }
170 #define ASR_RD_RS \
171    {\
172      C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
173      value = (s32)reg[dest].I >> (int)value;\
174    }
175 #define ROR_RD_RS \
176    {\
177      C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
178      value = ((reg[dest].I << (32 - value)) |\
179               (reg[dest].I >> value));\
180    }
181 #define NEG_RD_RS \
182    {\
183      u32 lhs = reg[source].I;\
184      u32 rhs = 0;\
185      u32 res = rhs - lhs;\
186      reg[dest].I = res;\
187      Z_FLAG = (res == 0) ? true : false;\
188      N_FLAG = NEG(res) ? true : false;\
189      SUBCARRY(rhs, lhs, res);\
190      SUBOVERFLOW(rhs, lhs, res);\
191    }
192 #define CMP_RD_RS \
193    {\
194      u32 lhs = reg[dest].I;\
195      u32 rhs = value;\
196      u32 res = lhs - rhs;\
197      Z_FLAG = (res == 0) ? true : false;\
198      N_FLAG = NEG(res) ? true : false;\
199      SUBCARRY(lhs, rhs, res);\
200      SUBOVERFLOW(lhs, rhs, res);\
201    }
202 #else
203 #ifdef __GNUC__
204 #ifdef __POWERPC__
205             #define ADD_RD_RS_RN \
206             {										\
207                 register int Flags;					\
208                 register int Result;				\
209                 asm volatile("addco. %0, %2, %3\n"	\
210                             "mcrxr cr1\n"			\
211                             "mfcr %1\n"				\
212                             : "=r" (Result), 		\
213                               "=r" (Flags)			\
214                             : "r" (reg[source].I), 	\
215                               "r" (value)			\
216                             );						\
217                 reg[dest].I = Result;				\
218                 Z_FLAG = (Flags >> 29) & 1;			\
219                 N_FLAG = (Flags >> 31) & 1;			\
220                 C_FLAG = (Flags >> 25) & 1;			\
221                 V_FLAG = (Flags >> 26) & 1;			\
222             }
223             #define ADD_RD_RS_O3 ADD_RD_RS_RN
224             #define ADD_RN_O8(d) \
225             {\
226                 register int Flags;					\
227                 register int Result;				\
228                 asm volatile("addco. %0, %2, %3\n"	\
229                             "mcrxr cr1\n"			\
230                             "mfcr %1\n"				\
231                             : "=r" (Result), 		\
232                               "=r" (Flags)			\
233                             : "r" (reg[(d)].I), 	\
234                               "r" (opcode & 255)	\
235                             );						\
236                 reg[(d)].I = Result;				\
237                 Z_FLAG = (Flags >> 29) & 1;			\
238                 N_FLAG = (Flags >> 31) & 1;			\
239                 C_FLAG = (Flags >> 25) & 1;			\
240                 V_FLAG = (Flags >> 26) & 1;			\
241             }
242             #define CMN_RD_RS \
243             {\
244                 register int Flags;					\
245                 register int Result;				\
246                 asm volatile("addco. %0, %2, %3\n"	\
247                             "mcrxr cr1\n"			\
248                             "mfcr %1\n"				\
249                             : "=r" (Result), 		\
250                               "=r" (Flags)			\
251                             : "r" (reg[dest].I), 	\
252                               "r" (value)			\
253                             );						\
254                 Z_FLAG = (Flags >> 29) & 1;			\
255                 N_FLAG = (Flags >> 31) & 1;			\
256                 C_FLAG = (Flags >> 25) & 1;			\
257                 V_FLAG = (Flags >> 26) & 1;			\
258             }
259             #define ADC_RD_RS \
260             {\
261                 register int Flags;					\
262                 register int Result;				\
263                 asm volatile("mtspr xer, %4\n"		\
264                              "addeo. %0, %2, %3\n"	\
265                              "mcrxr cr1\n"			\
266                              "mfcr	%1\n"			\
267                              : "=r" (Result),		\
268                                "=r" (Flags)			\
269                              : "r" (reg[dest].I),	\
270                                "r" (value),			\
271                                "r" (C_FLAG << 29)	\
272                              );						\
273                 reg[dest].I = Result;				\
274                 Z_FLAG = (Flags >> 29) & 1;			\
275                 N_FLAG = (Flags >> 31) & 1;			\
276                 C_FLAG = (Flags >> 25) & 1;			\
277                 V_FLAG = (Flags >> 26) & 1;			\
278             }
279             #define SUB_RD_RS_RN \
280             {\
281                 register int Flags;					\
282                 register int Result;				\
283                 asm volatile("subco. %0, %2, %3\n"	\
284                             "mcrxr cr1\n"			\
285                             "mfcr %1\n"				\
286                             : "=r" (Result), 		\
287                               "=r" (Flags)			\
288                             : "r" (reg[source].I), 	\
289                               "r" (value)			\
290                             );						\
291                 reg[dest].I = Result;				\
292                 Z_FLAG = (Flags >> 29) & 1;			\
293                 N_FLAG = (Flags >> 31) & 1;			\
294                 C_FLAG = (Flags >> 25) & 1;			\
295                 V_FLAG = (Flags >> 26) & 1;			\
296             }
297             #define SUB_RD_RS_O3 SUB_RD_RS_RN
298             #define SUB_RN_O8(d) \
299             {\
300                 register int Flags;					\
301                 register int Result;				\
302                 asm volatile("subco. %0, %2, %3\n"	\
303                             "mcrxr cr1\n"			\
304                             "mfcr %1\n"				\
305                             : "=r" (Result), 		\
306                               "=r" (Flags)			\
307                             : "r" (reg[(d)].I), 	\
308                               "r" (opcode & 255)	\
309                             );						\
310                 reg[(d)].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 CMP_RN_O8(d) \
317             {\
318                 register int Flags;					\
319                 register int Result;				\
320                 asm volatile("subco. %0, %2, %3\n"	\
321                             "mcrxr cr1\n"			\
322                             "mfcr %1\n"				\
323                             : "=r" (Result), 		\
324                               "=r" (Flags)			\
325                             : "r" (reg[(d)].I), 	\
326                               "r" (opcode & 255)	\
327                             );						\
328                 Z_FLAG = (Flags >> 29) & 1;			\
329                 N_FLAG = (Flags >> 31) & 1;			\
330                 C_FLAG = (Flags >> 25) & 1;			\
331                 V_FLAG = (Flags >> 26) & 1;			\
332             }
333             #define SBC_RD_RS \
334             {\
335                 register int Flags;					\
336                 register int Result;				\
337                 asm volatile("mtspr xer, %4\n"		\
338                              "subfeo. %0, %3, %2\n"	\
339                              "mcrxr cr1\n"			\
340                              "mfcr	%1\n"			\
341                              : "=r" (Result),		\
342                                "=r" (Flags)			\
343                              : "r" (reg[dest].I),	\
344                                "r" (value),			\
345                                "r" (C_FLAG << 29) 	\
346                              );						\
347                 reg[dest].I = Result;				\
348                 Z_FLAG = (Flags >> 29) & 1;			\
349                 N_FLAG = (Flags >> 31) & 1;			\
350                 C_FLAG = (Flags >> 25) & 1;			\
351                 V_FLAG = (Flags >> 26) & 1;			\
352             }
353             #define LSL_RD_RM_I5 \
354             {\
355                 C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\
356                 value = reg[source].I << shift;\
357             }
358             #define LSL_RD_RS \
359             {\
360                 C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\
361                 value = reg[dest].I << value;\
362             }
363             #define LSR_RD_RM_I5 \
364             {\
365                 C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\
366                 value = reg[source].I >> shift;\
367             }
368             #define LSR_RD_RS \
369             {\
370                 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
371                 value = reg[dest].I >> value;\
372             }
373             #define ASR_RD_RM_I5 \
374             {\
375                 C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
376                 value = (s32)reg[source].I >> (int)shift;\
377             }
378             #define ASR_RD_RS \
379             {\
380                 C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
381                 value = (s32)reg[dest].I >> (int)value;\
382             }
383             #define ROR_RD_RS \
384             {\
385                 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
386                 value = ((reg[dest].I << (32 - value)) |\
387                         (reg[dest].I >> value));\
388             }
389             #define NEG_RD_RS \
390             {\
391                 register int Flags;					\
392                 register int Result;				\
393                 asm volatile("subfco. %0, %2, %3\n"	\
394                             "mcrxr cr1\n"			\
395                             "mfcr %1\n"				\
396                             : "=r" (Result), 		\
397                               "=r" (Flags)			\
398                             : "r" (reg[source].I), 	\
399                               "r" (0)				\
400                             );						\
401                 reg[dest].I = Result;				\
402                 Z_FLAG = (Flags >> 29) & 1;			\
403                 N_FLAG = (Flags >> 31) & 1;			\
404                 C_FLAG = (Flags >> 25) & 1;			\
405                 V_FLAG = (Flags >> 26) & 1;			\
406             }
407             #define CMP_RD_RS \
408             {\
409                 register int Flags;					\
410                 register int Result;				\
411                 asm volatile("subco. %0, %2, %3\n"	\
412                             "mcrxr cr1\n"			\
413                             "mfcr %1\n"				\
414                             : "=r" (Result), 		\
415                               "=r" (Flags)			\
416                             : "r" (reg[dest].I), 	\
417                               "r" (value)			\
418                             );						\
419                 Z_FLAG = (Flags >> 29) & 1;			\
420                 N_FLAG = (Flags >> 31) & 1;			\
421                 C_FLAG = (Flags >> 25) & 1;			\
422                 V_FLAG = (Flags >> 26) & 1;			\
423             }
424 #else
425 #define ADD_RD_RS_RN \
426      asm ("add %1, %%ebx;"\
427           "setsb N_FLAG;"\
428           "setzb Z_FLAG;"\
429           "setcb C_FLAG;"\
430           "setob V_FLAG;"\
431           : "=b" (reg[dest].I)\
432           : "r" (value), "b" (reg[source].I));
433 #define ADD_RD_RS_O3 \
434      asm ("add %1, %%ebx;"\
435           "setsb N_FLAG;"\
436           "setzb Z_FLAG;"\
437           "setcb C_FLAG;"\
438           "setob V_FLAG;"\
439           : "=b" (reg[dest].I)\
440           : "r" (value), "b" (reg[source].I));
441 #define ADD_RN_O8(d) \
442      asm ("add %1, %%ebx;"\
443           "setsb N_FLAG;"\
444           "setzb Z_FLAG;"\
445           "setcb C_FLAG;"\
446           "setob V_FLAG;"\
447           : "=b" (reg[(d)].I)\
448           : "r" (opcode & 255), "b" (reg[(d)].I));
449 #define CMN_RD_RS \
450      asm ("add %0, %1;"\
451           "setsb N_FLAG;"\
452           "setzb Z_FLAG;"\
453           "setcb C_FLAG;"\
454           "setob V_FLAG;"\
455           : \
456           : "r" (value), "r" (reg[dest].I):"1");
457 #define ADC_RD_RS \
458      asm ("bt $0, C_FLAG;"\
459           "adc %1, %%ebx;"\
460           "setsb N_FLAG;"\
461           "setzb Z_FLAG;"\
462           "setcb C_FLAG;"\
463           "setob V_FLAG;"\
464           : "=b" (reg[dest].I)\
465           : "r" (value), "b" (reg[dest].I));
466 #define SUB_RD_RS_RN \
467      asm ("sub %1, %%ebx;"\
468           "setsb N_FLAG;"\
469           "setzb Z_FLAG;"\
470           "setncb C_FLAG;"\
471           "setob V_FLAG;"\
472           : "=b" (reg[dest].I)\
473           : "r" (value), "b" (reg[source].I));
474 #define SUB_RD_RS_O3 \
475      asm ("sub %1, %%ebx;"\
476           "setsb N_FLAG;"\
477           "setzb Z_FLAG;"\
478           "setncb C_FLAG;"\
479           "setob V_FLAG;"\
480           : "=b" (reg[dest].I)\
481           : "r" (value), "b" (reg[source].I));
482 #define SUB_RN_O8(d) \
483      asm ("sub %1, %%ebx;"\
484           "setsb N_FLAG;"\
485           "setzb Z_FLAG;"\
486           "setncb C_FLAG;"\
487           "setob V_FLAG;"\
488           : "=b" (reg[(d)].I)\
489           : "r" (opcode & 255), "b" (reg[(d)].I));
490 #define CMP_RN_O8(d) \
491      asm ("sub %0, %1;"\
492           "setsb N_FLAG;"\
493           "setzb Z_FLAG;"\
494           "setncb C_FLAG;"\
495           "setob V_FLAG;"\
496           : \
497           : "r" (opcode & 255), "r" (reg[(d)].I) : "1");
498 #define SBC_RD_RS \
499      asm volatile ("bt $0, C_FLAG;"\
500                    "cmc;"\
501                    "sbb %1, %%ebx;"\
502                    "setsb N_FLAG;"\
503                    "setzb Z_FLAG;"\
504                    "setncb C_FLAG;"\
505                    "setob V_FLAG;"\
506                    : "=b" (reg[dest].I)\
507                    : "r" (value), "b" (reg[dest].I) : "cc", "memory");
508 #define LSL_RD_RM_I5 \
509        asm ("shl %%cl, %%eax;"\
510             "setcb C_FLAG;"\
511             : "=a" (value)\
512             : "a" (reg[source].I), "c" (shift));
513 #define LSL_RD_RS \
514          asm ("shl %%cl, %%eax;"\
515               "setcb C_FLAG;"\
516               : "=a" (value)\
517               : "a" (reg[dest].I), "c" (value));
518 #define LSR_RD_RM_I5 \
519        asm ("shr %%cl, %%eax;"\
520             "setcb C_FLAG;"\
521             : "=a" (value)\
522             : "a" (reg[source].I), "c" (shift));
523 #define LSR_RD_RS \
524          asm ("shr %%cl, %%eax;"\
525               "setcb C_FLAG;"\
526               : "=a" (value)\
527               : "a" (reg[dest].I), "c" (value));
528 #define ASR_RD_RM_I5 \
529      asm ("sar %%cl, %%eax;"\
530           "setcb C_FLAG;"\
531           : "=a" (value)\
532           : "a" (reg[source].I), "c" (shift));
533 #define ASR_RD_RS \
534          asm ("sar %%cl, %%eax;"\
535               "setcb C_FLAG;"\
536               : "=a" (value)\
537               : "a" (reg[dest].I), "c" (value));
538 #define ROR_RD_RS \
539          asm ("ror %%cl, %%eax;"\
540               "setcb C_FLAG;"\
541               : "=a" (value)\
542               : "a" (reg[dest].I), "c" (value));
543 #define NEG_RD_RS \
544      asm ("neg %%ebx;"\
545           "setsb N_FLAG;"\
546           "setzb Z_FLAG;"\
547           "setncb C_FLAG;"\
548           "setob V_FLAG;"\
549           : "=b" (reg[dest].I)\
550           : "b" (reg[source].I));
551 #define CMP_RD_RS \
552      asm ("sub %0, %1;"\
553           "setsb N_FLAG;"\
554           "setzb Z_FLAG;"\
555           "setncb C_FLAG;"\
556           "setob V_FLAG;"\
557           : \
558           : "r" (value), "r" (reg[dest].I):"1");
559 #endif
560 #else
561 #define ADD_RD_RS_RN \
562    {\
563      __asm mov eax, source\
564      __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
565      __asm add ebx, value\
566      __asm mov eax, dest\
567      __asm mov dword ptr [OFFSET reg+4*eax], ebx\
568      __asm sets byte ptr N_FLAG\
569      __asm setz byte ptr Z_FLAG\
570      __asm setc byte ptr C_FLAG\
571      __asm seto byte ptr V_FLAG\
572    }
573 #define ADD_RD_RS_O3 \
574    {\
575      __asm mov eax, source\
576      __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
577      __asm add ebx, value\
578      __asm mov eax, dest\
579      __asm mov dword ptr [OFFSET reg+4*eax], ebx\
580      __asm sets byte ptr N_FLAG\
581      __asm setz byte ptr Z_FLAG\
582      __asm setc byte ptr C_FLAG\
583      __asm seto byte ptr V_FLAG\
584    }
585 #define ADD_RN_O8(d) \
586    {\
587      __asm mov ebx, opcode\
588      __asm and ebx, 255\
589      __asm add dword ptr [OFFSET reg+4*(d)], ebx\
590      __asm sets byte ptr N_FLAG\
591      __asm setz byte ptr Z_FLAG\
592      __asm setc byte ptr C_FLAG\
593      __asm seto byte ptr V_FLAG\
594    }
595 #define CMN_RD_RS \
596      {\
597        __asm mov eax, dest\
598        __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
599        __asm add ebx, value\
600        __asm sets byte ptr N_FLAG\
601        __asm setz byte ptr Z_FLAG\
602        __asm setc byte ptr C_FLAG\
603        __asm seto byte ptr V_FLAG\
604      }
605 #define ADC_RD_RS \
606      {\
607        __asm mov ebx, dest\
608        __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
609        __asm bt word ptr C_FLAG, 0\
610        __asm adc ebx, value\
611        __asm mov eax, dest\
612        __asm mov dword ptr [OFFSET reg+4*eax], ebx\
613        __asm sets byte ptr N_FLAG\
614        __asm setz byte ptr Z_FLAG\
615        __asm setc byte ptr C_FLAG\
616        __asm seto byte ptr V_FLAG\
617      }
618 #define SUB_RD_RS_RN \
619    {\
620      __asm mov eax, source\
621      __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
622      __asm sub ebx, value\
623      __asm mov eax, dest\
624      __asm mov dword ptr [OFFSET reg+4*eax], ebx\
625      __asm sets byte ptr N_FLAG\
626      __asm setz byte ptr Z_FLAG\
627      __asm setnc byte ptr C_FLAG\
628      __asm seto byte ptr V_FLAG\
629    }
630 #define SUB_RD_RS_O3 \
631    {\
632      __asm mov eax, source\
633      __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
634      __asm sub ebx, value\
635      __asm mov eax, dest\
636      __asm mov dword ptr [OFFSET reg+4*eax], ebx\
637      __asm sets byte ptr N_FLAG\
638      __asm setz byte ptr Z_FLAG\
639      __asm setnc byte ptr C_FLAG\
640      __asm seto byte ptr V_FLAG\
641    }
642 #define SUB_RN_O8(d) \
643    {\
644      __asm mov ebx, opcode\
645      __asm and ebx, 255\
646      __asm sub dword ptr [OFFSET reg + 4*(d)], ebx\
647      __asm sets byte ptr N_FLAG\
648      __asm setz byte ptr Z_FLAG\
649      __asm setnc byte ptr C_FLAG\
650      __asm seto byte ptr V_FLAG\
651    }
652 #define CMP_RN_O8(d) \
653    {\
654      __asm mov eax, dword ptr [OFFSET reg+4*(d)]\
655      __asm mov ebx, opcode\
656      __asm and ebx, 255\
657      __asm sub eax, ebx\
658      __asm sets byte ptr N_FLAG\
659      __asm setz byte ptr Z_FLAG\
660      __asm setnc byte ptr C_FLAG\
661      __asm seto byte ptr V_FLAG\
662    }
663 #define SBC_RD_RS \
664      {\
665        __asm mov ebx, dest\
666        __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
667        __asm mov eax, value\
668        __asm bt word ptr C_FLAG, 0\
669        __asm cmc\
670        __asm sbb ebx, eax\
671        __asm mov eax, dest\
672        __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
673        __asm sets byte ptr N_FLAG\
674        __asm setz byte ptr Z_FLAG\
675        __asm setnc byte ptr C_FLAG\
676        __asm seto byte ptr V_FLAG\
677      }
678 #define LSL_RD_RM_I5 \
679      {\
680        __asm mov eax, source\
681        __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
682        __asm mov cl, byte ptr shift\
683        __asm shl eax, cl\
684        __asm mov value, eax\
685        __asm setc byte ptr C_FLAG\
686      }
687 #define LSL_RD_RS \
688          {\
689            __asm mov eax, dest\
690            __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
691            __asm mov cl, byte ptr value\
692            __asm shl eax, cl\
693            __asm mov value, eax\
694            __asm setc byte ptr C_FLAG\
695          }
696 #define LSR_RD_RM_I5 \
697      {\
698        __asm mov eax, source\
699        __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
700        __asm mov cl, byte ptr shift\
701        __asm shr eax, cl\
702        __asm mov value, eax\
703        __asm setc byte ptr C_FLAG\
704      }
705 #define LSR_RD_RS \
706          {\
707            __asm mov eax, dest\
708            __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
709            __asm mov cl, byte ptr value\
710            __asm shr eax, cl\
711            __asm mov value, eax\
712            __asm setc byte ptr C_FLAG\
713          }
714 #define ASR_RD_RM_I5 \
715      {\
716        __asm mov eax, source\
717        __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
718        __asm mov cl, byte ptr shift\
719        __asm sar eax, cl\
720        __asm mov value, eax\
721        __asm setc byte ptr C_FLAG\
722      }
723 #define ASR_RD_RS \
724          {\
725            __asm mov eax, dest\
726            __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
727            __asm mov cl, byte ptr value\
728            __asm sar eax, cl\
729            __asm mov value, eax\
730            __asm setc byte ptr C_FLAG\
731          }
732 #define ROR_RD_RS \
733          {\
734            __asm mov eax, dest\
735            __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
736            __asm mov cl, byte ptr value\
737            __asm ror eax, cl\
738            __asm mov value, eax\
739            __asm setc byte ptr C_FLAG\
740          }
741 #define NEG_RD_RS \
742      {\
743        __asm mov ebx, source\
744        __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
745        __asm neg ebx\
746        __asm mov eax, dest\
747        __asm mov dword ptr [OFFSET reg+4*eax],ebx\
748        __asm sets byte ptr N_FLAG\
749        __asm setz byte ptr Z_FLAG\
750        __asm setnc byte ptr C_FLAG\
751        __asm seto byte ptr V_FLAG\
752      }
753 #define CMP_RD_RS \
754      {\
755        __asm mov eax, dest\
756        __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
757        __asm sub ebx, value\
758        __asm sets byte ptr N_FLAG\
759        __asm setz byte ptr Z_FLAG\
760        __asm setnc byte ptr C_FLAG\
761        __asm seto byte ptr V_FLAG\
762      }
763 #endif
764 #endif
765 
766 u32 opcode = CPUReadHalfWordQuick(armNextPC);
767 clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15];
768 #ifndef FINAL_VERSION
769 if(armNextPC == stop) {
770   armNextPC = armNextPC++;
771 }
772 #endif
773 
774 armNextPC = reg[15].I;
775 reg[15].I += 2;
776 
777 switch(opcode >> 8) {
778  case 0x00:
779  case 0x01:
780  case 0x02:
781  case 0x03:
782  case 0x04:
783  case 0x05:
784  case 0x06:
785  case 0x07:
786    {
787      // LSL Rd, Rm, #Imm 5
788      int dest = opcode & 0x07;
789      int source = (opcode >> 3) & 0x07;
790      int shift = (opcode >> 6) & 0x1f;
791      u32 value;
792 
793      if(shift) {
794        LSL_RD_RM_I5;
795      } else {
796        value = reg[source].I;
797      }
798      reg[dest].I = value;
799      // C_FLAG set above
800      N_FLAG = (value & 0x80000000 ? true : false);
801      Z_FLAG = (value ? false : true);
802    }
803    break;
804  case 0x08:
805  case 0x09:
806  case 0x0a:
807  case 0x0b:
808  case 0x0c:
809  case 0x0d:
810  case 0x0e:
811  case 0x0f:
812    {
813      // LSR Rd, Rm, #Imm 5
814      int dest = opcode & 0x07;
815      int source = (opcode >> 3) & 0x07;
816      int shift = (opcode >> 6) & 0x1f;
817      u32 value;
818 
819      if(shift) {
820        LSR_RD_RM_I5;
821      } else {
822        C_FLAG = reg[source].I & 0x80000000 ? true : false;
823        value = 0;
824      }
825      reg[dest].I = value;
826      // C_FLAG set above
827      N_FLAG = (value & 0x80000000 ? true : false);
828      Z_FLAG = (value ? false : true);
829    }
830    break;
831  case 0x10:
832  case 0x11:
833  case 0x12:
834  case 0x13:
835  case 0x14:
836  case 0x15:
837  case 0x16:
838  case 0x17:
839    {
840      // ASR Rd, Rm, #Imm 5
841      int dest = opcode & 0x07;
842      int source = (opcode >> 3) & 0x07;
843      int shift = (opcode >> 6) & 0x1f;
844      u32 value;
845 
846      if(shift) {
847        ASR_RD_RM_I5;
848      } else {
849        if(reg[source].I & 0x80000000) {
850          value = 0xFFFFFFFF;
851          C_FLAG = true;
852        } else {
853          value = 0;
854          C_FLAG = false;
855        }
856      }
857      reg[dest].I = value;
858      // C_FLAG set above
859      N_FLAG = (value & 0x80000000 ? true : false);
860      Z_FLAG = (value ? false :true);
861    }
862    break;
863  case 0x18:
864  case 0x19:
865    {
866      // ADD Rd, Rs, Rn
867      int dest = opcode & 0x07;
868      int source = (opcode >> 3) & 0x07;
869      u32 value = reg[(opcode>>6)& 0x07].I;
870      ADD_RD_RS_RN;
871    }
872    break;
873  case 0x1a:
874  case 0x1b:
875    {
876      // SUB Rd, Rs, Rn
877      int dest = opcode & 0x07;
878      int source = (opcode >> 3) & 0x07;
879      u32 value = reg[(opcode>>6)& 0x07].I;
880      SUB_RD_RS_RN;
881    }
882    break;
883  case 0x1c:
884  case 0x1d:
885    {
886      // ADD Rd, Rs, #Offset3
887      int dest = opcode & 0x07;
888      int source = (opcode >> 3) & 0x07;
889      u32 value = (opcode >> 6) & 7;
890      ADD_RD_RS_O3;
891    }
892    break;
893  case 0x1e:
894  case 0x1f:
895    {
896      // SUB Rd, Rs, #Offset3
897      int dest = opcode & 0x07;
898      int source = (opcode >> 3) & 0x07;
899      u32 value = (opcode >> 6) & 7;
900      SUB_RD_RS_O3;
901    }
902    break;
903  case 0x20:
904    // MOV R0, #Offset8
905    reg[0].I = opcode & 255;
906    N_FLAG = false;
907    Z_FLAG = (reg[0].I ? false : true);
908    break;
909  case 0x21:
910    // MOV R1, #Offset8
911    reg[1].I = opcode & 255;
912    N_FLAG = false;
913    Z_FLAG = (reg[1].I ? false : true);
914    break;
915  case 0x22:
916    // MOV R2, #Offset8
917    reg[2].I = opcode & 255;
918    N_FLAG = false;
919    Z_FLAG = (reg[2].I ? false : true);
920    break;
921  case 0x23:
922    // MOV R3, #Offset8
923    reg[3].I = opcode & 255;
924    N_FLAG = false;
925    Z_FLAG = (reg[3].I ? false : true);
926    break;
927  case 0x24:
928    // MOV R4, #Offset8
929    reg[4].I = opcode & 255;
930    N_FLAG = false;
931    Z_FLAG = (reg[4].I ? false : true);
932    break;
933  case 0x25:
934    // MOV R5, #Offset8
935    reg[5].I = opcode & 255;
936    N_FLAG = false;
937    Z_FLAG = (reg[5].I ? false : true);
938    break;
939  case 0x26:
940    // MOV R6, #Offset8
941    reg[6].I = opcode & 255;
942    N_FLAG = false;
943    Z_FLAG = (reg[6].I ? false : true);
944    break;
945  case 0x27:
946    // MOV R7, #Offset8
947    reg[7].I = opcode & 255;
948    N_FLAG = false;
949    Z_FLAG = (reg[7].I ? false : true);
950    break;
951  case 0x28:
952    // CMP R0, #Offset8
953    CMP_RN_O8(0);
954    break;
955  case 0x29:
956    // CMP R1, #Offset8
957    CMP_RN_O8(1);
958    break;
959  case 0x2a:
960    // CMP R2, #Offset8
961    CMP_RN_O8(2);
962    break;
963  case 0x2b:
964    // CMP R3, #Offset8
965    CMP_RN_O8(3);
966    break;
967  case 0x2c:
968    // CMP R4, #Offset8
969    CMP_RN_O8(4);
970    break;
971  case 0x2d:
972    // CMP R5, #Offset8
973    CMP_RN_O8(5);
974    break;
975  case 0x2e:
976    // CMP R6, #Offset8
977    CMP_RN_O8(6);
978    break;
979  case 0x2f:
980    // CMP R7, #Offset8
981    CMP_RN_O8(7);
982    break;
983  case 0x30:
984    // ADD R0,#Offset8
985    ADD_RN_O8(0);
986    break;
987  case 0x31:
988    // ADD R1,#Offset8
989    ADD_RN_O8(1);
990    break;
991  case 0x32:
992    // ADD R2,#Offset8
993    ADD_RN_O8(2);
994    break;
995  case 0x33:
996    // ADD R3,#Offset8
997    ADD_RN_O8(3);
998    break;
999  case 0x34:
1000    // ADD R4,#Offset8
1001    ADD_RN_O8(4);
1002    break;
1003  case 0x35:
1004    // ADD R5,#Offset8
1005    ADD_RN_O8(5);
1006    break;
1007  case 0x36:
1008    // ADD R6,#Offset8
1009    ADD_RN_O8(6);
1010    break;
1011  case 0x37:
1012    // ADD R7,#Offset8
1013    ADD_RN_O8(7);
1014    break;
1015  case 0x38:
1016    // SUB R0,#Offset8
1017    SUB_RN_O8(0);
1018    break;
1019  case 0x39:
1020    // SUB R1,#Offset8
1021    SUB_RN_O8(1);
1022    break;
1023  case 0x3a:
1024    // SUB R2,#Offset8
1025    SUB_RN_O8(2);
1026    break;
1027  case 0x3b:
1028    // SUB R3,#Offset8
1029    SUB_RN_O8(3);
1030    break;
1031  case 0x3c:
1032    // SUB R4,#Offset8
1033    SUB_RN_O8(4);
1034    break;
1035  case 0x3d:
1036    // SUB R5,#Offset8
1037    SUB_RN_O8(5);
1038    break;
1039  case 0x3e:
1040    // SUB R6,#Offset8
1041    SUB_RN_O8(6);
1042    break;
1043  case 0x3f:
1044    // SUB R7,#Offset8
1045    SUB_RN_O8(7);
1046    break;
1047  case 0x40:
1048    switch((opcode >> 6) & 3) {
1049    case 0x00:
1050      {
1051        // AND Rd, Rs
1052        int dest = opcode & 7;
1053        reg[dest].I &= reg[(opcode >> 3)&7].I;
1054        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1055        Z_FLAG = reg[dest].I ? false : true;
1056 #ifdef BKPT_SUPPORT
1057 #define THUMB_CONSOLE_OUTPUT(a,b) \
1058   if((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) {\
1059     extern void (*dbgOutput)(char *, u32);\
1060     dbgOutput((a), (b));\
1061   }
1062 #else
1063 #define THUMB_CONSOLE_OUTPUT(a,b)
1064 #endif
1065        THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
1066      }
1067      break;
1068    case 0x01:
1069      // EOR Rd, Rs
1070      {
1071        int dest = opcode & 7;
1072        reg[dest].I ^= reg[(opcode >> 3)&7].I;
1073        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1074        Z_FLAG = reg[dest].I ? false : true;
1075      }
1076      break;
1077    case 0x02:
1078      // LSL Rd, Rs
1079      {
1080        int dest = opcode & 7;
1081        u32 value = reg[(opcode >> 3)&7].B.B0;
1082        if(value) {
1083          if(value == 32) {
1084            value = 0;
1085            C_FLAG = (reg[dest].I & 1 ? true : false);
1086          } else if(value < 32) {
1087            LSL_RD_RS;
1088          } else {
1089            value = 0;
1090            C_FLAG = false;
1091          }
1092          reg[dest].I = value;
1093        }
1094        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1095        Z_FLAG = reg[dest].I ? false : true;
1096        clockTicks++;
1097      }
1098      break;
1099    case 0x03:
1100      {
1101        // LSR Rd, Rs
1102        int dest = opcode & 7;
1103        u32 value = reg[(opcode >> 3)&7].B.B0;
1104        if(value) {
1105          if(value == 32) {
1106            value = 0;
1107            C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
1108          } else if(value < 32) {
1109            LSR_RD_RS;
1110          } else {
1111            value = 0;
1112            C_FLAG = false;
1113          }
1114          reg[dest].I = value;
1115        }
1116        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1117        Z_FLAG = reg[dest].I ? false : true;
1118        clockTicks++;
1119      }
1120      break;
1121    }
1122    break;
1123  case 0x41:
1124    switch((opcode >> 6) & 3) {
1125    case 0x00:
1126      {
1127        // ASR Rd, Rs
1128        int dest = opcode & 7;
1129        u32 value = reg[(opcode >> 3)&7].B.B0;
1130        // ASR
1131        if(value) {
1132          if(value < 32) {
1133            ASR_RD_RS;
1134            reg[dest].I = value;
1135          } else {
1136            if(reg[dest].I & 0x80000000){
1137              reg[dest].I = 0xFFFFFFFF;
1138              C_FLAG = true;
1139            } else {
1140              reg[dest].I = 0x00000000;
1141              C_FLAG = false;
1142            }
1143          }
1144        }
1145        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1146        Z_FLAG = reg[dest].I ? false : true;
1147        clockTicks++;
1148      }
1149      break;
1150    case 0x01:
1151      {
1152        // ADC Rd, Rs
1153        int dest = opcode & 0x07;
1154        u32 value = reg[(opcode >> 3)&7].I;
1155        // ADC
1156        ADC_RD_RS;
1157      }
1158      break;
1159    case 0x02:
1160      {
1161        // SBC Rd, Rs
1162        int dest = opcode & 0x07;
1163        u32 value = reg[(opcode >> 3)&7].I;
1164 
1165        // SBC
1166        SBC_RD_RS;
1167      }
1168      break;
1169    case 0x03:
1170      // ROR Rd, Rs
1171      {
1172        int dest = opcode & 7;
1173        u32 value = reg[(opcode >> 3)&7].B.B0;
1174 
1175        if(value) {
1176          value = value & 0x1f;
1177          if(value == 0) {
1178            C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
1179          } else {
1180            ROR_RD_RS;
1181            reg[dest].I = value;
1182          }
1183        }
1184        clockTicks++;
1185        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1186        Z_FLAG = reg[dest].I ? false : true;
1187      }
1188      break;
1189    }
1190    break;
1191  case 0x42:
1192    switch((opcode >> 6) & 3) {
1193    case 0x00:
1194      {
1195        // TST Rd, Rs
1196        u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
1197        N_FLAG = value & 0x80000000 ? true : false;
1198        Z_FLAG = value ? false : true;
1199      }
1200      break;
1201    case 0x01:
1202      {
1203        // NEG Rd, Rs
1204        int dest = opcode & 7;
1205        int source = (opcode >> 3) & 7;
1206        NEG_RD_RS;
1207      }
1208      break;
1209    case 0x02:
1210      {
1211        // CMP Rd, Rs
1212        int dest = opcode & 7;
1213        u32 value = reg[(opcode >> 3)&7].I;
1214        CMP_RD_RS;
1215      }
1216      break;
1217    case 0x03:
1218      {
1219        // CMN Rd, Rs
1220        int dest = opcode & 7;
1221        u32 value = reg[(opcode >> 3)&7].I;
1222        // CMN
1223        CMN_RD_RS;
1224      }
1225      break;
1226    }
1227    break;
1228  case 0x43:
1229    switch((opcode >> 6) & 3) {
1230    case 0x00:
1231      {
1232        // ORR Rd, Rs
1233        int dest = opcode & 7;
1234        reg[dest].I |= reg[(opcode >> 3) & 7].I;
1235        Z_FLAG = reg[dest].I ? false : true;
1236        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1237      }
1238      break;
1239    case 0x01:
1240      {
1241        // MUL Rd, Rs
1242        int dest = opcode & 7;
1243        u32 rm = reg[(opcode >> 3) & 7].I;
1244        reg[dest].I = reg[dest].I * rm;
1245        if (((s32)rm) < 0)
1246          rm = ~rm;
1247        if ((rm & 0xFFFFFF00) == 0)
1248          clockTicks += 1;
1249        else if ((rm & 0xFFFF0000) == 0)
1250          clockTicks += 2;
1251        else if ((rm & 0xFF000000) == 0)
1252          clockTicks += 3;
1253        else
1254          clockTicks += 4;
1255        Z_FLAG = reg[dest].I ? false : true;
1256        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1257      }
1258      break;
1259    case 0x02:
1260      {
1261        // BIC Rd, Rs
1262        int dest = opcode & 7;
1263        reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
1264        Z_FLAG = reg[dest].I ? false : true;
1265        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1266      }
1267      break;
1268    case 0x03:
1269      {
1270        // MVN Rd, Rs
1271        int dest = opcode & 7;
1272        reg[dest].I = ~reg[(opcode >> 3) & 7].I;
1273        Z_FLAG = reg[dest].I ? false : true;
1274        N_FLAG = reg[dest].I & 0x80000000 ? true : false;
1275      }
1276      break;
1277    }
1278    break;
1279  case 0x44:
1280    {
1281      int dest = opcode & 7;
1282      int base = (opcode >> 3) & 7;
1283      switch((opcode >> 6)& 3) {
1284      default:
1285        goto unknown_thumb;
1286      case 1:
1287        // ADD Rd, Hs
1288        reg[dest].I += reg[base+8].I;
1289        break;
1290      case 2:
1291        // ADD Hd, Rs
1292        reg[dest+8].I += reg[base].I;
1293        if(dest == 7) {
1294          reg[15].I &= 0xFFFFFFFE;
1295          armNextPC = reg[15].I;
1296          reg[15].I += 2;
1297          clockTicks++;
1298        }
1299        break;
1300      case 3:
1301        // ADD Hd, Hs
1302        reg[dest+8].I += reg[base+8].I;
1303        if(dest == 7) {
1304          reg[15].I &= 0xFFFFFFFE;
1305          armNextPC = reg[15].I;
1306          reg[15].I += 2;
1307          clockTicks++;
1308        }
1309        break;
1310      }
1311    }
1312    break;
1313  case 0x45:
1314    {
1315      int dest = opcode & 7;
1316      int base = (opcode >> 3) & 7;
1317      u32 value;
1318      switch((opcode >> 6) & 3) {
1319      case 0:
1320        // CMP Rd, Hs
1321        value = reg[base].I;
1322        CMP_RD_RS;
1323        break;
1324      case 1:
1325        // CMP Rd, Hs
1326        value = reg[base+8].I;
1327        CMP_RD_RS;
1328        break;
1329      case 2:
1330        // CMP Hd, Rs
1331        value = reg[base].I;
1332        dest += 8;
1333        CMP_RD_RS;
1334        break;
1335      case 3:
1336        // CMP Hd, Hs
1337        value = reg[base+8].I;
1338        dest += 8;
1339        CMP_RD_RS;
1340        break;
1341      }
1342    }
1343    break;
1344  case 0x46:
1345    {
1346      int dest = opcode & 7;
1347      int base = (opcode >> 3) & 7;
1348      switch((opcode >> 6) & 3) {
1349      case 0:
1350        // this form should not be used...
1351        // MOV Rd, Rs
1352        reg[dest].I = reg[base].I;
1353        break;
1354      case 1:
1355        // MOV Rd, Hs
1356        reg[dest].I = reg[base+8].I;
1357        break;
1358      case 2:
1359        // MOV Hd, Rs
1360        reg[dest+8].I = reg[base].I;
1361        if(dest == 7) {
1362          reg[15].I &= 0xFFFFFFFE;
1363          armNextPC = reg[15].I;
1364          reg[15].I += 2;
1365          clockTicks++;
1366        }
1367        break;
1368      case 3:
1369        // MOV Hd, Hs
1370        reg[dest+8].I = reg[base+8].I;
1371        if(dest == 7) {
1372          reg[15].I &= 0xFFFFFFFE;
1373          armNextPC = reg[15].I;
1374          reg[15].I += 2;
1375          clockTicks++;
1376        }
1377        break;
1378      }
1379    }
1380    break;
1381  case 0x47:
1382    {
1383      int base = (opcode >> 3) & 7;
1384      switch((opcode >>6) & 3) {
1385      case 0:
1386        // BX Rs
1387        reg[15].I = (reg[base].I) & 0xFFFFFFFE;
1388        if(reg[base].I & 1) {
1389          armState = false;
1390          armNextPC = reg[15].I;
1391          reg[15].I += 2;
1392        } else {
1393          armState = true;
1394          reg[15].I &= 0xFFFFFFFC;
1395          armNextPC = reg[15].I;
1396          reg[15].I += 4;
1397        }
1398        break;
1399      case 1:
1400        // BX Hs
1401        reg[15].I = (reg[8+base].I) & 0xFFFFFFFE;
1402        if(reg[8+base].I & 1) {
1403          armState = false;
1404          armNextPC = reg[15].I;
1405          reg[15].I += 2;
1406        } else {
1407          armState = true;
1408          reg[15].I &= 0xFFFFFFFC;
1409          armNextPC = reg[15].I;
1410          reg[15].I += 4;
1411        }
1412        break;
1413      default:
1414        goto unknown_thumb;
1415      }
1416    }
1417    break;
1418  case 0x48:
1419    // LDR R0,[PC, #Imm]
1420    {
1421      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1422      reg[0].I = CPUReadMemoryQuick(address);
1423      clockTicks += CPUUpdateTicksAccess32(address);
1424    }
1425    break;
1426  case 0x49:
1427    // LDR R1,[PC, #Imm]
1428    {
1429      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1430      reg[1].I = CPUReadMemoryQuick(address);
1431      clockTicks += CPUUpdateTicksAccess32(address);
1432    }
1433    break;
1434  case 0x4a:
1435    // LDR R2,[PC, #Imm]
1436    {
1437      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1438      reg[2].I = CPUReadMemoryQuick(address);
1439      clockTicks += CPUUpdateTicksAccess32(address);
1440    }
1441    break;
1442  case 0x4b:
1443    // LDR R3,[PC, #Imm]
1444    {
1445      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1446      reg[3].I = CPUReadMemoryQuick(address);
1447      clockTicks += CPUUpdateTicksAccess32(address);
1448    }
1449    break;
1450  case 0x4c:
1451    // LDR R4,[PC, #Imm]
1452    {
1453      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1454      reg[4].I = CPUReadMemoryQuick(address);
1455      clockTicks += CPUUpdateTicksAccess32(address);
1456    }
1457    break;
1458  case 0x4d:
1459    // LDR R5,[PC, #Imm]
1460    {
1461      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1462      reg[5].I = CPUReadMemoryQuick(address);
1463      clockTicks += CPUUpdateTicksAccess32(address);
1464    }
1465    break;
1466  case 0x4e:
1467    // LDR R6,[PC, #Imm]
1468    {
1469      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1470      reg[6].I = CPUReadMemoryQuick(address);
1471      clockTicks += CPUUpdateTicksAccess32(address);
1472    }
1473    break;
1474  case 0x4f:
1475    // LDR R7,[PC, #Imm]
1476    {
1477      u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
1478      reg[7].I = CPUReadMemoryQuick(address);
1479      clockTicks += CPUUpdateTicksAccess32(address);
1480    }
1481    break;
1482  case 0x50:
1483  case 0x51:
1484    // STR Rd, [Rs, Rn]
1485    {
1486      u32
1487        address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1488      CPUWriteMemory(address,
1489                     reg[opcode & 7].I);
1490      clockTicks += CPUUpdateTicksAccess32(address);
1491    }
1492    break;
1493  case 0x52:
1494  case 0x53:
1495    // STRH Rd, [Rs, Rn]
1496    {
1497      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1498      CPUWriteHalfWord(address,
1499                       reg[opcode&7].W.W0);
1500      clockTicks += CPUUpdateTicksAccess16(address);
1501    }
1502    break;
1503  case 0x54:
1504  case 0x55:
1505    // STRB Rd, [Rs, Rn]
1506    {
1507      u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I;
1508      CPUWriteByte(address,
1509                   reg[opcode & 7].B.B0);
1510      clockTicks += CPUUpdateTicksAccess16(address);
1511    }
1512    break;
1513  case 0x56:
1514  case 0x57:
1515    // LDSB Rd, [Rs, Rn]
1516    {
1517      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1518      reg[opcode&7].I = (s8)CPUReadByte(address);
1519      clockTicks += CPUUpdateTicksAccess16(address);
1520    }
1521    break;
1522  case 0x58:
1523  case 0x59:
1524    // LDR Rd, [Rs, Rn]
1525    {
1526      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1527      reg[opcode&7].I = CPUReadMemory(address);
1528      clockTicks += CPUUpdateTicksAccess32(address);
1529    }
1530    break;
1531  case 0x5a:
1532  case 0x5b:
1533    // LDRH Rd, [Rs, Rn]
1534    {
1535      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1536      reg[opcode&7].I = CPUReadHalfWord(address);
1537      clockTicks += CPUUpdateTicksAccess16(address);
1538    }
1539    break;
1540  case 0x5c:
1541  case 0x5d:
1542    // LDRB Rd, [Rs, Rn]
1543    {
1544      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1545      reg[opcode&7].I = CPUReadByte(address);
1546      clockTicks += CPUUpdateTicksAccess16(address);
1547    }
1548    break;
1549  case 0x5e:
1550  case 0x5f:
1551    // LDSH Rd, [Rs, Rn]
1552    {
1553      u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
1554      reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
1555      clockTicks += CPUUpdateTicksAccess16(address);
1556    }
1557    break;
1558  case 0x60:
1559  case 0x61:
1560  case 0x62:
1561  case 0x63:
1562  case 0x64:
1563  case 0x65:
1564  case 0x66:
1565  case 0x67:
1566    // STR Rd, [Rs, #Imm]
1567    {
1568      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
1569      CPUWriteMemory(address,
1570                     reg[opcode&7].I);
1571      clockTicks += CPUUpdateTicksAccess32(address);
1572    }
1573    break;
1574  case 0x68:
1575  case 0x69:
1576  case 0x6a:
1577  case 0x6b:
1578  case 0x6c:
1579  case 0x6d:
1580  case 0x6e:
1581  case 0x6f:
1582    // LDR Rd, [Rs, #Imm]
1583    {
1584      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
1585      reg[opcode&7].I = CPUReadMemory(address);
1586      clockTicks += CPUUpdateTicksAccess32(address);
1587    }
1588    break;
1589  case 0x70:
1590  case 0x71:
1591  case 0x72:
1592  case 0x73:
1593  case 0x74:
1594  case 0x75:
1595  case 0x76:
1596  case 0x77:
1597    // STRB Rd, [Rs, #Imm]
1598    {
1599      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
1600      CPUWriteByte(address,
1601                   reg[opcode&7].B.B0);
1602      clockTicks += CPUUpdateTicksAccess16(address);
1603    }
1604    break;
1605  case 0x78:
1606  case 0x79:
1607  case 0x7a:
1608  case 0x7b:
1609  case 0x7c:
1610  case 0x7d:
1611  case 0x7e:
1612  case 0x7f:
1613    // LDRB Rd, [Rs, #Imm]
1614    {
1615      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
1616      reg[opcode&7].I = CPUReadByte(address);
1617      clockTicks += CPUUpdateTicksAccess16(address);
1618    }
1619    break;
1620  case 0x80:
1621  case 0x81:
1622  case 0x82:
1623  case 0x83:
1624  case 0x84:
1625  case 0x85:
1626  case 0x86:
1627  case 0x87:
1628    // STRH Rd, [Rs, #Imm]
1629    {
1630      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
1631      CPUWriteHalfWord(address,
1632                       reg[opcode&7].W.W0);
1633      clockTicks += CPUUpdateTicksAccess16(address);
1634    }
1635    break;
1636  case 0x88:
1637  case 0x89:
1638  case 0x8a:
1639  case 0x8b:
1640  case 0x8c:
1641  case 0x8d:
1642  case 0x8e:
1643  case 0x8f:
1644    // LDRH Rd, [Rs, #Imm]
1645    {
1646      u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
1647      reg[opcode&7].I = CPUReadHalfWord(address);
1648      clockTicks += CPUUpdateTicksAccess16(address);
1649    }
1650    break;
1651  case 0x90:
1652    // STR R0, [SP, #Imm]
1653    {
1654      u32 address = reg[13].I + ((opcode&255)<<2);
1655      CPUWriteMemory(address, reg[0].I);
1656      clockTicks += CPUUpdateTicksAccess32(address);
1657    }
1658    break;
1659  case 0x91:
1660    // STR R1, [SP, #Imm]
1661    {
1662      u32 address = reg[13].I + ((opcode&255)<<2);
1663      CPUWriteMemory(address, reg[1].I);
1664      clockTicks += CPUUpdateTicksAccess32(address);
1665    }
1666    break;
1667  case 0x92:
1668    // STR R2, [SP, #Imm]
1669    {
1670      u32 address = reg[13].I + ((opcode&255)<<2);
1671      CPUWriteMemory(address, reg[2].I);
1672      clockTicks += CPUUpdateTicksAccess32(address);
1673    }
1674    break;
1675  case 0x93:
1676    // STR R3, [SP, #Imm]
1677    {
1678      u32 address = reg[13].I + ((opcode&255)<<2);
1679      CPUWriteMemory(address, reg[3].I);
1680      clockTicks += CPUUpdateTicksAccess32(address);
1681    }
1682    break;
1683  case 0x94:
1684    // STR R4, [SP, #Imm]
1685    {
1686      u32 address = reg[13].I + ((opcode&255)<<2);
1687      CPUWriteMemory(address, reg[4].I);
1688      clockTicks += CPUUpdateTicksAccess32(address);
1689    }
1690    break;
1691  case 0x95:
1692    // STR R5, [SP, #Imm]
1693    {
1694      u32 address = reg[13].I + ((opcode&255)<<2);
1695      CPUWriteMemory(address, reg[5].I);
1696      clockTicks += CPUUpdateTicksAccess32(address);
1697    }
1698    break;
1699  case 0x96:
1700    // STR R6, [SP, #Imm]
1701    {
1702      u32 address = reg[13].I + ((opcode&255)<<2);
1703      CPUWriteMemory(address, reg[6].I);
1704      clockTicks += CPUUpdateTicksAccess32(address);
1705    }
1706    break;
1707  case 0x97:
1708    // STR R7, [SP, #Imm]
1709    {
1710      u32 address = reg[13].I + ((opcode&255)<<2);
1711      CPUWriteMemory(address, reg[7].I);
1712      clockTicks += CPUUpdateTicksAccess32(address);
1713    }
1714    break;
1715  case 0x98:
1716    // LDR R0, [SP, #Imm]
1717    {
1718      u32 address = reg[13].I + ((opcode&255)<<2);
1719      reg[0].I = CPUReadMemoryQuick(address);
1720      clockTicks += CPUUpdateTicksAccess32(address);
1721    }
1722    break;
1723  case 0x99:
1724    // LDR R1, [SP, #Imm]
1725    {
1726      u32 address = reg[13].I + ((opcode&255)<<2);
1727      reg[1].I = CPUReadMemoryQuick(address);
1728      clockTicks += CPUUpdateTicksAccess32(address);
1729    }
1730    break;
1731  case 0x9a:
1732    // LDR R2, [SP, #Imm]
1733    {
1734      u32 address = reg[13].I + ((opcode&255)<<2);
1735      reg[2].I = CPUReadMemoryQuick(address);
1736      clockTicks += CPUUpdateTicksAccess32(address);
1737    }
1738    break;
1739  case 0x9b:
1740    // LDR R3, [SP, #Imm]
1741    {
1742      u32 address = reg[13].I + ((opcode&255)<<2);
1743      reg[3].I = CPUReadMemoryQuick(address);
1744      clockTicks += CPUUpdateTicksAccess32(address);
1745    }
1746    break;
1747  case 0x9c:
1748    // LDR R4, [SP, #Imm]
1749    {
1750      u32 address = reg[13].I + ((opcode&255)<<2);
1751      reg[4].I = CPUReadMemoryQuick(address);
1752      clockTicks += CPUUpdateTicksAccess32(address);
1753    }
1754    break;
1755  case 0x9d:
1756    // LDR R5, [SP, #Imm]
1757    {
1758      u32 address = reg[13].I + ((opcode&255)<<2);
1759      reg[5].I = CPUReadMemoryQuick(address);
1760      clockTicks += CPUUpdateTicksAccess32(address);
1761    }
1762    break;
1763  case 0x9e:
1764    // LDR R6, [SP, #Imm]
1765    {
1766      u32 address = reg[13].I + ((opcode&255)<<2);
1767      reg[6].I = CPUReadMemoryQuick(address);
1768      clockTicks += CPUUpdateTicksAccess32(address);
1769    }
1770    break;
1771  case 0x9f:
1772    // LDR R7, [SP, #Imm]
1773    {
1774      u32 address = reg[13].I + ((opcode&255)<<2);
1775      reg[7].I = CPUReadMemoryQuick(address);
1776      clockTicks += CPUUpdateTicksAccess32(address);
1777    }
1778    break;
1779  case 0xa0:
1780    // ADD R0, PC, Imm
1781    reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1782    break;
1783  case 0xa1:
1784    // ADD R1, PC, Imm
1785    reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1786    break;
1787  case 0xa2:
1788    // ADD R2, PC, Imm
1789    reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1790    break;
1791  case 0xa3:
1792    // ADD R3, PC, Imm
1793    reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1794    break;
1795  case 0xa4:
1796    // ADD R4, PC, Imm
1797    reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1798    break;
1799  case 0xa5:
1800    // ADD R5, PC, Imm
1801    reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1802    break;
1803  case 0xa6:
1804    // ADD R6, PC, Imm
1805    reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1806    break;
1807  case 0xa7:
1808    // ADD R7, PC, Imm
1809    reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
1810    break;
1811  case 0xa8:
1812    // ADD R0, SP, Imm
1813    reg[0].I = reg[13].I + ((opcode&255)<<2);
1814    break;
1815  case 0xa9:
1816    // ADD R1, SP, Imm
1817    reg[1].I = reg[13].I + ((opcode&255)<<2);
1818    break;
1819  case 0xaa:
1820    // ADD R2, SP, Imm
1821    reg[2].I = reg[13].I + ((opcode&255)<<2);
1822    break;
1823  case 0xab:
1824    // ADD R3, SP, Imm
1825    reg[3].I = reg[13].I + ((opcode&255)<<2);
1826    break;
1827  case 0xac:
1828    // ADD R4, SP, Imm
1829    reg[4].I = reg[13].I + ((opcode&255)<<2);
1830    break;
1831  case 0xad:
1832    // ADD R5, SP, Imm
1833    reg[5].I = reg[13].I + ((opcode&255)<<2);
1834    break;
1835  case 0xae:
1836    // ADD R6, SP, Imm
1837    reg[6].I = reg[13].I + ((opcode&255)<<2);
1838    break;
1839  case 0xaf:
1840    // ADD R7, SP, Imm
1841    reg[7].I = reg[13].I + ((opcode&255)<<2);
1842    break;
1843  case 0xb0:
1844    {
1845      // ADD SP, Imm
1846      int offset = (opcode & 127) << 2;
1847      if(opcode & 0x80)
1848        offset = -offset;
1849      reg[13].I += offset;
1850    }
1851    break;
1852 #define PUSH_REG(val, r) \
1853   if(opcode & (val)) {\
1854     CPUWriteMemory(address, reg[(r)].I);\
1855     if(offset)\
1856       clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
1857     else\
1858       clockTicks += 1 + CPUUpdateTicksAccess32(address);\
1859     offset = 1;\
1860     address += 4;\
1861   }
1862  case 0xb4:
1863    // PUSH {Rlist}
1864    {
1865      int offset = 0;
1866      u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
1867      u32 address = temp & 0xFFFFFFFC;
1868      PUSH_REG(1, 0);
1869      PUSH_REG(2, 1);
1870      PUSH_REG(4, 2);
1871      PUSH_REG(8, 3);
1872      PUSH_REG(16, 4);
1873      PUSH_REG(32, 5);
1874      PUSH_REG(64, 6);
1875      PUSH_REG(128, 7);
1876      reg[13].I = temp;
1877    }
1878    break;
1879  case 0xb5:
1880    // PUSH {Rlist, LR}
1881    {
1882      int offset = 0;
1883      u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
1884      u32 address = temp & 0xFFFFFFFC;
1885      PUSH_REG(1, 0);
1886      PUSH_REG(2, 1);
1887      PUSH_REG(4, 2);
1888      PUSH_REG(8, 3);
1889      PUSH_REG(16, 4);
1890      PUSH_REG(32, 5);
1891      PUSH_REG(64, 6);
1892      PUSH_REG(128, 7);
1893      PUSH_REG(256, 14);
1894      reg[13].I = temp;
1895    }
1896    break;
1897 #define POP_REG(val, r) \
1898   if(opcode & (val)) {\
1899     reg[(r)].I = CPUReadMemory(address);\
1900     if(offset)\
1901       clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\
1902     else\
1903       clockTicks += 2 + CPUUpdateTicksAccess32(address);\
1904     offset = 1;\
1905     address += 4;\
1906   }
1907  case 0xbc:
1908    // POP {Rlist}
1909    {
1910      int offset = 0;
1911      u32 address = reg[13].I & 0xFFFFFFFC;
1912      u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
1913      POP_REG(1, 0);
1914      POP_REG(2, 1);
1915      POP_REG(4, 2);
1916      POP_REG(8, 3);
1917      POP_REG(16, 4);
1918      POP_REG(32, 5);
1919      POP_REG(64, 6);
1920      POP_REG(128, 7);
1921      reg[13].I = temp;
1922    }
1923    break;
1924  case 0xbd:
1925    // POP {Rlist, PC}
1926    {
1927      int offset = 0;
1928      u32 address = reg[13].I & 0xFFFFFFFC;
1929      u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
1930      POP_REG(1, 0);
1931      POP_REG(2, 1);
1932      POP_REG(4, 2);
1933      POP_REG(8, 3);
1934      POP_REG(16, 4);
1935      POP_REG(32, 5);
1936      POP_REG(64, 6);
1937      POP_REG(128, 7);
1938      reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
1939      if(offset)
1940        clockTicks += CPUUpdateTicksAccessSeq32(address);
1941      else
1942        clockTicks += CPUUpdateTicksAccess32(address);
1943      armNextPC = reg[15].I;
1944      reg[15].I += 2;
1945      reg[13].I = temp;
1946    }
1947    break;
1948 #define THUMB_STM_REG(val,r,b) \
1949   if(opcode & (val)) {\
1950     CPUWriteMemory(address, reg[(r)].I);\
1951     if(!offset) {\
1952       reg[(b)].I = temp;\
1953       clockTicks += 1 + CPUUpdateTicksAccess32(address);\
1954     } else \
1955       clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
1956     offset = 1;\
1957     address += 4;\
1958   }
1959  case 0xc0:
1960    {
1961      // STM R0!, {Rlist}
1962      u32 address = reg[0].I & 0xFFFFFFFC;
1963      u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xff];
1964      int offset = 0;
1965      // store
1966      THUMB_STM_REG(1, 0, 0);
1967      THUMB_STM_REG(2, 1, 0);
1968      THUMB_STM_REG(4, 2, 0);
1969      THUMB_STM_REG(8, 3, 0);
1970      THUMB_STM_REG(16, 4, 0);
1971      THUMB_STM_REG(32, 5, 0);
1972      THUMB_STM_REG(64, 6, 0);
1973      THUMB_STM_REG(128, 7, 0);
1974    }
1975    break;
1976  case 0xc1:
1977    {
1978      // STM R1!, {Rlist}
1979      u32 address = reg[1].I & 0xFFFFFFFC;
1980      u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xff];
1981      int offset = 0;
1982      // store
1983      THUMB_STM_REG(1, 0, 1);
1984      THUMB_STM_REG(2, 1, 1);
1985      THUMB_STM_REG(4, 2, 1);
1986      THUMB_STM_REG(8, 3, 1);
1987      THUMB_STM_REG(16, 4, 1);
1988      THUMB_STM_REG(32, 5, 1);
1989      THUMB_STM_REG(64, 6, 1);
1990      THUMB_STM_REG(128, 7, 1);
1991    }
1992    break;
1993  case 0xc2:
1994    {
1995      // STM R2!, {Rlist}
1996      u32 address = reg[2].I & 0xFFFFFFFC;
1997      u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xff];
1998      int offset = 0;
1999      // store
2000      THUMB_STM_REG(1, 0, 2);
2001      THUMB_STM_REG(2, 1, 2);
2002      THUMB_STM_REG(4, 2, 2);
2003      THUMB_STM_REG(8, 3, 2);
2004      THUMB_STM_REG(16, 4, 2);
2005      THUMB_STM_REG(32, 5, 2);
2006      THUMB_STM_REG(64, 6, 2);
2007      THUMB_STM_REG(128, 7, 2);
2008    }
2009    break;
2010  case 0xc3:
2011    {
2012      // STM R3!, {Rlist}
2013      u32 address = reg[3].I & 0xFFFFFFFC;
2014      u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xff];
2015      int offset = 0;
2016      // store
2017      THUMB_STM_REG(1, 0, 3);
2018      THUMB_STM_REG(2, 1, 3);
2019      THUMB_STM_REG(4, 2, 3);
2020      THUMB_STM_REG(8, 3, 3);
2021      THUMB_STM_REG(16, 4, 3);
2022      THUMB_STM_REG(32, 5, 3);
2023      THUMB_STM_REG(64, 6, 3);
2024      THUMB_STM_REG(128, 7, 3);
2025    }
2026    break;
2027  case 0xc4:
2028    {
2029      // STM R4!, {Rlist}
2030      u32 address = reg[4].I & 0xFFFFFFFC;
2031      u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xff];
2032      int offset = 0;
2033      // store
2034      THUMB_STM_REG(1, 0, 4);
2035      THUMB_STM_REG(2, 1, 4);
2036      THUMB_STM_REG(4, 2, 4);
2037      THUMB_STM_REG(8, 3, 4);
2038      THUMB_STM_REG(16, 4, 4);
2039      THUMB_STM_REG(32, 5, 4);
2040      THUMB_STM_REG(64, 6, 4);
2041      THUMB_STM_REG(128, 7, 4);
2042    }
2043    break;
2044  case 0xc5:
2045    {
2046      // STM R5!, {Rlist}
2047      u32 address = reg[5].I & 0xFFFFFFFC;
2048      u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xff];
2049      int offset = 0;
2050      // store
2051      THUMB_STM_REG(1, 0, 5);
2052      THUMB_STM_REG(2, 1, 5);
2053      THUMB_STM_REG(4, 2, 5);
2054      THUMB_STM_REG(8, 3, 5);
2055      THUMB_STM_REG(16, 4, 5);
2056      THUMB_STM_REG(32, 5, 5);
2057      THUMB_STM_REG(64, 6, 5);
2058      THUMB_STM_REG(128, 7, 5);
2059    }
2060    break;
2061  case 0xc6:
2062    {
2063      // STM R6!, {Rlist}
2064      u32 address = reg[6].I & 0xFFFFFFFC;
2065      u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xff];
2066      int offset = 0;
2067      // store
2068      THUMB_STM_REG(1, 0, 6);
2069      THUMB_STM_REG(2, 1, 6);
2070      THUMB_STM_REG(4, 2, 6);
2071      THUMB_STM_REG(8, 3, 6);
2072      THUMB_STM_REG(16, 4, 6);
2073      THUMB_STM_REG(32, 5, 6);
2074      THUMB_STM_REG(64, 6, 6);
2075      THUMB_STM_REG(128, 7, 6);
2076    }
2077    break;
2078  case 0xc7:
2079    {
2080      // STM R7!, {Rlist}
2081      u32 address = reg[7].I & 0xFFFFFFFC;
2082      u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xff];
2083      int offset = 0;
2084      // store
2085      THUMB_STM_REG(1, 0, 7);
2086      THUMB_STM_REG(2, 1, 7);
2087      THUMB_STM_REG(4, 2, 7);
2088      THUMB_STM_REG(8, 3, 7);
2089      THUMB_STM_REG(16, 4, 7);
2090      THUMB_STM_REG(32, 5, 7);
2091      THUMB_STM_REG(64, 6, 7);
2092      THUMB_STM_REG(128, 7, 7);
2093    }
2094    break;
2095 #define THUMB_LDM_REG(val,r) \
2096   if(opcode & (val)) {\
2097     reg[(r)].I = CPUReadMemory(address);\
2098     if(offset)\
2099       clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\
2100     else\
2101       clockTicks += 2 + CPUUpdateTicksAccess32(address);\
2102     offset = 1;\
2103     address += 4;\
2104   }
2105  case 0xc8:
2106    {
2107      // LDM R0!, {Rlist}
2108      u32 address = reg[0].I & 0xFFFFFFFC;
2109      u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xFF];
2110      int offset = 0;
2111      // load
2112      THUMB_LDM_REG(1, 0);
2113      THUMB_LDM_REG(2, 1);
2114      THUMB_LDM_REG(4, 2);
2115      THUMB_LDM_REG(8, 3);
2116      THUMB_LDM_REG(16, 4);
2117      THUMB_LDM_REG(32, 5);
2118      THUMB_LDM_REG(64, 6);
2119      THUMB_LDM_REG(128, 7);
2120      if(!(opcode & 1))
2121        reg[0].I = temp;
2122    }
2123    break;
2124  case 0xc9:
2125    {
2126      // LDM R1!, {Rlist}
2127      u32 address = reg[1].I & 0xFFFFFFFC;
2128      u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xFF];
2129      int offset = 0;
2130      // load
2131      THUMB_LDM_REG(1, 0);
2132      THUMB_LDM_REG(2, 1);
2133      THUMB_LDM_REG(4, 2);
2134      THUMB_LDM_REG(8, 3);
2135      THUMB_LDM_REG(16, 4);
2136      THUMB_LDM_REG(32, 5);
2137      THUMB_LDM_REG(64, 6);
2138      THUMB_LDM_REG(128, 7);
2139      if(!(opcode & 2))
2140        reg[1].I = temp;
2141    }
2142    break;
2143  case 0xca:
2144    {
2145      // LDM R2!, {Rlist}
2146      u32 address = reg[2].I & 0xFFFFFFFC;
2147      u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xFF];
2148      int offset = 0;
2149      // load
2150      THUMB_LDM_REG(1, 0);
2151      THUMB_LDM_REG(2, 1);
2152      THUMB_LDM_REG(4, 2);
2153      THUMB_LDM_REG(8, 3);
2154      THUMB_LDM_REG(16, 4);
2155      THUMB_LDM_REG(32, 5);
2156      THUMB_LDM_REG(64, 6);
2157      THUMB_LDM_REG(128, 7);
2158      if(!(opcode & 4))
2159        reg[2].I = temp;
2160    }
2161    break;
2162  case 0xcb:
2163    {
2164      // LDM R3!, {Rlist}
2165      u32 address = reg[3].I & 0xFFFFFFFC;
2166      u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xFF];
2167      int offset = 0;
2168      // load
2169      THUMB_LDM_REG(1, 0);
2170      THUMB_LDM_REG(2, 1);
2171      THUMB_LDM_REG(4, 2);
2172      THUMB_LDM_REG(8, 3);
2173      THUMB_LDM_REG(16, 4);
2174      THUMB_LDM_REG(32, 5);
2175      THUMB_LDM_REG(64, 6);
2176      THUMB_LDM_REG(128, 7);
2177      if(!(opcode & 8))
2178        reg[3].I = temp;
2179    }
2180    break;
2181  case 0xcc:
2182    {
2183      // LDM R4!, {Rlist}
2184      u32 address = reg[4].I & 0xFFFFFFFC;
2185      u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xFF];
2186      int offset = 0;
2187      // load
2188      THUMB_LDM_REG(1, 0);
2189      THUMB_LDM_REG(2, 1);
2190      THUMB_LDM_REG(4, 2);
2191      THUMB_LDM_REG(8, 3);
2192      THUMB_LDM_REG(16, 4);
2193      THUMB_LDM_REG(32, 5);
2194      THUMB_LDM_REG(64, 6);
2195      THUMB_LDM_REG(128, 7);
2196      if(!(opcode & 16))
2197        reg[4].I = temp;
2198    }
2199    break;
2200  case 0xcd:
2201    {
2202      // LDM R5!, {Rlist}
2203      u32 address = reg[5].I & 0xFFFFFFFC;
2204      u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xFF];
2205      int offset = 0;
2206      // load
2207      THUMB_LDM_REG(1, 0);
2208      THUMB_LDM_REG(2, 1);
2209      THUMB_LDM_REG(4, 2);
2210      THUMB_LDM_REG(8, 3);
2211      THUMB_LDM_REG(16, 4);
2212      THUMB_LDM_REG(32, 5);
2213      THUMB_LDM_REG(64, 6);
2214      THUMB_LDM_REG(128, 7);
2215      if(!(opcode & 32))
2216        reg[5].I = temp;
2217    }
2218    break;
2219  case 0xce:
2220    {
2221      // LDM R6!, {Rlist}
2222      u32 address = reg[6].I & 0xFFFFFFFC;
2223      u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xFF];
2224      int offset = 0;
2225      // load
2226      THUMB_LDM_REG(1, 0);
2227      THUMB_LDM_REG(2, 1);
2228      THUMB_LDM_REG(4, 2);
2229      THUMB_LDM_REG(8, 3);
2230      THUMB_LDM_REG(16, 4);
2231      THUMB_LDM_REG(32, 5);
2232      THUMB_LDM_REG(64, 6);
2233      THUMB_LDM_REG(128, 7);
2234      if(!(opcode & 64))
2235        reg[6].I = temp;
2236    }
2237    break;
2238  case 0xcf:
2239    {
2240      // LDM R7!, {Rlist}
2241      u32 address = reg[7].I & 0xFFFFFFFC;
2242      u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xFF];
2243      int offset = 0;
2244      // load
2245      THUMB_LDM_REG(1, 0);
2246      THUMB_LDM_REG(2, 1);
2247      THUMB_LDM_REG(4, 2);
2248      THUMB_LDM_REG(8, 3);
2249      THUMB_LDM_REG(16, 4);
2250      THUMB_LDM_REG(32, 5);
2251      THUMB_LDM_REG(64, 6);
2252      THUMB_LDM_REG(128, 7);
2253      if(!(opcode & 128))
2254        reg[7].I = temp;
2255    }
2256    break;
2257  case 0xd0:
2258    // BEQ offset
2259    if(Z_FLAG) {
2260      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2261      armNextPC = reg[15].I;
2262      reg[15].I += 2;
2263      clockTicks = 3;
2264    }
2265    break;
2266  case 0xd1:
2267    // BNE offset
2268    if(!Z_FLAG) {
2269      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2270      armNextPC = reg[15].I;
2271      reg[15].I += 2;
2272      clockTicks = 3;
2273    }
2274    break;
2275  case 0xd2:
2276    // BCS offset
2277    if(C_FLAG) {
2278      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2279      armNextPC = reg[15].I;
2280      reg[15].I += 2;
2281      clockTicks = 3;
2282    }
2283    break;
2284  case 0xd3:
2285    // BCC offset
2286    if(!C_FLAG) {
2287      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2288      armNextPC = reg[15].I;
2289      reg[15].I += 2;
2290      clockTicks = 3;
2291    }
2292    break;
2293  case 0xd4:
2294    // BMI offset
2295    if(N_FLAG) {
2296      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2297      armNextPC = reg[15].I;
2298      reg[15].I += 2;
2299      clockTicks = 3;
2300    }
2301    break;
2302  case 0xd5:
2303    // BPL offset
2304    if(!N_FLAG) {
2305      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2306      armNextPC = reg[15].I;
2307      reg[15].I += 2;
2308      clockTicks = 3;
2309    }
2310    break;
2311  case 0xd6:
2312    // BVS offset
2313    if(V_FLAG) {
2314      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2315      armNextPC = reg[15].I;
2316      reg[15].I += 2;
2317      clockTicks = 3;
2318    }
2319    break;
2320  case 0xd7:
2321    // BVC offset
2322    if(!V_FLAG) {
2323      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2324      armNextPC = reg[15].I;
2325      reg[15].I += 2;
2326      clockTicks = 3;
2327    }
2328    break;
2329  case 0xd8:
2330    // BHI offset
2331    if(C_FLAG && !Z_FLAG) {
2332      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2333      armNextPC = reg[15].I;
2334      reg[15].I += 2;
2335      clockTicks = 3;
2336    }
2337    break;
2338  case 0xd9:
2339    // BLS offset
2340    if(!C_FLAG || Z_FLAG) {
2341      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2342      armNextPC = reg[15].I;
2343      reg[15].I += 2;
2344      clockTicks = 3;
2345    }
2346    break;
2347  case 0xda:
2348    // BGE offset
2349    if(N_FLAG == V_FLAG) {
2350      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2351      armNextPC = reg[15].I;
2352      reg[15].I += 2;
2353      clockTicks = 3;
2354    }
2355    break;
2356  case 0xdb:
2357    // BLT offset
2358    if(N_FLAG != V_FLAG) {
2359      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2360      armNextPC = reg[15].I;
2361      reg[15].I += 2;
2362      clockTicks = 3;
2363    }
2364    break;
2365  case 0xdc:
2366    // BGT offset
2367    if(!Z_FLAG && (N_FLAG == V_FLAG)) {
2368      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2369      armNextPC = reg[15].I;
2370      reg[15].I += 2;
2371      clockTicks = 3;
2372    }
2373    break;
2374  case 0xdd:
2375    // BLE offset
2376    if(Z_FLAG || (N_FLAG != V_FLAG)) {
2377      reg[15].I += ((s8)(opcode & 0xFF)) << 1;
2378      armNextPC = reg[15].I;
2379      reg[15].I += 2;
2380      clockTicks = 3;
2381    }
2382    break;
2383  case 0xdf:
2384    // SWI #comment
2385    CPUSoftwareInterrupt(opcode & 0xFF);
2386    break;
2387  case 0xe0:
2388  case 0xe1:
2389  case 0xe2:
2390  case 0xe3:
2391  case 0xe4:
2392  case 0xe5:
2393  case 0xe6:
2394  case 0xe7:
2395    {
2396      // B offset
2397      int offset = (opcode & 0x3FF) << 1;
2398      if(opcode & 0x0400)
2399        offset |= 0xFFFFF800;
2400      reg[15].I += offset;
2401      armNextPC = reg[15].I;
2402      reg[15].I += 2;
2403    }
2404    break;
2405  case 0xf0:
2406  case 0xf1:
2407  case 0xf2:
2408  case 0xf3:
2409    {
2410      // BLL #offset
2411      int offset = (opcode & 0x7FF);
2412      reg[14].I = reg[15].I + (offset << 12);
2413    }
2414    break;
2415  case 0xf4:
2416  case 0xf5:
2417  case 0xf6:
2418  case 0xf7:
2419    {
2420      // BLL #offset
2421      int offset = (opcode & 0x7FF);
2422      reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
2423    }
2424    break;
2425  case 0xf8:
2426  case 0xf9:
2427  case 0xfa:
2428  case 0xfb:
2429  case 0xfc:
2430  case 0xfd:
2431  case 0xfe:
2432  case 0xff:
2433    {
2434      // BLH #offset
2435      int offset = (opcode & 0x7FF);
2436      u32 temp = reg[15].I-2;
2437      reg[15].I = (reg[14].I + (offset<<1))&0xFFFFFFFE;
2438      armNextPC = reg[15].I;
2439      reg[15].I += 2;
2440      reg[14].I = temp|1;
2441    }
2442    break;
2443 #ifdef BKPT_SUPPORT
2444  case 0xbe:
2445    // BKPT #comment
2446    extern void (*dbgSignal)(int,int);
2447    reg[15].I -= 2;
2448    armNextPC -= 2;
2449    dbgSignal(5, opcode & 255);
2450    return;
2451 #endif
2452  case 0xb1:
2453  case 0xb2:
2454  case 0xb3:
2455  case 0xb6:
2456  case 0xb7:
2457  case 0xb8:
2458  case 0xb9:
2459  case 0xba:
2460  case 0xbb:
2461 #ifndef BKPT_SUPPORT
2462  case 0xbe:
2463 #endif
2464  case 0xbf:
2465  case 0xde:
2466  default:
2467  unknown_thumb:
2468 #ifdef DEV_VERSION
2469    if(systemVerbose & VERBOSE_UNDEFINED)
2470      log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2);
2471 #endif
2472    CPUUndefinedException();
2473    break;
2474 }
2475