gpsp-kai 

File Info

Rev. 316
Size 289,101 bytes
Time 2007-10-18 19:30:57
Author takka
Log Message

(empty log message)

Content

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