1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator. 2 Copyright (C) 1994 Advanced RISC Machines Ltd. 3 Modifications to add arch. v4 support by <jsmith@cygnus.com>. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. */ 17 18 #include "armdefs.h" 19 #include "armemu.h" 20 #include "armos.h" 21 #include "iwmmxt.h" 22 23 static ARMword GetDPRegRHS (ARMul_State *, ARMword); 24 static ARMword GetDPSRegRHS (ARMul_State *, ARMword); 25 static void WriteR15 (ARMul_State *, ARMword); 26 static void WriteSR15 (ARMul_State *, ARMword); 27 static void WriteR15Branch (ARMul_State *, ARMword); 28 static ARMword GetLSRegRHS (ARMul_State *, ARMword); 29 static ARMword GetLS7RHS (ARMul_State *, ARMword); 30 static unsigned LoadWord (ARMul_State *, ARMword, ARMword); 31 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int); 32 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int); 33 static unsigned StoreWord (ARMul_State *, ARMword, ARMword); 34 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword); 35 static unsigned StoreByte (ARMul_State *, ARMword, ARMword); 36 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword); 37 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword); 38 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword); 39 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword); 40 static unsigned Multiply64 (ARMul_State *, ARMword, int, int); 41 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); 42 static void Handle_Load_Double (ARMul_State *, ARMword); 43 static void Handle_Store_Double (ARMul_State *, ARMword); 44 45 #define LUNSIGNED (0) /* unsigned operation */ 46 #define LSIGNED (1) /* signed operation */ 47 #define LDEFAULT (0) /* default : do nothing */ 48 #define LSCC (1) /* set condition codes on result */ 49 50 #ifdef NEED_UI_LOOP_HOOK 51 /* How often to run the ui_loop update, when in use. */ 52 #define UI_LOOP_POLL_INTERVAL 0x32000 53 54 /* Counter for the ui_loop_hook update. */ 55 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; 56 57 /* Actual hook to call to run through gdb's gui event loop. */ 58 extern int (*deprecated_ui_loop_hook) (int); 59 #endif /* NEED_UI_LOOP_HOOK */ 60 61 extern int stop_simulator; 62 63 /* Short-hand macros for LDR/STR. */ 64 65 /* Store post decrement writeback. */ 66 #define SHDOWNWB() \ 67 lhs = LHS ; \ 68 if (StoreHalfWord (state, instr, lhs)) \ 69 LSBase = lhs - GetLS7RHS (state, instr); 70 71 /* Store post increment writeback. */ 72 #define SHUPWB() \ 73 lhs = LHS ; \ 74 if (StoreHalfWord (state, instr, lhs)) \ 75 LSBase = lhs + GetLS7RHS (state, instr); 76 77 /* Store pre decrement. */ 78 #define SHPREDOWN() \ 79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr)); 80 81 /* Store pre decrement writeback. */ 82 #define SHPREDOWNWB() \ 83 temp = LHS - GetLS7RHS (state, instr); \ 84 if (StoreHalfWord (state, instr, temp)) \ 85 LSBase = temp; 86 87 /* Store pre increment. */ 88 #define SHPREUP() \ 89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr)); 90 91 /* Store pre increment writeback. */ 92 #define SHPREUPWB() \ 93 temp = LHS + GetLS7RHS (state, instr); \ 94 if (StoreHalfWord (state, instr, temp)) \ 95 LSBase = temp; 96 97 /* Load post decrement writeback. */ 98 #define LHPOSTDOWN() \ 99 { \ 100 int done = 1; \ 101 lhs = LHS; \ 102 temp = lhs - GetLS7RHS (state, instr); \ 103 \ 104 switch (BITS (5, 6)) \ 105 { \ 106 case 1: /* H */ \ 107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \ 108 LSBase = temp; \ 109 break; \ 110 case 2: /* SB */ \ 111 if (LoadByte (state, instr, lhs, LSIGNED)) \ 112 LSBase = temp; \ 113 break; \ 114 case 3: /* SH */ \ 115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \ 116 LSBase = temp; \ 117 break; \ 118 case 0: /* SWP handled elsewhere. */ \ 119 default: \ 120 done = 0; \ 121 break; \ 122 } \ 123 if (done) \ 124 break; \ 125 } 126 127 /* Load post increment writeback. */ 128 #define LHPOSTUP() \ 129 { \ 130 int done = 1; \ 131 lhs = LHS; \ 132 temp = lhs + GetLS7RHS (state, instr); \ 133 \ 134 switch (BITS (5, 6)) \ 135 { \ 136 case 1: /* H */ \ 137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \ 138 LSBase = temp; \ 139 break; \ 140 case 2: /* SB */ \ 141 if (LoadByte (state, instr, lhs, LSIGNED)) \ 142 LSBase = temp; \ 143 break; \ 144 case 3: /* SH */ \ 145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \ 146 LSBase = temp; \ 147 break; \ 148 case 0: /* SWP handled elsewhere. */ \ 149 default: \ 150 done = 0; \ 151 break; \ 152 } \ 153 if (done) \ 154 break; \ 155 } 156 157 /* Load pre decrement. */ 158 #define LHPREDOWN() \ 159 { \ 160 int done = 1; \ 161 \ 162 temp = LHS - GetLS7RHS (state, instr); \ 163 switch (BITS (5, 6)) \ 164 { \ 165 case 1: /* H */ \ 166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ 167 break; \ 168 case 2: /* SB */ \ 169 (void) LoadByte (state, instr, temp, LSIGNED); \ 170 break; \ 171 case 3: /* SH */ \ 172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \ 173 break; \ 174 case 0: \ 175 /* SWP handled elsewhere. */ \ 176 default: \ 177 done = 0; \ 178 break; \ 179 } \ 180 if (done) \ 181 break; \ 182 } 183 184 /* Load pre decrement writeback. */ 185 #define LHPREDOWNWB() \ 186 { \ 187 int done = 1; \ 188 \ 189 temp = LHS - GetLS7RHS (state, instr); \ 190 switch (BITS (5, 6)) \ 191 { \ 192 case 1: /* H */ \ 193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ 194 LSBase = temp; \ 195 break; \ 196 case 2: /* SB */ \ 197 if (LoadByte (state, instr, temp, LSIGNED)) \ 198 LSBase = temp; \ 199 break; \ 200 case 3: /* SH */ \ 201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \ 202 LSBase = temp; \ 203 break; \ 204 case 0: \ 205 /* SWP handled elsewhere. */ \ 206 default: \ 207 done = 0; \ 208 break; \ 209 } \ 210 if (done) \ 211 break; \ 212 } 213 214 /* Load pre increment. */ 215 #define LHPREUP() \ 216 { \ 217 int done = 1; \ 218 \ 219 temp = LHS + GetLS7RHS (state, instr); \ 220 switch (BITS (5, 6)) \ 221 { \ 222 case 1: /* H */ \ 223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ 224 break; \ 225 case 2: /* SB */ \ 226 (void) LoadByte (state, instr, temp, LSIGNED); \ 227 break; \ 228 case 3: /* SH */ \ 229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \ 230 break; \ 231 case 0: \ 232 /* SWP handled elsewhere. */ \ 233 default: \ 234 done = 0; \ 235 break; \ 236 } \ 237 if (done) \ 238 break; \ 239 } 240 241 /* Load pre increment writeback. */ 242 #define LHPREUPWB() \ 243 { \ 244 int done = 1; \ 245 \ 246 temp = LHS + GetLS7RHS (state, instr); \ 247 switch (BITS (5, 6)) \ 248 { \ 249 case 1: /* H */ \ 250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ 251 LSBase = temp; \ 252 break; \ 253 case 2: /* SB */ \ 254 if (LoadByte (state, instr, temp, LSIGNED)) \ 255 LSBase = temp; \ 256 break; \ 257 case 3: /* SH */ \ 258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \ 259 LSBase = temp; \ 260 break; \ 261 case 0: \ 262 /* SWP handled elsewhere. */ \ 263 default: \ 264 done = 0; \ 265 break; \ 266 } \ 267 if (done) \ 268 break; \ 269 } 270 271 /* Attempt to emulate an ARMv6 instruction. 272 Returns non-zero upon success. */ 273 274 static int 275 handle_v6_insn (ARMul_State * state, ARMword instr) 276 { 277 switch (BITS (20, 27)) 278 { 279 #if 0 280 case 0x03: printf ("Unhandled v6 insn: ldr\n"); break; 281 case 0x04: printf ("Unhandled v6 insn: umaal\n"); break; 282 case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break; 283 case 0x16: printf ("Unhandled v6 insn: smi\n"); break; 284 case 0x18: printf ("Unhandled v6 insn: strex\n"); break; 285 case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break; 286 case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break; 287 case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break; 288 case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break; 289 case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break; 290 case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break; 291 case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break; 292 case 0x30: printf ("Unhandled v6 insn: movw\n"); break; 293 case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break; 294 case 0x34: printf ("Unhandled v6 insn: movt\n"); break; 295 case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break; 296 #endif 297 case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break; 298 case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break; 299 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break; 300 case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break; 301 case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break; 302 case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break; 303 case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break; 304 case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break; 305 case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break; 306 case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break; 307 case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break; 308 case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break; 309 case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break; 310 case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break; 311 312 case 0x6a: 313 { 314 ARMword Rm; 315 int ror = -1; 316 317 switch (BITS (4, 11)) 318 { 319 case 0x07: ror = 0; break; 320 case 0x47: ror = 8; break; 321 case 0x87: ror = 16; break; 322 case 0xc7: ror = 24; break; 323 324 case 0x01: 325 case 0xf3: 326 printf ("Unhandled v6 insn: ssat\n"); 327 return 0; 328 default: 329 break; 330 } 331 332 if (ror == -1) 333 { 334 if (BITS (4, 6) == 0x7) 335 { 336 printf ("Unhandled v6 insn: ssat\n"); 337 return 0; 338 } 339 break; 340 } 341 342 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); 343 if (Rm & 0x80) 344 Rm |= 0xffffff00; 345 346 if (BITS (16, 19) == 0xf) 347 /* SXTB */ 348 state->Reg[BITS (12, 15)] = Rm; 349 else 350 /* SXTAB */ 351 state->Reg[BITS (12, 15)] += Rm; 352 } 353 return 1; 354 355 case 0x6b: 356 { 357 ARMword Rm; 358 int ror = -1; 359 360 switch (BITS (4, 11)) 361 { 362 case 0x07: ror = 0; break; 363 case 0x47: ror = 8; break; 364 case 0x87: ror = 16; break; 365 case 0xc7: ror = 24; break; 366 367 case 0xfb: 368 printf ("Unhandled v6 insn: rev\n"); 369 return 0; 370 default: 371 break; 372 } 373 374 if (ror == -1) 375 break; 376 377 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); 378 if (Rm & 0x8000) 379 Rm |= 0xffff0000; 380 381 if (BITS (16, 19) == 0xf) 382 /* SXTH */ 383 state->Reg[BITS (12, 15)] = Rm; 384 else 385 /* SXTAH */ 386 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; 387 } 388 return 1; 389 390 case 0x6e: 391 { 392 ARMword Rm; 393 int ror = -1; 394 395 switch (BITS (4, 11)) 396 { 397 case 0x07: ror = 0; break; 398 case 0x47: ror = 8; break; 399 case 0x87: ror = 16; break; 400 case 0xc7: ror = 24; break; 401 402 case 0x01: 403 case 0xf3: 404 printf ("Unhandled v6 insn: usat\n"); 405 return 0; 406 default: 407 break; 408 } 409 410 if (ror == -1) 411 { 412 if (BITS (4, 6) == 0x7) 413 { 414 printf ("Unhandled v6 insn: usat\n"); 415 return 0; 416 } 417 break; 418 } 419 420 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); 421 422 if (BITS (16, 19) == 0xf) 423 /* UXTB */ 424 state->Reg[BITS (12, 15)] = Rm; 425 else 426 /* UXTAB */ 427 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; 428 } 429 return 1; 430 431 case 0x6f: 432 { 433 ARMword Rm; 434 int ror = -1; 435 436 switch (BITS (4, 11)) 437 { 438 case 0x07: ror = 0; break; 439 case 0x47: ror = 8; break; 440 case 0x87: ror = 16; break; 441 case 0xc7: ror = 24; break; 442 443 case 0xfb: 444 printf ("Unhandled v6 insn: revsh\n"); 445 return 0; 446 default: 447 break; 448 } 449 450 if (ror == -1) 451 break; 452 453 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); 454 455 if (BITS (16, 19) == 0xf) 456 /* UXT */ 457 state->Reg[BITS (12, 15)] = Rm; 458 else 459 { 460 /* UXTAH */ 461 state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; 462 } 463 } 464 return 1; 465 466 #if 0 467 case 0x84: printf ("Unhandled v6 insn: srs\n"); break; 468 #endif 469 default: 470 break; 471 } 472 printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr); 473 return 0; 474 } 475 476 /* EMULATION of ARM6. */ 477 478 /* The PC pipeline value depends on whether ARM 479 or Thumb instructions are being executed. */ 480 ARMword isize; 481 482 ARMword 483 #ifdef MODE32 484 ARMul_Emulate32 (ARMul_State * state) 485 #else 486 ARMul_Emulate26 (ARMul_State * state) 487 #endif 488 { 489 ARMword instr; /* The current instruction. */ 490 ARMword dest = 0; /* Almost the DestBus. */ 491 ARMword temp; /* Ubiquitous third hand. */ 492 ARMword pc = 0; /* The address of the current instruction. */ 493 ARMword lhs; /* Almost the ABus and BBus. */ 494 ARMword rhs; 495 ARMword decoded = 0; /* Instruction pipeline. */ 496 ARMword loaded = 0; 497 498 /* Execute the next instruction. */ 499 500 if (state->NextInstr < PRIMEPIPE) 501 { 502 decoded = state->decoded; 503 loaded = state->loaded; 504 pc = state->pc; 505 } 506 507 do 508 { 509 /* Just keep going. */ 510 isize = INSN_SIZE; 511 512 switch (state->NextInstr) 513 { 514 case SEQ: 515 /* Advance the pipeline, and an S cycle. */ 516 state->Reg[15] += isize; 517 pc += isize; 518 instr = decoded; 519 decoded = loaded; 520 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); 521 break; 522 523 case NONSEQ: 524 /* Advance the pipeline, and an N cycle. */ 525 state->Reg[15] += isize; 526 pc += isize; 527 instr = decoded; 528 decoded = loaded; 529 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize); 530 NORMALCYCLE; 531 break; 532 533 case PCINCEDSEQ: 534 /* Program counter advanced, and an S cycle. */ 535 pc += isize; 536 instr = decoded; 537 decoded = loaded; 538 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); 539 NORMALCYCLE; 540 break; 541 542 case PCINCEDNONSEQ: 543 /* Program counter advanced, and an N cycle. */ 544 pc += isize; 545 instr = decoded; 546 decoded = loaded; 547 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize); 548 NORMALCYCLE; 549 break; 550 551 case RESUME: 552 /* The program counter has been changed. */ 553 pc = state->Reg[15]; 554 #ifndef MODE32 555 pc = pc & R15PCBITS; 556 #endif 557 state->Reg[15] = pc + (isize * 2); 558 state->Aborted = 0; 559 instr = ARMul_ReLoadInstr (state, pc, isize); 560 decoded = ARMul_ReLoadInstr (state, pc + isize, isize); 561 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize); 562 NORMALCYCLE; 563 break; 564 565 default: 566 /* The program counter has been changed. */ 567 pc = state->Reg[15]; 568 #ifndef MODE32 569 pc = pc & R15PCBITS; 570 #endif 571 state->Reg[15] = pc + (isize * 2); 572 state->Aborted = 0; 573 instr = ARMul_LoadInstrN (state, pc, isize); 574 decoded = ARMul_LoadInstrS (state, pc + (isize), isize); 575 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); 576 NORMALCYCLE; 577 break; 578 } 579 580 if (state->EventSet) 581 ARMul_EnvokeEvent (state); 582 #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */ 583 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr); 584 if (instr == 0) 585 abort (); 586 #endif 587 #if 0 /* Enable this code to help track down stack alignment bugs. */ 588 { 589 static ARMword old_sp = -1; 590 591 if (old_sp != state->Reg[13]) 592 { 593 old_sp = state->Reg[13]; 594 fprintf (stderr, "pc: %08x: SP set to %08x%s\n", 595 pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : ""); 596 } 597 } 598 #endif 599 600 if (state->Exception) 601 { 602 /* Any exceptions ? */ 603 if (state->NresetSig == LOW) 604 { 605 ARMul_Abort (state, ARMul_ResetV); 606 break; 607 } 608 else if (!state->NfiqSig && !FFLAG) 609 { 610 ARMul_Abort (state, ARMul_FIQV); 611 break; 612 } 613 else if (!state->NirqSig && !IFLAG) 614 { 615 ARMul_Abort (state, ARMul_IRQV); 616 break; 617 } 618 } 619 620 if (state->CallDebug > 0) 621 { 622 instr = ARMul_Debug (state, pc, instr); 623 if (state->Emulate < ONCE) 624 { 625 state->NextInstr = RESUME; 626 break; 627 } 628 if (state->Debug) 629 { 630 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr, 631 state->Mode); 632 (void) fgetc (stdin); 633 } 634 } 635 else if (state->Emulate < ONCE) 636 { 637 state->NextInstr = RESUME; 638 break; 639 } 640 641 state->NumInstrs++; 642 643 #ifdef MODET 644 /* Provide Thumb instruction decoding. If the processor is in Thumb 645 mode, then we can simply decode the Thumb instruction, and map it 646 to the corresponding ARM instruction (by directly loading the 647 instr variable, and letting the normal ARM simulator 648 execute). There are some caveats to ensure that the correct 649 pipelined PC value is used when executing Thumb code, and also for 650 dealing with the BL instruction. */ 651 if (TFLAG) 652 { 653 ARMword new; 654 655 /* Check if in Thumb mode. */ 656 switch (ARMul_ThumbDecode (state, pc, instr, &new)) 657 { 658 case t_undefined: 659 /* This is a Thumb instruction. */ 660 ARMul_UndefInstr (state, instr); 661 goto donext; 662 663 case t_branch: 664 /* Already processed. */ 665 goto donext; 666 667 case t_decoded: 668 /* ARM instruction available. */ 669 instr = new; 670 /* So continue instruction decoding. */ 671 break; 672 default: 673 break; 674 } 675 } 676 #endif 677 678 /* Check the condition codes. */ 679 if ((temp = TOPBITS (28)) == AL) 680 /* Vile deed in the need for speed. */ 681 goto mainswitch; 682 683 /* Check the condition code. */ 684 switch ((int) TOPBITS (28)) 685 { 686 case AL: 687 temp = TRUE; 688 break; 689 case NV: 690 if (state->is_v5) 691 { 692 if (BITS (25, 27) == 5) /* BLX(1) */ 693 { 694 ARMword dest; 695 696 state->Reg[14] = pc + 4; 697 698 /* Force entry into Thumb mode. */ 699 dest = pc + 8 + 1; 700 if (BIT (23)) 701 dest += (NEGBRANCH + (BIT (24) << 1)); 702 else 703 dest += POSBRANCH + (BIT (24) << 1); 704 705 WriteR15Branch (state, dest); 706 goto donext; 707 } 708 else if ((instr & 0xFC70F000) == 0xF450F000) 709 /* The PLD instruction. Ignored. */ 710 goto donext; 711 else if ( ((instr & 0xfe500f00) == 0xfc100100) 712 || ((instr & 0xfe500f00) == 0xfc000100)) 713 /* wldrw and wstrw are unconditional. */ 714 goto mainswitch; 715 else 716 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */ 717 ARMul_UndefInstr (state, instr); 718 } 719 temp = FALSE; 720 break; 721 case EQ: 722 temp = ZFLAG; 723 break; 724 case NE: 725 temp = !ZFLAG; 726 break; 727 case VS: 728 temp = VFLAG; 729 break; 730 case VC: 731 temp = !VFLAG; 732 break; 733 case MI: 734 temp = NFLAG; 735 break; 736 case PL: 737 temp = !NFLAG; 738 break; 739 case CS: 740 temp = CFLAG; 741 break; 742 case CC: 743 temp = !CFLAG; 744 break; 745 case HI: 746 temp = (CFLAG && !ZFLAG); 747 break; 748 case LS: 749 temp = (!CFLAG || ZFLAG); 750 break; 751 case GE: 752 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); 753 break; 754 case LT: 755 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); 756 break; 757 case GT: 758 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)); 759 break; 760 case LE: 761 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG; 762 break; 763 } /* cc check */ 764 765 /* Handle the Clock counter here. */ 766 if (state->is_XScale) 767 { 768 ARMword cp14r0; 769 int ok; 770 771 ok = state->CPRead[14] (state, 0, & cp14r0); 772 773 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE)) 774 { 775 unsigned long newcycles, nowtime = ARMul_Time (state); 776 777 newcycles = nowtime - state->LastTime; 778 state->LastTime = nowtime; 779 780 if (cp14r0 & ARMul_CP14_R0_CCD) 781 { 782 if (state->CP14R0_CCD == -1) 783 state->CP14R0_CCD = newcycles; 784 else 785 state->CP14R0_CCD += newcycles; 786 787 if (state->CP14R0_CCD >= 64) 788 { 789 newcycles = 0; 790 791 while (state->CP14R0_CCD >= 64) 792 state->CP14R0_CCD -= 64, newcycles++; 793 794 goto check_PMUintr; 795 } 796 } 797 else 798 { 799 ARMword cp14r1; 800 int do_int = 0; 801 802 state->CP14R0_CCD = -1; 803 check_PMUintr: 804 cp14r0 |= ARMul_CP14_R0_FLAG2; 805 (void) state->CPWrite[14] (state, 0, cp14r0); 806 807 ok = state->CPRead[14] (state, 1, & cp14r1); 808 809 /* Coded like this for portability. */ 810 while (ok && newcycles) 811 { 812 if (cp14r1 == 0xffffffff) 813 { 814 cp14r1 = 0; 815 do_int = 1; 816 } 817 else 818 cp14r1 ++; 819 820 newcycles --; 821 } 822 823 (void) state->CPWrite[14] (state, 1, cp14r1); 824 825 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2)) 826 { 827 ARMword temp; 828 829 if (state->CPRead[13] (state, 8, & temp) 830 && (temp & ARMul_CP13_R8_PMUS)) 831 ARMul_Abort (state, ARMul_FIQV); 832 else 833 ARMul_Abort (state, ARMul_IRQV); 834 } 835 } 836 } 837 } 838 839 /* Handle hardware instructions breakpoints here. */ 840 if (state->is_XScale) 841 { 842 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2) 843 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2)) 844 { 845 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB)) 846 ARMul_OSHandleSWI (state, SWI_Breakpoint); 847 } 848 } 849 850 /* Actual execution of instructions begins here. */ 851 /* If the condition codes don't match, stop here. */ 852 if (temp) 853 { 854 mainswitch: 855 856 if (state->is_XScale) 857 { 858 if (BIT (20) == 0 && BITS (25, 27) == 0) 859 { 860 if (BITS (4, 7) == 0xD) 861 { 862 /* XScale Load Consecutive insn. */ 863 ARMword temp = GetLS7RHS (state, instr); 864 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp; 865 ARMword addr = BIT (24) ? temp2 : LHS; 866 867 if (BIT (12)) 868 ARMul_UndefInstr (state, instr); 869 else if (addr & 7) 870 /* Alignment violation. */ 871 ARMul_Abort (state, ARMul_DataAbortV); 872 else 873 { 874 int wb = BIT (21) || (! BIT (24)); 875 876 state->Reg[BITS (12, 15)] = 877 ARMul_LoadWordN (state, addr); 878 state->Reg[BITS (12, 15) + 1] = 879 ARMul_LoadWordN (state, addr + 4); 880 if (wb) 881 LSBase = temp2; 882 } 883 884 goto donext; 885 } 886 else if (BITS (4, 7) == 0xF) 887 { 888 /* XScale Store Consecutive insn. */ 889 ARMword temp = GetLS7RHS (state, instr); 890 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp; 891 ARMword addr = BIT (24) ? temp2 : LHS; 892 893 if (BIT (12)) 894 ARMul_UndefInstr (state, instr); 895 else if (addr & 7) 896 /* Alignment violation. */ 897 ARMul_Abort (state, ARMul_DataAbortV); 898 else 899 { 900 ARMul_StoreWordN (state, addr, 901 state->Reg[BITS (12, 15)]); 902 ARMul_StoreWordN (state, addr + 4, 903 state->Reg[BITS (12, 15) + 1]); 904 905 if (BIT (21)|| ! BIT (24)) 906 LSBase = temp2; 907 } 908 909 goto donext; 910 } 911 } 912 913 if (ARMul_HandleIwmmxt (state, instr)) 914 goto donext; 915 } 916 917 switch ((int) BITS (20, 27)) 918 { 919 /* Data Processing Register RHS Instructions. */ 920 921 case 0x00: /* AND reg and MUL */ 922 #ifdef MODET 923 if (BITS (4, 11) == 0xB) 924 { 925 /* STRH register offset, no write-back, down, post indexed. */ 926 SHDOWNWB (); 927 break; 928 } 929 if (BITS (4, 7) == 0xD) 930 { 931 Handle_Load_Double (state, instr); 932 break; 933 } 934 if (BITS (4, 7) == 0xF) 935 { 936 Handle_Store_Double (state, instr); 937 break; 938 } 939 #endif 940 if (BITS (4, 7) == 9) 941 { 942 /* MUL */ 943 rhs = state->Reg[MULRHSReg]; 944 if (MULLHSReg == MULDESTReg) 945 { 946 UNDEF_MULDestEQOp1; 947 state->Reg[MULDESTReg] = 0; 948 } 949 else if (MULDESTReg != 15) 950 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs; 951 else 952 UNDEF_MULPCDest; 953 954 for (dest = 0, temp = 0; dest < 32; dest ++) 955 if (rhs & (1L << dest)) 956 temp = dest; 957 958 /* Mult takes this many/2 I cycles. */ 959 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 960 } 961 else 962 { 963 /* AND reg. */ 964 rhs = DPRegRHS; 965 dest = LHS & rhs; 966 WRITEDEST (dest); 967 } 968 break; 969 970 case 0x01: /* ANDS reg and MULS */ 971 #ifdef MODET 972 if ((BITS (4, 11) & 0xF9) == 0x9) 973 /* LDR register offset, no write-back, down, post indexed. */ 974 LHPOSTDOWN (); 975 /* Fall through to rest of decoding. */ 976 #endif 977 if (BITS (4, 7) == 9) 978 { 979 /* MULS */ 980 rhs = state->Reg[MULRHSReg]; 981 982 if (MULLHSReg == MULDESTReg) 983 { 984 UNDEF_MULDestEQOp1; 985 state->Reg[MULDESTReg] = 0; 986 CLEARN; 987 SETZ; 988 } 989 else if (MULDESTReg != 15) 990 { 991 dest = state->Reg[MULLHSReg] * rhs; 992 ARMul_NegZero (state, dest); 993 state->Reg[MULDESTReg] = dest; 994 } 995 else 996 UNDEF_MULPCDest; 997 998 for (dest = 0, temp = 0; dest < 32; dest ++) 999 if (rhs & (1L << dest)) 1000 temp = dest; 1001 1002 /* Mult takes this many/2 I cycles. */ 1003 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1004 } 1005 else 1006 { 1007 /* ANDS reg. */ 1008 rhs = DPSRegRHS; 1009 dest = LHS & rhs; 1010 WRITESDEST (dest); 1011 } 1012 break; 1013 1014 case 0x02: /* EOR reg and MLA */ 1015 #ifdef MODET 1016 if (BITS (4, 11) == 0xB) 1017 { 1018 /* STRH register offset, write-back, down, post indexed. */ 1019 SHDOWNWB (); 1020 break; 1021 } 1022 #endif 1023 if (BITS (4, 7) == 9) 1024 { /* MLA */ 1025 rhs = state->Reg[MULRHSReg]; 1026 if (MULLHSReg == MULDESTReg) 1027 { 1028 UNDEF_MULDestEQOp1; 1029 state->Reg[MULDESTReg] = state->Reg[MULACCReg]; 1030 } 1031 else if (MULDESTReg != 15) 1032 state->Reg[MULDESTReg] = 1033 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; 1034 else 1035 UNDEF_MULPCDest; 1036 1037 for (dest = 0, temp = 0; dest < 32; dest ++) 1038 if (rhs & (1L << dest)) 1039 temp = dest; 1040 1041 /* Mult takes this many/2 I cycles. */ 1042 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1043 } 1044 else 1045 { 1046 rhs = DPRegRHS; 1047 dest = LHS ^ rhs; 1048 WRITEDEST (dest); 1049 } 1050 break; 1051 1052 case 0x03: /* EORS reg and MLAS */ 1053 #ifdef MODET 1054 if ((BITS (4, 11) & 0xF9) == 0x9) 1055 /* LDR register offset, write-back, down, post-indexed. */ 1056 LHPOSTDOWN (); 1057 /* Fall through to rest of the decoding. */ 1058 #endif 1059 if (BITS (4, 7) == 9) 1060 { 1061 /* MLAS */ 1062 rhs = state->Reg[MULRHSReg]; 1063 1064 if (MULLHSReg == MULDESTReg) 1065 { 1066 UNDEF_MULDestEQOp1; 1067 dest = state->Reg[MULACCReg]; 1068 ARMul_NegZero (state, dest); 1069 state->Reg[MULDESTReg] = dest; 1070 } 1071 else if (MULDESTReg != 15) 1072 { 1073 dest = 1074 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; 1075 ARMul_NegZero (state, dest); 1076 state->Reg[MULDESTReg] = dest; 1077 } 1078 else 1079 UNDEF_MULPCDest; 1080 1081 for (dest = 0, temp = 0; dest < 32; dest ++) 1082 if (rhs & (1L << dest)) 1083 temp = dest; 1084 1085 /* Mult takes this many/2 I cycles. */ 1086 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1087 } 1088 else 1089 { 1090 /* EORS Reg. */ 1091 rhs = DPSRegRHS; 1092 dest = LHS ^ rhs; 1093 WRITESDEST (dest); 1094 } 1095 break; 1096 1097 case 0x04: /* SUB reg */ 1098 #ifdef MODET 1099 if (BITS (4, 7) == 0xB) 1100 { 1101 /* STRH immediate offset, no write-back, down, post indexed. */ 1102 SHDOWNWB (); 1103 break; 1104 } 1105 if (BITS (4, 7) == 0xD) 1106 { 1107 Handle_Load_Double (state, instr); 1108 break; 1109 } 1110 if (BITS (4, 7) == 0xF) 1111 { 1112 Handle_Store_Double (state, instr); 1113 break; 1114 } 1115 #endif 1116 rhs = DPRegRHS; 1117 dest = LHS - rhs; 1118 WRITEDEST (dest); 1119 break; 1120 1121 case 0x05: /* SUBS reg */ 1122 #ifdef MODET 1123 if ((BITS (4, 7) & 0x9) == 0x9) 1124 /* LDR immediate offset, no write-back, down, post indexed. */ 1125 LHPOSTDOWN (); 1126 /* Fall through to the rest of the instruction decoding. */ 1127 #endif 1128 lhs = LHS; 1129 rhs = DPRegRHS; 1130 dest = lhs - rhs; 1131 1132 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 1133 { 1134 ARMul_SubCarry (state, lhs, rhs, dest); 1135 ARMul_SubOverflow (state, lhs, rhs, dest); 1136 } 1137 else 1138 { 1139 CLEARC; 1140 CLEARV; 1141 } 1142 WRITESDEST (dest); 1143 break; 1144 1145 case 0x06: /* RSB reg */ 1146 #ifdef MODET 1147 if (BITS (4, 7) == 0xB) 1148 { 1149 /* STRH immediate offset, write-back, down, post indexed. */ 1150 SHDOWNWB (); 1151 break; 1152 } 1153 #endif 1154 rhs = DPRegRHS; 1155 dest = rhs - LHS; 1156 WRITEDEST (dest); 1157 break; 1158 1159 case 0x07: /* RSBS reg */ 1160 #ifdef MODET 1161 if ((BITS (4, 7) & 0x9) == 0x9) 1162 /* LDR immediate offset, write-back, down, post indexed. */ 1163 LHPOSTDOWN (); 1164 /* Fall through to remainder of instruction decoding. */ 1165 #endif 1166 lhs = LHS; 1167 rhs = DPRegRHS; 1168 dest = rhs - lhs; 1169 1170 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 1171 { 1172 ARMul_SubCarry (state, rhs, lhs, dest); 1173 ARMul_SubOverflow (state, rhs, lhs, dest); 1174 } 1175 else 1176 { 1177 CLEARC; 1178 CLEARV; 1179 } 1180 WRITESDEST (dest); 1181 break; 1182 1183 case 0x08: /* ADD reg */ 1184 #ifdef MODET 1185 if (BITS (4, 11) == 0xB) 1186 { 1187 /* STRH register offset, no write-back, up, post indexed. */ 1188 SHUPWB (); 1189 break; 1190 } 1191 if (BITS (4, 7) == 0xD) 1192 { 1193 Handle_Load_Double (state, instr); 1194 break; 1195 } 1196 if (BITS (4, 7) == 0xF) 1197 { 1198 Handle_Store_Double (state, instr); 1199 break; 1200 } 1201 #endif 1202 #ifdef MODET 1203 if (BITS (4, 7) == 0x9) 1204 { 1205 /* MULL */ 1206 /* 32x32 = 64 */ 1207 ARMul_Icycles (state, 1208 Multiply64 (state, instr, LUNSIGNED, 1209 LDEFAULT), 0L); 1210 break; 1211 } 1212 #endif 1213 rhs = DPRegRHS; 1214 dest = LHS + rhs; 1215 WRITEDEST (dest); 1216 break; 1217 1218 case 0x09: /* ADDS reg */ 1219 #ifdef MODET 1220 if ((BITS (4, 11) & 0xF9) == 0x9) 1221 /* LDR register offset, no write-back, up, post indexed. */ 1222 LHPOSTUP (); 1223 /* Fall through to remaining instruction decoding. */ 1224 #endif 1225 #ifdef MODET 1226 if (BITS (4, 7) == 0x9) 1227 { 1228 /* MULL */ 1229 /* 32x32=64 */ 1230 ARMul_Icycles (state, 1231 Multiply64 (state, instr, LUNSIGNED, LSCC), 1232 0L); 1233 break; 1234 } 1235 #endif 1236 lhs = LHS; 1237 rhs = DPRegRHS; 1238 dest = lhs + rhs; 1239 ASSIGNZ (dest == 0); 1240 if ((lhs | rhs) >> 30) 1241 { 1242 /* Possible C,V,N to set. */ 1243 ASSIGNN (NEG (dest)); 1244 ARMul_AddCarry (state, lhs, rhs, dest); 1245 ARMul_AddOverflow (state, lhs, rhs, dest); 1246 } 1247 else 1248 { 1249 CLEARN; 1250 CLEARC; 1251 CLEARV; 1252 } 1253 WRITESDEST (dest); 1254 break; 1255 1256 case 0x0a: /* ADC reg */ 1257 #ifdef MODET 1258 if (BITS (4, 11) == 0xB) 1259 { 1260 /* STRH register offset, write-back, up, post-indexed. */ 1261 SHUPWB (); 1262 break; 1263 } 1264 if (BITS (4, 7) == 0x9) 1265 { 1266 /* MULL */ 1267 /* 32x32=64 */ 1268 ARMul_Icycles (state, 1269 MultiplyAdd64 (state, instr, LUNSIGNED, 1270 LDEFAULT), 0L); 1271 break; 1272 } 1273 #endif 1274 rhs = DPRegRHS; 1275 dest = LHS + rhs + CFLAG; 1276 WRITEDEST (dest); 1277 break; 1278 1279 case 0x0b: /* ADCS reg */ 1280 #ifdef MODET 1281 if ((BITS (4, 11) & 0xF9) == 0x9) 1282 /* LDR register offset, write-back, up, post indexed. */ 1283 LHPOSTUP (); 1284 /* Fall through to remaining instruction decoding. */ 1285 if (BITS (4, 7) == 0x9) 1286 { 1287 /* MULL */ 1288 /* 32x32=64 */ 1289 ARMul_Icycles (state, 1290 MultiplyAdd64 (state, instr, LUNSIGNED, 1291 LSCC), 0L); 1292 break; 1293 } 1294 #endif 1295 lhs = LHS; 1296 rhs = DPRegRHS; 1297 dest = lhs + rhs + CFLAG; 1298 ASSIGNZ (dest == 0); 1299 if ((lhs | rhs) >> 30) 1300 { 1301 /* Possible C,V,N to set. */ 1302 ASSIGNN (NEG (dest)); 1303 ARMul_AddCarry (state, lhs, rhs, dest); 1304 ARMul_AddOverflow (state, lhs, rhs, dest); 1305 } 1306 else 1307 { 1308 CLEARN; 1309 CLEARC; 1310 CLEARV; 1311 } 1312 WRITESDEST (dest); 1313 break; 1314 1315 case 0x0c: /* SBC reg */ 1316 #ifdef MODET 1317 if (BITS (4, 7) == 0xB) 1318 { 1319 /* STRH immediate offset, no write-back, up post indexed. */ 1320 SHUPWB (); 1321 break; 1322 } 1323 if (BITS (4, 7) == 0xD) 1324 { 1325 Handle_Load_Double (state, instr); 1326 break; 1327 } 1328 if (BITS (4, 7) == 0xF) 1329 { 1330 Handle_Store_Double (state, instr); 1331 break; 1332 } 1333 if (BITS (4, 7) == 0x9) 1334 { 1335 /* MULL */ 1336 /* 32x32=64 */ 1337 ARMul_Icycles (state, 1338 Multiply64 (state, instr, LSIGNED, LDEFAULT), 1339 0L); 1340 break; 1341 } 1342 #endif 1343 rhs = DPRegRHS; 1344 dest = LHS - rhs - !CFLAG; 1345 WRITEDEST (dest); 1346 break; 1347 1348 case 0x0d: /* SBCS reg */ 1349 #ifdef MODET 1350 if ((BITS (4, 7) & 0x9) == 0x9) 1351 /* LDR immediate offset, no write-back, up, post indexed. */ 1352 LHPOSTUP (); 1353 1354 if (BITS (4, 7) == 0x9) 1355 { 1356 /* MULL */ 1357 /* 32x32=64 */ 1358 ARMul_Icycles (state, 1359 Multiply64 (state, instr, LSIGNED, LSCC), 1360 0L); 1361 break; 1362 } 1363 #endif 1364 lhs = LHS; 1365 rhs = DPRegRHS; 1366 dest = lhs - rhs - !CFLAG; 1367 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 1368 { 1369 ARMul_SubCarry (state, lhs, rhs, dest); 1370 ARMul_SubOverflow (state, lhs, rhs, dest); 1371 } 1372 else 1373 { 1374 CLEARC; 1375 CLEARV; 1376 } 1377 WRITESDEST (dest); 1378 break; 1379 1380 case 0x0e: /* RSC reg */ 1381 #ifdef MODET 1382 if (BITS (4, 7) == 0xB) 1383 { 1384 /* STRH immediate offset, write-back, up, post indexed. */ 1385 SHUPWB (); 1386 break; 1387 } 1388 1389 if (BITS (4, 7) == 0x9) 1390 { 1391 /* MULL */ 1392 /* 32x32=64 */ 1393 ARMul_Icycles (state, 1394 MultiplyAdd64 (state, instr, LSIGNED, 1395 LDEFAULT), 0L); 1396 break; 1397 } 1398 #endif 1399 rhs = DPRegRHS; 1400 dest = rhs - LHS - !CFLAG; 1401 WRITEDEST (dest); 1402 break; 1403 1404 case 0x0f: /* RSCS reg */ 1405 #ifdef MODET 1406 if ((BITS (4, 7) & 0x9) == 0x9) 1407 /* LDR immediate offset, write-back, up, post indexed. */ 1408 LHPOSTUP (); 1409 /* Fall through to remaining instruction decoding. */ 1410 1411 if (BITS (4, 7) == 0x9) 1412 { 1413 /* MULL */ 1414 /* 32x32=64 */ 1415 ARMul_Icycles (state, 1416 MultiplyAdd64 (state, instr, LSIGNED, LSCC), 1417 0L); 1418 break; 1419 } 1420 #endif 1421 lhs = LHS; 1422 rhs = DPRegRHS; 1423 dest = rhs - lhs - !CFLAG; 1424 1425 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 1426 { 1427 ARMul_SubCarry (state, rhs, lhs, dest); 1428 ARMul_SubOverflow (state, rhs, lhs, dest); 1429 } 1430 else 1431 { 1432 CLEARC; 1433 CLEARV; 1434 } 1435 WRITESDEST (dest); 1436 break; 1437 1438 case 0x10: /* TST reg and MRS CPSR and SWP word. */ 1439 if (state->is_v5e) 1440 { 1441 if (BIT (4) == 0 && BIT (7) == 1) 1442 { 1443 /* ElSegundo SMLAxy insn. */ 1444 ARMword op1 = state->Reg[BITS (0, 3)]; 1445 ARMword op2 = state->Reg[BITS (8, 11)]; 1446 ARMword Rn = state->Reg[BITS (12, 15)]; 1447 1448 if (BIT (5)) 1449 op1 >>= 16; 1450 if (BIT (6)) 1451 op2 >>= 16; 1452 op1 &= 0xFFFF; 1453 op2 &= 0xFFFF; 1454 if (op1 & 0x8000) 1455 op1 -= 65536; 1456 if (op2 & 0x8000) 1457 op2 -= 65536; 1458 op1 *= op2; 1459 1460 if (AddOverflow (op1, Rn, op1 + Rn)) 1461 SETS; 1462 state->Reg[BITS (16, 19)] = op1 + Rn; 1463 break; 1464 } 1465 1466 if (BITS (4, 11) == 5) 1467 { 1468 /* ElSegundo QADD insn. */ 1469 ARMword op1 = state->Reg[BITS (0, 3)]; 1470 ARMword op2 = state->Reg[BITS (16, 19)]; 1471 ARMword result = op1 + op2; 1472 if (AddOverflow (op1, op2, result)) 1473 { 1474 result = POS (result) ? 0x80000000 : 0x7fffffff; 1475 SETS; 1476 } 1477 state->Reg[BITS (12, 15)] = result; 1478 break; 1479 } 1480 } 1481 #ifdef MODET 1482 if (BITS (4, 11) == 0xB) 1483 { 1484 /* STRH register offset, no write-back, down, pre indexed. */ 1485 SHPREDOWN (); 1486 break; 1487 } 1488 if (BITS (4, 7) == 0xD) 1489 { 1490 Handle_Load_Double (state, instr); 1491 break; 1492 } 1493 if (BITS (4, 7) == 0xF) 1494 { 1495 Handle_Store_Double (state, instr); 1496 break; 1497 } 1498 #endif 1499 if (BITS (4, 11) == 9) 1500 { 1501 /* SWP */ 1502 UNDEF_SWPPC; 1503 temp = LHS; 1504 BUSUSEDINCPCS; 1505 #ifndef MODE32 1506 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) 1507 { 1508 INTERNALABORT (temp); 1509 (void) ARMul_LoadWordN (state, temp); 1510 (void) ARMul_LoadWordN (state, temp); 1511 } 1512 else 1513 #endif 1514 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]); 1515 if (temp & 3) 1516 DEST = ARMul_Align (state, temp, dest); 1517 else 1518 DEST = dest; 1519 if (state->abortSig || state->Aborted) 1520 TAKEABORT; 1521 } 1522 else if ((BITS (0, 11) == 0) && (LHSReg == 15)) 1523 { /* MRS CPSR */ 1524 UNDEF_MRSPC; 1525 DEST = ECC | EINT | EMODE; 1526 } 1527 else 1528 { 1529 UNDEF_Test; 1530 } 1531 break; 1532 1533 case 0x11: /* TSTP reg */ 1534 #ifdef MODET 1535 if ((BITS (4, 11) & 0xF9) == 0x9) 1536 /* LDR register offset, no write-back, down, pre indexed. */ 1537 LHPREDOWN (); 1538 /* Continue with remaining instruction decode. */ 1539 #endif 1540 if (DESTReg == 15) 1541 { 1542 /* TSTP reg */ 1543 #ifdef MODE32 1544 state->Cpsr = GETSPSR (state->Bank); 1545 ARMul_CPSRAltered (state); 1546 #else 1547 rhs = DPRegRHS; 1548 temp = LHS & rhs; 1549 SETR15PSR (temp); 1550 #endif 1551 } 1552 else 1553 { 1554 /* TST reg */ 1555 rhs = DPSRegRHS; 1556 dest = LHS & rhs; 1557 ARMul_NegZero (state, dest); 1558 } 1559 break; 1560 1561 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */ 1562 if (state->is_v5) 1563 { 1564 if (BITS (4, 7) == 3) 1565 { 1566 /* BLX(2) */ 1567 ARMword temp; 1568 1569 if (TFLAG) 1570 temp = (pc + 2) | 1; 1571 else 1572 temp = pc + 4; 1573 1574 WriteR15Branch (state, state->Reg[RHSReg]); 1575 state->Reg[14] = temp; 1576 break; 1577 } 1578 } 1579 1580 if (state->is_v5e) 1581 { 1582 if (BIT (4) == 0 && BIT (7) == 1 1583 && (BIT (5) == 0 || BITS (12, 15) == 0)) 1584 { 1585 /* ElSegundo SMLAWy/SMULWy insn. */ 1586 ARMdword op1 = state->Reg[BITS (0, 3)]; 1587 ARMdword op2 = state->Reg[BITS (8, 11)]; 1588 ARMdword result; 1589 1590 if (BIT (6)) 1591 op2 >>= 16; 1592 if (op1 & 0x80000000) 1593 op1 -= 1ULL << 32; 1594 op2 &= 0xFFFF; 1595 if (op2 & 0x8000) 1596 op2 -= 65536; 1597 result = (op1 * op2) >> 16; 1598 1599 if (BIT (5) == 0) 1600 { 1601 ARMword Rn = state->Reg[BITS (12, 15)]; 1602 1603 if (AddOverflow (result, Rn, result + Rn)) 1604 SETS; 1605 result += Rn; 1606 } 1607 state->Reg[BITS (16, 19)] = result; 1608 break; 1609 } 1610 1611 if (BITS (4, 11) == 5) 1612 { 1613 /* ElSegundo QSUB insn. */ 1614 ARMword op1 = state->Reg[BITS (0, 3)]; 1615 ARMword op2 = state->Reg[BITS (16, 19)]; 1616 ARMword result = op1 - op2; 1617 1618 if (SubOverflow (op1, op2, result)) 1619 { 1620 result = POS (result) ? 0x80000000 : 0x7fffffff; 1621 SETS; 1622 } 1623 1624 state->Reg[BITS (12, 15)] = result; 1625 break; 1626 } 1627 } 1628 #ifdef MODET 1629 if (BITS (4, 11) == 0xB) 1630 { 1631 /* STRH register offset, write-back, down, pre indexed. */ 1632 SHPREDOWNWB (); 1633 break; 1634 } 1635 if (BITS (4, 27) == 0x12FFF1) 1636 { 1637 /* BX */ 1638 WriteR15Branch (state, state->Reg[RHSReg]); 1639 break; 1640 } 1641 if (BITS (4, 7) == 0xD) 1642 { 1643 Handle_Load_Double (state, instr); 1644 break; 1645 } 1646 if (BITS (4, 7) == 0xF) 1647 { 1648 Handle_Store_Double (state, instr); 1649 break; 1650 } 1651 #endif 1652 if (state->is_v5) 1653 { 1654 if (BITS (4, 7) == 0x7) 1655 { 1656 ARMword value; 1657 extern int SWI_vector_installed; 1658 1659 /* Hardware is allowed to optionally override this 1660 instruction and treat it as a breakpoint. Since 1661 this is a simulator not hardware, we take the position 1662 that if a SWI vector was not installed, then an Abort 1663 vector was probably not installed either, and so 1664 normally this instruction would be ignored, even if an 1665 Abort is generated. This is a bad thing, since GDB 1666 uses this instruction for its breakpoints (at least in 1667 Thumb mode it does). So intercept the instruction here 1668 and generate a breakpoint SWI instead. */ 1669 if (! SWI_vector_installed) 1670 ARMul_OSHandleSWI (state, SWI_Breakpoint); 1671 else 1672 { 1673 /* BKPT - normally this will cause an abort, but on the 1674 XScale we must check the DCSR. */ 1675 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); 1676 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT)) 1677 break; 1678 } 1679 1680 /* Force the next instruction to be refetched. */ 1681 state->NextInstr = RESUME; 1682 break; 1683 } 1684 } 1685 if (DESTReg == 15) 1686 { 1687 /* MSR reg to CPSR. */ 1688 UNDEF_MSRPC; 1689 temp = DPRegRHS; 1690 #ifdef MODET 1691 /* Don't allow TBIT to be set by MSR. */ 1692 temp &= ~ TBIT; 1693 #endif 1694 ARMul_FixCPSR (state, instr, temp); 1695 } 1696 else 1697 UNDEF_Test; 1698 1699 break; 1700 1701 case 0x13: /* TEQP reg */ 1702 #ifdef MODET 1703 if ((BITS (4, 11) & 0xF9) == 0x9) 1704 /* LDR register offset, write-back, down, pre indexed. */ 1705 LHPREDOWNWB (); 1706 /* Continue with remaining instruction decode. */ 1707 #endif 1708 if (DESTReg == 15) 1709 { 1710 /* TEQP reg */ 1711 #ifdef MODE32 1712 state->Cpsr = GETSPSR (state->Bank); 1713 ARMul_CPSRAltered (state); 1714 #else 1715 rhs = DPRegRHS; 1716 temp = LHS ^ rhs; 1717 SETR15PSR (temp); 1718 #endif 1719 } 1720 else 1721 { 1722 /* TEQ Reg. */ 1723 rhs = DPSRegRHS; 1724 dest = LHS ^ rhs; 1725 ARMul_NegZero (state, dest); 1726 } 1727 break; 1728 1729 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */ 1730 if (state->is_v5e) 1731 { 1732 if (BIT (4) == 0 && BIT (7) == 1) 1733 { 1734 /* ElSegundo SMLALxy insn. */ 1735 ARMdword op1 = state->Reg[BITS (0, 3)]; 1736 ARMdword op2 = state->Reg[BITS (8, 11)]; 1737 ARMdword dest; 1738 ARMdword result; 1739 1740 if (BIT (5)) 1741 op1 >>= 16; 1742 if (BIT (6)) 1743 op2 >>= 16; 1744 op1 &= 0xFFFF; 1745 if (op1 & 0x8000) 1746 op1 -= 65536; 1747 op2 &= 0xFFFF; 1748 if (op2 & 0x8000) 1749 op2 -= 65536; 1750 1751 dest = (ARMdword) state->Reg[BITS (16, 19)] << 32; 1752 dest |= state->Reg[BITS (12, 15)]; 1753 dest += op1 * op2; 1754 state->Reg[BITS (12, 15)] = dest; 1755 state->Reg[BITS (16, 19)] = dest >> 32; 1756 break; 1757 } 1758 1759 if (BITS (4, 11) == 5) 1760 { 1761 /* ElSegundo QDADD insn. */ 1762 ARMword op1 = state->Reg[BITS (0, 3)]; 1763 ARMword op2 = state->Reg[BITS (16, 19)]; 1764 ARMword op2d = op2 + op2; 1765 ARMword result; 1766 1767 if (AddOverflow (op2, op2, op2d)) 1768 { 1769 SETS; 1770 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 1771 } 1772 1773 result = op1 + op2d; 1774 if (AddOverflow (op1, op2d, result)) 1775 { 1776 SETS; 1777 result = POS (result) ? 0x80000000 : 0x7fffffff; 1778 } 1779 1780 state->Reg[BITS (12, 15)] = result; 1781 break; 1782 } 1783 } 1784 #ifdef MODET 1785 if (BITS (4, 7) == 0xB) 1786 { 1787 /* STRH immediate offset, no write-back, down, pre indexed. */ 1788 SHPREDOWN (); 1789 break; 1790 } 1791 if (BITS (4, 7) == 0xD) 1792 { 1793 Handle_Load_Double (state, instr); 1794 break; 1795 } 1796 if (BITS (4, 7) == 0xF) 1797 { 1798 Handle_Store_Double (state, instr); 1799 break; 1800 } 1801 #endif 1802 if (BITS (4, 11) == 9) 1803 { 1804 /* SWP */ 1805 UNDEF_SWPPC; 1806 temp = LHS; 1807 BUSUSEDINCPCS; 1808 #ifndef MODE32 1809 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) 1810 { 1811 INTERNALABORT (temp); 1812 (void) ARMul_LoadByte (state, temp); 1813 (void) ARMul_LoadByte (state, temp); 1814 } 1815 else 1816 #endif 1817 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]); 1818 if (state->abortSig || state->Aborted) 1819 TAKEABORT; 1820 } 1821 else if ((BITS (0, 11) == 0) && (LHSReg == 15)) 1822 { 1823 /* MRS SPSR */ 1824 UNDEF_MRSPC; 1825 DEST = GETSPSR (state->Bank); 1826 } 1827 else 1828 UNDEF_Test; 1829 1830 break; 1831 1832 case 0x15: /* CMPP reg. */ 1833 #ifdef MODET 1834 if ((BITS (4, 7) & 0x9) == 0x9) 1835 /* LDR immediate offset, no write-back, down, pre indexed. */ 1836 LHPREDOWN (); 1837 /* Continue with remaining instruction decode. */ 1838 #endif 1839 if (DESTReg == 15) 1840 { 1841 /* CMPP reg. */ 1842 #ifdef MODE32 1843 state->Cpsr = GETSPSR (state->Bank); 1844 ARMul_CPSRAltered (state); 1845 #else 1846 rhs = DPRegRHS; 1847 temp = LHS - rhs; 1848 SETR15PSR (temp); 1849 #endif 1850 } 1851 else 1852 { 1853 /* CMP reg. */ 1854 lhs = LHS; 1855 rhs = DPRegRHS; 1856 dest = lhs - rhs; 1857 ARMul_NegZero (state, dest); 1858 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 1859 { 1860 ARMul_SubCarry (state, lhs, rhs, dest); 1861 ARMul_SubOverflow (state, lhs, rhs, dest); 1862 } 1863 else 1864 { 1865 CLEARC; 1866 CLEARV; 1867 } 1868 } 1869 break; 1870 1871 case 0x16: /* CMN reg and MSR reg to SPSR */ 1872 if (state->is_v5e) 1873 { 1874 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0) 1875 { 1876 /* ElSegundo SMULxy insn. */ 1877 ARMword op1 = state->Reg[BITS (0, 3)]; 1878 ARMword op2 = state->Reg[BITS (8, 11)]; 1879 ARMword Rn = state->Reg[BITS (12, 15)]; 1880 1881 if (BIT (5)) 1882 op1 >>= 16; 1883 if (BIT (6)) 1884 op2 >>= 16; 1885 op1 &= 0xFFFF; 1886 op2 &= 0xFFFF; 1887 if (op1 & 0x8000) 1888 op1 -= 65536; 1889 if (op2 & 0x8000) 1890 op2 -= 65536; 1891 1892 state->Reg[BITS (16, 19)] = op1 * op2; 1893 break; 1894 } 1895 1896 if (BITS (4, 11) == 5) 1897 { 1898 /* ElSegundo QDSUB insn. */ 1899 ARMword op1 = state->Reg[BITS (0, 3)]; 1900 ARMword op2 = state->Reg[BITS (16, 19)]; 1901 ARMword op2d = op2 + op2; 1902 ARMword result; 1903 1904 if (AddOverflow (op2, op2, op2d)) 1905 { 1906 SETS; 1907 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 1908 } 1909 1910 result = op1 - op2d; 1911 if (SubOverflow (op1, op2d, result)) 1912 { 1913 SETS; 1914 result = POS (result) ? 0x80000000 : 0x7fffffff; 1915 } 1916 1917 state->Reg[BITS (12, 15)] = result; 1918 break; 1919 } 1920 } 1921 1922 if (state->is_v5) 1923 { 1924 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF) 1925 { 1926 /* ARM5 CLZ insn. */ 1927 ARMword op1 = state->Reg[BITS (0, 3)]; 1928 int result = 32; 1929 1930 if (op1) 1931 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1) 1932 result++; 1933 1934 state->Reg[BITS (12, 15)] = result; 1935 break; 1936 } 1937 } 1938 #ifdef MODET 1939 if (BITS (4, 7) == 0xB) 1940 { 1941 /* STRH immediate offset, write-back, down, pre indexed. */ 1942 SHPREDOWNWB (); 1943 break; 1944 } 1945 if (BITS (4, 7) == 0xD) 1946 { 1947 Handle_Load_Double (state, instr); 1948 break; 1949 } 1950 if (BITS (4, 7) == 0xF) 1951 { 1952 Handle_Store_Double (state, instr); 1953 break; 1954 } 1955 #endif 1956 if (DESTReg == 15) 1957 { 1958 /* MSR */ 1959 UNDEF_MSRPC; 1960 ARMul_FixSPSR (state, instr, DPRegRHS); 1961 } 1962 else 1963 { 1964 UNDEF_Test; 1965 } 1966 break; 1967 1968 case 0x17: /* CMNP reg */ 1969 #ifdef MODET 1970 if ((BITS (4, 7) & 0x9) == 0x9) 1971 /* LDR immediate offset, write-back, down, pre indexed. */ 1972 LHPREDOWNWB (); 1973 /* Continue with remaining instruction decoding. */ 1974 #endif 1975 if (DESTReg == 15) 1976 { 1977 #ifdef MODE32 1978 state->Cpsr = GETSPSR (state->Bank); 1979 ARMul_CPSRAltered (state); 1980 #else 1981 rhs = DPRegRHS; 1982 temp = LHS + rhs; 1983 SETR15PSR (temp); 1984 #endif 1985 break; 1986 } 1987 else 1988 { 1989 /* CMN reg. */ 1990 lhs = LHS; 1991 rhs = DPRegRHS; 1992 dest = lhs + rhs; 1993 ASSIGNZ (dest == 0); 1994 if ((lhs | rhs) >> 30) 1995 { 1996 /* Possible C,V,N to set. */ 1997 ASSIGNN (NEG (dest)); 1998 ARMul_AddCarry (state, lhs, rhs, dest); 1999 ARMul_AddOverflow (state, lhs, rhs, dest); 2000 } 2001 else 2002 { 2003 CLEARN; 2004 CLEARC; 2005 CLEARV; 2006 } 2007 } 2008 break; 2009 2010 case 0x18: /* ORR reg */ 2011 #ifdef MODET 2012 if (BITS (4, 11) == 0xB) 2013 { 2014 /* STRH register offset, no write-back, up, pre indexed. */ 2015 SHPREUP (); 2016 break; 2017 } 2018 if (BITS (4, 7) == 0xD) 2019 { 2020 Handle_Load_Double (state, instr); 2021 break; 2022 } 2023 if (BITS (4, 7) == 0xF) 2024 { 2025 Handle_Store_Double (state, instr); 2026 break; 2027 } 2028 #endif 2029 rhs = DPRegRHS; 2030 dest = LHS | rhs; 2031 WRITEDEST (dest); 2032 break; 2033 2034 case 0x19: /* ORRS reg */ 2035 #ifdef MODET 2036 if ((BITS (4, 11) & 0xF9) == 0x9) 2037 /* LDR register offset, no write-back, up, pre indexed. */ 2038 LHPREUP (); 2039 /* Continue with remaining instruction decoding. */ 2040 #endif 2041 rhs = DPSRegRHS; 2042 dest = LHS | rhs; 2043 WRITESDEST (dest); 2044 break; 2045 2046 case 0x1a: /* MOV reg */ 2047 #ifdef MODET 2048 if (BITS (4, 11) == 0xB) 2049 { 2050 /* STRH register offset, write-back, up, pre indexed. */ 2051 SHPREUPWB (); 2052 break; 2053 } 2054 if (BITS (4, 7) == 0xD) 2055 { 2056 Handle_Load_Double (state, instr); 2057 break; 2058 } 2059 if (BITS (4, 7) == 0xF) 2060 { 2061 Handle_Store_Double (state, instr); 2062 break; 2063 } 2064 #endif 2065 dest = DPRegRHS; 2066 WRITEDEST (dest); 2067 break; 2068 2069 case 0x1b: /* MOVS reg */ 2070 #ifdef MODET 2071 if ((BITS (4, 11) & 0xF9) == 0x9) 2072 /* LDR register offset, write-back, up, pre indexed. */ 2073 LHPREUPWB (); 2074 /* Continue with remaining instruction decoding. */ 2075 #endif 2076 dest = DPSRegRHS; 2077 WRITESDEST (dest); 2078 break; 2079 2080 case 0x1c: /* BIC reg */ 2081 #ifdef MODET 2082 if (BITS (4, 7) == 0xB) 2083 { 2084 /* STRH immediate offset, no write-back, up, pre indexed. */ 2085 SHPREUP (); 2086 break; 2087 } 2088 if (BITS (4, 7) == 0xD) 2089 { 2090 Handle_Load_Double (state, instr); 2091 break; 2092 } 2093 else if (BITS (4, 7) == 0xF) 2094 { 2095 Handle_Store_Double (state, instr); 2096 break; 2097 } 2098 #endif 2099 rhs = DPRegRHS; 2100 dest = LHS & ~rhs; 2101 WRITEDEST (dest); 2102 break; 2103 2104 case 0x1d: /* BICS reg */ 2105 #ifdef MODET 2106 if ((BITS (4, 7) & 0x9) == 0x9) 2107 /* LDR immediate offset, no write-back, up, pre indexed. */ 2108 LHPREUP (); 2109 /* Continue with instruction decoding. */ 2110 #endif 2111 rhs = DPSRegRHS; 2112 dest = LHS & ~rhs; 2113 WRITESDEST (dest); 2114 break; 2115 2116 case 0x1e: /* MVN reg */ 2117 #ifdef MODET 2118 if (BITS (4, 7) == 0xB) 2119 { 2120 /* STRH immediate offset, write-back, up, pre indexed. */ 2121 SHPREUPWB (); 2122 break; 2123 } 2124 if (BITS (4, 7) == 0xD) 2125 { 2126 Handle_Load_Double (state, instr); 2127 break; 2128 } 2129 if (BITS (4, 7) == 0xF) 2130 { 2131 Handle_Store_Double (state, instr); 2132 break; 2133 } 2134 #endif 2135 dest = ~DPRegRHS; 2136 WRITEDEST (dest); 2137 break; 2138 2139 case 0x1f: /* MVNS reg */ 2140 #ifdef MODET 2141 if ((BITS (4, 7) & 0x9) == 0x9) 2142 /* LDR immediate offset, write-back, up, pre indexed. */ 2143 LHPREUPWB (); 2144 /* Continue instruction decoding. */ 2145 #endif 2146 dest = ~DPSRegRHS; 2147 WRITESDEST (dest); 2148 break; 2149 2150 2151 /* Data Processing Immediate RHS Instructions. */ 2152 2153 case 0x20: /* AND immed */ 2154 dest = LHS & DPImmRHS; 2155 WRITEDEST (dest); 2156 break; 2157 2158 case 0x21: /* ANDS immed */ 2159 DPSImmRHS; 2160 dest = LHS & rhs; 2161 WRITESDEST (dest); 2162 break; 2163 2164 case 0x22: /* EOR immed */ 2165 dest = LHS ^ DPImmRHS; 2166 WRITEDEST (dest); 2167 break; 2168 2169 case 0x23: /* EORS immed */ 2170 DPSImmRHS; 2171 dest = LHS ^ rhs; 2172 WRITESDEST (dest); 2173 break; 2174 2175 case 0x24: /* SUB immed */ 2176 dest = LHS - DPImmRHS; 2177 WRITEDEST (dest); 2178 break; 2179 2180 case 0x25: /* SUBS immed */ 2181 lhs = LHS; 2182 rhs = DPImmRHS; 2183 dest = lhs - rhs; 2184 2185 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2186 { 2187 ARMul_SubCarry (state, lhs, rhs, dest); 2188 ARMul_SubOverflow (state, lhs, rhs, dest); 2189 } 2190 else 2191 { 2192 CLEARC; 2193 CLEARV; 2194 } 2195 WRITESDEST (dest); 2196 break; 2197 2198 case 0x26: /* RSB immed */ 2199 dest = DPImmRHS - LHS; 2200 WRITEDEST (dest); 2201 break; 2202 2203 case 0x27: /* RSBS immed */ 2204 lhs = LHS; 2205 rhs = DPImmRHS; 2206 dest = rhs - lhs; 2207 2208 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 2209 { 2210 ARMul_SubCarry (state, rhs, lhs, dest); 2211 ARMul_SubOverflow (state, rhs, lhs, dest); 2212 } 2213 else 2214 { 2215 CLEARC; 2216 CLEARV; 2217 } 2218 WRITESDEST (dest); 2219 break; 2220 2221 case 0x28: /* ADD immed */ 2222 dest = LHS + DPImmRHS; 2223 WRITEDEST (dest); 2224 break; 2225 2226 case 0x29: /* ADDS immed */ 2227 lhs = LHS; 2228 rhs = DPImmRHS; 2229 dest = lhs + rhs; 2230 ASSIGNZ (dest == 0); 2231 2232 if ((lhs | rhs) >> 30) 2233 { 2234 /* Possible C,V,N to set. */ 2235 ASSIGNN (NEG (dest)); 2236 ARMul_AddCarry (state, lhs, rhs, dest); 2237 ARMul_AddOverflow (state, lhs, rhs, dest); 2238 } 2239 else 2240 { 2241 CLEARN; 2242 CLEARC; 2243 CLEARV; 2244 } 2245 WRITESDEST (dest); 2246 break; 2247 2248 case 0x2a: /* ADC immed */ 2249 dest = LHS + DPImmRHS + CFLAG; 2250 WRITEDEST (dest); 2251 break; 2252 2253 case 0x2b: /* ADCS immed */ 2254 lhs = LHS; 2255 rhs = DPImmRHS; 2256 dest = lhs + rhs + CFLAG; 2257 ASSIGNZ (dest == 0); 2258 if ((lhs | rhs) >> 30) 2259 { 2260 /* Possible C,V,N to set. */ 2261 ASSIGNN (NEG (dest)); 2262 ARMul_AddCarry (state, lhs, rhs, dest); 2263 ARMul_AddOverflow (state, lhs, rhs, dest); 2264 } 2265 else 2266 { 2267 CLEARN; 2268 CLEARC; 2269 CLEARV; 2270 } 2271 WRITESDEST (dest); 2272 break; 2273 2274 case 0x2c: /* SBC immed */ 2275 dest = LHS - DPImmRHS - !CFLAG; 2276 WRITEDEST (dest); 2277 break; 2278 2279 case 0x2d: /* SBCS immed */ 2280 lhs = LHS; 2281 rhs = DPImmRHS; 2282 dest = lhs - rhs - !CFLAG; 2283 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2284 { 2285 ARMul_SubCarry (state, lhs, rhs, dest); 2286 ARMul_SubOverflow (state, lhs, rhs, dest); 2287 } 2288 else 2289 { 2290 CLEARC; 2291 CLEARV; 2292 } 2293 WRITESDEST (dest); 2294 break; 2295 2296 case 0x2e: /* RSC immed */ 2297 dest = DPImmRHS - LHS - !CFLAG; 2298 WRITEDEST (dest); 2299 break; 2300 2301 case 0x2f: /* RSCS immed */ 2302 lhs = LHS; 2303 rhs = DPImmRHS; 2304 dest = rhs - lhs - !CFLAG; 2305 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 2306 { 2307 ARMul_SubCarry (state, rhs, lhs, dest); 2308 ARMul_SubOverflow (state, rhs, lhs, dest); 2309 } 2310 else 2311 { 2312 CLEARC; 2313 CLEARV; 2314 } 2315 WRITESDEST (dest); 2316 break; 2317 2318 case 0x30: /* TST immed */ 2319 UNDEF_Test; 2320 break; 2321 2322 case 0x31: /* TSTP immed */ 2323 if (DESTReg == 15) 2324 { 2325 /* TSTP immed. */ 2326 #ifdef MODE32 2327 state->Cpsr = GETSPSR (state->Bank); 2328 ARMul_CPSRAltered (state); 2329 #else 2330 temp = LHS & DPImmRHS; 2331 SETR15PSR (temp); 2332 #endif 2333 } 2334 else 2335 { 2336 /* TST immed. */ 2337 DPSImmRHS; 2338 dest = LHS & rhs; 2339 ARMul_NegZero (state, dest); 2340 } 2341 break; 2342 2343 case 0x32: /* TEQ immed and MSR immed to CPSR */ 2344 if (DESTReg == 15) 2345 /* MSR immed to CPSR. */ 2346 ARMul_FixCPSR (state, instr, DPImmRHS); 2347 else 2348 UNDEF_Test; 2349 break; 2350 2351 case 0x33: /* TEQP immed */ 2352 if (DESTReg == 15) 2353 { 2354 /* TEQP immed. */ 2355 #ifdef MODE32 2356 state->Cpsr = GETSPSR (state->Bank); 2357 ARMul_CPSRAltered (state); 2358 #else 2359 temp = LHS ^ DPImmRHS; 2360 SETR15PSR (temp); 2361 #endif 2362 } 2363 else 2364 { 2365 DPSImmRHS; /* TEQ immed */ 2366 dest = LHS ^ rhs; 2367 ARMul_NegZero (state, dest); 2368 } 2369 break; 2370 2371 case 0x34: /* CMP immed */ 2372 UNDEF_Test; 2373 break; 2374 2375 case 0x35: /* CMPP immed */ 2376 if (DESTReg == 15) 2377 { 2378 /* CMPP immed. */ 2379 #ifdef MODE32 2380 state->Cpsr = GETSPSR (state->Bank); 2381 ARMul_CPSRAltered (state); 2382 #else 2383 temp = LHS - DPImmRHS; 2384 SETR15PSR (temp); 2385 #endif 2386 break; 2387 } 2388 else 2389 { 2390 /* CMP immed. */ 2391 lhs = LHS; 2392 rhs = DPImmRHS; 2393 dest = lhs - rhs; 2394 ARMul_NegZero (state, dest); 2395 2396 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2397 { 2398 ARMul_SubCarry (state, lhs, rhs, dest); 2399 ARMul_SubOverflow (state, lhs, rhs, dest); 2400 } 2401 else 2402 { 2403 CLEARC; 2404 CLEARV; 2405 } 2406 } 2407 break; 2408 2409 case 0x36: /* CMN immed and MSR immed to SPSR */ 2410 if (DESTReg == 15) 2411 ARMul_FixSPSR (state, instr, DPImmRHS); 2412 else 2413 UNDEF_Test; 2414 break; 2415 2416 case 0x37: /* CMNP immed. */ 2417 if (DESTReg == 15) 2418 { 2419 /* CMNP immed. */ 2420 #ifdef MODE32 2421 state->Cpsr = GETSPSR (state->Bank); 2422 ARMul_CPSRAltered (state); 2423 #else 2424 temp = LHS + DPImmRHS; 2425 SETR15PSR (temp); 2426 #endif 2427 break; 2428 } 2429 else 2430 { 2431 /* CMN immed. */ 2432 lhs = LHS; 2433 rhs = DPImmRHS; 2434 dest = lhs + rhs; 2435 ASSIGNZ (dest == 0); 2436 if ((lhs | rhs) >> 30) 2437 { 2438 /* Possible C,V,N to set. */ 2439 ASSIGNN (NEG (dest)); 2440 ARMul_AddCarry (state, lhs, rhs, dest); 2441 ARMul_AddOverflow (state, lhs, rhs, dest); 2442 } 2443 else 2444 { 2445 CLEARN; 2446 CLEARC; 2447 CLEARV; 2448 } 2449 } 2450 break; 2451 2452 case 0x38: /* ORR immed. */ 2453 dest = LHS | DPImmRHS; 2454 WRITEDEST (dest); 2455 break; 2456 2457 case 0x39: /* ORRS immed. */ 2458 DPSImmRHS; 2459 dest = LHS | rhs; 2460 WRITESDEST (dest); 2461 break; 2462 2463 case 0x3a: /* MOV immed. */ 2464 dest = DPImmRHS; 2465 WRITEDEST (dest); 2466 break; 2467 2468 case 0x3b: /* MOVS immed. */ 2469 DPSImmRHS; 2470 WRITESDEST (rhs); 2471 break; 2472 2473 case 0x3c: /* BIC immed. */ 2474 dest = LHS & ~DPImmRHS; 2475 WRITEDEST (dest); 2476 break; 2477 2478 case 0x3d: /* BICS immed. */ 2479 DPSImmRHS; 2480 dest = LHS & ~rhs; 2481 WRITESDEST (dest); 2482 break; 2483 2484 case 0x3e: /* MVN immed. */ 2485 dest = ~DPImmRHS; 2486 WRITEDEST (dest); 2487 break; 2488 2489 case 0x3f: /* MVNS immed. */ 2490 DPSImmRHS; 2491 WRITESDEST (~rhs); 2492 break; 2493 2494 2495 /* Single Data Transfer Immediate RHS Instructions. */ 2496 2497 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */ 2498 lhs = LHS; 2499 if (StoreWord (state, instr, lhs)) 2500 LSBase = lhs - LSImmRHS; 2501 break; 2502 2503 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */ 2504 lhs = LHS; 2505 if (LoadWord (state, instr, lhs)) 2506 LSBase = lhs - LSImmRHS; 2507 break; 2508 2509 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */ 2510 UNDEF_LSRBaseEQDestWb; 2511 UNDEF_LSRPCBaseWb; 2512 lhs = LHS; 2513 temp = lhs - LSImmRHS; 2514 state->NtransSig = LOW; 2515 if (StoreWord (state, instr, lhs)) 2516 LSBase = temp; 2517 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2518 break; 2519 2520 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */ 2521 UNDEF_LSRBaseEQDestWb; 2522 UNDEF_LSRPCBaseWb; 2523 lhs = LHS; 2524 state->NtransSig = LOW; 2525 if (LoadWord (state, instr, lhs)) 2526 LSBase = lhs - LSImmRHS; 2527 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2528 break; 2529 2530 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */ 2531 lhs = LHS; 2532 if (StoreByte (state, instr, lhs)) 2533 LSBase = lhs - LSImmRHS; 2534 break; 2535 2536 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */ 2537 lhs = LHS; 2538 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2539 LSBase = lhs - LSImmRHS; 2540 break; 2541 2542 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */ 2543 UNDEF_LSRBaseEQDestWb; 2544 UNDEF_LSRPCBaseWb; 2545 lhs = LHS; 2546 state->NtransSig = LOW; 2547 if (StoreByte (state, instr, lhs)) 2548 LSBase = lhs - LSImmRHS; 2549 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2550 break; 2551 2552 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */ 2553 UNDEF_LSRBaseEQDestWb; 2554 UNDEF_LSRPCBaseWb; 2555 lhs = LHS; 2556 state->NtransSig = LOW; 2557 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2558 LSBase = lhs - LSImmRHS; 2559 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2560 break; 2561 2562 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */ 2563 lhs = LHS; 2564 if (StoreWord (state, instr, lhs)) 2565 LSBase = lhs + LSImmRHS; 2566 break; 2567 2568 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */ 2569 lhs = LHS; 2570 if (LoadWord (state, instr, lhs)) 2571 LSBase = lhs + LSImmRHS; 2572 break; 2573 2574 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */ 2575 UNDEF_LSRBaseEQDestWb; 2576 UNDEF_LSRPCBaseWb; 2577 lhs = LHS; 2578 state->NtransSig = LOW; 2579 if (StoreWord (state, instr, lhs)) 2580 LSBase = lhs + LSImmRHS; 2581 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2582 break; 2583 2584 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */ 2585 UNDEF_LSRBaseEQDestWb; 2586 UNDEF_LSRPCBaseWb; 2587 lhs = LHS; 2588 state->NtransSig = LOW; 2589 if (LoadWord (state, instr, lhs)) 2590 LSBase = lhs + LSImmRHS; 2591 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2592 break; 2593 2594 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */ 2595 lhs = LHS; 2596 if (StoreByte (state, instr, lhs)) 2597 LSBase = lhs + LSImmRHS; 2598 break; 2599 2600 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */ 2601 lhs = LHS; 2602 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2603 LSBase = lhs + LSImmRHS; 2604 break; 2605 2606 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */ 2607 UNDEF_LSRBaseEQDestWb; 2608 UNDEF_LSRPCBaseWb; 2609 lhs = LHS; 2610 state->NtransSig = LOW; 2611 if (StoreByte (state, instr, lhs)) 2612 LSBase = lhs + LSImmRHS; 2613 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2614 break; 2615 2616 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */ 2617 UNDEF_LSRBaseEQDestWb; 2618 UNDEF_LSRPCBaseWb; 2619 lhs = LHS; 2620 state->NtransSig = LOW; 2621 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2622 LSBase = lhs + LSImmRHS; 2623 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2624 break; 2625 2626 2627 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */ 2628 (void) StoreWord (state, instr, LHS - LSImmRHS); 2629 break; 2630 2631 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */ 2632 (void) LoadWord (state, instr, LHS - LSImmRHS); 2633 break; 2634 2635 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */ 2636 UNDEF_LSRBaseEQDestWb; 2637 UNDEF_LSRPCBaseWb; 2638 temp = LHS - LSImmRHS; 2639 if (StoreWord (state, instr, temp)) 2640 LSBase = temp; 2641 break; 2642 2643 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */ 2644 UNDEF_LSRBaseEQDestWb; 2645 UNDEF_LSRPCBaseWb; 2646 temp = LHS - LSImmRHS; 2647 if (LoadWord (state, instr, temp)) 2648 LSBase = temp; 2649 break; 2650 2651 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */ 2652 (void) StoreByte (state, instr, LHS - LSImmRHS); 2653 break; 2654 2655 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */ 2656 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED); 2657 break; 2658 2659 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */ 2660 UNDEF_LSRBaseEQDestWb; 2661 UNDEF_LSRPCBaseWb; 2662 temp = LHS - LSImmRHS; 2663 if (StoreByte (state, instr, temp)) 2664 LSBase = temp; 2665 break; 2666 2667 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */ 2668 UNDEF_LSRBaseEQDestWb; 2669 UNDEF_LSRPCBaseWb; 2670 temp = LHS - LSImmRHS; 2671 if (LoadByte (state, instr, temp, LUNSIGNED)) 2672 LSBase = temp; 2673 break; 2674 2675 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */ 2676 (void) StoreWord (state, instr, LHS + LSImmRHS); 2677 break; 2678 2679 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */ 2680 (void) LoadWord (state, instr, LHS + LSImmRHS); 2681 break; 2682 2683 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */ 2684 UNDEF_LSRBaseEQDestWb; 2685 UNDEF_LSRPCBaseWb; 2686 temp = LHS + LSImmRHS; 2687 if (StoreWord (state, instr, temp)) 2688 LSBase = temp; 2689 break; 2690 2691 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */ 2692 UNDEF_LSRBaseEQDestWb; 2693 UNDEF_LSRPCBaseWb; 2694 temp = LHS + LSImmRHS; 2695 if (LoadWord (state, instr, temp)) 2696 LSBase = temp; 2697 break; 2698 2699 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */ 2700 (void) StoreByte (state, instr, LHS + LSImmRHS); 2701 break; 2702 2703 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */ 2704 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED); 2705 break; 2706 2707 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */ 2708 UNDEF_LSRBaseEQDestWb; 2709 UNDEF_LSRPCBaseWb; 2710 temp = LHS + LSImmRHS; 2711 if (StoreByte (state, instr, temp)) 2712 LSBase = temp; 2713 break; 2714 2715 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */ 2716 UNDEF_LSRBaseEQDestWb; 2717 UNDEF_LSRPCBaseWb; 2718 temp = LHS + LSImmRHS; 2719 if (LoadByte (state, instr, temp, LUNSIGNED)) 2720 LSBase = temp; 2721 break; 2722 2723 2724 /* Single Data Transfer Register RHS Instructions. */ 2725 2726 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */ 2727 if (BIT (4)) 2728 { 2729 ARMul_UndefInstr (state, instr); 2730 break; 2731 } 2732 UNDEF_LSRBaseEQOffWb; 2733 UNDEF_LSRBaseEQDestWb; 2734 UNDEF_LSRPCBaseWb; 2735 UNDEF_LSRPCOffWb; 2736 lhs = LHS; 2737 if (StoreWord (state, instr, lhs)) 2738 LSBase = lhs - LSRegRHS; 2739 break; 2740 2741 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */ 2742 if (BIT (4)) 2743 { 2744 #ifdef MODE32 2745 if (state->is_v6 2746 && handle_v6_insn (state, instr)) 2747 break; 2748 #endif 2749 ARMul_UndefInstr (state, instr); 2750 break; 2751 } 2752 UNDEF_LSRBaseEQOffWb; 2753 UNDEF_LSRBaseEQDestWb; 2754 UNDEF_LSRPCBaseWb; 2755 UNDEF_LSRPCOffWb; 2756 lhs = LHS; 2757 temp = lhs - LSRegRHS; 2758 if (LoadWord (state, instr, lhs)) 2759 LSBase = temp; 2760 break; 2761 2762 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */ 2763 if (BIT (4)) 2764 { 2765 #ifdef MODE32 2766 if (state->is_v6 2767 && handle_v6_insn (state, instr)) 2768 break; 2769 #endif 2770 ARMul_UndefInstr (state, instr); 2771 break; 2772 } 2773 UNDEF_LSRBaseEQOffWb; 2774 UNDEF_LSRBaseEQDestWb; 2775 UNDEF_LSRPCBaseWb; 2776 UNDEF_LSRPCOffWb; 2777 lhs = LHS; 2778 state->NtransSig = LOW; 2779 if (StoreWord (state, instr, lhs)) 2780 LSBase = lhs - LSRegRHS; 2781 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2782 break; 2783 2784 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */ 2785 if (BIT (4)) 2786 { 2787 #ifdef MODE32 2788 if (state->is_v6 2789 && handle_v6_insn (state, instr)) 2790 break; 2791 #endif 2792 ARMul_UndefInstr (state, instr); 2793 break; 2794 } 2795 UNDEF_LSRBaseEQOffWb; 2796 UNDEF_LSRBaseEQDestWb; 2797 UNDEF_LSRPCBaseWb; 2798 UNDEF_LSRPCOffWb; 2799 lhs = LHS; 2800 temp = lhs - LSRegRHS; 2801 state->NtransSig = LOW; 2802 if (LoadWord (state, instr, lhs)) 2803 LSBase = temp; 2804 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2805 break; 2806 2807 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */ 2808 if (BIT (4)) 2809 { 2810 ARMul_UndefInstr (state, instr); 2811 break; 2812 } 2813 UNDEF_LSRBaseEQOffWb; 2814 UNDEF_LSRBaseEQDestWb; 2815 UNDEF_LSRPCBaseWb; 2816 UNDEF_LSRPCOffWb; 2817 lhs = LHS; 2818 if (StoreByte (state, instr, lhs)) 2819 LSBase = lhs - LSRegRHS; 2820 break; 2821 2822 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */ 2823 if (BIT (4)) 2824 { 2825 #ifdef MODE32 2826 if (state->is_v6 2827 && handle_v6_insn (state, instr)) 2828 break; 2829 #endif 2830 ARMul_UndefInstr (state, instr); 2831 break; 2832 } 2833 UNDEF_LSRBaseEQOffWb; 2834 UNDEF_LSRBaseEQDestWb; 2835 UNDEF_LSRPCBaseWb; 2836 UNDEF_LSRPCOffWb; 2837 lhs = LHS; 2838 temp = lhs - LSRegRHS; 2839 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2840 LSBase = temp; 2841 break; 2842 2843 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */ 2844 if (BIT (4)) 2845 { 2846 #ifdef MODE32 2847 if (state->is_v6 2848 && handle_v6_insn (state, instr)) 2849 break; 2850 #endif 2851 ARMul_UndefInstr (state, instr); 2852 break; 2853 } 2854 UNDEF_LSRBaseEQOffWb; 2855 UNDEF_LSRBaseEQDestWb; 2856 UNDEF_LSRPCBaseWb; 2857 UNDEF_LSRPCOffWb; 2858 lhs = LHS; 2859 state->NtransSig = LOW; 2860 if (StoreByte (state, instr, lhs)) 2861 LSBase = lhs - LSRegRHS; 2862 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2863 break; 2864 2865 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */ 2866 if (BIT (4)) 2867 { 2868 #ifdef MODE32 2869 if (state->is_v6 2870 && handle_v6_insn (state, instr)) 2871 break; 2872 #endif 2873 ARMul_UndefInstr (state, instr); 2874 break; 2875 } 2876 UNDEF_LSRBaseEQOffWb; 2877 UNDEF_LSRBaseEQDestWb; 2878 UNDEF_LSRPCBaseWb; 2879 UNDEF_LSRPCOffWb; 2880 lhs = LHS; 2881 temp = lhs - LSRegRHS; 2882 state->NtransSig = LOW; 2883 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2884 LSBase = temp; 2885 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2886 break; 2887 2888 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 2889 if (BIT (4)) 2890 { 2891 #ifdef MODE32 2892 if (state->is_v6 2893 && handle_v6_insn (state, instr)) 2894 break; 2895 #endif 2896 ARMul_UndefInstr (state, instr); 2897 break; 2898 } 2899 UNDEF_LSRBaseEQOffWb; 2900 UNDEF_LSRBaseEQDestWb; 2901 UNDEF_LSRPCBaseWb; 2902 UNDEF_LSRPCOffWb; 2903 lhs = LHS; 2904 if (StoreWord (state, instr, lhs)) 2905 LSBase = lhs + LSRegRHS; 2906 break; 2907 2908 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */ 2909 if (BIT (4)) 2910 { 2911 ARMul_UndefInstr (state, instr); 2912 break; 2913 } 2914 UNDEF_LSRBaseEQOffWb; 2915 UNDEF_LSRBaseEQDestWb; 2916 UNDEF_LSRPCBaseWb; 2917 UNDEF_LSRPCOffWb; 2918 lhs = LHS; 2919 temp = lhs + LSRegRHS; 2920 if (LoadWord (state, instr, lhs)) 2921 LSBase = temp; 2922 break; 2923 2924 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */ 2925 if (BIT (4)) 2926 { 2927 #ifdef MODE32 2928 if (state->is_v6 2929 && handle_v6_insn (state, instr)) 2930 break; 2931 #endif 2932 ARMul_UndefInstr (state, instr); 2933 break; 2934 } 2935 UNDEF_LSRBaseEQOffWb; 2936 UNDEF_LSRBaseEQDestWb; 2937 UNDEF_LSRPCBaseWb; 2938 UNDEF_LSRPCOffWb; 2939 lhs = LHS; 2940 state->NtransSig = LOW; 2941 if (StoreWord (state, instr, lhs)) 2942 LSBase = lhs + LSRegRHS; 2943 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2944 break; 2945 2946 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */ 2947 if (BIT (4)) 2948 { 2949 #ifdef MODE32 2950 if (state->is_v6 2951 && handle_v6_insn (state, instr)) 2952 break; 2953 #endif 2954 ARMul_UndefInstr (state, instr); 2955 break; 2956 } 2957 UNDEF_LSRBaseEQOffWb; 2958 UNDEF_LSRBaseEQDestWb; 2959 UNDEF_LSRPCBaseWb; 2960 UNDEF_LSRPCOffWb; 2961 lhs = LHS; 2962 temp = lhs + LSRegRHS; 2963 state->NtransSig = LOW; 2964 if (LoadWord (state, instr, lhs)) 2965 LSBase = temp; 2966 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2967 break; 2968 2969 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */ 2970 if (BIT (4)) 2971 { 2972 #ifdef MODE32 2973 if (state->is_v6 2974 && handle_v6_insn (state, instr)) 2975 break; 2976 #endif 2977 ARMul_UndefInstr (state, instr); 2978 break; 2979 } 2980 UNDEF_LSRBaseEQOffWb; 2981 UNDEF_LSRBaseEQDestWb; 2982 UNDEF_LSRPCBaseWb; 2983 UNDEF_LSRPCOffWb; 2984 lhs = LHS; 2985 if (StoreByte (state, instr, lhs)) 2986 LSBase = lhs + LSRegRHS; 2987 break; 2988 2989 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */ 2990 if (BIT (4)) 2991 { 2992 ARMul_UndefInstr (state, instr); 2993 break; 2994 } 2995 UNDEF_LSRBaseEQOffWb; 2996 UNDEF_LSRBaseEQDestWb; 2997 UNDEF_LSRPCBaseWb; 2998 UNDEF_LSRPCOffWb; 2999 lhs = LHS; 3000 temp = lhs + LSRegRHS; 3001 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3002 LSBase = temp; 3003 break; 3004 3005 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */ 3006 if (BIT (4)) 3007 { 3008 #ifdef MODE32 3009 if (state->is_v6 3010 && handle_v6_insn (state, instr)) 3011 break; 3012 #endif 3013 ARMul_UndefInstr (state, instr); 3014 break; 3015 } 3016 UNDEF_LSRBaseEQOffWb; 3017 UNDEF_LSRBaseEQDestWb; 3018 UNDEF_LSRPCBaseWb; 3019 UNDEF_LSRPCOffWb; 3020 lhs = LHS; 3021 state->NtransSig = LOW; 3022 if (StoreByte (state, instr, lhs)) 3023 LSBase = lhs + LSRegRHS; 3024 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3025 break; 3026 3027 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */ 3028 if (BIT (4)) 3029 { 3030 #ifdef MODE32 3031 if (state->is_v6 3032 && handle_v6_insn (state, instr)) 3033 break; 3034 #endif 3035 ARMul_UndefInstr (state, instr); 3036 break; 3037 } 3038 UNDEF_LSRBaseEQOffWb; 3039 UNDEF_LSRBaseEQDestWb; 3040 UNDEF_LSRPCBaseWb; 3041 UNDEF_LSRPCOffWb; 3042 lhs = LHS; 3043 temp = lhs + LSRegRHS; 3044 state->NtransSig = LOW; 3045 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3046 LSBase = temp; 3047 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3048 break; 3049 3050 3051 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */ 3052 if (BIT (4)) 3053 { 3054 #ifdef MODE32 3055 if (state->is_v6 3056 && handle_v6_insn (state, instr)) 3057 break; 3058 #endif 3059 ARMul_UndefInstr (state, instr); 3060 break; 3061 } 3062 (void) StoreWord (state, instr, LHS - LSRegRHS); 3063 break; 3064 3065 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */ 3066 if (BIT (4)) 3067 { 3068 ARMul_UndefInstr (state, instr); 3069 break; 3070 } 3071 (void) LoadWord (state, instr, LHS - LSRegRHS); 3072 break; 3073 3074 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */ 3075 if (BIT (4)) 3076 { 3077 ARMul_UndefInstr (state, instr); 3078 break; 3079 } 3080 UNDEF_LSRBaseEQOffWb; 3081 UNDEF_LSRBaseEQDestWb; 3082 UNDEF_LSRPCBaseWb; 3083 UNDEF_LSRPCOffWb; 3084 temp = LHS - LSRegRHS; 3085 if (StoreWord (state, instr, temp)) 3086 LSBase = temp; 3087 break; 3088 3089 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */ 3090 if (BIT (4)) 3091 { 3092 ARMul_UndefInstr (state, instr); 3093 break; 3094 } 3095 UNDEF_LSRBaseEQOffWb; 3096 UNDEF_LSRBaseEQDestWb; 3097 UNDEF_LSRPCBaseWb; 3098 UNDEF_LSRPCOffWb; 3099 temp = LHS - LSRegRHS; 3100 if (LoadWord (state, instr, temp)) 3101 LSBase = temp; 3102 break; 3103 3104 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */ 3105 if (BIT (4)) 3106 { 3107 #ifdef MODE32 3108 if (state->is_v6 3109 && handle_v6_insn (state, instr)) 3110 break; 3111 #endif 3112 ARMul_UndefInstr (state, instr); 3113 break; 3114 } 3115 (void) StoreByte (state, instr, LHS - LSRegRHS); 3116 break; 3117 3118 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */ 3119 if (BIT (4)) 3120 { 3121 #ifdef MODE32 3122 if (state->is_v6 3123 && handle_v6_insn (state, instr)) 3124 break; 3125 #endif 3126 ARMul_UndefInstr (state, instr); 3127 break; 3128 } 3129 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED); 3130 break; 3131 3132 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */ 3133 if (BIT (4)) 3134 { 3135 ARMul_UndefInstr (state, instr); 3136 break; 3137 } 3138 UNDEF_LSRBaseEQOffWb; 3139 UNDEF_LSRBaseEQDestWb; 3140 UNDEF_LSRPCBaseWb; 3141 UNDEF_LSRPCOffWb; 3142 temp = LHS - LSRegRHS; 3143 if (StoreByte (state, instr, temp)) 3144 LSBase = temp; 3145 break; 3146 3147 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */ 3148 if (BIT (4)) 3149 { 3150 ARMul_UndefInstr (state, instr); 3151 break; 3152 } 3153 UNDEF_LSRBaseEQOffWb; 3154 UNDEF_LSRBaseEQDestWb; 3155 UNDEF_LSRPCBaseWb; 3156 UNDEF_LSRPCOffWb; 3157 temp = LHS - LSRegRHS; 3158 if (LoadByte (state, instr, temp, LUNSIGNED)) 3159 LSBase = temp; 3160 break; 3161 3162 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */ 3163 if (BIT (4)) 3164 { 3165 #ifdef MODE32 3166 if (state->is_v6 3167 && handle_v6_insn (state, instr)) 3168 break; 3169 #endif 3170 ARMul_UndefInstr (state, instr); 3171 break; 3172 } 3173 (void) StoreWord (state, instr, LHS + LSRegRHS); 3174 break; 3175 3176 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */ 3177 if (BIT (4)) 3178 { 3179 ARMul_UndefInstr (state, instr); 3180 break; 3181 } 3182 (void) LoadWord (state, instr, LHS + LSRegRHS); 3183 break; 3184 3185 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */ 3186 if (BIT (4)) 3187 { 3188 #ifdef MODE32 3189 if (state->is_v6 3190 && handle_v6_insn (state, instr)) 3191 break; 3192 #endif 3193 ARMul_UndefInstr (state, instr); 3194 break; 3195 } 3196 UNDEF_LSRBaseEQOffWb; 3197 UNDEF_LSRBaseEQDestWb; 3198 UNDEF_LSRPCBaseWb; 3199 UNDEF_LSRPCOffWb; 3200 temp = LHS + LSRegRHS; 3201 if (StoreWord (state, instr, temp)) 3202 LSBase = temp; 3203 break; 3204 3205 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */ 3206 if (BIT (4)) 3207 { 3208 ARMul_UndefInstr (state, instr); 3209 break; 3210 } 3211 UNDEF_LSRBaseEQOffWb; 3212 UNDEF_LSRBaseEQDestWb; 3213 UNDEF_LSRPCBaseWb; 3214 UNDEF_LSRPCOffWb; 3215 temp = LHS + LSRegRHS; 3216 if (LoadWord (state, instr, temp)) 3217 LSBase = temp; 3218 break; 3219 3220 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */ 3221 if (BIT (4)) 3222 { 3223 #ifdef MODE32 3224 if (state->is_v6 3225 && handle_v6_insn (state, instr)) 3226 break; 3227 #endif 3228 ARMul_UndefInstr (state, instr); 3229 break; 3230 } 3231 (void) StoreByte (state, instr, LHS + LSRegRHS); 3232 break; 3233 3234 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */ 3235 if (BIT (4)) 3236 { 3237 ARMul_UndefInstr (state, instr); 3238 break; 3239 } 3240 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED); 3241 break; 3242 3243 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */ 3244 if (BIT (4)) 3245 { 3246 ARMul_UndefInstr (state, instr); 3247 break; 3248 } 3249 UNDEF_LSRBaseEQOffWb; 3250 UNDEF_LSRBaseEQDestWb; 3251 UNDEF_LSRPCBaseWb; 3252 UNDEF_LSRPCOffWb; 3253 temp = LHS + LSRegRHS; 3254 if (StoreByte (state, instr, temp)) 3255 LSBase = temp; 3256 break; 3257 3258 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ 3259 if (BIT (4)) 3260 { 3261 /* Check for the special breakpoint opcode. 3262 This value should correspond to the value defined 3263 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */ 3264 if (BITS (0, 19) == 0xfdefe) 3265 { 3266 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint)) 3267 ARMul_Abort (state, ARMul_SWIV); 3268 } 3269 else 3270 ARMul_UndefInstr (state, instr); 3271 break; 3272 } 3273 UNDEF_LSRBaseEQOffWb; 3274 UNDEF_LSRBaseEQDestWb; 3275 UNDEF_LSRPCBaseWb; 3276 UNDEF_LSRPCOffWb; 3277 temp = LHS + LSRegRHS; 3278 if (LoadByte (state, instr, temp, LUNSIGNED)) 3279 LSBase = temp; 3280 break; 3281 3282 3283 /* Multiple Data Transfer Instructions. */ 3284 3285 case 0x80: /* Store, No WriteBack, Post Dec. */ 3286 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3287 break; 3288 3289 case 0x81: /* Load, No WriteBack, Post Dec. */ 3290 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3291 break; 3292 3293 case 0x82: /* Store, WriteBack, Post Dec. */ 3294 temp = LSBase - LSMNumRegs; 3295 STOREMULT (instr, temp + 4L, temp); 3296 break; 3297 3298 case 0x83: /* Load, WriteBack, Post Dec. */ 3299 temp = LSBase - LSMNumRegs; 3300 LOADMULT (instr, temp + 4L, temp); 3301 break; 3302 3303 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */ 3304 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3305 break; 3306 3307 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */ 3308 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3309 break; 3310 3311 case 0x86: /* Store, Flags, WriteBack, Post Dec. */ 3312 temp = LSBase - LSMNumRegs; 3313 STORESMULT (instr, temp + 4L, temp); 3314 break; 3315 3316 case 0x87: /* Load, Flags, WriteBack, Post Dec. */ 3317 temp = LSBase - LSMNumRegs; 3318 LOADSMULT (instr, temp + 4L, temp); 3319 break; 3320 3321 case 0x88: /* Store, No WriteBack, Post Inc. */ 3322 STOREMULT (instr, LSBase, 0L); 3323 break; 3324 3325 case 0x89: /* Load, No WriteBack, Post Inc. */ 3326 LOADMULT (instr, LSBase, 0L); 3327 break; 3328 3329 case 0x8a: /* Store, WriteBack, Post Inc. */ 3330 temp = LSBase; 3331 STOREMULT (instr, temp, temp + LSMNumRegs); 3332 break; 3333 3334 case 0x8b: /* Load, WriteBack, Post Inc. */ 3335 temp = LSBase; 3336 LOADMULT (instr, temp, temp + LSMNumRegs); 3337 break; 3338 3339 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */ 3340 STORESMULT (instr, LSBase, 0L); 3341 break; 3342 3343 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */ 3344 LOADSMULT (instr, LSBase, 0L); 3345 break; 3346 3347 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */ 3348 temp = LSBase; 3349 STORESMULT (instr, temp, temp + LSMNumRegs); 3350 break; 3351 3352 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */ 3353 temp = LSBase; 3354 LOADSMULT (instr, temp, temp + LSMNumRegs); 3355 break; 3356 3357 case 0x90: /* Store, No WriteBack, Pre Dec. */ 3358 STOREMULT (instr, LSBase - LSMNumRegs, 0L); 3359 break; 3360 3361 case 0x91: /* Load, No WriteBack, Pre Dec. */ 3362 LOADMULT (instr, LSBase - LSMNumRegs, 0L); 3363 break; 3364 3365 case 0x92: /* Store, WriteBack, Pre Dec. */ 3366 temp = LSBase - LSMNumRegs; 3367 STOREMULT (instr, temp, temp); 3368 break; 3369 3370 case 0x93: /* Load, WriteBack, Pre Dec. */ 3371 temp = LSBase - LSMNumRegs; 3372 LOADMULT (instr, temp, temp); 3373 break; 3374 3375 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */ 3376 STORESMULT (instr, LSBase - LSMNumRegs, 0L); 3377 break; 3378 3379 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */ 3380 LOADSMULT (instr, LSBase - LSMNumRegs, 0L); 3381 break; 3382 3383 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */ 3384 temp = LSBase - LSMNumRegs; 3385 STORESMULT (instr, temp, temp); 3386 break; 3387 3388 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */ 3389 temp = LSBase - LSMNumRegs; 3390 LOADSMULT (instr, temp, temp); 3391 break; 3392 3393 case 0x98: /* Store, No WriteBack, Pre Inc. */ 3394 STOREMULT (instr, LSBase + 4L, 0L); 3395 break; 3396 3397 case 0x99: /* Load, No WriteBack, Pre Inc. */ 3398 LOADMULT (instr, LSBase + 4L, 0L); 3399 break; 3400 3401 case 0x9a: /* Store, WriteBack, Pre Inc. */ 3402 temp = LSBase; 3403 STOREMULT (instr, temp + 4L, temp + LSMNumRegs); 3404 break; 3405 3406 case 0x9b: /* Load, WriteBack, Pre Inc. */ 3407 temp = LSBase; 3408 LOADMULT (instr, temp + 4L, temp + LSMNumRegs); 3409 break; 3410 3411 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */ 3412 STORESMULT (instr, LSBase + 4L, 0L); 3413 break; 3414 3415 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */ 3416 LOADSMULT (instr, LSBase + 4L, 0L); 3417 break; 3418 3419 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */ 3420 temp = LSBase; 3421 STORESMULT (instr, temp + 4L, temp + LSMNumRegs); 3422 break; 3423 3424 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */ 3425 temp = LSBase; 3426 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs); 3427 break; 3428 3429 3430 /* Branch forward. */ 3431 case 0xa0: 3432 case 0xa1: 3433 case 0xa2: 3434 case 0xa3: 3435 case 0xa4: 3436 case 0xa5: 3437 case 0xa6: 3438 case 0xa7: 3439 state->Reg[15] = pc + 8 + POSBRANCH; 3440 FLUSHPIPE; 3441 break; 3442 3443 3444 /* Branch backward. */ 3445 case 0xa8: 3446 case 0xa9: 3447 case 0xaa: 3448 case 0xab: 3449 case 0xac: 3450 case 0xad: 3451 case 0xae: 3452 case 0xaf: 3453 state->Reg[15] = pc + 8 + NEGBRANCH; 3454 FLUSHPIPE; 3455 break; 3456 3457 3458 /* Branch and Link forward. */ 3459 case 0xb0: 3460 case 0xb1: 3461 case 0xb2: 3462 case 0xb3: 3463 case 0xb4: 3464 case 0xb5: 3465 case 0xb6: 3466 case 0xb7: 3467 /* Put PC into Link. */ 3468 #ifdef MODE32 3469 state->Reg[14] = pc + 4; 3470 #else 3471 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 3472 #endif 3473 state->Reg[15] = pc + 8 + POSBRANCH; 3474 FLUSHPIPE; 3475 break; 3476 3477 3478 /* Branch and Link backward. */ 3479 case 0xb8: 3480 case 0xb9: 3481 case 0xba: 3482 case 0xbb: 3483 case 0xbc: 3484 case 0xbd: 3485 case 0xbe: 3486 case 0xbf: 3487 /* Put PC into Link. */ 3488 #ifdef MODE32 3489 state->Reg[14] = pc + 4; 3490 #else 3491 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 3492 #endif 3493 state->Reg[15] = pc + 8 + NEGBRANCH; 3494 FLUSHPIPE; 3495 break; 3496 3497 3498 /* Co-Processor Data Transfers. */ 3499 case 0xc4: 3500 if (state->is_v5) 3501 { 3502 /* Reading from R15 is UNPREDICTABLE. */ 3503 if (BITS (12, 15) == 15 || BITS (16, 19) == 15) 3504 ARMul_UndefInstr (state, instr); 3505 /* Is access to coprocessor 0 allowed ? */ 3506 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 3507 ARMul_UndefInstr (state, instr); 3508 /* Special treatment for XScale coprocessors. */ 3509 else if (state->is_XScale) 3510 { 3511 /* Only opcode 0 is supported. */ 3512 if (BITS (4, 7) != 0x00) 3513 ARMul_UndefInstr (state, instr); 3514 /* Only coporcessor 0 is supported. */ 3515 else if (CPNum != 0x00) 3516 ARMul_UndefInstr (state, instr); 3517 /* Only accumulator 0 is supported. */ 3518 else if (BITS (0, 3) != 0x00) 3519 ARMul_UndefInstr (state, instr); 3520 else 3521 { 3522 /* XScale MAR insn. Move two registers into accumulator. */ 3523 state->Accumulator = state->Reg[BITS (12, 15)]; 3524 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32; 3525 } 3526 } 3527 else 3528 /* FIXME: Not sure what to do for other v5 processors. */ 3529 ARMul_UndefInstr (state, instr); 3530 break; 3531 } 3532 /* Drop through. */ 3533 3534 case 0xc0: /* Store , No WriteBack , Post Dec. */ 3535 ARMul_STC (state, instr, LHS); 3536 break; 3537 3538 case 0xc5: 3539 if (state->is_v5) 3540 { 3541 /* Writes to R15 are UNPREDICATABLE. */ 3542 if (DESTReg == 15 || LHSReg == 15) 3543 ARMul_UndefInstr (state, instr); 3544 /* Is access to the coprocessor allowed ? */ 3545 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 3546 ARMul_UndefInstr (state, instr); 3547 /* Special handling for XScale coprcoessors. */ 3548 else if (state->is_XScale) 3549 { 3550 /* Only opcode 0 is supported. */ 3551 if (BITS (4, 7) != 0x00) 3552 ARMul_UndefInstr (state, instr); 3553 /* Only coprocessor 0 is supported. */ 3554 else if (CPNum != 0x00) 3555 ARMul_UndefInstr (state, instr); 3556 /* Only accumulator 0 is supported. */ 3557 else if (BITS (0, 3) != 0x00) 3558 ARMul_UndefInstr (state, instr); 3559 else 3560 { 3561 /* XScale MRA insn. Move accumulator into two registers. */ 3562 ARMword t1 = (state->Accumulator >> 32) & 255; 3563 3564 if (t1 & 128) 3565 t1 -= 256; 3566 3567 state->Reg[BITS (12, 15)] = state->Accumulator; 3568 state->Reg[BITS (16, 19)] = t1; 3569 break; 3570 } 3571 } 3572 else 3573 /* FIXME: Not sure what to do for other v5 processors. */ 3574 ARMul_UndefInstr (state, instr); 3575 break; 3576 } 3577 /* Drop through. */ 3578 3579 case 0xc1: /* Load , No WriteBack , Post Dec. */ 3580 ARMul_LDC (state, instr, LHS); 3581 break; 3582 3583 case 0xc2: 3584 case 0xc6: /* Store , WriteBack , Post Dec. */ 3585 lhs = LHS; 3586 state->Base = lhs - LSCOff; 3587 ARMul_STC (state, instr, lhs); 3588 break; 3589 3590 case 0xc3: 3591 case 0xc7: /* Load , WriteBack , Post Dec. */ 3592 lhs = LHS; 3593 state->Base = lhs - LSCOff; 3594 ARMul_LDC (state, instr, lhs); 3595 break; 3596 3597 case 0xc8: 3598 case 0xcc: /* Store , No WriteBack , Post Inc. */ 3599 ARMul_STC (state, instr, LHS); 3600 break; 3601 3602 case 0xc9: 3603 case 0xcd: /* Load , No WriteBack , Post Inc. */ 3604 ARMul_LDC (state, instr, LHS); 3605 break; 3606 3607 case 0xca: 3608 case 0xce: /* Store , WriteBack , Post Inc. */ 3609 lhs = LHS; 3610 state->Base = lhs + LSCOff; 3611 ARMul_STC (state, instr, LHS); 3612 break; 3613 3614 case 0xcb: 3615 case 0xcf: /* Load , WriteBack , Post Inc. */ 3616 lhs = LHS; 3617 state->Base = lhs + LSCOff; 3618 ARMul_LDC (state, instr, LHS); 3619 break; 3620 3621 case 0xd0: 3622 case 0xd4: /* Store , No WriteBack , Pre Dec. */ 3623 ARMul_STC (state, instr, LHS - LSCOff); 3624 break; 3625 3626 case 0xd1: 3627 case 0xd5: /* Load , No WriteBack , Pre Dec. */ 3628 ARMul_LDC (state, instr, LHS - LSCOff); 3629 break; 3630 3631 case 0xd2: 3632 case 0xd6: /* Store , WriteBack , Pre Dec. */ 3633 lhs = LHS - LSCOff; 3634 state->Base = lhs; 3635 ARMul_STC (state, instr, lhs); 3636 break; 3637 3638 case 0xd3: 3639 case 0xd7: /* Load , WriteBack , Pre Dec. */ 3640 lhs = LHS - LSCOff; 3641 state->Base = lhs; 3642 ARMul_LDC (state, instr, lhs); 3643 break; 3644 3645 case 0xd8: 3646 case 0xdc: /* Store , No WriteBack , Pre Inc. */ 3647 ARMul_STC (state, instr, LHS + LSCOff); 3648 break; 3649 3650 case 0xd9: 3651 case 0xdd: /* Load , No WriteBack , Pre Inc. */ 3652 ARMul_LDC (state, instr, LHS + LSCOff); 3653 break; 3654 3655 case 0xda: 3656 case 0xde: /* Store , WriteBack , Pre Inc. */ 3657 lhs = LHS + LSCOff; 3658 state->Base = lhs; 3659 ARMul_STC (state, instr, lhs); 3660 break; 3661 3662 case 0xdb: 3663 case 0xdf: /* Load , WriteBack , Pre Inc. */ 3664 lhs = LHS + LSCOff; 3665 state->Base = lhs; 3666 ARMul_LDC (state, instr, lhs); 3667 break; 3668 3669 3670 /* Co-Processor Register Transfers (MCR) and Data Ops. */ 3671 3672 case 0xe2: 3673 if (! CP_ACCESS_ALLOWED (state, CPNum)) 3674 { 3675 ARMul_UndefInstr (state, instr); 3676 break; 3677 } 3678 if (state->is_XScale) 3679 switch (BITS (18, 19)) 3680 { 3681 case 0x0: 3682 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 3683 { 3684 /* XScale MIA instruction. Signed multiplication of 3685 two 32 bit values and addition to 40 bit accumulator. */ 3686 ARMsdword Rm = state->Reg[MULLHSReg]; 3687 ARMsdword Rs = state->Reg[MULACCReg]; 3688 3689 if (Rm & (1 << 31)) 3690 Rm -= 1ULL << 32; 3691 if (Rs & (1 << 31)) 3692 Rs -= 1ULL << 32; 3693 state->Accumulator += Rm * Rs; 3694 goto donext; 3695 } 3696 break; 3697 3698 case 0x2: 3699 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 3700 { 3701 /* XScale MIAPH instruction. */ 3702 ARMword t1 = state->Reg[MULLHSReg] >> 16; 3703 ARMword t2 = state->Reg[MULACCReg] >> 16; 3704 ARMword t3 = state->Reg[MULLHSReg] & 0xffff; 3705 ARMword t4 = state->Reg[MULACCReg] & 0xffff; 3706 ARMsdword t5; 3707 3708 if (t1 & (1 << 15)) 3709 t1 -= 1 << 16; 3710 if (t2 & (1 << 15)) 3711 t2 -= 1 << 16; 3712 if (t3 & (1 << 15)) 3713 t3 -= 1 << 16; 3714 if (t4 & (1 << 15)) 3715 t4 -= 1 << 16; 3716 t1 *= t2; 3717 t5 = t1; 3718 if (t5 & (1 << 31)) 3719 t5 -= 1ULL << 32; 3720 state->Accumulator += t5; 3721 t3 *= t4; 3722 t5 = t3; 3723 if (t5 & (1 << 31)) 3724 t5 -= 1ULL << 32; 3725 state->Accumulator += t5; 3726 goto donext; 3727 } 3728 break; 3729 3730 case 0x3: 3731 if (BITS (4, 11) == 1) 3732 { 3733 /* XScale MIAxy instruction. */ 3734 ARMword t1; 3735 ARMword t2; 3736 ARMsdword t5; 3737 3738 if (BIT (17)) 3739 t1 = state->Reg[MULLHSReg] >> 16; 3740 else 3741 t1 = state->Reg[MULLHSReg] & 0xffff; 3742 3743 if (BIT (16)) 3744 t2 = state->Reg[MULACCReg] >> 16; 3745 else 3746 t2 = state->Reg[MULACCReg] & 0xffff; 3747 3748 if (t1 & (1 << 15)) 3749 t1 -= 1 << 16; 3750 if (t2 & (1 << 15)) 3751 t2 -= 1 << 16; 3752 t1 *= t2; 3753 t5 = t1; 3754 if (t5 & (1 << 31)) 3755 t5 -= 1ULL << 32; 3756 state->Accumulator += t5; 3757 goto donext; 3758 } 3759 break; 3760 3761 default: 3762 break; 3763 } 3764 /* Drop through. */ 3765 3766 case 0xe0: 3767 case 0xe4: 3768 case 0xe6: 3769 case 0xe8: 3770 case 0xea: 3771 case 0xec: 3772 case 0xee: 3773 if (BIT (4)) 3774 { 3775 /* MCR. */ 3776 if (DESTReg == 15) 3777 { 3778 UNDEF_MCRPC; 3779 #ifdef MODE32 3780 ARMul_MCR (state, instr, state->Reg[15] + isize); 3781 #else 3782 ARMul_MCR (state, instr, ECC | ER15INT | EMODE | 3783 ((state->Reg[15] + isize) & R15PCBITS)); 3784 #endif 3785 } 3786 else 3787 ARMul_MCR (state, instr, DEST); 3788 } 3789 else 3790 /* CDP Part 1. */ 3791 ARMul_CDP (state, instr); 3792 break; 3793 3794 3795 /* Co-Processor Register Transfers (MRC) and Data Ops. */ 3796 case 0xe1: 3797 case 0xe3: 3798 case 0xe5: 3799 case 0xe7: 3800 case 0xe9: 3801 case 0xeb: 3802 case 0xed: 3803 case 0xef: 3804 if (BIT (4)) 3805 { 3806 /* MRC */ 3807 temp = ARMul_MRC (state, instr); 3808 if (DESTReg == 15) 3809 { 3810 ASSIGNN ((temp & NBIT) != 0); 3811 ASSIGNZ ((temp & ZBIT) != 0); 3812 ASSIGNC ((temp & CBIT) != 0); 3813 ASSIGNV ((temp & VBIT) != 0); 3814 } 3815 else 3816 DEST = temp; 3817 } 3818 else 3819 /* CDP Part 2. */ 3820 ARMul_CDP (state, instr); 3821 break; 3822 3823 3824 /* SWI instruction. */ 3825 case 0xf0: 3826 case 0xf1: 3827 case 0xf2: 3828 case 0xf3: 3829 case 0xf4: 3830 case 0xf5: 3831 case 0xf6: 3832 case 0xf7: 3833 case 0xf8: 3834 case 0xf9: 3835 case 0xfa: 3836 case 0xfb: 3837 case 0xfc: 3838 case 0xfd: 3839 case 0xfe: 3840 case 0xff: 3841 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) 3842 { 3843 /* A prefetch abort. */ 3844 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); 3845 ARMul_Abort (state, ARMul_PrefetchAbortV); 3846 break; 3847 } 3848 3849 if (!ARMul_OSHandleSWI (state, BITS (0, 23))) 3850 ARMul_Abort (state, ARMul_SWIV); 3851 3852 break; 3853 } 3854 } 3855 3856 #ifdef MODET 3857 donext: 3858 #endif 3859 3860 #ifdef NEED_UI_LOOP_HOOK 3861 if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0) 3862 { 3863 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; 3864 deprecated_ui_loop_hook (0); 3865 } 3866 #endif /* NEED_UI_LOOP_HOOK */ 3867 3868 if (state->Emulate == ONCE) 3869 state->Emulate = STOP; 3870 /* If we have changed mode, allow the PC to advance before stopping. */ 3871 else if (state->Emulate == CHANGEMODE) 3872 continue; 3873 else if (state->Emulate != RUN) 3874 break; 3875 } 3876 while (!stop_simulator); 3877 3878 state->decoded = decoded; 3879 state->loaded = loaded; 3880 state->pc = pc; 3881 3882 return pc; 3883 } 3884 3885 /* This routine evaluates most Data Processing register RHS's with the S 3886 bit clear. It is intended to be called from the macro DPRegRHS, which 3887 filters the common case of an unshifted register with in line code. */ 3888 3889 static ARMword 3890 GetDPRegRHS (ARMul_State * state, ARMword instr) 3891 { 3892 ARMword shamt, base; 3893 3894 base = RHSReg; 3895 if (BIT (4)) 3896 { 3897 /* Shift amount in a register. */ 3898 UNDEF_Shift; 3899 INCPC; 3900 #ifndef MODE32 3901 if (base == 15) 3902 base = ECC | ER15INT | R15PC | EMODE; 3903 else 3904 #endif 3905 base = state->Reg[base]; 3906 ARMul_Icycles (state, 1, 0L); 3907 shamt = state->Reg[BITS (8, 11)] & 0xff; 3908 switch ((int) BITS (5, 6)) 3909 { 3910 case LSL: 3911 if (shamt == 0) 3912 return (base); 3913 else if (shamt >= 32) 3914 return (0); 3915 else 3916 return (base << shamt); 3917 case LSR: 3918 if (shamt == 0) 3919 return (base); 3920 else if (shamt >= 32) 3921 return (0); 3922 else 3923 return (base >> shamt); 3924 case ASR: 3925 if (shamt == 0) 3926 return (base); 3927 else if (shamt >= 32) 3928 return ((ARMword) ((ARMsword) base >> 31L)); 3929 else 3930 return ((ARMword) ((ARMsword) base >> (int) shamt)); 3931 case ROR: 3932 shamt &= 0x1f; 3933 if (shamt == 0) 3934 return (base); 3935 else 3936 return ((base << (32 - shamt)) | (base >> shamt)); 3937 } 3938 } 3939 else 3940 { 3941 /* Shift amount is a constant. */ 3942 #ifndef MODE32 3943 if (base == 15) 3944 base = ECC | ER15INT | R15PC | EMODE; 3945 else 3946 #endif 3947 base = state->Reg[base]; 3948 shamt = BITS (7, 11); 3949 switch ((int) BITS (5, 6)) 3950 { 3951 case LSL: 3952 return (base << shamt); 3953 case LSR: 3954 if (shamt == 0) 3955 return (0); 3956 else 3957 return (base >> shamt); 3958 case ASR: 3959 if (shamt == 0) 3960 return ((ARMword) ((ARMsword) base >> 31L)); 3961 else 3962 return ((ARMword) ((ARMsword) base >> (int) shamt)); 3963 case ROR: 3964 if (shamt == 0) 3965 /* It's an RRX. */ 3966 return ((base >> 1) | (CFLAG << 31)); 3967 else 3968 return ((base << (32 - shamt)) | (base >> shamt)); 3969 } 3970 } 3971 3972 return 0; 3973 } 3974 3975 /* This routine evaluates most Logical Data Processing register RHS's 3976 with the S bit set. It is intended to be called from the macro 3977 DPSRegRHS, which filters the common case of an unshifted register 3978 with in line code. */ 3979 3980 static ARMword 3981 GetDPSRegRHS (ARMul_State * state, ARMword instr) 3982 { 3983 ARMword shamt, base; 3984 3985 base = RHSReg; 3986 if (BIT (4)) 3987 { 3988 /* Shift amount in a register. */ 3989 UNDEF_Shift; 3990 INCPC; 3991 #ifndef MODE32 3992 if (base == 15) 3993 base = ECC | ER15INT | R15PC | EMODE; 3994 else 3995 #endif 3996 base = state->Reg[base]; 3997 ARMul_Icycles (state, 1, 0L); 3998 shamt = state->Reg[BITS (8, 11)] & 0xff; 3999 switch ((int) BITS (5, 6)) 4000 { 4001 case LSL: 4002 if (shamt == 0) 4003 return (base); 4004 else if (shamt == 32) 4005 { 4006 ASSIGNC (base & 1); 4007 return (0); 4008 } 4009 else if (shamt > 32) 4010 { 4011 CLEARC; 4012 return (0); 4013 } 4014 else 4015 { 4016 ASSIGNC ((base >> (32 - shamt)) & 1); 4017 return (base << shamt); 4018 } 4019 case LSR: 4020 if (shamt == 0) 4021 return (base); 4022 else if (shamt == 32) 4023 { 4024 ASSIGNC (base >> 31); 4025 return (0); 4026 } 4027 else if (shamt > 32) 4028 { 4029 CLEARC; 4030 return (0); 4031 } 4032 else 4033 { 4034 ASSIGNC ((base >> (shamt - 1)) & 1); 4035 return (base >> shamt); 4036 } 4037 case ASR: 4038 if (shamt == 0) 4039 return (base); 4040 else if (shamt >= 32) 4041 { 4042 ASSIGNC (base >> 31L); 4043 return ((ARMword) ((ARMsword) base >> 31L)); 4044 } 4045 else 4046 { 4047 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 4048 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4049 } 4050 case ROR: 4051 if (shamt == 0) 4052 return (base); 4053 shamt &= 0x1f; 4054 if (shamt == 0) 4055 { 4056 ASSIGNC (base >> 31); 4057 return (base); 4058 } 4059 else 4060 { 4061 ASSIGNC ((base >> (shamt - 1)) & 1); 4062 return ((base << (32 - shamt)) | (base >> shamt)); 4063 } 4064 } 4065 } 4066 else 4067 { 4068 /* Shift amount is a constant. */ 4069 #ifndef MODE32 4070 if (base == 15) 4071 base = ECC | ER15INT | R15PC | EMODE; 4072 else 4073 #endif 4074 base = state->Reg[base]; 4075 shamt = BITS (7, 11); 4076 4077 switch ((int) BITS (5, 6)) 4078 { 4079 case LSL: 4080 ASSIGNC ((base >> (32 - shamt)) & 1); 4081 return (base << shamt); 4082 case LSR: 4083 if (shamt == 0) 4084 { 4085 ASSIGNC (base >> 31); 4086 return (0); 4087 } 4088 else 4089 { 4090 ASSIGNC ((base >> (shamt - 1)) & 1); 4091 return (base >> shamt); 4092 } 4093 case ASR: 4094 if (shamt == 0) 4095 { 4096 ASSIGNC (base >> 31L); 4097 return ((ARMword) ((ARMsword) base >> 31L)); 4098 } 4099 else 4100 { 4101 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 4102 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4103 } 4104 case ROR: 4105 if (shamt == 0) 4106 { 4107 /* It's an RRX. */ 4108 shamt = CFLAG; 4109 ASSIGNC (base & 1); 4110 return ((base >> 1) | (shamt << 31)); 4111 } 4112 else 4113 { 4114 ASSIGNC ((base >> (shamt - 1)) & 1); 4115 return ((base << (32 - shamt)) | (base >> shamt)); 4116 } 4117 } 4118 } 4119 4120 return 0; 4121 } 4122 4123 /* This routine handles writes to register 15 when the S bit is not set. */ 4124 4125 static void 4126 WriteR15 (ARMul_State * state, ARMword src) 4127 { 4128 /* The ARM documentation states that the two least significant bits 4129 are discarded when setting PC, except in the cases handled by 4130 WriteR15Branch() below. It's probably an oversight: in THUMB 4131 mode, the second least significant bit should probably not be 4132 discarded. */ 4133 #ifdef MODET 4134 if (TFLAG) 4135 src &= 0xfffffffe; 4136 else 4137 #endif 4138 src &= 0xfffffffc; 4139 4140 #ifdef MODE32 4141 state->Reg[15] = src & PCBITS; 4142 #else 4143 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE; 4144 ARMul_R15Altered (state); 4145 #endif 4146 4147 FLUSHPIPE; 4148 } 4149 4150 /* This routine handles writes to register 15 when the S bit is set. */ 4151 4152 static void 4153 WriteSR15 (ARMul_State * state, ARMword src) 4154 { 4155 #ifdef MODE32 4156 if (state->Bank > 0) 4157 { 4158 state->Cpsr = state->Spsr[state->Bank]; 4159 ARMul_CPSRAltered (state); 4160 } 4161 #ifdef MODET 4162 if (TFLAG) 4163 src &= 0xfffffffe; 4164 else 4165 #endif 4166 src &= 0xfffffffc; 4167 state->Reg[15] = src & PCBITS; 4168 #else 4169 #ifdef MODET 4170 if (TFLAG) 4171 /* ARMul_R15Altered would have to support it. */ 4172 abort (); 4173 else 4174 #endif 4175 src &= 0xfffffffc; 4176 4177 if (state->Bank == USERBANK) 4178 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; 4179 else 4180 state->Reg[15] = src; 4181 4182 ARMul_R15Altered (state); 4183 #endif 4184 FLUSHPIPE; 4185 } 4186 4187 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM 4188 will switch to Thumb mode if the least significant bit is set. */ 4189 4190 static void 4191 WriteR15Branch (ARMul_State * state, ARMword src) 4192 { 4193 #ifdef MODET 4194 if (src & 1) 4195 { 4196 /* Thumb bit. */ 4197 SETT; 4198 state->Reg[15] = src & 0xfffffffe; 4199 } 4200 else 4201 { 4202 CLEART; 4203 state->Reg[15] = src & 0xfffffffc; 4204 } 4205 FLUSHPIPE; 4206 #else 4207 WriteR15 (state, src); 4208 #endif 4209 } 4210 4211 /* This routine evaluates most Load and Store register RHS's. It is 4212 intended to be called from the macro LSRegRHS, which filters the 4213 common case of an unshifted register with in line code. */ 4214 4215 static ARMword 4216 GetLSRegRHS (ARMul_State * state, ARMword instr) 4217 { 4218 ARMword shamt, base; 4219 4220 base = RHSReg; 4221 #ifndef MODE32 4222 if (base == 15) 4223 /* Now forbidden, but ... */ 4224 base = ECC | ER15INT | R15PC | EMODE; 4225 else 4226 #endif 4227 base = state->Reg[base]; 4228 4229 shamt = BITS (7, 11); 4230 switch ((int) BITS (5, 6)) 4231 { 4232 case LSL: 4233 return (base << shamt); 4234 case LSR: 4235 if (shamt == 0) 4236 return (0); 4237 else 4238 return (base >> shamt); 4239 case ASR: 4240 if (shamt == 0) 4241 return ((ARMword) ((ARMsword) base >> 31L)); 4242 else 4243 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4244 case ROR: 4245 if (shamt == 0) 4246 /* It's an RRX. */ 4247 return ((base >> 1) | (CFLAG << 31)); 4248 else 4249 return ((base << (32 - shamt)) | (base >> shamt)); 4250 default: 4251 break; 4252 } 4253 return 0; 4254 } 4255 4256 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */ 4257 4258 static ARMword 4259 GetLS7RHS (ARMul_State * state, ARMword instr) 4260 { 4261 if (BIT (22) == 0) 4262 { 4263 /* Register. */ 4264 #ifndef MODE32 4265 if (RHSReg == 15) 4266 /* Now forbidden, but ... */ 4267 return ECC | ER15INT | R15PC | EMODE; 4268 #endif 4269 return state->Reg[RHSReg]; 4270 } 4271 4272 /* Immediate. */ 4273 return BITS (0, 3) | (BITS (8, 11) << 4); 4274 } 4275 4276 /* This function does the work of loading a word for a LDR instruction. */ 4277 4278 static unsigned 4279 LoadWord (ARMul_State * state, ARMword instr, ARMword address) 4280 { 4281 ARMword dest; 4282 4283 BUSUSEDINCPCS; 4284 #ifndef MODE32 4285 if (ADDREXCEPT (address)) 4286 INTERNALABORT (address); 4287 #endif 4288 4289 dest = ARMul_LoadWordN (state, address); 4290 4291 if (state->Aborted) 4292 { 4293 TAKEABORT; 4294 return state->lateabtSig; 4295 } 4296 if (address & 3) 4297 dest = ARMul_Align (state, address, dest); 4298 WRITEDESTB (dest); 4299 ARMul_Icycles (state, 1, 0L); 4300 4301 return (DESTReg != LHSReg); 4302 } 4303 4304 #ifdef MODET 4305 /* This function does the work of loading a halfword. */ 4306 4307 static unsigned 4308 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, 4309 int signextend) 4310 { 4311 ARMword dest; 4312 4313 BUSUSEDINCPCS; 4314 #ifndef MODE32 4315 if (ADDREXCEPT (address)) 4316 INTERNALABORT (address); 4317 #endif 4318 dest = ARMul_LoadHalfWord (state, address); 4319 if (state->Aborted) 4320 { 4321 TAKEABORT; 4322 return state->lateabtSig; 4323 } 4324 UNDEF_LSRBPC; 4325 if (signextend) 4326 if (dest & 1 << (16 - 1)) 4327 dest = (dest & ((1 << 16) - 1)) - (1 << 16); 4328 4329 WRITEDEST (dest); 4330 ARMul_Icycles (state, 1, 0L); 4331 return (DESTReg != LHSReg); 4332 } 4333 4334 #endif /* MODET */ 4335 4336 /* This function does the work of loading a byte for a LDRB instruction. */ 4337 4338 static unsigned 4339 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) 4340 { 4341 ARMword dest; 4342 4343 BUSUSEDINCPCS; 4344 #ifndef MODE32 4345 if (ADDREXCEPT (address)) 4346 INTERNALABORT (address); 4347 #endif 4348 dest = ARMul_LoadByte (state, address); 4349 if (state->Aborted) 4350 { 4351 TAKEABORT; 4352 return state->lateabtSig; 4353 } 4354 UNDEF_LSRBPC; 4355 if (signextend) 4356 if (dest & 1 << (8 - 1)) 4357 dest = (dest & ((1 << 8) - 1)) - (1 << 8); 4358 4359 WRITEDEST (dest); 4360 ARMul_Icycles (state, 1, 0L); 4361 4362 return (DESTReg != LHSReg); 4363 } 4364 4365 /* This function does the work of loading two words for a LDRD instruction. */ 4366 4367 static void 4368 Handle_Load_Double (ARMul_State * state, ARMword instr) 4369 { 4370 ARMword dest_reg; 4371 ARMword addr_reg; 4372 ARMword write_back = BIT (21); 4373 ARMword immediate = BIT (22); 4374 ARMword add_to_base = BIT (23); 4375 ARMword pre_indexed = BIT (24); 4376 ARMword offset; 4377 ARMword addr; 4378 ARMword sum; 4379 ARMword base; 4380 ARMword value1; 4381 ARMword value2; 4382 4383 BUSUSEDINCPCS; 4384 4385 /* If the writeback bit is set, the pre-index bit must be clear. */ 4386 if (write_back && ! pre_indexed) 4387 { 4388 ARMul_UndefInstr (state, instr); 4389 return; 4390 } 4391 4392 /* Extract the base address register. */ 4393 addr_reg = LHSReg; 4394 4395 /* Extract the destination register and check it. */ 4396 dest_reg = DESTReg; 4397 4398 /* Destination register must be even. */ 4399 if ((dest_reg & 1) 4400 /* Destination register cannot be LR. */ 4401 || (dest_reg == 14)) 4402 { 4403 ARMul_UndefInstr (state, instr); 4404 return; 4405 } 4406 4407 /* Compute the base address. */ 4408 base = state->Reg[addr_reg]; 4409 4410 /* Compute the offset. */ 4411 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 4412 4413 /* Compute the sum of the two. */ 4414 if (add_to_base) 4415 sum = base + offset; 4416 else 4417 sum = base - offset; 4418 4419 /* If this is a pre-indexed mode use the sum. */ 4420 if (pre_indexed) 4421 addr = sum; 4422 else 4423 addr = base; 4424 4425 /* The address must be aligned on a 8 byte boundary. */ 4426 if (addr & 0x7) 4427 { 4428 #ifdef ABORTS 4429 ARMul_DATAABORT (addr); 4430 #else 4431 ARMul_UndefInstr (state, instr); 4432 #endif 4433 return; 4434 } 4435 4436 /* For pre indexed or post indexed addressing modes, 4437 check that the destination registers do not overlap 4438 the address registers. */ 4439 if ((! pre_indexed || write_back) 4440 && ( addr_reg == dest_reg 4441 || addr_reg == dest_reg + 1)) 4442 { 4443 ARMul_UndefInstr (state, instr); 4444 return; 4445 } 4446 4447 /* Load the words. */ 4448 value1 = ARMul_LoadWordN (state, addr); 4449 value2 = ARMul_LoadWordN (state, addr + 4); 4450 4451 /* Check for data aborts. */ 4452 if (state->Aborted) 4453 { 4454 TAKEABORT; 4455 return; 4456 } 4457 4458 ARMul_Icycles (state, 2, 0L); 4459 4460 /* Store the values. */ 4461 state->Reg[dest_reg] = value1; 4462 state->Reg[dest_reg + 1] = value2; 4463 4464 /* Do the post addressing and writeback. */ 4465 if (! pre_indexed) 4466 addr = sum; 4467 4468 if (! pre_indexed || write_back) 4469 state->Reg[addr_reg] = addr; 4470 } 4471 4472 /* This function does the work of storing two words for a STRD instruction. */ 4473 4474 static void 4475 Handle_Store_Double (ARMul_State * state, ARMword instr) 4476 { 4477 ARMword src_reg; 4478 ARMword addr_reg; 4479 ARMword write_back = BIT (21); 4480 ARMword immediate = BIT (22); 4481 ARMword add_to_base = BIT (23); 4482 ARMword pre_indexed = BIT (24); 4483 ARMword offset; 4484 ARMword addr; 4485 ARMword sum; 4486 ARMword base; 4487 4488 BUSUSEDINCPCS; 4489 4490 /* If the writeback bit is set, the pre-index bit must be clear. */ 4491 if (write_back && ! pre_indexed) 4492 { 4493 ARMul_UndefInstr (state, instr); 4494 return; 4495 } 4496 4497 /* Extract the base address register. */ 4498 addr_reg = LHSReg; 4499 4500 /* Base register cannot be PC. */ 4501 if (addr_reg == 15) 4502 { 4503 ARMul_UndefInstr (state, instr); 4504 return; 4505 } 4506 4507 /* Extract the source register. */ 4508 src_reg = DESTReg; 4509 4510 /* Source register must be even. */ 4511 if (src_reg & 1) 4512 { 4513 ARMul_UndefInstr (state, instr); 4514 return; 4515 } 4516 4517 /* Compute the base address. */ 4518 base = state->Reg[addr_reg]; 4519 4520 /* Compute the offset. */ 4521 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 4522 4523 /* Compute the sum of the two. */ 4524 if (add_to_base) 4525 sum = base + offset; 4526 else 4527 sum = base - offset; 4528 4529 /* If this is a pre-indexed mode use the sum. */ 4530 if (pre_indexed) 4531 addr = sum; 4532 else 4533 addr = base; 4534 4535 /* The address must be aligned on a 8 byte boundary. */ 4536 if (addr & 0x7) 4537 { 4538 #ifdef ABORTS 4539 ARMul_DATAABORT (addr); 4540 #else 4541 ARMul_UndefInstr (state, instr); 4542 #endif 4543 return; 4544 } 4545 4546 /* For pre indexed or post indexed addressing modes, 4547 check that the destination registers do not overlap 4548 the address registers. */ 4549 if ((! pre_indexed || write_back) 4550 && ( addr_reg == src_reg 4551 || addr_reg == src_reg + 1)) 4552 { 4553 ARMul_UndefInstr (state, instr); 4554 return; 4555 } 4556 4557 /* Load the words. */ 4558 ARMul_StoreWordN (state, addr, state->Reg[src_reg]); 4559 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]); 4560 4561 if (state->Aborted) 4562 { 4563 TAKEABORT; 4564 return; 4565 } 4566 4567 /* Do the post addressing and writeback. */ 4568 if (! pre_indexed) 4569 addr = sum; 4570 4571 if (! pre_indexed || write_back) 4572 state->Reg[addr_reg] = addr; 4573 } 4574 4575 /* This function does the work of storing a word from a STR instruction. */ 4576 4577 static unsigned 4578 StoreWord (ARMul_State * state, ARMword instr, ARMword address) 4579 { 4580 BUSUSEDINCPCN; 4581 #ifndef MODE32 4582 if (DESTReg == 15) 4583 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4584 #endif 4585 #ifdef MODE32 4586 ARMul_StoreWordN (state, address, DEST); 4587 #else 4588 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4589 { 4590 INTERNALABORT (address); 4591 (void) ARMul_LoadWordN (state, address); 4592 } 4593 else 4594 ARMul_StoreWordN (state, address, DEST); 4595 #endif 4596 if (state->Aborted) 4597 { 4598 TAKEABORT; 4599 return state->lateabtSig; 4600 } 4601 return TRUE; 4602 } 4603 4604 #ifdef MODET 4605 /* This function does the work of storing a byte for a STRH instruction. */ 4606 4607 static unsigned 4608 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) 4609 { 4610 BUSUSEDINCPCN; 4611 4612 #ifndef MODE32 4613 if (DESTReg == 15) 4614 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4615 #endif 4616 4617 #ifdef MODE32 4618 ARMul_StoreHalfWord (state, address, DEST); 4619 #else 4620 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4621 { 4622 INTERNALABORT (address); 4623 (void) ARMul_LoadHalfWord (state, address); 4624 } 4625 else 4626 ARMul_StoreHalfWord (state, address, DEST); 4627 #endif 4628 4629 if (state->Aborted) 4630 { 4631 TAKEABORT; 4632 return state->lateabtSig; 4633 } 4634 return TRUE; 4635 } 4636 4637 #endif /* MODET */ 4638 4639 /* This function does the work of storing a byte for a STRB instruction. */ 4640 4641 static unsigned 4642 StoreByte (ARMul_State * state, ARMword instr, ARMword address) 4643 { 4644 BUSUSEDINCPCN; 4645 #ifndef MODE32 4646 if (DESTReg == 15) 4647 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4648 #endif 4649 #ifdef MODE32 4650 ARMul_StoreByte (state, address, DEST); 4651 #else 4652 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4653 { 4654 INTERNALABORT (address); 4655 (void) ARMul_LoadByte (state, address); 4656 } 4657 else 4658 ARMul_StoreByte (state, address, DEST); 4659 #endif 4660 if (state->Aborted) 4661 { 4662 TAKEABORT; 4663 return state->lateabtSig; 4664 } 4665 UNDEF_LSRBPC; 4666 return TRUE; 4667 } 4668 4669 /* This function does the work of loading the registers listed in an LDM 4670 instruction, when the S bit is clear. The code here is always increment 4671 after, it's up to the caller to get the input address correct and to 4672 handle base register modification. */ 4673 4674 static void 4675 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) 4676 { 4677 ARMword dest, temp; 4678 4679 UNDEF_LSMNoRegs; 4680 UNDEF_LSMPCBase; 4681 UNDEF_LSMBaseInListWb; 4682 BUSUSEDINCPCS; 4683 #ifndef MODE32 4684 if (ADDREXCEPT (address)) 4685 INTERNALABORT (address); 4686 #endif 4687 if (BIT (21) && LHSReg != 15) 4688 LSBase = WBBase; 4689 4690 /* N cycle first. */ 4691 for (temp = 0; !BIT (temp); temp++) 4692 ; 4693 4694 dest = ARMul_LoadWordN (state, address); 4695 4696 if (!state->abortSig && !state->Aborted) 4697 state->Reg[temp++] = dest; 4698 else if (!state->Aborted) 4699 { 4700 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4701 state->Aborted = ARMul_DataAbortV; 4702 } 4703 4704 /* S cycles from here on. */ 4705 for (; temp < 16; temp ++) 4706 if (BIT (temp)) 4707 { 4708 /* Load this register. */ 4709 address += 4; 4710 dest = ARMul_LoadWordS (state, address); 4711 4712 if (!state->abortSig && !state->Aborted) 4713 state->Reg[temp] = dest; 4714 else if (!state->Aborted) 4715 { 4716 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4717 state->Aborted = ARMul_DataAbortV; 4718 } 4719 } 4720 4721 if (BIT (15) && !state->Aborted) 4722 /* PC is in the reg list. */ 4723 WriteR15Branch (state, PC); 4724 4725 /* To write back the final register. */ 4726 ARMul_Icycles (state, 1, 0L); 4727 4728 if (state->Aborted) 4729 { 4730 if (BIT (21) && LHSReg != 15) 4731 LSBase = WBBase; 4732 TAKEABORT; 4733 } 4734 } 4735 4736 /* This function does the work of loading the registers listed in an LDM 4737 instruction, when the S bit is set. The code here is always increment 4738 after, it's up to the caller to get the input address correct and to 4739 handle base register modification. */ 4740 4741 static void 4742 LoadSMult (ARMul_State * state, 4743 ARMword instr, 4744 ARMword address, 4745 ARMword WBBase) 4746 { 4747 ARMword dest, temp; 4748 4749 UNDEF_LSMNoRegs; 4750 UNDEF_LSMPCBase; 4751 UNDEF_LSMBaseInListWb; 4752 4753 BUSUSEDINCPCS; 4754 4755 #ifndef MODE32 4756 if (ADDREXCEPT (address)) 4757 INTERNALABORT (address); 4758 #endif 4759 4760 if (BIT (21) && LHSReg != 15) 4761 LSBase = WBBase; 4762 4763 if (!BIT (15) && state->Bank != USERBANK) 4764 { 4765 /* Temporary reg bank switch. */ 4766 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 4767 UNDEF_LSMUserBankWb; 4768 } 4769 4770 /* N cycle first. */ 4771 for (temp = 0; !BIT (temp); temp ++) 4772 ; 4773 4774 dest = ARMul_LoadWordN (state, address); 4775 4776 if (!state->abortSig) 4777 state->Reg[temp++] = dest; 4778 else if (!state->Aborted) 4779 { 4780 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4781 state->Aborted = ARMul_DataAbortV; 4782 } 4783 4784 /* S cycles from here on. */ 4785 for (; temp < 16; temp++) 4786 if (BIT (temp)) 4787 { 4788 /* Load this register. */ 4789 address += 4; 4790 dest = ARMul_LoadWordS (state, address); 4791 4792 if (!state->abortSig && !state->Aborted) 4793 state->Reg[temp] = dest; 4794 else if (!state->Aborted) 4795 { 4796 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4797 state->Aborted = ARMul_DataAbortV; 4798 } 4799 } 4800 4801 if (BIT (15) && !state->Aborted) 4802 { 4803 /* PC is in the reg list. */ 4804 #ifdef MODE32 4805 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 4806 { 4807 state->Cpsr = GETSPSR (state->Bank); 4808 ARMul_CPSRAltered (state); 4809 } 4810 4811 WriteR15 (state, PC); 4812 #else 4813 if (state->Mode == USER26MODE || state->Mode == USER32MODE) 4814 { 4815 /* Protect bits in user mode. */ 4816 ASSIGNN ((state->Reg[15] & NBIT) != 0); 4817 ASSIGNZ ((state->Reg[15] & ZBIT) != 0); 4818 ASSIGNC ((state->Reg[15] & CBIT) != 0); 4819 ASSIGNV ((state->Reg[15] & VBIT) != 0); 4820 } 4821 else 4822 ARMul_R15Altered (state); 4823 4824 FLUSHPIPE; 4825 #endif 4826 } 4827 4828 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE) 4829 /* Restore the correct bank. */ 4830 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 4831 4832 /* To write back the final register. */ 4833 ARMul_Icycles (state, 1, 0L); 4834 4835 if (state->Aborted) 4836 { 4837 if (BIT (21) && LHSReg != 15) 4838 LSBase = WBBase; 4839 4840 TAKEABORT; 4841 } 4842 } 4843 4844 /* This function does the work of storing the registers listed in an STM 4845 instruction, when the S bit is clear. The code here is always increment 4846 after, it's up to the caller to get the input address correct and to 4847 handle base register modification. */ 4848 4849 static void 4850 StoreMult (ARMul_State * state, 4851 ARMword instr, 4852 ARMword address, 4853 ARMword WBBase) 4854 { 4855 ARMword temp; 4856 4857 UNDEF_LSMNoRegs; 4858 UNDEF_LSMPCBase; 4859 UNDEF_LSMBaseInListWb; 4860 4861 if (!TFLAG) 4862 /* N-cycle, increment the PC and update the NextInstr state. */ 4863 BUSUSEDINCPCN; 4864 4865 #ifndef MODE32 4866 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4867 INTERNALABORT (address); 4868 4869 if (BIT (15)) 4870 PATCHR15; 4871 #endif 4872 4873 /* N cycle first. */ 4874 for (temp = 0; !BIT (temp); temp ++) 4875 ; 4876 4877 #ifdef MODE32 4878 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4879 #else 4880 if (state->Aborted) 4881 { 4882 (void) ARMul_LoadWordN (state, address); 4883 4884 /* Fake the Stores as Loads. */ 4885 for (; temp < 16; temp++) 4886 if (BIT (temp)) 4887 { 4888 /* Save this register. */ 4889 address += 4; 4890 (void) ARMul_LoadWordS (state, address); 4891 } 4892 4893 if (BIT (21) && LHSReg != 15) 4894 LSBase = WBBase; 4895 TAKEABORT; 4896 return; 4897 } 4898 else 4899 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4900 #endif 4901 4902 if (state->abortSig && !state->Aborted) 4903 { 4904 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4905 state->Aborted = ARMul_DataAbortV; 4906 } 4907 4908 if (BIT (21) && LHSReg != 15) 4909 LSBase = WBBase; 4910 4911 /* S cycles from here on. */ 4912 for (; temp < 16; temp ++) 4913 if (BIT (temp)) 4914 { 4915 /* Save this register. */ 4916 address += 4; 4917 4918 ARMul_StoreWordS (state, address, state->Reg[temp]); 4919 4920 if (state->abortSig && !state->Aborted) 4921 { 4922 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4923 state->Aborted = ARMul_DataAbortV; 4924 } 4925 } 4926 4927 if (state->Aborted) 4928 TAKEABORT; 4929 } 4930 4931 /* This function does the work of storing the registers listed in an STM 4932 instruction when the S bit is set. The code here is always increment 4933 after, it's up to the caller to get the input address correct and to 4934 handle base register modification. */ 4935 4936 static void 4937 StoreSMult (ARMul_State * state, 4938 ARMword instr, 4939 ARMword address, 4940 ARMword WBBase) 4941 { 4942 ARMword temp; 4943 4944 UNDEF_LSMNoRegs; 4945 UNDEF_LSMPCBase; 4946 UNDEF_LSMBaseInListWb; 4947 4948 BUSUSEDINCPCN; 4949 4950 #ifndef MODE32 4951 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4952 INTERNALABORT (address); 4953 4954 if (BIT (15)) 4955 PATCHR15; 4956 #endif 4957 4958 if (state->Bank != USERBANK) 4959 { 4960 /* Force User Bank. */ 4961 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 4962 UNDEF_LSMUserBankWb; 4963 } 4964 4965 for (temp = 0; !BIT (temp); temp++) 4966 ; /* N cycle first. */ 4967 4968 #ifdef MODE32 4969 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4970 #else 4971 if (state->Aborted) 4972 { 4973 (void) ARMul_LoadWordN (state, address); 4974 4975 for (; temp < 16; temp++) 4976 /* Fake the Stores as Loads. */ 4977 if (BIT (temp)) 4978 { 4979 /* Save this register. */ 4980 address += 4; 4981 4982 (void) ARMul_LoadWordS (state, address); 4983 } 4984 4985 if (BIT (21) && LHSReg != 15) 4986 LSBase = WBBase; 4987 4988 TAKEABORT; 4989 return; 4990 } 4991 else 4992 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4993 #endif 4994 4995 if (state->abortSig && !state->Aborted) 4996 { 4997 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4998 state->Aborted = ARMul_DataAbortV; 4999 } 5000 5001 /* S cycles from here on. */ 5002 for (; temp < 16; temp++) 5003 if (BIT (temp)) 5004 { 5005 /* Save this register. */ 5006 address += 4; 5007 5008 ARMul_StoreWordS (state, address, state->Reg[temp]); 5009 5010 if (state->abortSig && !state->Aborted) 5011 { 5012 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5013 state->Aborted = ARMul_DataAbortV; 5014 } 5015 } 5016 5017 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 5018 /* Restore the correct bank. */ 5019 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 5020 5021 if (BIT (21) && LHSReg != 15) 5022 LSBase = WBBase; 5023 5024 if (state->Aborted) 5025 TAKEABORT; 5026 } 5027 5028 /* This function does the work of adding two 32bit values 5029 together, and calculating if a carry has occurred. */ 5030 5031 static ARMword 5032 Add32 (ARMword a1, ARMword a2, int *carry) 5033 { 5034 ARMword result = (a1 + a2); 5035 unsigned int uresult = (unsigned int) result; 5036 unsigned int ua1 = (unsigned int) a1; 5037 5038 /* If (result == RdLo) and (state->Reg[nRdLo] == 0), 5039 or (result > RdLo) then we have no carry. */ 5040 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) 5041 *carry = 1; 5042 else 5043 *carry = 0; 5044 5045 return result; 5046 } 5047 5048 /* This function does the work of multiplying 5049 two 32bit values to give a 64bit result. */ 5050 5051 static unsigned 5052 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) 5053 { 5054 /* Operand register numbers. */ 5055 int nRdHi, nRdLo, nRs, nRm; 5056 ARMword RdHi = 0, RdLo = 0, Rm; 5057 /* Cycle count. */ 5058 int scount; 5059 5060 nRdHi = BITS (16, 19); 5061 nRdLo = BITS (12, 15); 5062 nRs = BITS (8, 11); 5063 nRm = BITS (0, 3); 5064 5065 /* Needed to calculate the cycle count. */ 5066 Rm = state->Reg[nRm]; 5067 5068 /* Check for illegal operand combinations first. */ 5069 if ( nRdHi != 15 5070 && nRdLo != 15 5071 && nRs != 15 5072 && nRm != 15 5073 && nRdHi != nRdLo 5074 && nRdHi != nRm 5075 && nRdLo != nRm) 5076 { 5077 /* Intermediate results. */ 5078 ARMword lo, mid1, mid2, hi; 5079 int carry; 5080 ARMword Rs = state->Reg[nRs]; 5081 int sign = 0; 5082 5083 if (msigned) 5084 { 5085 /* Compute sign of result and adjust operands if necessary. */ 5086 sign = (Rm ^ Rs) & 0x80000000; 5087 5088 if (((ARMsword) Rm) < 0) 5089 Rm = -Rm; 5090 5091 if (((ARMsword) Rs) < 0) 5092 Rs = -Rs; 5093 } 5094 5095 /* We can split the 32x32 into four 16x16 operations. This 5096 ensures that we do not lose precision on 32bit only hosts. */ 5097 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); 5098 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 5099 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); 5100 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 5101 5102 /* We now need to add all of these results together, taking 5103 care to propogate the carries from the additions. */ 5104 RdLo = Add32 (lo, (mid1 << 16), &carry); 5105 RdHi = carry; 5106 RdLo = Add32 (RdLo, (mid2 << 16), &carry); 5107 RdHi += 5108 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); 5109 5110 if (sign) 5111 { 5112 /* Negate result if necessary. */ 5113 RdLo = ~RdLo; 5114 RdHi = ~RdHi; 5115 if (RdLo == 0xFFFFFFFF) 5116 { 5117 RdLo = 0; 5118 RdHi += 1; 5119 } 5120 else 5121 RdLo += 1; 5122 } 5123 5124 state->Reg[nRdLo] = RdLo; 5125 state->Reg[nRdHi] = RdHi; 5126 } 5127 else 5128 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n"); 5129 5130 if (scc) 5131 /* Ensure that both RdHi and RdLo are used to compute Z, 5132 but don't let RdLo's sign bit make it to N. */ 5133 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 5134 5135 /* The cycle count depends on whether the instruction is a signed or 5136 unsigned multiply, and what bits are clear in the multiplier. */ 5137 if (msigned && (Rm & ((unsigned) 1 << 31))) 5138 /* Invert the bits to make the check against zero. */ 5139 Rm = ~Rm; 5140 5141 if ((Rm & 0xFFFFFF00) == 0) 5142 scount = 1; 5143 else if ((Rm & 0xFFFF0000) == 0) 5144 scount = 2; 5145 else if ((Rm & 0xFF000000) == 0) 5146 scount = 3; 5147 else 5148 scount = 4; 5149 5150 return 2 + scount; 5151 } 5152 5153 /* This function does the work of multiplying two 32bit 5154 values and adding a 64bit value to give a 64bit result. */ 5155 5156 static unsigned 5157 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) 5158 { 5159 unsigned scount; 5160 ARMword RdLo, RdHi; 5161 int nRdHi, nRdLo; 5162 int carry = 0; 5163 5164 nRdHi = BITS (16, 19); 5165 nRdLo = BITS (12, 15); 5166 5167 RdHi = state->Reg[nRdHi]; 5168 RdLo = state->Reg[nRdLo]; 5169 5170 scount = Multiply64 (state, instr, msigned, LDEFAULT); 5171 5172 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry); 5173 RdHi = (RdHi + state->Reg[nRdHi]) + carry; 5174 5175 state->Reg[nRdLo] = RdLo; 5176 state->Reg[nRdHi] = RdHi; 5177 5178 if (scc) 5179 /* Ensure that both RdHi and RdLo are used to compute Z, 5180 but don't let RdLo's sign bit make it to N. */ 5181 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 5182 5183 /* Extra cycle for addition. */ 5184 return scount + 1; 5185 } 5186