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