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: /* MOVW immed */ 2319 dest = BITS (0, 11); 2320 dest |= (BITS (16, 19) << 12); 2321 WRITEDEST (dest); 2322 break; 2323 2324 case 0x31: /* TSTP immed */ 2325 if (DESTReg == 15) 2326 { 2327 /* TSTP immed. */ 2328 #ifdef MODE32 2329 state->Cpsr = GETSPSR (state->Bank); 2330 ARMul_CPSRAltered (state); 2331 #else 2332 temp = LHS & DPImmRHS; 2333 SETR15PSR (temp); 2334 #endif 2335 } 2336 else 2337 { 2338 /* TST immed. */ 2339 DPSImmRHS; 2340 dest = LHS & rhs; 2341 ARMul_NegZero (state, dest); 2342 } 2343 break; 2344 2345 case 0x32: /* TEQ immed and MSR immed to CPSR */ 2346 if (DESTReg == 15) 2347 /* MSR immed to CPSR. */ 2348 ARMul_FixCPSR (state, instr, DPImmRHS); 2349 else 2350 UNDEF_Test; 2351 break; 2352 2353 case 0x33: /* TEQP immed */ 2354 if (DESTReg == 15) 2355 { 2356 /* TEQP immed. */ 2357 #ifdef MODE32 2358 state->Cpsr = GETSPSR (state->Bank); 2359 ARMul_CPSRAltered (state); 2360 #else 2361 temp = LHS ^ DPImmRHS; 2362 SETR15PSR (temp); 2363 #endif 2364 } 2365 else 2366 { 2367 DPSImmRHS; /* TEQ immed */ 2368 dest = LHS ^ rhs; 2369 ARMul_NegZero (state, dest); 2370 } 2371 break; 2372 2373 case 0x34: /* MOVT immed */ 2374 dest = BITS (0, 11); 2375 dest |= (BITS (16, 19) << 12); 2376 DEST |= (dest << 16); 2377 break; 2378 2379 case 0x35: /* CMPP immed */ 2380 if (DESTReg == 15) 2381 { 2382 /* CMPP immed. */ 2383 #ifdef MODE32 2384 state->Cpsr = GETSPSR (state->Bank); 2385 ARMul_CPSRAltered (state); 2386 #else 2387 temp = LHS - DPImmRHS; 2388 SETR15PSR (temp); 2389 #endif 2390 break; 2391 } 2392 else 2393 { 2394 /* CMP immed. */ 2395 lhs = LHS; 2396 rhs = DPImmRHS; 2397 dest = lhs - rhs; 2398 ARMul_NegZero (state, dest); 2399 2400 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2401 { 2402 ARMul_SubCarry (state, lhs, rhs, dest); 2403 ARMul_SubOverflow (state, lhs, rhs, dest); 2404 } 2405 else 2406 { 2407 CLEARC; 2408 CLEARV; 2409 } 2410 } 2411 break; 2412 2413 case 0x36: /* CMN immed and MSR immed to SPSR */ 2414 if (DESTReg == 15) 2415 ARMul_FixSPSR (state, instr, DPImmRHS); 2416 else 2417 UNDEF_Test; 2418 break; 2419 2420 case 0x37: /* CMNP immed. */ 2421 if (DESTReg == 15) 2422 { 2423 /* CMNP immed. */ 2424 #ifdef MODE32 2425 state->Cpsr = GETSPSR (state->Bank); 2426 ARMul_CPSRAltered (state); 2427 #else 2428 temp = LHS + DPImmRHS; 2429 SETR15PSR (temp); 2430 #endif 2431 break; 2432 } 2433 else 2434 { 2435 /* CMN immed. */ 2436 lhs = LHS; 2437 rhs = DPImmRHS; 2438 dest = lhs + rhs; 2439 ASSIGNZ (dest == 0); 2440 if ((lhs | rhs) >> 30) 2441 { 2442 /* Possible C,V,N to set. */ 2443 ASSIGNN (NEG (dest)); 2444 ARMul_AddCarry (state, lhs, rhs, dest); 2445 ARMul_AddOverflow (state, lhs, rhs, dest); 2446 } 2447 else 2448 { 2449 CLEARN; 2450 CLEARC; 2451 CLEARV; 2452 } 2453 } 2454 break; 2455 2456 case 0x38: /* ORR immed. */ 2457 dest = LHS | DPImmRHS; 2458 WRITEDEST (dest); 2459 break; 2460 2461 case 0x39: /* ORRS immed. */ 2462 DPSImmRHS; 2463 dest = LHS | rhs; 2464 WRITESDEST (dest); 2465 break; 2466 2467 case 0x3a: /* MOV immed. */ 2468 dest = DPImmRHS; 2469 WRITEDEST (dest); 2470 break; 2471 2472 case 0x3b: /* MOVS immed. */ 2473 DPSImmRHS; 2474 WRITESDEST (rhs); 2475 break; 2476 2477 case 0x3c: /* BIC immed. */ 2478 dest = LHS & ~DPImmRHS; 2479 WRITEDEST (dest); 2480 break; 2481 2482 case 0x3d: /* BICS immed. */ 2483 DPSImmRHS; 2484 dest = LHS & ~rhs; 2485 WRITESDEST (dest); 2486 break; 2487 2488 case 0x3e: /* MVN immed. */ 2489 dest = ~DPImmRHS; 2490 WRITEDEST (dest); 2491 break; 2492 2493 case 0x3f: /* MVNS immed. */ 2494 DPSImmRHS; 2495 WRITESDEST (~rhs); 2496 break; 2497 2498 2499 /* Single Data Transfer Immediate RHS Instructions. */ 2500 2501 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */ 2502 lhs = LHS; 2503 if (StoreWord (state, instr, lhs)) 2504 LSBase = lhs - LSImmRHS; 2505 break; 2506 2507 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */ 2508 lhs = LHS; 2509 if (LoadWord (state, instr, lhs)) 2510 LSBase = lhs - LSImmRHS; 2511 break; 2512 2513 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */ 2514 UNDEF_LSRBaseEQDestWb; 2515 UNDEF_LSRPCBaseWb; 2516 lhs = LHS; 2517 temp = lhs - LSImmRHS; 2518 state->NtransSig = LOW; 2519 if (StoreWord (state, instr, lhs)) 2520 LSBase = temp; 2521 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2522 break; 2523 2524 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */ 2525 UNDEF_LSRBaseEQDestWb; 2526 UNDEF_LSRPCBaseWb; 2527 lhs = LHS; 2528 state->NtransSig = LOW; 2529 if (LoadWord (state, instr, lhs)) 2530 LSBase = lhs - LSImmRHS; 2531 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2532 break; 2533 2534 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */ 2535 lhs = LHS; 2536 if (StoreByte (state, instr, lhs)) 2537 LSBase = lhs - LSImmRHS; 2538 break; 2539 2540 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */ 2541 lhs = LHS; 2542 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2543 LSBase = lhs - LSImmRHS; 2544 break; 2545 2546 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */ 2547 UNDEF_LSRBaseEQDestWb; 2548 UNDEF_LSRPCBaseWb; 2549 lhs = LHS; 2550 state->NtransSig = LOW; 2551 if (StoreByte (state, instr, lhs)) 2552 LSBase = lhs - LSImmRHS; 2553 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2554 break; 2555 2556 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */ 2557 UNDEF_LSRBaseEQDestWb; 2558 UNDEF_LSRPCBaseWb; 2559 lhs = LHS; 2560 state->NtransSig = LOW; 2561 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2562 LSBase = lhs - LSImmRHS; 2563 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2564 break; 2565 2566 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */ 2567 lhs = LHS; 2568 if (StoreWord (state, instr, lhs)) 2569 LSBase = lhs + LSImmRHS; 2570 break; 2571 2572 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */ 2573 lhs = LHS; 2574 if (LoadWord (state, instr, lhs)) 2575 LSBase = lhs + LSImmRHS; 2576 break; 2577 2578 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */ 2579 UNDEF_LSRBaseEQDestWb; 2580 UNDEF_LSRPCBaseWb; 2581 lhs = LHS; 2582 state->NtransSig = LOW; 2583 if (StoreWord (state, instr, lhs)) 2584 LSBase = lhs + LSImmRHS; 2585 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2586 break; 2587 2588 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */ 2589 UNDEF_LSRBaseEQDestWb; 2590 UNDEF_LSRPCBaseWb; 2591 lhs = LHS; 2592 state->NtransSig = LOW; 2593 if (LoadWord (state, instr, lhs)) 2594 LSBase = lhs + LSImmRHS; 2595 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2596 break; 2597 2598 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */ 2599 lhs = LHS; 2600 if (StoreByte (state, instr, lhs)) 2601 LSBase = lhs + LSImmRHS; 2602 break; 2603 2604 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */ 2605 lhs = LHS; 2606 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2607 LSBase = lhs + LSImmRHS; 2608 break; 2609 2610 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */ 2611 UNDEF_LSRBaseEQDestWb; 2612 UNDEF_LSRPCBaseWb; 2613 lhs = LHS; 2614 state->NtransSig = LOW; 2615 if (StoreByte (state, instr, lhs)) 2616 LSBase = lhs + LSImmRHS; 2617 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2618 break; 2619 2620 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */ 2621 UNDEF_LSRBaseEQDestWb; 2622 UNDEF_LSRPCBaseWb; 2623 lhs = LHS; 2624 state->NtransSig = LOW; 2625 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2626 LSBase = lhs + LSImmRHS; 2627 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2628 break; 2629 2630 2631 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */ 2632 (void) StoreWord (state, instr, LHS - LSImmRHS); 2633 break; 2634 2635 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */ 2636 (void) LoadWord (state, instr, LHS - LSImmRHS); 2637 break; 2638 2639 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */ 2640 UNDEF_LSRBaseEQDestWb; 2641 UNDEF_LSRPCBaseWb; 2642 temp = LHS - LSImmRHS; 2643 if (StoreWord (state, instr, temp)) 2644 LSBase = temp; 2645 break; 2646 2647 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */ 2648 UNDEF_LSRBaseEQDestWb; 2649 UNDEF_LSRPCBaseWb; 2650 temp = LHS - LSImmRHS; 2651 if (LoadWord (state, instr, temp)) 2652 LSBase = temp; 2653 break; 2654 2655 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */ 2656 (void) StoreByte (state, instr, LHS - LSImmRHS); 2657 break; 2658 2659 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */ 2660 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED); 2661 break; 2662 2663 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */ 2664 UNDEF_LSRBaseEQDestWb; 2665 UNDEF_LSRPCBaseWb; 2666 temp = LHS - LSImmRHS; 2667 if (StoreByte (state, instr, temp)) 2668 LSBase = temp; 2669 break; 2670 2671 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */ 2672 UNDEF_LSRBaseEQDestWb; 2673 UNDEF_LSRPCBaseWb; 2674 temp = LHS - LSImmRHS; 2675 if (LoadByte (state, instr, temp, LUNSIGNED)) 2676 LSBase = temp; 2677 break; 2678 2679 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */ 2680 (void) StoreWord (state, instr, LHS + LSImmRHS); 2681 break; 2682 2683 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */ 2684 (void) LoadWord (state, instr, LHS + LSImmRHS); 2685 break; 2686 2687 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */ 2688 UNDEF_LSRBaseEQDestWb; 2689 UNDEF_LSRPCBaseWb; 2690 temp = LHS + LSImmRHS; 2691 if (StoreWord (state, instr, temp)) 2692 LSBase = temp; 2693 break; 2694 2695 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */ 2696 UNDEF_LSRBaseEQDestWb; 2697 UNDEF_LSRPCBaseWb; 2698 temp = LHS + LSImmRHS; 2699 if (LoadWord (state, instr, temp)) 2700 LSBase = temp; 2701 break; 2702 2703 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */ 2704 (void) StoreByte (state, instr, LHS + LSImmRHS); 2705 break; 2706 2707 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */ 2708 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED); 2709 break; 2710 2711 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */ 2712 UNDEF_LSRBaseEQDestWb; 2713 UNDEF_LSRPCBaseWb; 2714 temp = LHS + LSImmRHS; 2715 if (StoreByte (state, instr, temp)) 2716 LSBase = temp; 2717 break; 2718 2719 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */ 2720 UNDEF_LSRBaseEQDestWb; 2721 UNDEF_LSRPCBaseWb; 2722 temp = LHS + LSImmRHS; 2723 if (LoadByte (state, instr, temp, LUNSIGNED)) 2724 LSBase = temp; 2725 break; 2726 2727 2728 /* Single Data Transfer Register RHS Instructions. */ 2729 2730 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */ 2731 if (BIT (4)) 2732 { 2733 ARMul_UndefInstr (state, instr); 2734 break; 2735 } 2736 UNDEF_LSRBaseEQOffWb; 2737 UNDEF_LSRBaseEQDestWb; 2738 UNDEF_LSRPCBaseWb; 2739 UNDEF_LSRPCOffWb; 2740 lhs = LHS; 2741 if (StoreWord (state, instr, lhs)) 2742 LSBase = lhs - LSRegRHS; 2743 break; 2744 2745 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */ 2746 if (BIT (4)) 2747 { 2748 #ifdef MODE32 2749 if (state->is_v6 2750 && handle_v6_insn (state, instr)) 2751 break; 2752 #endif 2753 ARMul_UndefInstr (state, instr); 2754 break; 2755 } 2756 UNDEF_LSRBaseEQOffWb; 2757 UNDEF_LSRBaseEQDestWb; 2758 UNDEF_LSRPCBaseWb; 2759 UNDEF_LSRPCOffWb; 2760 lhs = LHS; 2761 temp = lhs - LSRegRHS; 2762 if (LoadWord (state, instr, lhs)) 2763 LSBase = temp; 2764 break; 2765 2766 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */ 2767 if (BIT (4)) 2768 { 2769 #ifdef MODE32 2770 if (state->is_v6 2771 && handle_v6_insn (state, instr)) 2772 break; 2773 #endif 2774 ARMul_UndefInstr (state, instr); 2775 break; 2776 } 2777 UNDEF_LSRBaseEQOffWb; 2778 UNDEF_LSRBaseEQDestWb; 2779 UNDEF_LSRPCBaseWb; 2780 UNDEF_LSRPCOffWb; 2781 lhs = LHS; 2782 state->NtransSig = LOW; 2783 if (StoreWord (state, instr, lhs)) 2784 LSBase = lhs - LSRegRHS; 2785 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2786 break; 2787 2788 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */ 2789 if (BIT (4)) 2790 { 2791 #ifdef MODE32 2792 if (state->is_v6 2793 && handle_v6_insn (state, instr)) 2794 break; 2795 #endif 2796 ARMul_UndefInstr (state, instr); 2797 break; 2798 } 2799 UNDEF_LSRBaseEQOffWb; 2800 UNDEF_LSRBaseEQDestWb; 2801 UNDEF_LSRPCBaseWb; 2802 UNDEF_LSRPCOffWb; 2803 lhs = LHS; 2804 temp = lhs - LSRegRHS; 2805 state->NtransSig = LOW; 2806 if (LoadWord (state, instr, lhs)) 2807 LSBase = temp; 2808 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2809 break; 2810 2811 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */ 2812 if (BIT (4)) 2813 { 2814 ARMul_UndefInstr (state, instr); 2815 break; 2816 } 2817 UNDEF_LSRBaseEQOffWb; 2818 UNDEF_LSRBaseEQDestWb; 2819 UNDEF_LSRPCBaseWb; 2820 UNDEF_LSRPCOffWb; 2821 lhs = LHS; 2822 if (StoreByte (state, instr, lhs)) 2823 LSBase = lhs - LSRegRHS; 2824 break; 2825 2826 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */ 2827 if (BIT (4)) 2828 { 2829 #ifdef MODE32 2830 if (state->is_v6 2831 && handle_v6_insn (state, instr)) 2832 break; 2833 #endif 2834 ARMul_UndefInstr (state, instr); 2835 break; 2836 } 2837 UNDEF_LSRBaseEQOffWb; 2838 UNDEF_LSRBaseEQDestWb; 2839 UNDEF_LSRPCBaseWb; 2840 UNDEF_LSRPCOffWb; 2841 lhs = LHS; 2842 temp = lhs - LSRegRHS; 2843 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2844 LSBase = temp; 2845 break; 2846 2847 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */ 2848 if (BIT (4)) 2849 { 2850 #ifdef MODE32 2851 if (state->is_v6 2852 && handle_v6_insn (state, instr)) 2853 break; 2854 #endif 2855 ARMul_UndefInstr (state, instr); 2856 break; 2857 } 2858 UNDEF_LSRBaseEQOffWb; 2859 UNDEF_LSRBaseEQDestWb; 2860 UNDEF_LSRPCBaseWb; 2861 UNDEF_LSRPCOffWb; 2862 lhs = LHS; 2863 state->NtransSig = LOW; 2864 if (StoreByte (state, instr, lhs)) 2865 LSBase = lhs - LSRegRHS; 2866 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2867 break; 2868 2869 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */ 2870 if (BIT (4)) 2871 { 2872 #ifdef MODE32 2873 if (state->is_v6 2874 && handle_v6_insn (state, instr)) 2875 break; 2876 #endif 2877 ARMul_UndefInstr (state, instr); 2878 break; 2879 } 2880 UNDEF_LSRBaseEQOffWb; 2881 UNDEF_LSRBaseEQDestWb; 2882 UNDEF_LSRPCBaseWb; 2883 UNDEF_LSRPCOffWb; 2884 lhs = LHS; 2885 temp = lhs - LSRegRHS; 2886 state->NtransSig = LOW; 2887 if (LoadByte (state, instr, lhs, LUNSIGNED)) 2888 LSBase = temp; 2889 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2890 break; 2891 2892 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 2893 if (BIT (4)) 2894 { 2895 #ifdef MODE32 2896 if (state->is_v6 2897 && handle_v6_insn (state, instr)) 2898 break; 2899 #endif 2900 ARMul_UndefInstr (state, instr); 2901 break; 2902 } 2903 UNDEF_LSRBaseEQOffWb; 2904 UNDEF_LSRBaseEQDestWb; 2905 UNDEF_LSRPCBaseWb; 2906 UNDEF_LSRPCOffWb; 2907 lhs = LHS; 2908 if (StoreWord (state, instr, lhs)) 2909 LSBase = lhs + LSRegRHS; 2910 break; 2911 2912 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */ 2913 if (BIT (4)) 2914 { 2915 ARMul_UndefInstr (state, instr); 2916 break; 2917 } 2918 UNDEF_LSRBaseEQOffWb; 2919 UNDEF_LSRBaseEQDestWb; 2920 UNDEF_LSRPCBaseWb; 2921 UNDEF_LSRPCOffWb; 2922 lhs = LHS; 2923 temp = lhs + LSRegRHS; 2924 if (LoadWord (state, instr, lhs)) 2925 LSBase = temp; 2926 break; 2927 2928 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */ 2929 if (BIT (4)) 2930 { 2931 #ifdef MODE32 2932 if (state->is_v6 2933 && handle_v6_insn (state, instr)) 2934 break; 2935 #endif 2936 ARMul_UndefInstr (state, instr); 2937 break; 2938 } 2939 UNDEF_LSRBaseEQOffWb; 2940 UNDEF_LSRBaseEQDestWb; 2941 UNDEF_LSRPCBaseWb; 2942 UNDEF_LSRPCOffWb; 2943 lhs = LHS; 2944 state->NtransSig = LOW; 2945 if (StoreWord (state, instr, lhs)) 2946 LSBase = lhs + LSRegRHS; 2947 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2948 break; 2949 2950 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */ 2951 if (BIT (4)) 2952 { 2953 #ifdef MODE32 2954 if (state->is_v6 2955 && handle_v6_insn (state, instr)) 2956 break; 2957 #endif 2958 ARMul_UndefInstr (state, instr); 2959 break; 2960 } 2961 UNDEF_LSRBaseEQOffWb; 2962 UNDEF_LSRBaseEQDestWb; 2963 UNDEF_LSRPCBaseWb; 2964 UNDEF_LSRPCOffWb; 2965 lhs = LHS; 2966 temp = lhs + LSRegRHS; 2967 state->NtransSig = LOW; 2968 if (LoadWord (state, instr, lhs)) 2969 LSBase = temp; 2970 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 2971 break; 2972 2973 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */ 2974 if (BIT (4)) 2975 { 2976 #ifdef MODE32 2977 if (state->is_v6 2978 && handle_v6_insn (state, instr)) 2979 break; 2980 #endif 2981 ARMul_UndefInstr (state, instr); 2982 break; 2983 } 2984 UNDEF_LSRBaseEQOffWb; 2985 UNDEF_LSRBaseEQDestWb; 2986 UNDEF_LSRPCBaseWb; 2987 UNDEF_LSRPCOffWb; 2988 lhs = LHS; 2989 if (StoreByte (state, instr, lhs)) 2990 LSBase = lhs + LSRegRHS; 2991 break; 2992 2993 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */ 2994 if (BIT (4)) 2995 { 2996 ARMul_UndefInstr (state, instr); 2997 break; 2998 } 2999 UNDEF_LSRBaseEQOffWb; 3000 UNDEF_LSRBaseEQDestWb; 3001 UNDEF_LSRPCBaseWb; 3002 UNDEF_LSRPCOffWb; 3003 lhs = LHS; 3004 temp = lhs + LSRegRHS; 3005 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3006 LSBase = temp; 3007 break; 3008 3009 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */ 3010 if (BIT (4)) 3011 { 3012 #ifdef MODE32 3013 if (state->is_v6 3014 && handle_v6_insn (state, instr)) 3015 break; 3016 #endif 3017 ARMul_UndefInstr (state, instr); 3018 break; 3019 } 3020 UNDEF_LSRBaseEQOffWb; 3021 UNDEF_LSRBaseEQDestWb; 3022 UNDEF_LSRPCBaseWb; 3023 UNDEF_LSRPCOffWb; 3024 lhs = LHS; 3025 state->NtransSig = LOW; 3026 if (StoreByte (state, instr, lhs)) 3027 LSBase = lhs + LSRegRHS; 3028 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3029 break; 3030 3031 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */ 3032 if (BIT (4)) 3033 { 3034 #ifdef MODE32 3035 if (state->is_v6 3036 && handle_v6_insn (state, instr)) 3037 break; 3038 #endif 3039 ARMul_UndefInstr (state, instr); 3040 break; 3041 } 3042 UNDEF_LSRBaseEQOffWb; 3043 UNDEF_LSRBaseEQDestWb; 3044 UNDEF_LSRPCBaseWb; 3045 UNDEF_LSRPCOffWb; 3046 lhs = LHS; 3047 temp = lhs + LSRegRHS; 3048 state->NtransSig = LOW; 3049 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3050 LSBase = temp; 3051 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3052 break; 3053 3054 3055 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */ 3056 if (BIT (4)) 3057 { 3058 #ifdef MODE32 3059 if (state->is_v6 3060 && handle_v6_insn (state, instr)) 3061 break; 3062 #endif 3063 ARMul_UndefInstr (state, instr); 3064 break; 3065 } 3066 (void) StoreWord (state, instr, LHS - LSRegRHS); 3067 break; 3068 3069 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */ 3070 if (BIT (4)) 3071 { 3072 ARMul_UndefInstr (state, instr); 3073 break; 3074 } 3075 (void) LoadWord (state, instr, LHS - LSRegRHS); 3076 break; 3077 3078 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */ 3079 if (BIT (4)) 3080 { 3081 ARMul_UndefInstr (state, instr); 3082 break; 3083 } 3084 UNDEF_LSRBaseEQOffWb; 3085 UNDEF_LSRBaseEQDestWb; 3086 UNDEF_LSRPCBaseWb; 3087 UNDEF_LSRPCOffWb; 3088 temp = LHS - LSRegRHS; 3089 if (StoreWord (state, instr, temp)) 3090 LSBase = temp; 3091 break; 3092 3093 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */ 3094 if (BIT (4)) 3095 { 3096 ARMul_UndefInstr (state, instr); 3097 break; 3098 } 3099 UNDEF_LSRBaseEQOffWb; 3100 UNDEF_LSRBaseEQDestWb; 3101 UNDEF_LSRPCBaseWb; 3102 UNDEF_LSRPCOffWb; 3103 temp = LHS - LSRegRHS; 3104 if (LoadWord (state, instr, temp)) 3105 LSBase = temp; 3106 break; 3107 3108 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */ 3109 if (BIT (4)) 3110 { 3111 #ifdef MODE32 3112 if (state->is_v6 3113 && handle_v6_insn (state, instr)) 3114 break; 3115 #endif 3116 ARMul_UndefInstr (state, instr); 3117 break; 3118 } 3119 (void) StoreByte (state, instr, LHS - LSRegRHS); 3120 break; 3121 3122 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */ 3123 if (BIT (4)) 3124 { 3125 #ifdef MODE32 3126 if (state->is_v6 3127 && handle_v6_insn (state, instr)) 3128 break; 3129 #endif 3130 ARMul_UndefInstr (state, instr); 3131 break; 3132 } 3133 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED); 3134 break; 3135 3136 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */ 3137 if (BIT (4)) 3138 { 3139 ARMul_UndefInstr (state, instr); 3140 break; 3141 } 3142 UNDEF_LSRBaseEQOffWb; 3143 UNDEF_LSRBaseEQDestWb; 3144 UNDEF_LSRPCBaseWb; 3145 UNDEF_LSRPCOffWb; 3146 temp = LHS - LSRegRHS; 3147 if (StoreByte (state, instr, temp)) 3148 LSBase = temp; 3149 break; 3150 3151 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */ 3152 if (BIT (4)) 3153 { 3154 ARMul_UndefInstr (state, instr); 3155 break; 3156 } 3157 UNDEF_LSRBaseEQOffWb; 3158 UNDEF_LSRBaseEQDestWb; 3159 UNDEF_LSRPCBaseWb; 3160 UNDEF_LSRPCOffWb; 3161 temp = LHS - LSRegRHS; 3162 if (LoadByte (state, instr, temp, LUNSIGNED)) 3163 LSBase = temp; 3164 break; 3165 3166 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */ 3167 if (BIT (4)) 3168 { 3169 #ifdef MODE32 3170 if (state->is_v6 3171 && handle_v6_insn (state, instr)) 3172 break; 3173 #endif 3174 ARMul_UndefInstr (state, instr); 3175 break; 3176 } 3177 (void) StoreWord (state, instr, LHS + LSRegRHS); 3178 break; 3179 3180 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */ 3181 if (BIT (4)) 3182 { 3183 ARMul_UndefInstr (state, instr); 3184 break; 3185 } 3186 (void) LoadWord (state, instr, LHS + LSRegRHS); 3187 break; 3188 3189 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */ 3190 if (BIT (4)) 3191 { 3192 #ifdef MODE32 3193 if (state->is_v6 3194 && handle_v6_insn (state, instr)) 3195 break; 3196 #endif 3197 ARMul_UndefInstr (state, instr); 3198 break; 3199 } 3200 UNDEF_LSRBaseEQOffWb; 3201 UNDEF_LSRBaseEQDestWb; 3202 UNDEF_LSRPCBaseWb; 3203 UNDEF_LSRPCOffWb; 3204 temp = LHS + LSRegRHS; 3205 if (StoreWord (state, instr, temp)) 3206 LSBase = temp; 3207 break; 3208 3209 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */ 3210 if (BIT (4)) 3211 { 3212 ARMul_UndefInstr (state, instr); 3213 break; 3214 } 3215 UNDEF_LSRBaseEQOffWb; 3216 UNDEF_LSRBaseEQDestWb; 3217 UNDEF_LSRPCBaseWb; 3218 UNDEF_LSRPCOffWb; 3219 temp = LHS + LSRegRHS; 3220 if (LoadWord (state, instr, temp)) 3221 LSBase = temp; 3222 break; 3223 3224 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */ 3225 if (BIT (4)) 3226 { 3227 #ifdef MODE32 3228 if (state->is_v6 3229 && handle_v6_insn (state, instr)) 3230 break; 3231 #endif 3232 ARMul_UndefInstr (state, instr); 3233 break; 3234 } 3235 (void) StoreByte (state, instr, LHS + LSRegRHS); 3236 break; 3237 3238 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */ 3239 if (BIT (4)) 3240 { 3241 ARMul_UndefInstr (state, instr); 3242 break; 3243 } 3244 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED); 3245 break; 3246 3247 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */ 3248 if (BIT (4)) 3249 { 3250 ARMul_UndefInstr (state, instr); 3251 break; 3252 } 3253 UNDEF_LSRBaseEQOffWb; 3254 UNDEF_LSRBaseEQDestWb; 3255 UNDEF_LSRPCBaseWb; 3256 UNDEF_LSRPCOffWb; 3257 temp = LHS + LSRegRHS; 3258 if (StoreByte (state, instr, temp)) 3259 LSBase = temp; 3260 break; 3261 3262 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ 3263 if (BIT (4)) 3264 { 3265 /* Check for the special breakpoint opcode. 3266 This value should correspond to the value defined 3267 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */ 3268 if (BITS (0, 19) == 0xfdefe) 3269 { 3270 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint)) 3271 ARMul_Abort (state, ARMul_SWIV); 3272 } 3273 else 3274 ARMul_UndefInstr (state, instr); 3275 break; 3276 } 3277 UNDEF_LSRBaseEQOffWb; 3278 UNDEF_LSRBaseEQDestWb; 3279 UNDEF_LSRPCBaseWb; 3280 UNDEF_LSRPCOffWb; 3281 temp = LHS + LSRegRHS; 3282 if (LoadByte (state, instr, temp, LUNSIGNED)) 3283 LSBase = temp; 3284 break; 3285 3286 3287 /* Multiple Data Transfer Instructions. */ 3288 3289 case 0x80: /* Store, No WriteBack, Post Dec. */ 3290 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3291 break; 3292 3293 case 0x81: /* Load, No WriteBack, Post Dec. */ 3294 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3295 break; 3296 3297 case 0x82: /* Store, WriteBack, Post Dec. */ 3298 temp = LSBase - LSMNumRegs; 3299 STOREMULT (instr, temp + 4L, temp); 3300 break; 3301 3302 case 0x83: /* Load, WriteBack, Post Dec. */ 3303 temp = LSBase - LSMNumRegs; 3304 LOADMULT (instr, temp + 4L, temp); 3305 break; 3306 3307 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */ 3308 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3309 break; 3310 3311 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */ 3312 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 3313 break; 3314 3315 case 0x86: /* Store, Flags, WriteBack, Post Dec. */ 3316 temp = LSBase - LSMNumRegs; 3317 STORESMULT (instr, temp + 4L, temp); 3318 break; 3319 3320 case 0x87: /* Load, Flags, WriteBack, Post Dec. */ 3321 temp = LSBase - LSMNumRegs; 3322 LOADSMULT (instr, temp + 4L, temp); 3323 break; 3324 3325 case 0x88: /* Store, No WriteBack, Post Inc. */ 3326 STOREMULT (instr, LSBase, 0L); 3327 break; 3328 3329 case 0x89: /* Load, No WriteBack, Post Inc. */ 3330 LOADMULT (instr, LSBase, 0L); 3331 break; 3332 3333 case 0x8a: /* Store, WriteBack, Post Inc. */ 3334 temp = LSBase; 3335 STOREMULT (instr, temp, temp + LSMNumRegs); 3336 break; 3337 3338 case 0x8b: /* Load, WriteBack, Post Inc. */ 3339 temp = LSBase; 3340 LOADMULT (instr, temp, temp + LSMNumRegs); 3341 break; 3342 3343 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */ 3344 STORESMULT (instr, LSBase, 0L); 3345 break; 3346 3347 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */ 3348 LOADSMULT (instr, LSBase, 0L); 3349 break; 3350 3351 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */ 3352 temp = LSBase; 3353 STORESMULT (instr, temp, temp + LSMNumRegs); 3354 break; 3355 3356 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */ 3357 temp = LSBase; 3358 LOADSMULT (instr, temp, temp + LSMNumRegs); 3359 break; 3360 3361 case 0x90: /* Store, No WriteBack, Pre Dec. */ 3362 STOREMULT (instr, LSBase - LSMNumRegs, 0L); 3363 break; 3364 3365 case 0x91: /* Load, No WriteBack, Pre Dec. */ 3366 LOADMULT (instr, LSBase - LSMNumRegs, 0L); 3367 break; 3368 3369 case 0x92: /* Store, WriteBack, Pre Dec. */ 3370 temp = LSBase - LSMNumRegs; 3371 STOREMULT (instr, temp, temp); 3372 break; 3373 3374 case 0x93: /* Load, WriteBack, Pre Dec. */ 3375 temp = LSBase - LSMNumRegs; 3376 LOADMULT (instr, temp, temp); 3377 break; 3378 3379 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */ 3380 STORESMULT (instr, LSBase - LSMNumRegs, 0L); 3381 break; 3382 3383 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */ 3384 LOADSMULT (instr, LSBase - LSMNumRegs, 0L); 3385 break; 3386 3387 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */ 3388 temp = LSBase - LSMNumRegs; 3389 STORESMULT (instr, temp, temp); 3390 break; 3391 3392 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */ 3393 temp = LSBase - LSMNumRegs; 3394 LOADSMULT (instr, temp, temp); 3395 break; 3396 3397 case 0x98: /* Store, No WriteBack, Pre Inc. */ 3398 STOREMULT (instr, LSBase + 4L, 0L); 3399 break; 3400 3401 case 0x99: /* Load, No WriteBack, Pre Inc. */ 3402 LOADMULT (instr, LSBase + 4L, 0L); 3403 break; 3404 3405 case 0x9a: /* Store, WriteBack, Pre Inc. */ 3406 temp = LSBase; 3407 STOREMULT (instr, temp + 4L, temp + LSMNumRegs); 3408 break; 3409 3410 case 0x9b: /* Load, WriteBack, Pre Inc. */ 3411 temp = LSBase; 3412 LOADMULT (instr, temp + 4L, temp + LSMNumRegs); 3413 break; 3414 3415 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */ 3416 STORESMULT (instr, LSBase + 4L, 0L); 3417 break; 3418 3419 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */ 3420 LOADSMULT (instr, LSBase + 4L, 0L); 3421 break; 3422 3423 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */ 3424 temp = LSBase; 3425 STORESMULT (instr, temp + 4L, temp + LSMNumRegs); 3426 break; 3427 3428 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */ 3429 temp = LSBase; 3430 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs); 3431 break; 3432 3433 3434 /* Branch forward. */ 3435 case 0xa0: 3436 case 0xa1: 3437 case 0xa2: 3438 case 0xa3: 3439 case 0xa4: 3440 case 0xa5: 3441 case 0xa6: 3442 case 0xa7: 3443 state->Reg[15] = pc + 8 + POSBRANCH; 3444 FLUSHPIPE; 3445 break; 3446 3447 3448 /* Branch backward. */ 3449 case 0xa8: 3450 case 0xa9: 3451 case 0xaa: 3452 case 0xab: 3453 case 0xac: 3454 case 0xad: 3455 case 0xae: 3456 case 0xaf: 3457 state->Reg[15] = pc + 8 + NEGBRANCH; 3458 FLUSHPIPE; 3459 break; 3460 3461 3462 /* Branch and Link forward. */ 3463 case 0xb0: 3464 case 0xb1: 3465 case 0xb2: 3466 case 0xb3: 3467 case 0xb4: 3468 case 0xb5: 3469 case 0xb6: 3470 case 0xb7: 3471 /* Put PC into Link. */ 3472 #ifdef MODE32 3473 state->Reg[14] = pc + 4; 3474 #else 3475 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 3476 #endif 3477 state->Reg[15] = pc + 8 + POSBRANCH; 3478 FLUSHPIPE; 3479 break; 3480 3481 3482 /* Branch and Link backward. */ 3483 case 0xb8: 3484 case 0xb9: 3485 case 0xba: 3486 case 0xbb: 3487 case 0xbc: 3488 case 0xbd: 3489 case 0xbe: 3490 case 0xbf: 3491 /* Put PC into Link. */ 3492 #ifdef MODE32 3493 state->Reg[14] = pc + 4; 3494 #else 3495 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 3496 #endif 3497 state->Reg[15] = pc + 8 + NEGBRANCH; 3498 FLUSHPIPE; 3499 break; 3500 3501 3502 /* Co-Processor Data Transfers. */ 3503 case 0xc4: 3504 if (state->is_v5) 3505 { 3506 /* Reading from R15 is UNPREDICTABLE. */ 3507 if (BITS (12, 15) == 15 || BITS (16, 19) == 15) 3508 ARMul_UndefInstr (state, instr); 3509 /* Is access to coprocessor 0 allowed ? */ 3510 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 3511 ARMul_UndefInstr (state, instr); 3512 /* Special treatment for XScale coprocessors. */ 3513 else if (state->is_XScale) 3514 { 3515 /* Only opcode 0 is supported. */ 3516 if (BITS (4, 7) != 0x00) 3517 ARMul_UndefInstr (state, instr); 3518 /* Only coporcessor 0 is supported. */ 3519 else if (CPNum != 0x00) 3520 ARMul_UndefInstr (state, instr); 3521 /* Only accumulator 0 is supported. */ 3522 else if (BITS (0, 3) != 0x00) 3523 ARMul_UndefInstr (state, instr); 3524 else 3525 { 3526 /* XScale MAR insn. Move two registers into accumulator. */ 3527 state->Accumulator = state->Reg[BITS (12, 15)]; 3528 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32; 3529 } 3530 } 3531 else 3532 /* FIXME: Not sure what to do for other v5 processors. */ 3533 ARMul_UndefInstr (state, instr); 3534 break; 3535 } 3536 /* Drop through. */ 3537 3538 case 0xc0: /* Store , No WriteBack , Post Dec. */ 3539 ARMul_STC (state, instr, LHS); 3540 break; 3541 3542 case 0xc5: 3543 if (state->is_v5) 3544 { 3545 /* Writes to R15 are UNPREDICATABLE. */ 3546 if (DESTReg == 15 || LHSReg == 15) 3547 ARMul_UndefInstr (state, instr); 3548 /* Is access to the coprocessor allowed ? */ 3549 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 3550 ARMul_UndefInstr (state, instr); 3551 /* Special handling for XScale coprcoessors. */ 3552 else if (state->is_XScale) 3553 { 3554 /* Only opcode 0 is supported. */ 3555 if (BITS (4, 7) != 0x00) 3556 ARMul_UndefInstr (state, instr); 3557 /* Only coprocessor 0 is supported. */ 3558 else if (CPNum != 0x00) 3559 ARMul_UndefInstr (state, instr); 3560 /* Only accumulator 0 is supported. */ 3561 else if (BITS (0, 3) != 0x00) 3562 ARMul_UndefInstr (state, instr); 3563 else 3564 { 3565 /* XScale MRA insn. Move accumulator into two registers. */ 3566 ARMword t1 = (state->Accumulator >> 32) & 255; 3567 3568 if (t1 & 128) 3569 t1 -= 256; 3570 3571 state->Reg[BITS (12, 15)] = state->Accumulator; 3572 state->Reg[BITS (16, 19)] = t1; 3573 break; 3574 } 3575 } 3576 else 3577 /* FIXME: Not sure what to do for other v5 processors. */ 3578 ARMul_UndefInstr (state, instr); 3579 break; 3580 } 3581 /* Drop through. */ 3582 3583 case 0xc1: /* Load , No WriteBack , Post Dec. */ 3584 ARMul_LDC (state, instr, LHS); 3585 break; 3586 3587 case 0xc2: 3588 case 0xc6: /* Store , WriteBack , Post Dec. */ 3589 lhs = LHS; 3590 state->Base = lhs - LSCOff; 3591 ARMul_STC (state, instr, lhs); 3592 break; 3593 3594 case 0xc3: 3595 case 0xc7: /* Load , WriteBack , Post Dec. */ 3596 lhs = LHS; 3597 state->Base = lhs - LSCOff; 3598 ARMul_LDC (state, instr, lhs); 3599 break; 3600 3601 case 0xc8: 3602 case 0xcc: /* Store , No WriteBack , Post Inc. */ 3603 ARMul_STC (state, instr, LHS); 3604 break; 3605 3606 case 0xc9: 3607 case 0xcd: /* Load , No WriteBack , Post Inc. */ 3608 ARMul_LDC (state, instr, LHS); 3609 break; 3610 3611 case 0xca: 3612 case 0xce: /* Store , WriteBack , Post Inc. */ 3613 lhs = LHS; 3614 state->Base = lhs + LSCOff; 3615 ARMul_STC (state, instr, LHS); 3616 break; 3617 3618 case 0xcb: 3619 case 0xcf: /* Load , WriteBack , Post Inc. */ 3620 lhs = LHS; 3621 state->Base = lhs + LSCOff; 3622 ARMul_LDC (state, instr, LHS); 3623 break; 3624 3625 case 0xd0: 3626 case 0xd4: /* Store , No WriteBack , Pre Dec. */ 3627 ARMul_STC (state, instr, LHS - LSCOff); 3628 break; 3629 3630 case 0xd1: 3631 case 0xd5: /* Load , No WriteBack , Pre Dec. */ 3632 ARMul_LDC (state, instr, LHS - LSCOff); 3633 break; 3634 3635 case 0xd2: 3636 case 0xd6: /* Store , WriteBack , Pre Dec. */ 3637 lhs = LHS - LSCOff; 3638 state->Base = lhs; 3639 ARMul_STC (state, instr, lhs); 3640 break; 3641 3642 case 0xd3: 3643 case 0xd7: /* Load , WriteBack , Pre Dec. */ 3644 lhs = LHS - LSCOff; 3645 state->Base = lhs; 3646 ARMul_LDC (state, instr, lhs); 3647 break; 3648 3649 case 0xd8: 3650 case 0xdc: /* Store , No WriteBack , Pre Inc. */ 3651 ARMul_STC (state, instr, LHS + LSCOff); 3652 break; 3653 3654 case 0xd9: 3655 case 0xdd: /* Load , No WriteBack , Pre Inc. */ 3656 ARMul_LDC (state, instr, LHS + LSCOff); 3657 break; 3658 3659 case 0xda: 3660 case 0xde: /* Store , WriteBack , Pre Inc. */ 3661 lhs = LHS + LSCOff; 3662 state->Base = lhs; 3663 ARMul_STC (state, instr, lhs); 3664 break; 3665 3666 case 0xdb: 3667 case 0xdf: /* Load , WriteBack , Pre Inc. */ 3668 lhs = LHS + LSCOff; 3669 state->Base = lhs; 3670 ARMul_LDC (state, instr, lhs); 3671 break; 3672 3673 3674 /* Co-Processor Register Transfers (MCR) and Data Ops. */ 3675 3676 case 0xe2: 3677 if (! CP_ACCESS_ALLOWED (state, CPNum)) 3678 { 3679 ARMul_UndefInstr (state, instr); 3680 break; 3681 } 3682 if (state->is_XScale) 3683 switch (BITS (18, 19)) 3684 { 3685 case 0x0: 3686 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 3687 { 3688 /* XScale MIA instruction. Signed multiplication of 3689 two 32 bit values and addition to 40 bit accumulator. */ 3690 ARMsdword Rm = state->Reg[MULLHSReg]; 3691 ARMsdword Rs = state->Reg[MULACCReg]; 3692 3693 if (Rm & (1 << 31)) 3694 Rm -= 1ULL << 32; 3695 if (Rs & (1 << 31)) 3696 Rs -= 1ULL << 32; 3697 state->Accumulator += Rm * Rs; 3698 goto donext; 3699 } 3700 break; 3701 3702 case 0x2: 3703 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 3704 { 3705 /* XScale MIAPH instruction. */ 3706 ARMword t1 = state->Reg[MULLHSReg] >> 16; 3707 ARMword t2 = state->Reg[MULACCReg] >> 16; 3708 ARMword t3 = state->Reg[MULLHSReg] & 0xffff; 3709 ARMword t4 = state->Reg[MULACCReg] & 0xffff; 3710 ARMsdword t5; 3711 3712 if (t1 & (1 << 15)) 3713 t1 -= 1 << 16; 3714 if (t2 & (1 << 15)) 3715 t2 -= 1 << 16; 3716 if (t3 & (1 << 15)) 3717 t3 -= 1 << 16; 3718 if (t4 & (1 << 15)) 3719 t4 -= 1 << 16; 3720 t1 *= t2; 3721 t5 = t1; 3722 if (t5 & (1 << 31)) 3723 t5 -= 1ULL << 32; 3724 state->Accumulator += t5; 3725 t3 *= t4; 3726 t5 = t3; 3727 if (t5 & (1 << 31)) 3728 t5 -= 1ULL << 32; 3729 state->Accumulator += t5; 3730 goto donext; 3731 } 3732 break; 3733 3734 case 0x3: 3735 if (BITS (4, 11) == 1) 3736 { 3737 /* XScale MIAxy instruction. */ 3738 ARMword t1; 3739 ARMword t2; 3740 ARMsdword t5; 3741 3742 if (BIT (17)) 3743 t1 = state->Reg[MULLHSReg] >> 16; 3744 else 3745 t1 = state->Reg[MULLHSReg] & 0xffff; 3746 3747 if (BIT (16)) 3748 t2 = state->Reg[MULACCReg] >> 16; 3749 else 3750 t2 = state->Reg[MULACCReg] & 0xffff; 3751 3752 if (t1 & (1 << 15)) 3753 t1 -= 1 << 16; 3754 if (t2 & (1 << 15)) 3755 t2 -= 1 << 16; 3756 t1 *= t2; 3757 t5 = t1; 3758 if (t5 & (1 << 31)) 3759 t5 -= 1ULL << 32; 3760 state->Accumulator += t5; 3761 goto donext; 3762 } 3763 break; 3764 3765 default: 3766 break; 3767 } 3768 /* Drop through. */ 3769 3770 case 0xe0: 3771 case 0xe4: 3772 case 0xe6: 3773 case 0xe8: 3774 case 0xea: 3775 case 0xec: 3776 case 0xee: 3777 if (BIT (4)) 3778 { 3779 /* MCR. */ 3780 if (DESTReg == 15) 3781 { 3782 UNDEF_MCRPC; 3783 #ifdef MODE32 3784 ARMul_MCR (state, instr, state->Reg[15] + isize); 3785 #else 3786 ARMul_MCR (state, instr, ECC | ER15INT | EMODE | 3787 ((state->Reg[15] + isize) & R15PCBITS)); 3788 #endif 3789 } 3790 else 3791 ARMul_MCR (state, instr, DEST); 3792 } 3793 else 3794 /* CDP Part 1. */ 3795 ARMul_CDP (state, instr); 3796 break; 3797 3798 3799 /* Co-Processor Register Transfers (MRC) and Data Ops. */ 3800 case 0xe1: 3801 case 0xe3: 3802 case 0xe5: 3803 case 0xe7: 3804 case 0xe9: 3805 case 0xeb: 3806 case 0xed: 3807 case 0xef: 3808 if (BIT (4)) 3809 { 3810 /* MRC */ 3811 temp = ARMul_MRC (state, instr); 3812 if (DESTReg == 15) 3813 { 3814 ASSIGNN ((temp & NBIT) != 0); 3815 ASSIGNZ ((temp & ZBIT) != 0); 3816 ASSIGNC ((temp & CBIT) != 0); 3817 ASSIGNV ((temp & VBIT) != 0); 3818 } 3819 else 3820 DEST = temp; 3821 } 3822 else 3823 /* CDP Part 2. */ 3824 ARMul_CDP (state, instr); 3825 break; 3826 3827 3828 /* SWI instruction. */ 3829 case 0xf0: 3830 case 0xf1: 3831 case 0xf2: 3832 case 0xf3: 3833 case 0xf4: 3834 case 0xf5: 3835 case 0xf6: 3836 case 0xf7: 3837 case 0xf8: 3838 case 0xf9: 3839 case 0xfa: 3840 case 0xfb: 3841 case 0xfc: 3842 case 0xfd: 3843 case 0xfe: 3844 case 0xff: 3845 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) 3846 { 3847 /* A prefetch abort. */ 3848 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); 3849 ARMul_Abort (state, ARMul_PrefetchAbortV); 3850 break; 3851 } 3852 3853 if (!ARMul_OSHandleSWI (state, BITS (0, 23))) 3854 ARMul_Abort (state, ARMul_SWIV); 3855 3856 break; 3857 } 3858 } 3859 3860 #ifdef MODET 3861 donext: 3862 #endif 3863 3864 #ifdef NEED_UI_LOOP_HOOK 3865 if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0) 3866 { 3867 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; 3868 deprecated_ui_loop_hook (0); 3869 } 3870 #endif /* NEED_UI_LOOP_HOOK */ 3871 3872 if (state->Emulate == ONCE) 3873 state->Emulate = STOP; 3874 /* If we have changed mode, allow the PC to advance before stopping. */ 3875 else if (state->Emulate == CHANGEMODE) 3876 continue; 3877 else if (state->Emulate != RUN) 3878 break; 3879 } 3880 while (!stop_simulator); 3881 3882 state->decoded = decoded; 3883 state->loaded = loaded; 3884 state->pc = pc; 3885 3886 return pc; 3887 } 3888 3889 /* This routine evaluates most Data Processing register RHS's with the S 3890 bit clear. It is intended to be called from the macro DPRegRHS, which 3891 filters the common case of an unshifted register with in line code. */ 3892 3893 static ARMword 3894 GetDPRegRHS (ARMul_State * state, ARMword instr) 3895 { 3896 ARMword shamt, base; 3897 3898 base = RHSReg; 3899 if (BIT (4)) 3900 { 3901 /* Shift amount in a register. */ 3902 UNDEF_Shift; 3903 INCPC; 3904 #ifndef MODE32 3905 if (base == 15) 3906 base = ECC | ER15INT | R15PC | EMODE; 3907 else 3908 #endif 3909 base = state->Reg[base]; 3910 ARMul_Icycles (state, 1, 0L); 3911 shamt = state->Reg[BITS (8, 11)] & 0xff; 3912 switch ((int) BITS (5, 6)) 3913 { 3914 case LSL: 3915 if (shamt == 0) 3916 return (base); 3917 else if (shamt >= 32) 3918 return (0); 3919 else 3920 return (base << shamt); 3921 case LSR: 3922 if (shamt == 0) 3923 return (base); 3924 else if (shamt >= 32) 3925 return (0); 3926 else 3927 return (base >> shamt); 3928 case ASR: 3929 if (shamt == 0) 3930 return (base); 3931 else if (shamt >= 32) 3932 return ((ARMword) ((ARMsword) base >> 31L)); 3933 else 3934 return ((ARMword) ((ARMsword) base >> (int) shamt)); 3935 case ROR: 3936 shamt &= 0x1f; 3937 if (shamt == 0) 3938 return (base); 3939 else 3940 return ((base << (32 - shamt)) | (base >> shamt)); 3941 } 3942 } 3943 else 3944 { 3945 /* Shift amount is a constant. */ 3946 #ifndef MODE32 3947 if (base == 15) 3948 base = ECC | ER15INT | R15PC | EMODE; 3949 else 3950 #endif 3951 base = state->Reg[base]; 3952 shamt = BITS (7, 11); 3953 switch ((int) BITS (5, 6)) 3954 { 3955 case LSL: 3956 return (base << shamt); 3957 case LSR: 3958 if (shamt == 0) 3959 return (0); 3960 else 3961 return (base >> shamt); 3962 case ASR: 3963 if (shamt == 0) 3964 return ((ARMword) ((ARMsword) base >> 31L)); 3965 else 3966 return ((ARMword) ((ARMsword) base >> (int) shamt)); 3967 case ROR: 3968 if (shamt == 0) 3969 /* It's an RRX. */ 3970 return ((base >> 1) | (CFLAG << 31)); 3971 else 3972 return ((base << (32 - shamt)) | (base >> shamt)); 3973 } 3974 } 3975 3976 return 0; 3977 } 3978 3979 /* This routine evaluates most Logical Data Processing register RHS's 3980 with the S bit set. It is intended to be called from the macro 3981 DPSRegRHS, which filters the common case of an unshifted register 3982 with in line code. */ 3983 3984 static ARMword 3985 GetDPSRegRHS (ARMul_State * state, ARMword instr) 3986 { 3987 ARMword shamt, base; 3988 3989 base = RHSReg; 3990 if (BIT (4)) 3991 { 3992 /* Shift amount in a register. */ 3993 UNDEF_Shift; 3994 INCPC; 3995 #ifndef MODE32 3996 if (base == 15) 3997 base = ECC | ER15INT | R15PC | EMODE; 3998 else 3999 #endif 4000 base = state->Reg[base]; 4001 ARMul_Icycles (state, 1, 0L); 4002 shamt = state->Reg[BITS (8, 11)] & 0xff; 4003 switch ((int) BITS (5, 6)) 4004 { 4005 case LSL: 4006 if (shamt == 0) 4007 return (base); 4008 else if (shamt == 32) 4009 { 4010 ASSIGNC (base & 1); 4011 return (0); 4012 } 4013 else if (shamt > 32) 4014 { 4015 CLEARC; 4016 return (0); 4017 } 4018 else 4019 { 4020 ASSIGNC ((base >> (32 - shamt)) & 1); 4021 return (base << shamt); 4022 } 4023 case LSR: 4024 if (shamt == 0) 4025 return (base); 4026 else if (shamt == 32) 4027 { 4028 ASSIGNC (base >> 31); 4029 return (0); 4030 } 4031 else if (shamt > 32) 4032 { 4033 CLEARC; 4034 return (0); 4035 } 4036 else 4037 { 4038 ASSIGNC ((base >> (shamt - 1)) & 1); 4039 return (base >> shamt); 4040 } 4041 case ASR: 4042 if (shamt == 0) 4043 return (base); 4044 else if (shamt >= 32) 4045 { 4046 ASSIGNC (base >> 31L); 4047 return ((ARMword) ((ARMsword) base >> 31L)); 4048 } 4049 else 4050 { 4051 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 4052 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4053 } 4054 case ROR: 4055 if (shamt == 0) 4056 return (base); 4057 shamt &= 0x1f; 4058 if (shamt == 0) 4059 { 4060 ASSIGNC (base >> 31); 4061 return (base); 4062 } 4063 else 4064 { 4065 ASSIGNC ((base >> (shamt - 1)) & 1); 4066 return ((base << (32 - shamt)) | (base >> shamt)); 4067 } 4068 } 4069 } 4070 else 4071 { 4072 /* Shift amount is a constant. */ 4073 #ifndef MODE32 4074 if (base == 15) 4075 base = ECC | ER15INT | R15PC | EMODE; 4076 else 4077 #endif 4078 base = state->Reg[base]; 4079 shamt = BITS (7, 11); 4080 4081 switch ((int) BITS (5, 6)) 4082 { 4083 case LSL: 4084 ASSIGNC ((base >> (32 - shamt)) & 1); 4085 return (base << shamt); 4086 case LSR: 4087 if (shamt == 0) 4088 { 4089 ASSIGNC (base >> 31); 4090 return (0); 4091 } 4092 else 4093 { 4094 ASSIGNC ((base >> (shamt - 1)) & 1); 4095 return (base >> shamt); 4096 } 4097 case ASR: 4098 if (shamt == 0) 4099 { 4100 ASSIGNC (base >> 31L); 4101 return ((ARMword) ((ARMsword) base >> 31L)); 4102 } 4103 else 4104 { 4105 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 4106 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4107 } 4108 case ROR: 4109 if (shamt == 0) 4110 { 4111 /* It's an RRX. */ 4112 shamt = CFLAG; 4113 ASSIGNC (base & 1); 4114 return ((base >> 1) | (shamt << 31)); 4115 } 4116 else 4117 { 4118 ASSIGNC ((base >> (shamt - 1)) & 1); 4119 return ((base << (32 - shamt)) | (base >> shamt)); 4120 } 4121 } 4122 } 4123 4124 return 0; 4125 } 4126 4127 /* This routine handles writes to register 15 when the S bit is not set. */ 4128 4129 static void 4130 WriteR15 (ARMul_State * state, ARMword src) 4131 { 4132 /* The ARM documentation states that the two least significant bits 4133 are discarded when setting PC, except in the cases handled by 4134 WriteR15Branch() below. It's probably an oversight: in THUMB 4135 mode, the second least significant bit should probably not be 4136 discarded. */ 4137 #ifdef MODET 4138 if (TFLAG) 4139 src &= 0xfffffffe; 4140 else 4141 #endif 4142 src &= 0xfffffffc; 4143 4144 #ifdef MODE32 4145 state->Reg[15] = src & PCBITS; 4146 #else 4147 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE; 4148 ARMul_R15Altered (state); 4149 #endif 4150 4151 FLUSHPIPE; 4152 } 4153 4154 /* This routine handles writes to register 15 when the S bit is set. */ 4155 4156 static void 4157 WriteSR15 (ARMul_State * state, ARMword src) 4158 { 4159 #ifdef MODE32 4160 if (state->Bank > 0) 4161 { 4162 state->Cpsr = state->Spsr[state->Bank]; 4163 ARMul_CPSRAltered (state); 4164 } 4165 #ifdef MODET 4166 if (TFLAG) 4167 src &= 0xfffffffe; 4168 else 4169 #endif 4170 src &= 0xfffffffc; 4171 state->Reg[15] = src & PCBITS; 4172 #else 4173 #ifdef MODET 4174 if (TFLAG) 4175 /* ARMul_R15Altered would have to support it. */ 4176 abort (); 4177 else 4178 #endif 4179 src &= 0xfffffffc; 4180 4181 if (state->Bank == USERBANK) 4182 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; 4183 else 4184 state->Reg[15] = src; 4185 4186 ARMul_R15Altered (state); 4187 #endif 4188 FLUSHPIPE; 4189 } 4190 4191 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM 4192 will switch to Thumb mode if the least significant bit is set. */ 4193 4194 static void 4195 WriteR15Branch (ARMul_State * state, ARMword src) 4196 { 4197 #ifdef MODET 4198 if (src & 1) 4199 { 4200 /* Thumb bit. */ 4201 SETT; 4202 state->Reg[15] = src & 0xfffffffe; 4203 } 4204 else 4205 { 4206 CLEART; 4207 state->Reg[15] = src & 0xfffffffc; 4208 } 4209 FLUSHPIPE; 4210 #else 4211 WriteR15 (state, src); 4212 #endif 4213 } 4214 4215 /* This routine evaluates most Load and Store register RHS's. It is 4216 intended to be called from the macro LSRegRHS, which filters the 4217 common case of an unshifted register with in line code. */ 4218 4219 static ARMword 4220 GetLSRegRHS (ARMul_State * state, ARMword instr) 4221 { 4222 ARMword shamt, base; 4223 4224 base = RHSReg; 4225 #ifndef MODE32 4226 if (base == 15) 4227 /* Now forbidden, but ... */ 4228 base = ECC | ER15INT | R15PC | EMODE; 4229 else 4230 #endif 4231 base = state->Reg[base]; 4232 4233 shamt = BITS (7, 11); 4234 switch ((int) BITS (5, 6)) 4235 { 4236 case LSL: 4237 return (base << shamt); 4238 case LSR: 4239 if (shamt == 0) 4240 return (0); 4241 else 4242 return (base >> shamt); 4243 case ASR: 4244 if (shamt == 0) 4245 return ((ARMword) ((ARMsword) base >> 31L)); 4246 else 4247 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4248 case ROR: 4249 if (shamt == 0) 4250 /* It's an RRX. */ 4251 return ((base >> 1) | (CFLAG << 31)); 4252 else 4253 return ((base << (32 - shamt)) | (base >> shamt)); 4254 default: 4255 break; 4256 } 4257 return 0; 4258 } 4259 4260 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */ 4261 4262 static ARMword 4263 GetLS7RHS (ARMul_State * state, ARMword instr) 4264 { 4265 if (BIT (22) == 0) 4266 { 4267 /* Register. */ 4268 #ifndef MODE32 4269 if (RHSReg == 15) 4270 /* Now forbidden, but ... */ 4271 return ECC | ER15INT | R15PC | EMODE; 4272 #endif 4273 return state->Reg[RHSReg]; 4274 } 4275 4276 /* Immediate. */ 4277 return BITS (0, 3) | (BITS (8, 11) << 4); 4278 } 4279 4280 /* This function does the work of loading a word for a LDR instruction. */ 4281 4282 static unsigned 4283 LoadWord (ARMul_State * state, ARMword instr, ARMword address) 4284 { 4285 ARMword dest; 4286 4287 BUSUSEDINCPCS; 4288 #ifndef MODE32 4289 if (ADDREXCEPT (address)) 4290 INTERNALABORT (address); 4291 #endif 4292 4293 dest = ARMul_LoadWordN (state, address); 4294 4295 if (state->Aborted) 4296 { 4297 TAKEABORT; 4298 return state->lateabtSig; 4299 } 4300 if (address & 3) 4301 dest = ARMul_Align (state, address, dest); 4302 WRITEDESTB (dest); 4303 ARMul_Icycles (state, 1, 0L); 4304 4305 return (DESTReg != LHSReg); 4306 } 4307 4308 #ifdef MODET 4309 /* This function does the work of loading a halfword. */ 4310 4311 static unsigned 4312 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, 4313 int signextend) 4314 { 4315 ARMword dest; 4316 4317 BUSUSEDINCPCS; 4318 #ifndef MODE32 4319 if (ADDREXCEPT (address)) 4320 INTERNALABORT (address); 4321 #endif 4322 dest = ARMul_LoadHalfWord (state, address); 4323 if (state->Aborted) 4324 { 4325 TAKEABORT; 4326 return state->lateabtSig; 4327 } 4328 UNDEF_LSRBPC; 4329 if (signextend) 4330 if (dest & 1 << (16 - 1)) 4331 dest = (dest & ((1 << 16) - 1)) - (1 << 16); 4332 4333 WRITEDEST (dest); 4334 ARMul_Icycles (state, 1, 0L); 4335 return (DESTReg != LHSReg); 4336 } 4337 4338 #endif /* MODET */ 4339 4340 /* This function does the work of loading a byte for a LDRB instruction. */ 4341 4342 static unsigned 4343 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) 4344 { 4345 ARMword dest; 4346 4347 BUSUSEDINCPCS; 4348 #ifndef MODE32 4349 if (ADDREXCEPT (address)) 4350 INTERNALABORT (address); 4351 #endif 4352 dest = ARMul_LoadByte (state, address); 4353 if (state->Aborted) 4354 { 4355 TAKEABORT; 4356 return state->lateabtSig; 4357 } 4358 UNDEF_LSRBPC; 4359 if (signextend) 4360 if (dest & 1 << (8 - 1)) 4361 dest = (dest & ((1 << 8) - 1)) - (1 << 8); 4362 4363 WRITEDEST (dest); 4364 ARMul_Icycles (state, 1, 0L); 4365 4366 return (DESTReg != LHSReg); 4367 } 4368 4369 /* This function does the work of loading two words for a LDRD instruction. */ 4370 4371 static void 4372 Handle_Load_Double (ARMul_State * state, ARMword instr) 4373 { 4374 ARMword dest_reg; 4375 ARMword addr_reg; 4376 ARMword write_back = BIT (21); 4377 ARMword immediate = BIT (22); 4378 ARMword add_to_base = BIT (23); 4379 ARMword pre_indexed = BIT (24); 4380 ARMword offset; 4381 ARMword addr; 4382 ARMword sum; 4383 ARMword base; 4384 ARMword value1; 4385 ARMword value2; 4386 4387 BUSUSEDINCPCS; 4388 4389 /* If the writeback bit is set, the pre-index bit must be clear. */ 4390 if (write_back && ! pre_indexed) 4391 { 4392 ARMul_UndefInstr (state, instr); 4393 return; 4394 } 4395 4396 /* Extract the base address register. */ 4397 addr_reg = LHSReg; 4398 4399 /* Extract the destination register and check it. */ 4400 dest_reg = DESTReg; 4401 4402 /* Destination register must be even. */ 4403 if ((dest_reg & 1) 4404 /* Destination register cannot be LR. */ 4405 || (dest_reg == 14)) 4406 { 4407 ARMul_UndefInstr (state, instr); 4408 return; 4409 } 4410 4411 /* Compute the base address. */ 4412 base = state->Reg[addr_reg]; 4413 4414 /* Compute the offset. */ 4415 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 4416 4417 /* Compute the sum of the two. */ 4418 if (add_to_base) 4419 sum = base + offset; 4420 else 4421 sum = base - offset; 4422 4423 /* If this is a pre-indexed mode use the sum. */ 4424 if (pre_indexed) 4425 addr = sum; 4426 else 4427 addr = base; 4428 4429 /* The address must be aligned on a 8 byte boundary. */ 4430 if (addr & 0x7) 4431 { 4432 #ifdef ABORTS 4433 ARMul_DATAABORT (addr); 4434 #else 4435 ARMul_UndefInstr (state, instr); 4436 #endif 4437 return; 4438 } 4439 4440 /* For pre indexed or post indexed addressing modes, 4441 check that the destination registers do not overlap 4442 the address registers. */ 4443 if ((! pre_indexed || write_back) 4444 && ( addr_reg == dest_reg 4445 || addr_reg == dest_reg + 1)) 4446 { 4447 ARMul_UndefInstr (state, instr); 4448 return; 4449 } 4450 4451 /* Load the words. */ 4452 value1 = ARMul_LoadWordN (state, addr); 4453 value2 = ARMul_LoadWordN (state, addr + 4); 4454 4455 /* Check for data aborts. */ 4456 if (state->Aborted) 4457 { 4458 TAKEABORT; 4459 return; 4460 } 4461 4462 ARMul_Icycles (state, 2, 0L); 4463 4464 /* Store the values. */ 4465 state->Reg[dest_reg] = value1; 4466 state->Reg[dest_reg + 1] = value2; 4467 4468 /* Do the post addressing and writeback. */ 4469 if (! pre_indexed) 4470 addr = sum; 4471 4472 if (! pre_indexed || write_back) 4473 state->Reg[addr_reg] = addr; 4474 } 4475 4476 /* This function does the work of storing two words for a STRD instruction. */ 4477 4478 static void 4479 Handle_Store_Double (ARMul_State * state, ARMword instr) 4480 { 4481 ARMword src_reg; 4482 ARMword addr_reg; 4483 ARMword write_back = BIT (21); 4484 ARMword immediate = BIT (22); 4485 ARMword add_to_base = BIT (23); 4486 ARMword pre_indexed = BIT (24); 4487 ARMword offset; 4488 ARMword addr; 4489 ARMword sum; 4490 ARMword base; 4491 4492 BUSUSEDINCPCS; 4493 4494 /* If the writeback bit is set, the pre-index bit must be clear. */ 4495 if (write_back && ! pre_indexed) 4496 { 4497 ARMul_UndefInstr (state, instr); 4498 return; 4499 } 4500 4501 /* Extract the base address register. */ 4502 addr_reg = LHSReg; 4503 4504 /* Base register cannot be PC. */ 4505 if (addr_reg == 15) 4506 { 4507 ARMul_UndefInstr (state, instr); 4508 return; 4509 } 4510 4511 /* Extract the source register. */ 4512 src_reg = DESTReg; 4513 4514 /* Source register must be even. */ 4515 if (src_reg & 1) 4516 { 4517 ARMul_UndefInstr (state, instr); 4518 return; 4519 } 4520 4521 /* Compute the base address. */ 4522 base = state->Reg[addr_reg]; 4523 4524 /* Compute the offset. */ 4525 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 4526 4527 /* Compute the sum of the two. */ 4528 if (add_to_base) 4529 sum = base + offset; 4530 else 4531 sum = base - offset; 4532 4533 /* If this is a pre-indexed mode use the sum. */ 4534 if (pre_indexed) 4535 addr = sum; 4536 else 4537 addr = base; 4538 4539 /* The address must be aligned on a 8 byte boundary. */ 4540 if (addr & 0x7) 4541 { 4542 #ifdef ABORTS 4543 ARMul_DATAABORT (addr); 4544 #else 4545 ARMul_UndefInstr (state, instr); 4546 #endif 4547 return; 4548 } 4549 4550 /* For pre indexed or post indexed addressing modes, 4551 check that the destination registers do not overlap 4552 the address registers. */ 4553 if ((! pre_indexed || write_back) 4554 && ( addr_reg == src_reg 4555 || addr_reg == src_reg + 1)) 4556 { 4557 ARMul_UndefInstr (state, instr); 4558 return; 4559 } 4560 4561 /* Load the words. */ 4562 ARMul_StoreWordN (state, addr, state->Reg[src_reg]); 4563 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]); 4564 4565 if (state->Aborted) 4566 { 4567 TAKEABORT; 4568 return; 4569 } 4570 4571 /* Do the post addressing and writeback. */ 4572 if (! pre_indexed) 4573 addr = sum; 4574 4575 if (! pre_indexed || write_back) 4576 state->Reg[addr_reg] = addr; 4577 } 4578 4579 /* This function does the work of storing a word from a STR instruction. */ 4580 4581 static unsigned 4582 StoreWord (ARMul_State * state, ARMword instr, ARMword address) 4583 { 4584 BUSUSEDINCPCN; 4585 #ifndef MODE32 4586 if (DESTReg == 15) 4587 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4588 #endif 4589 #ifdef MODE32 4590 ARMul_StoreWordN (state, address, DEST); 4591 #else 4592 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4593 { 4594 INTERNALABORT (address); 4595 (void) ARMul_LoadWordN (state, address); 4596 } 4597 else 4598 ARMul_StoreWordN (state, address, DEST); 4599 #endif 4600 if (state->Aborted) 4601 { 4602 TAKEABORT; 4603 return state->lateabtSig; 4604 } 4605 return TRUE; 4606 } 4607 4608 #ifdef MODET 4609 /* This function does the work of storing a byte for a STRH instruction. */ 4610 4611 static unsigned 4612 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) 4613 { 4614 BUSUSEDINCPCN; 4615 4616 #ifndef MODE32 4617 if (DESTReg == 15) 4618 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4619 #endif 4620 4621 #ifdef MODE32 4622 ARMul_StoreHalfWord (state, address, DEST); 4623 #else 4624 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4625 { 4626 INTERNALABORT (address); 4627 (void) ARMul_LoadHalfWord (state, address); 4628 } 4629 else 4630 ARMul_StoreHalfWord (state, address, DEST); 4631 #endif 4632 4633 if (state->Aborted) 4634 { 4635 TAKEABORT; 4636 return state->lateabtSig; 4637 } 4638 return TRUE; 4639 } 4640 4641 #endif /* MODET */ 4642 4643 /* This function does the work of storing a byte for a STRB instruction. */ 4644 4645 static unsigned 4646 StoreByte (ARMul_State * state, ARMword instr, ARMword address) 4647 { 4648 BUSUSEDINCPCN; 4649 #ifndef MODE32 4650 if (DESTReg == 15) 4651 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 4652 #endif 4653 #ifdef MODE32 4654 ARMul_StoreByte (state, address, DEST); 4655 #else 4656 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4657 { 4658 INTERNALABORT (address); 4659 (void) ARMul_LoadByte (state, address); 4660 } 4661 else 4662 ARMul_StoreByte (state, address, DEST); 4663 #endif 4664 if (state->Aborted) 4665 { 4666 TAKEABORT; 4667 return state->lateabtSig; 4668 } 4669 UNDEF_LSRBPC; 4670 return TRUE; 4671 } 4672 4673 /* This function does the work of loading the registers listed in an LDM 4674 instruction, when the S bit is clear. The code here is always increment 4675 after, it's up to the caller to get the input address correct and to 4676 handle base register modification. */ 4677 4678 static void 4679 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) 4680 { 4681 ARMword dest, temp; 4682 4683 UNDEF_LSMNoRegs; 4684 UNDEF_LSMPCBase; 4685 UNDEF_LSMBaseInListWb; 4686 BUSUSEDINCPCS; 4687 #ifndef MODE32 4688 if (ADDREXCEPT (address)) 4689 INTERNALABORT (address); 4690 #endif 4691 if (BIT (21) && LHSReg != 15) 4692 LSBase = WBBase; 4693 4694 /* N cycle first. */ 4695 for (temp = 0; !BIT (temp); temp++) 4696 ; 4697 4698 dest = ARMul_LoadWordN (state, address); 4699 4700 if (!state->abortSig && !state->Aborted) 4701 state->Reg[temp++] = dest; 4702 else if (!state->Aborted) 4703 { 4704 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4705 state->Aborted = ARMul_DataAbortV; 4706 } 4707 4708 /* S cycles from here on. */ 4709 for (; temp < 16; temp ++) 4710 if (BIT (temp)) 4711 { 4712 /* Load this register. */ 4713 address += 4; 4714 dest = ARMul_LoadWordS (state, address); 4715 4716 if (!state->abortSig && !state->Aborted) 4717 state->Reg[temp] = dest; 4718 else if (!state->Aborted) 4719 { 4720 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4721 state->Aborted = ARMul_DataAbortV; 4722 } 4723 } 4724 4725 if (BIT (15) && !state->Aborted) 4726 /* PC is in the reg list. */ 4727 WriteR15Branch (state, PC); 4728 4729 /* To write back the final register. */ 4730 ARMul_Icycles (state, 1, 0L); 4731 4732 if (state->Aborted) 4733 { 4734 if (BIT (21) && LHSReg != 15) 4735 LSBase = WBBase; 4736 TAKEABORT; 4737 } 4738 } 4739 4740 /* This function does the work of loading the registers listed in an LDM 4741 instruction, when the S bit is set. The code here is always increment 4742 after, it's up to the caller to get the input address correct and to 4743 handle base register modification. */ 4744 4745 static void 4746 LoadSMult (ARMul_State * state, 4747 ARMword instr, 4748 ARMword address, 4749 ARMword WBBase) 4750 { 4751 ARMword dest, temp; 4752 4753 UNDEF_LSMNoRegs; 4754 UNDEF_LSMPCBase; 4755 UNDEF_LSMBaseInListWb; 4756 4757 BUSUSEDINCPCS; 4758 4759 #ifndef MODE32 4760 if (ADDREXCEPT (address)) 4761 INTERNALABORT (address); 4762 #endif 4763 4764 if (BIT (21) && LHSReg != 15) 4765 LSBase = WBBase; 4766 4767 if (!BIT (15) && state->Bank != USERBANK) 4768 { 4769 /* Temporary reg bank switch. */ 4770 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 4771 UNDEF_LSMUserBankWb; 4772 } 4773 4774 /* N cycle first. */ 4775 for (temp = 0; !BIT (temp); temp ++) 4776 ; 4777 4778 dest = ARMul_LoadWordN (state, address); 4779 4780 if (!state->abortSig) 4781 state->Reg[temp++] = dest; 4782 else if (!state->Aborted) 4783 { 4784 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4785 state->Aborted = ARMul_DataAbortV; 4786 } 4787 4788 /* S cycles from here on. */ 4789 for (; temp < 16; temp++) 4790 if (BIT (temp)) 4791 { 4792 /* Load this register. */ 4793 address += 4; 4794 dest = ARMul_LoadWordS (state, address); 4795 4796 if (!state->abortSig && !state->Aborted) 4797 state->Reg[temp] = dest; 4798 else if (!state->Aborted) 4799 { 4800 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4801 state->Aborted = ARMul_DataAbortV; 4802 } 4803 } 4804 4805 if (BIT (15) && !state->Aborted) 4806 { 4807 /* PC is in the reg list. */ 4808 #ifdef MODE32 4809 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 4810 { 4811 state->Cpsr = GETSPSR (state->Bank); 4812 ARMul_CPSRAltered (state); 4813 } 4814 4815 WriteR15 (state, PC); 4816 #else 4817 if (state->Mode == USER26MODE || state->Mode == USER32MODE) 4818 { 4819 /* Protect bits in user mode. */ 4820 ASSIGNN ((state->Reg[15] & NBIT) != 0); 4821 ASSIGNZ ((state->Reg[15] & ZBIT) != 0); 4822 ASSIGNC ((state->Reg[15] & CBIT) != 0); 4823 ASSIGNV ((state->Reg[15] & VBIT) != 0); 4824 } 4825 else 4826 ARMul_R15Altered (state); 4827 4828 FLUSHPIPE; 4829 #endif 4830 } 4831 4832 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE) 4833 /* Restore the correct bank. */ 4834 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 4835 4836 /* To write back the final register. */ 4837 ARMul_Icycles (state, 1, 0L); 4838 4839 if (state->Aborted) 4840 { 4841 if (BIT (21) && LHSReg != 15) 4842 LSBase = WBBase; 4843 4844 TAKEABORT; 4845 } 4846 } 4847 4848 /* This function does the work of storing the registers listed in an STM 4849 instruction, when the S bit is clear. The code here is always increment 4850 after, it's up to the caller to get the input address correct and to 4851 handle base register modification. */ 4852 4853 static void 4854 StoreMult (ARMul_State * state, 4855 ARMword instr, 4856 ARMword address, 4857 ARMword WBBase) 4858 { 4859 ARMword temp; 4860 4861 UNDEF_LSMNoRegs; 4862 UNDEF_LSMPCBase; 4863 UNDEF_LSMBaseInListWb; 4864 4865 if (!TFLAG) 4866 /* N-cycle, increment the PC and update the NextInstr state. */ 4867 BUSUSEDINCPCN; 4868 4869 #ifndef MODE32 4870 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4871 INTERNALABORT (address); 4872 4873 if (BIT (15)) 4874 PATCHR15; 4875 #endif 4876 4877 /* N cycle first. */ 4878 for (temp = 0; !BIT (temp); temp ++) 4879 ; 4880 4881 #ifdef MODE32 4882 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4883 #else 4884 if (state->Aborted) 4885 { 4886 (void) ARMul_LoadWordN (state, address); 4887 4888 /* Fake the Stores as Loads. */ 4889 for (; temp < 16; temp++) 4890 if (BIT (temp)) 4891 { 4892 /* Save this register. */ 4893 address += 4; 4894 (void) ARMul_LoadWordS (state, address); 4895 } 4896 4897 if (BIT (21) && LHSReg != 15) 4898 LSBase = WBBase; 4899 TAKEABORT; 4900 return; 4901 } 4902 else 4903 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4904 #endif 4905 4906 if (state->abortSig && !state->Aborted) 4907 { 4908 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4909 state->Aborted = ARMul_DataAbortV; 4910 } 4911 4912 if (BIT (21) && LHSReg != 15) 4913 LSBase = WBBase; 4914 4915 /* S cycles from here on. */ 4916 for (; temp < 16; temp ++) 4917 if (BIT (temp)) 4918 { 4919 /* Save this register. */ 4920 address += 4; 4921 4922 ARMul_StoreWordS (state, address, state->Reg[temp]); 4923 4924 if (state->abortSig && !state->Aborted) 4925 { 4926 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 4927 state->Aborted = ARMul_DataAbortV; 4928 } 4929 } 4930 4931 if (state->Aborted) 4932 TAKEABORT; 4933 } 4934 4935 /* This function does the work of storing the registers listed in an STM 4936 instruction when the S bit is set. The code here is always increment 4937 after, it's up to the caller to get the input address correct and to 4938 handle base register modification. */ 4939 4940 static void 4941 StoreSMult (ARMul_State * state, 4942 ARMword instr, 4943 ARMword address, 4944 ARMword WBBase) 4945 { 4946 ARMword temp; 4947 4948 UNDEF_LSMNoRegs; 4949 UNDEF_LSMPCBase; 4950 UNDEF_LSMBaseInListWb; 4951 4952 BUSUSEDINCPCN; 4953 4954 #ifndef MODE32 4955 if (VECTORACCESS (address) || ADDREXCEPT (address)) 4956 INTERNALABORT (address); 4957 4958 if (BIT (15)) 4959 PATCHR15; 4960 #endif 4961 4962 if (state->Bank != USERBANK) 4963 { 4964 /* Force User Bank. */ 4965 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 4966 UNDEF_LSMUserBankWb; 4967 } 4968 4969 for (temp = 0; !BIT (temp); temp++) 4970 ; /* N cycle first. */ 4971 4972 #ifdef MODE32 4973 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4974 #else 4975 if (state->Aborted) 4976 { 4977 (void) ARMul_LoadWordN (state, address); 4978 4979 for (; temp < 16; temp++) 4980 /* Fake the Stores as Loads. */ 4981 if (BIT (temp)) 4982 { 4983 /* Save this register. */ 4984 address += 4; 4985 4986 (void) ARMul_LoadWordS (state, address); 4987 } 4988 4989 if (BIT (21) && LHSReg != 15) 4990 LSBase = WBBase; 4991 4992 TAKEABORT; 4993 return; 4994 } 4995 else 4996 ARMul_StoreWordN (state, address, state->Reg[temp++]); 4997 #endif 4998 4999 if (state->abortSig && !state->Aborted) 5000 { 5001 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5002 state->Aborted = ARMul_DataAbortV; 5003 } 5004 5005 /* S cycles from here on. */ 5006 for (; temp < 16; temp++) 5007 if (BIT (temp)) 5008 { 5009 /* Save this register. */ 5010 address += 4; 5011 5012 ARMul_StoreWordS (state, address, state->Reg[temp]); 5013 5014 if (state->abortSig && !state->Aborted) 5015 { 5016 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5017 state->Aborted = ARMul_DataAbortV; 5018 } 5019 } 5020 5021 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 5022 /* Restore the correct bank. */ 5023 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 5024 5025 if (BIT (21) && LHSReg != 15) 5026 LSBase = WBBase; 5027 5028 if (state->Aborted) 5029 TAKEABORT; 5030 } 5031 5032 /* This function does the work of adding two 32bit values 5033 together, and calculating if a carry has occurred. */ 5034 5035 static ARMword 5036 Add32 (ARMword a1, ARMword a2, int *carry) 5037 { 5038 ARMword result = (a1 + a2); 5039 unsigned int uresult = (unsigned int) result; 5040 unsigned int ua1 = (unsigned int) a1; 5041 5042 /* If (result == RdLo) and (state->Reg[nRdLo] == 0), 5043 or (result > RdLo) then we have no carry. */ 5044 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) 5045 *carry = 1; 5046 else 5047 *carry = 0; 5048 5049 return result; 5050 } 5051 5052 /* This function does the work of multiplying 5053 two 32bit values to give a 64bit result. */ 5054 5055 static unsigned 5056 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) 5057 { 5058 /* Operand register numbers. */ 5059 int nRdHi, nRdLo, nRs, nRm; 5060 ARMword RdHi = 0, RdLo = 0, Rm; 5061 /* Cycle count. */ 5062 int scount; 5063 5064 nRdHi = BITS (16, 19); 5065 nRdLo = BITS (12, 15); 5066 nRs = BITS (8, 11); 5067 nRm = BITS (0, 3); 5068 5069 /* Needed to calculate the cycle count. */ 5070 Rm = state->Reg[nRm]; 5071 5072 /* Check for illegal operand combinations first. */ 5073 if ( nRdHi != 15 5074 && nRdLo != 15 5075 && nRs != 15 5076 && nRm != 15 5077 && nRdHi != nRdLo 5078 && nRdHi != nRm 5079 && nRdLo != nRm) 5080 { 5081 /* Intermediate results. */ 5082 ARMword lo, mid1, mid2, hi; 5083 int carry; 5084 ARMword Rs = state->Reg[nRs]; 5085 int sign = 0; 5086 5087 if (msigned) 5088 { 5089 /* Compute sign of result and adjust operands if necessary. */ 5090 sign = (Rm ^ Rs) & 0x80000000; 5091 5092 if (((ARMsword) Rm) < 0) 5093 Rm = -Rm; 5094 5095 if (((ARMsword) Rs) < 0) 5096 Rs = -Rs; 5097 } 5098 5099 /* We can split the 32x32 into four 16x16 operations. This 5100 ensures that we do not lose precision on 32bit only hosts. */ 5101 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); 5102 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 5103 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); 5104 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 5105 5106 /* We now need to add all of these results together, taking 5107 care to propogate the carries from the additions. */ 5108 RdLo = Add32 (lo, (mid1 << 16), &carry); 5109 RdHi = carry; 5110 RdLo = Add32 (RdLo, (mid2 << 16), &carry); 5111 RdHi += 5112 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); 5113 5114 if (sign) 5115 { 5116 /* Negate result if necessary. */ 5117 RdLo = ~RdLo; 5118 RdHi = ~RdHi; 5119 if (RdLo == 0xFFFFFFFF) 5120 { 5121 RdLo = 0; 5122 RdHi += 1; 5123 } 5124 else 5125 RdLo += 1; 5126 } 5127 5128 state->Reg[nRdLo] = RdLo; 5129 state->Reg[nRdHi] = RdHi; 5130 } 5131 else 5132 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n"); 5133 5134 if (scc) 5135 /* Ensure that both RdHi and RdLo are used to compute Z, 5136 but don't let RdLo's sign bit make it to N. */ 5137 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 5138 5139 /* The cycle count depends on whether the instruction is a signed or 5140 unsigned multiply, and what bits are clear in the multiplier. */ 5141 if (msigned && (Rm & ((unsigned) 1 << 31))) 5142 /* Invert the bits to make the check against zero. */ 5143 Rm = ~Rm; 5144 5145 if ((Rm & 0xFFFFFF00) == 0) 5146 scount = 1; 5147 else if ((Rm & 0xFFFF0000) == 0) 5148 scount = 2; 5149 else if ((Rm & 0xFF000000) == 0) 5150 scount = 3; 5151 else 5152 scount = 4; 5153 5154 return 2 + scount; 5155 } 5156 5157 /* This function does the work of multiplying two 32bit 5158 values and adding a 64bit value to give a 64bit result. */ 5159 5160 static unsigned 5161 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) 5162 { 5163 unsigned scount; 5164 ARMword RdLo, RdHi; 5165 int nRdHi, nRdLo; 5166 int carry = 0; 5167 5168 nRdHi = BITS (16, 19); 5169 nRdLo = BITS (12, 15); 5170 5171 RdHi = state->Reg[nRdHi]; 5172 RdLo = state->Reg[nRdLo]; 5173 5174 scount = Multiply64 (state, instr, msigned, LDEFAULT); 5175 5176 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry); 5177 RdHi = (RdHi + state->Reg[nRdHi]) + carry; 5178 5179 state->Reg[nRdLo] = RdLo; 5180 state->Reg[nRdHi] = RdHi; 5181 5182 if (scc) 5183 /* Ensure that both RdHi and RdLo are used to compute Z, 5184 but don't let RdLo's sign bit make it to N. */ 5185 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 5186 5187 /* Extra cycle for addition. */ 5188 return scount + 1; 5189 } 5190