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