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