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