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 ARMword 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 ARMword dest; 1438 1439 state->Reg[14] = pc + 4; 1440 1441 /* Force entry into Thumb mode. */ 1442 dest = pc + 8 + 1; 1443 if (BIT (23)) 1444 dest += (NEGBRANCH + (BIT (24) << 1)); 1445 else 1446 dest += POSBRANCH + (BIT (24) << 1); 1447 1448 WriteR15Branch (state, dest); 1449 goto donext; 1450 } 1451 else if ((instr & 0xFC70F000) == 0xF450F000) 1452 /* The PLD instruction. Ignored. */ 1453 goto donext; 1454 else if ( ((instr & 0xfe500f00) == 0xfc100100) 1455 || ((instr & 0xfe500f00) == 0xfc000100)) 1456 /* wldrw and wstrw are unconditional. */ 1457 goto mainswitch; 1458 else 1459 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */ 1460 ARMul_UndefInstr (state, instr); 1461 } 1462 temp = FALSE; 1463 break; 1464 case EQ: 1465 temp = ZFLAG; 1466 break; 1467 case NE: 1468 temp = !ZFLAG; 1469 break; 1470 case VS: 1471 temp = VFLAG; 1472 break; 1473 case VC: 1474 temp = !VFLAG; 1475 break; 1476 case MI: 1477 temp = NFLAG; 1478 break; 1479 case PL: 1480 temp = !NFLAG; 1481 break; 1482 case CS: 1483 temp = CFLAG; 1484 break; 1485 case CC: 1486 temp = !CFLAG; 1487 break; 1488 case HI: 1489 temp = (CFLAG && !ZFLAG); 1490 break; 1491 case LS: 1492 temp = (!CFLAG || ZFLAG); 1493 break; 1494 case GE: 1495 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); 1496 break; 1497 case LT: 1498 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); 1499 break; 1500 case GT: 1501 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)); 1502 break; 1503 case LE: 1504 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG; 1505 break; 1506 } /* cc check */ 1507 1508 /* Handle the Clock counter here. */ 1509 if (state->is_XScale) 1510 { 1511 ARMword cp14r0; 1512 int ok; 1513 1514 ok = state->CPRead[14] (state, 0, & cp14r0); 1515 1516 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE)) 1517 { 1518 unsigned long newcycles, nowtime = ARMul_Time (state); 1519 1520 newcycles = nowtime - state->LastTime; 1521 state->LastTime = nowtime; 1522 1523 if (cp14r0 & ARMul_CP14_R0_CCD) 1524 { 1525 if (state->CP14R0_CCD == -1) 1526 state->CP14R0_CCD = newcycles; 1527 else 1528 state->CP14R0_CCD += newcycles; 1529 1530 if (state->CP14R0_CCD >= 64) 1531 { 1532 newcycles = 0; 1533 1534 while (state->CP14R0_CCD >= 64) 1535 state->CP14R0_CCD -= 64, newcycles++; 1536 1537 goto check_PMUintr; 1538 } 1539 } 1540 else 1541 { 1542 ARMword cp14r1; 1543 int do_int; 1544 1545 state->CP14R0_CCD = -1; 1546 check_PMUintr: 1547 do_int = 0; 1548 cp14r0 |= ARMul_CP14_R0_FLAG2; 1549 (void) state->CPWrite[14] (state, 0, cp14r0); 1550 1551 ok = state->CPRead[14] (state, 1, & cp14r1); 1552 1553 /* Coded like this for portability. */ 1554 while (ok && newcycles) 1555 { 1556 if (cp14r1 == 0xffffffff) 1557 { 1558 cp14r1 = 0; 1559 do_int = 1; 1560 } 1561 else 1562 cp14r1 ++; 1563 1564 newcycles --; 1565 } 1566 1567 (void) state->CPWrite[14] (state, 1, cp14r1); 1568 1569 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2)) 1570 { 1571 ARMword temp; 1572 1573 if (state->CPRead[13] (state, 8, & temp) 1574 && (temp & ARMul_CP13_R8_PMUS)) 1575 ARMul_Abort (state, ARMul_FIQV); 1576 else 1577 ARMul_Abort (state, ARMul_IRQV); 1578 } 1579 } 1580 } 1581 } 1582 1583 /* Handle hardware instructions breakpoints here. */ 1584 if (state->is_XScale) 1585 { 1586 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2) 1587 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2)) 1588 { 1589 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB)) 1590 ARMul_OSHandleSWI (state, SWI_Breakpoint); 1591 } 1592 } 1593 1594 /* Actual execution of instructions begins here. */ 1595 /* If the condition codes don't match, stop here. */ 1596 if (temp) 1597 { 1598 mainswitch: 1599 1600 if (state->is_XScale) 1601 { 1602 if (BIT (20) == 0 && BITS (25, 27) == 0) 1603 { 1604 if (BITS (4, 7) == 0xD) 1605 { 1606 /* XScale Load Consecutive insn. */ 1607 ARMword temp = GetLS7RHS (state, instr); 1608 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp; 1609 ARMword addr = BIT (24) ? temp2 : LHS; 1610 1611 if (BIT (12)) 1612 ARMul_UndefInstr (state, instr); 1613 else if (addr & 7) 1614 /* Alignment violation. */ 1615 ARMul_Abort (state, ARMul_DataAbortV); 1616 else 1617 { 1618 int wb = BIT (21) || (! BIT (24)); 1619 1620 state->Reg[BITS (12, 15)] = 1621 ARMul_LoadWordN (state, addr); 1622 state->Reg[BITS (12, 15) + 1] = 1623 ARMul_LoadWordN (state, addr + 4); 1624 if (wb) 1625 LSBase = temp2; 1626 } 1627 1628 goto donext; 1629 } 1630 else if (BITS (4, 7) == 0xF) 1631 { 1632 /* XScale Store Consecutive insn. */ 1633 ARMword temp = GetLS7RHS (state, instr); 1634 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp; 1635 ARMword addr = BIT (24) ? temp2 : LHS; 1636 1637 if (BIT (12)) 1638 ARMul_UndefInstr (state, instr); 1639 else if (addr & 7) 1640 /* Alignment violation. */ 1641 ARMul_Abort (state, ARMul_DataAbortV); 1642 else 1643 { 1644 ARMul_StoreWordN (state, addr, 1645 state->Reg[BITS (12, 15)]); 1646 ARMul_StoreWordN (state, addr + 4, 1647 state->Reg[BITS (12, 15) + 1]); 1648 1649 if (BIT (21)|| ! BIT (24)) 1650 LSBase = temp2; 1651 } 1652 1653 goto donext; 1654 } 1655 } 1656 1657 if (ARMul_HandleIwmmxt (state, instr)) 1658 goto donext; 1659 } 1660 1661 switch ((int) BITS (20, 27)) 1662 { 1663 /* Data Processing Register RHS Instructions. */ 1664 1665 case 0x00: /* AND reg and MUL */ 1666 #ifdef MODET 1667 if (BITS (4, 11) == 0xB) 1668 { 1669 /* STRH register offset, no write-back, down, post indexed. */ 1670 SHDOWNWB (); 1671 break; 1672 } 1673 if (BITS (4, 7) == 0xD) 1674 { 1675 Handle_Load_Double (state, instr); 1676 break; 1677 } 1678 if (BITS (4, 7) == 0xF) 1679 { 1680 Handle_Store_Double (state, instr); 1681 break; 1682 } 1683 #endif 1684 if (BITS (4, 7) == 9) 1685 { 1686 /* MUL */ 1687 rhs = state->Reg[MULRHSReg]; 1688 if (MULLHSReg == MULDESTReg) 1689 { 1690 UNDEF_MULDestEQOp1; 1691 state->Reg[MULDESTReg] = 0; 1692 } 1693 else if (MULDESTReg != 15) 1694 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs; 1695 else 1696 UNDEF_MULPCDest; 1697 1698 for (dest = 0, temp = 0; dest < 32; dest ++) 1699 if (rhs & (1L << dest)) 1700 temp = dest; 1701 1702 /* Mult takes this many/2 I cycles. */ 1703 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1704 } 1705 else 1706 { 1707 /* AND reg. */ 1708 rhs = DPRegRHS; 1709 dest = LHS & rhs; 1710 WRITEDEST (dest); 1711 } 1712 break; 1713 1714 case 0x01: /* ANDS reg and MULS */ 1715 #ifdef MODET 1716 if ((BITS (4, 11) & 0xF9) == 0x9) 1717 /* LDR register offset, no write-back, down, post indexed. */ 1718 LHPOSTDOWN (); 1719 /* Fall through to rest of decoding. */ 1720 #endif 1721 if (BITS (4, 7) == 9) 1722 { 1723 /* MULS */ 1724 rhs = state->Reg[MULRHSReg]; 1725 1726 if (MULLHSReg == MULDESTReg) 1727 { 1728 UNDEF_MULDestEQOp1; 1729 state->Reg[MULDESTReg] = 0; 1730 CLEARN; 1731 SETZ; 1732 } 1733 else if (MULDESTReg != 15) 1734 { 1735 dest = state->Reg[MULLHSReg] * rhs; 1736 ARMul_NegZero (state, dest); 1737 state->Reg[MULDESTReg] = dest; 1738 } 1739 else 1740 UNDEF_MULPCDest; 1741 1742 for (dest = 0, temp = 0; dest < 32; dest ++) 1743 if (rhs & (1L << dest)) 1744 temp = dest; 1745 1746 /* Mult takes this many/2 I cycles. */ 1747 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1748 } 1749 else 1750 { 1751 /* ANDS reg. */ 1752 rhs = DPSRegRHS; 1753 dest = LHS & rhs; 1754 WRITESDEST (dest); 1755 } 1756 break; 1757 1758 case 0x02: /* EOR reg and MLA */ 1759 #ifdef MODET 1760 if (BITS (4, 11) == 0xB) 1761 { 1762 /* STRH register offset, write-back, down, post indexed. */ 1763 SHDOWNWB (); 1764 break; 1765 } 1766 #endif 1767 if (BITS (4, 7) == 9) 1768 { /* MLA */ 1769 rhs = state->Reg[MULRHSReg]; 1770 if (MULLHSReg == MULDESTReg) 1771 { 1772 UNDEF_MULDestEQOp1; 1773 state->Reg[MULDESTReg] = state->Reg[MULACCReg]; 1774 } 1775 else if (MULDESTReg != 15) 1776 state->Reg[MULDESTReg] = 1777 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; 1778 else 1779 UNDEF_MULPCDest; 1780 1781 for (dest = 0, temp = 0; dest < 32; dest ++) 1782 if (rhs & (1L << dest)) 1783 temp = dest; 1784 1785 /* Mult takes this many/2 I cycles. */ 1786 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1787 } 1788 else 1789 { 1790 rhs = DPRegRHS; 1791 dest = LHS ^ rhs; 1792 WRITEDEST (dest); 1793 } 1794 break; 1795 1796 case 0x03: /* EORS reg and MLAS */ 1797 #ifdef MODET 1798 if ((BITS (4, 11) & 0xF9) == 0x9) 1799 /* LDR register offset, write-back, down, post-indexed. */ 1800 LHPOSTDOWN (); 1801 /* Fall through to rest of the decoding. */ 1802 #endif 1803 if (BITS (4, 7) == 9) 1804 { 1805 /* MLAS */ 1806 rhs = state->Reg[MULRHSReg]; 1807 1808 if (MULLHSReg == MULDESTReg) 1809 { 1810 UNDEF_MULDestEQOp1; 1811 dest = state->Reg[MULACCReg]; 1812 ARMul_NegZero (state, dest); 1813 state->Reg[MULDESTReg] = dest; 1814 } 1815 else if (MULDESTReg != 15) 1816 { 1817 dest = 1818 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; 1819 ARMul_NegZero (state, dest); 1820 state->Reg[MULDESTReg] = dest; 1821 } 1822 else 1823 UNDEF_MULPCDest; 1824 1825 for (dest = 0, temp = 0; dest < 32; dest ++) 1826 if (rhs & (1L << dest)) 1827 temp = dest; 1828 1829 /* Mult takes this many/2 I cycles. */ 1830 ARMul_Icycles (state, ARMul_MultTable[temp], 0L); 1831 } 1832 else 1833 { 1834 /* EORS Reg. */ 1835 rhs = DPSRegRHS; 1836 dest = LHS ^ rhs; 1837 WRITESDEST (dest); 1838 } 1839 break; 1840 1841 case 0x04: /* SUB reg */ 1842 #ifdef MODET 1843 if (BITS (4, 7) == 0xB) 1844 { 1845 /* STRH immediate offset, no write-back, down, post indexed. */ 1846 SHDOWNWB (); 1847 break; 1848 } 1849 if (BITS (4, 7) == 0xD) 1850 { 1851 Handle_Load_Double (state, instr); 1852 break; 1853 } 1854 if (BITS (4, 7) == 0xF) 1855 { 1856 Handle_Store_Double (state, instr); 1857 break; 1858 } 1859 #endif 1860 rhs = DPRegRHS; 1861 dest = LHS - rhs; 1862 WRITEDEST (dest); 1863 break; 1864 1865 case 0x05: /* SUBS reg */ 1866 #ifdef MODET 1867 if ((BITS (4, 7) & 0x9) == 0x9) 1868 /* LDR immediate offset, no write-back, down, post indexed. */ 1869 LHPOSTDOWN (); 1870 /* Fall through to the rest of the instruction decoding. */ 1871 #endif 1872 lhs = LHS; 1873 rhs = DPRegRHS; 1874 dest = lhs - rhs; 1875 1876 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 1877 { 1878 ARMul_SubCarry (state, lhs, rhs, dest); 1879 ARMul_SubOverflow (state, lhs, rhs, dest); 1880 } 1881 else 1882 { 1883 CLEARC; 1884 CLEARV; 1885 } 1886 WRITESDEST (dest); 1887 break; 1888 1889 case 0x06: /* RSB reg */ 1890 #ifdef MODET 1891 if (BITS (4, 7) == 0xB) 1892 { 1893 /* STRH immediate offset, write-back, down, post indexed. */ 1894 SHDOWNWB (); 1895 break; 1896 } 1897 #endif 1898 rhs = DPRegRHS; 1899 dest = rhs - LHS; 1900 WRITEDEST (dest); 1901 break; 1902 1903 case 0x07: /* RSBS reg */ 1904 #ifdef MODET 1905 if ((BITS (4, 7) & 0x9) == 0x9) 1906 /* LDR immediate offset, write-back, down, post indexed. */ 1907 LHPOSTDOWN (); 1908 /* Fall through to remainder of instruction decoding. */ 1909 #endif 1910 lhs = LHS; 1911 rhs = DPRegRHS; 1912 dest = rhs - lhs; 1913 1914 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 1915 { 1916 ARMul_SubCarry (state, rhs, lhs, dest); 1917 ARMul_SubOverflow (state, rhs, lhs, dest); 1918 } 1919 else 1920 { 1921 CLEARC; 1922 CLEARV; 1923 } 1924 WRITESDEST (dest); 1925 break; 1926 1927 case 0x08: /* ADD reg */ 1928 #ifdef MODET 1929 if (BITS (4, 11) == 0xB) 1930 { 1931 /* STRH register offset, no write-back, up, post indexed. */ 1932 SHUPWB (); 1933 break; 1934 } 1935 if (BITS (4, 7) == 0xD) 1936 { 1937 Handle_Load_Double (state, instr); 1938 break; 1939 } 1940 if (BITS (4, 7) == 0xF) 1941 { 1942 Handle_Store_Double (state, instr); 1943 break; 1944 } 1945 #endif 1946 #ifdef MODET 1947 if (BITS (4, 7) == 0x9) 1948 { 1949 /* MULL */ 1950 /* 32x32 = 64 */ 1951 ARMul_Icycles (state, 1952 Multiply64 (state, instr, LUNSIGNED, 1953 LDEFAULT), 0L); 1954 break; 1955 } 1956 #endif 1957 rhs = DPRegRHS; 1958 dest = LHS + rhs; 1959 WRITEDEST (dest); 1960 break; 1961 1962 case 0x09: /* ADDS reg */ 1963 #ifdef MODET 1964 if ((BITS (4, 11) & 0xF9) == 0x9) 1965 /* LDR register offset, no write-back, up, post indexed. */ 1966 LHPOSTUP (); 1967 /* Fall through to remaining instruction decoding. */ 1968 #endif 1969 #ifdef MODET 1970 if (BITS (4, 7) == 0x9) 1971 { 1972 /* MULL */ 1973 /* 32x32=64 */ 1974 ARMul_Icycles (state, 1975 Multiply64 (state, instr, LUNSIGNED, LSCC), 1976 0L); 1977 break; 1978 } 1979 #endif 1980 lhs = LHS; 1981 rhs = DPRegRHS; 1982 dest = lhs + rhs; 1983 ASSIGNZ (dest == 0); 1984 if ((lhs | rhs) >> 30) 1985 { 1986 /* Possible C,V,N to set. */ 1987 ASSIGNN (NEG (dest)); 1988 ARMul_AddCarry (state, lhs, rhs, dest); 1989 ARMul_AddOverflow (state, lhs, rhs, dest); 1990 } 1991 else 1992 { 1993 CLEARN; 1994 CLEARC; 1995 CLEARV; 1996 } 1997 WRITESDEST (dest); 1998 break; 1999 2000 case 0x0a: /* ADC reg */ 2001 #ifdef MODET 2002 if (BITS (4, 11) == 0xB) 2003 { 2004 /* STRH register offset, write-back, up, post-indexed. */ 2005 SHUPWB (); 2006 break; 2007 } 2008 if (BITS (4, 7) == 0x9) 2009 { 2010 /* MULL */ 2011 /* 32x32=64 */ 2012 ARMul_Icycles (state, 2013 MultiplyAdd64 (state, instr, LUNSIGNED, 2014 LDEFAULT), 0L); 2015 break; 2016 } 2017 #endif 2018 rhs = DPRegRHS; 2019 dest = LHS + rhs + CFLAG; 2020 WRITEDEST (dest); 2021 break; 2022 2023 case 0x0b: /* ADCS reg */ 2024 #ifdef MODET 2025 if ((BITS (4, 11) & 0xF9) == 0x9) 2026 /* LDR register offset, write-back, up, post indexed. */ 2027 LHPOSTUP (); 2028 /* Fall through to remaining instruction decoding. */ 2029 if (BITS (4, 7) == 0x9) 2030 { 2031 /* MULL */ 2032 /* 32x32=64 */ 2033 ARMul_Icycles (state, 2034 MultiplyAdd64 (state, instr, LUNSIGNED, 2035 LSCC), 0L); 2036 break; 2037 } 2038 #endif 2039 lhs = LHS; 2040 rhs = DPRegRHS; 2041 dest = lhs + rhs + CFLAG; 2042 ASSIGNZ (dest == 0); 2043 if ((lhs | rhs) >> 30) 2044 { 2045 /* Possible C,V,N to set. */ 2046 ASSIGNN (NEG (dest)); 2047 ARMul_AddCarry (state, lhs, rhs, dest); 2048 ARMul_AddOverflow (state, lhs, rhs, dest); 2049 } 2050 else 2051 { 2052 CLEARN; 2053 CLEARC; 2054 CLEARV; 2055 } 2056 WRITESDEST (dest); 2057 break; 2058 2059 case 0x0c: /* SBC reg */ 2060 #ifdef MODET 2061 if (BITS (4, 7) == 0xB) 2062 { 2063 /* STRH immediate offset, no write-back, up post indexed. */ 2064 SHUPWB (); 2065 break; 2066 } 2067 if (BITS (4, 7) == 0xD) 2068 { 2069 Handle_Load_Double (state, instr); 2070 break; 2071 } 2072 if (BITS (4, 7) == 0xF) 2073 { 2074 Handle_Store_Double (state, instr); 2075 break; 2076 } 2077 if (BITS (4, 7) == 0x9) 2078 { 2079 /* MULL */ 2080 /* 32x32=64 */ 2081 ARMul_Icycles (state, 2082 Multiply64 (state, instr, LSIGNED, LDEFAULT), 2083 0L); 2084 break; 2085 } 2086 #endif 2087 rhs = DPRegRHS; 2088 dest = LHS - rhs - !CFLAG; 2089 WRITEDEST (dest); 2090 break; 2091 2092 case 0x0d: /* SBCS reg */ 2093 #ifdef MODET 2094 if ((BITS (4, 7) & 0x9) == 0x9) 2095 /* LDR immediate offset, no write-back, up, post indexed. */ 2096 LHPOSTUP (); 2097 2098 if (BITS (4, 7) == 0x9) 2099 { 2100 /* MULL */ 2101 /* 32x32=64 */ 2102 ARMul_Icycles (state, 2103 Multiply64 (state, instr, LSIGNED, LSCC), 2104 0L); 2105 break; 2106 } 2107 #endif 2108 lhs = LHS; 2109 rhs = DPRegRHS; 2110 dest = lhs - rhs - !CFLAG; 2111 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2112 { 2113 ARMul_SubCarry (state, lhs, rhs, dest); 2114 ARMul_SubOverflow (state, lhs, rhs, dest); 2115 } 2116 else 2117 { 2118 CLEARC; 2119 CLEARV; 2120 } 2121 WRITESDEST (dest); 2122 break; 2123 2124 case 0x0e: /* RSC reg */ 2125 #ifdef MODET 2126 if (BITS (4, 7) == 0xB) 2127 { 2128 /* STRH immediate offset, write-back, up, post indexed. */ 2129 SHUPWB (); 2130 break; 2131 } 2132 2133 if (BITS (4, 7) == 0x9) 2134 { 2135 /* MULL */ 2136 /* 32x32=64 */ 2137 ARMul_Icycles (state, 2138 MultiplyAdd64 (state, instr, LSIGNED, 2139 LDEFAULT), 0L); 2140 break; 2141 } 2142 #endif 2143 rhs = DPRegRHS; 2144 dest = rhs - LHS - !CFLAG; 2145 WRITEDEST (dest); 2146 break; 2147 2148 case 0x0f: /* RSCS reg */ 2149 #ifdef MODET 2150 if ((BITS (4, 7) & 0x9) == 0x9) 2151 /* LDR immediate offset, write-back, up, post indexed. */ 2152 LHPOSTUP (); 2153 /* Fall through to remaining instruction decoding. */ 2154 2155 if (BITS (4, 7) == 0x9) 2156 { 2157 /* MULL */ 2158 /* 32x32=64 */ 2159 ARMul_Icycles (state, 2160 MultiplyAdd64 (state, instr, LSIGNED, LSCC), 2161 0L); 2162 break; 2163 } 2164 #endif 2165 lhs = LHS; 2166 rhs = DPRegRHS; 2167 dest = rhs - lhs - !CFLAG; 2168 2169 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 2170 { 2171 ARMul_SubCarry (state, rhs, lhs, dest); 2172 ARMul_SubOverflow (state, rhs, lhs, dest); 2173 } 2174 else 2175 { 2176 CLEARC; 2177 CLEARV; 2178 } 2179 WRITESDEST (dest); 2180 break; 2181 2182 case 0x10: /* TST reg and MRS CPSR and SWP word. */ 2183 if (state->is_v5e) 2184 { 2185 if (BIT (4) == 0 && BIT (7) == 1) 2186 { 2187 /* ElSegundo SMLAxy insn. */ 2188 ARMword op1 = state->Reg[BITS (0, 3)]; 2189 ARMword op2 = state->Reg[BITS (8, 11)]; 2190 ARMword Rn = state->Reg[BITS (12, 15)]; 2191 2192 if (BIT (5)) 2193 op1 >>= 16; 2194 if (BIT (6)) 2195 op2 >>= 16; 2196 op1 &= 0xFFFF; 2197 op2 &= 0xFFFF; 2198 if (op1 & 0x8000) 2199 op1 -= 65536; 2200 if (op2 & 0x8000) 2201 op2 -= 65536; 2202 op1 *= op2; 2203 2204 if (AddOverflow (op1, Rn, op1 + Rn)) 2205 SETS; 2206 state->Reg[BITS (16, 19)] = op1 + Rn; 2207 break; 2208 } 2209 2210 if (BITS (4, 11) == 5) 2211 { 2212 /* ElSegundo QADD insn. */ 2213 ARMword op1 = state->Reg[BITS (0, 3)]; 2214 ARMword op2 = state->Reg[BITS (16, 19)]; 2215 ARMword result = op1 + op2; 2216 if (AddOverflow (op1, op2, result)) 2217 { 2218 result = POS (result) ? 0x80000000 : 0x7fffffff; 2219 SETS; 2220 } 2221 state->Reg[BITS (12, 15)] = result; 2222 break; 2223 } 2224 } 2225 #ifdef MODET 2226 if (BITS (4, 11) == 0xB) 2227 { 2228 /* STRH register offset, no write-back, down, pre indexed. */ 2229 SHPREDOWN (); 2230 break; 2231 } 2232 if (BITS (4, 7) == 0xD) 2233 { 2234 Handle_Load_Double (state, instr); 2235 break; 2236 } 2237 if (BITS (4, 7) == 0xF) 2238 { 2239 Handle_Store_Double (state, instr); 2240 break; 2241 } 2242 #endif 2243 if (BITS (4, 11) == 9) 2244 { 2245 /* SWP */ 2246 UNDEF_SWPPC; 2247 temp = LHS; 2248 BUSUSEDINCPCS; 2249 #ifndef MODE32 2250 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) 2251 { 2252 INTERNALABORT (temp); 2253 (void) ARMul_LoadWordN (state, temp); 2254 (void) ARMul_LoadWordN (state, temp); 2255 } 2256 else 2257 #endif 2258 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]); 2259 if (temp & 3) 2260 DEST = ARMul_Align (state, temp, dest); 2261 else 2262 DEST = dest; 2263 if (state->abortSig || state->Aborted) 2264 TAKEABORT; 2265 } 2266 else if ((BITS (0, 11) == 0) && (LHSReg == 15)) 2267 { /* MRS CPSR */ 2268 UNDEF_MRSPC; 2269 DEST = ECC | EINT | EMODE; 2270 } 2271 else 2272 { 2273 #ifdef MODE32 2274 if (state->is_v6 2275 && handle_v6_insn (state, instr)) 2276 break; 2277 #endif 2278 UNDEF_Test; 2279 } 2280 break; 2281 2282 case 0x11: /* TSTP reg */ 2283 #ifdef MODET 2284 if ((BITS (4, 11) & 0xF9) == 0x9) 2285 /* LDR register offset, no write-back, down, pre indexed. */ 2286 LHPREDOWN (); 2287 /* Continue with remaining instruction decode. */ 2288 #endif 2289 if (DESTReg == 15) 2290 { 2291 /* TSTP reg */ 2292 #ifdef MODE32 2293 state->Cpsr = GETSPSR (state->Bank); 2294 ARMul_CPSRAltered (state); 2295 #else 2296 rhs = DPRegRHS; 2297 temp = LHS & rhs; 2298 SETR15PSR (temp); 2299 #endif 2300 } 2301 else 2302 { 2303 /* TST reg */ 2304 rhs = DPSRegRHS; 2305 dest = LHS & rhs; 2306 ARMul_NegZero (state, dest); 2307 } 2308 break; 2309 2310 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */ 2311 if (state->is_v5) 2312 { 2313 if (BITS (4, 7) == 3) 2314 { 2315 /* BLX(2) */ 2316 ARMword temp; 2317 2318 if (TFLAG) 2319 temp = (pc + 2) | 1; 2320 else 2321 temp = pc + 4; 2322 2323 WriteR15Branch (state, state->Reg[RHSReg]); 2324 state->Reg[14] = temp; 2325 break; 2326 } 2327 } 2328 2329 if (state->is_v5e) 2330 { 2331 if (BIT (4) == 0 && BIT (7) == 1 2332 && (BIT (5) == 0 || BITS (12, 15) == 0)) 2333 { 2334 /* ElSegundo SMLAWy/SMULWy insn. */ 2335 ARMdword op1 = state->Reg[BITS (0, 3)]; 2336 ARMdword op2 = state->Reg[BITS (8, 11)]; 2337 ARMdword result; 2338 2339 if (BIT (6)) 2340 op2 >>= 16; 2341 if (op1 & 0x80000000) 2342 op1 -= 1ULL << 32; 2343 op2 &= 0xFFFF; 2344 if (op2 & 0x8000) 2345 op2 -= 65536; 2346 result = (op1 * op2) >> 16; 2347 2348 if (BIT (5) == 0) 2349 { 2350 ARMword Rn = state->Reg[BITS (12, 15)]; 2351 2352 if (AddOverflow (result, Rn, result + Rn)) 2353 SETS; 2354 result += Rn; 2355 } 2356 state->Reg[BITS (16, 19)] = result; 2357 break; 2358 } 2359 2360 if (BITS (4, 11) == 5) 2361 { 2362 /* ElSegundo QSUB insn. */ 2363 ARMword op1 = state->Reg[BITS (0, 3)]; 2364 ARMword op2 = state->Reg[BITS (16, 19)]; 2365 ARMword result = op1 - op2; 2366 2367 if (SubOverflow (op1, op2, result)) 2368 { 2369 result = POS (result) ? 0x80000000 : 0x7fffffff; 2370 SETS; 2371 } 2372 2373 state->Reg[BITS (12, 15)] = result; 2374 break; 2375 } 2376 } 2377 #ifdef MODET 2378 if (BITS (4, 11) == 0xB) 2379 { 2380 /* STRH register offset, write-back, down, pre indexed. */ 2381 SHPREDOWNWB (); 2382 break; 2383 } 2384 if (BITS (4, 27) == 0x12FFF1) 2385 { 2386 /* BX */ 2387 WriteR15Branch (state, state->Reg[RHSReg]); 2388 break; 2389 } 2390 if (BITS (4, 7) == 0xD) 2391 { 2392 Handle_Load_Double (state, instr); 2393 break; 2394 } 2395 if (BITS (4, 7) == 0xF) 2396 { 2397 Handle_Store_Double (state, instr); 2398 break; 2399 } 2400 #endif 2401 if (state->is_v5) 2402 { 2403 if (BITS (4, 7) == 0x7) 2404 { 2405 extern int SWI_vector_installed; 2406 2407 /* Hardware is allowed to optionally override this 2408 instruction and treat it as a breakpoint. Since 2409 this is a simulator not hardware, we take the position 2410 that if a SWI vector was not installed, then an Abort 2411 vector was probably not installed either, and so 2412 normally this instruction would be ignored, even if an 2413 Abort is generated. This is a bad thing, since GDB 2414 uses this instruction for its breakpoints (at least in 2415 Thumb mode it does). So intercept the instruction here 2416 and generate a breakpoint SWI instead. */ 2417 if (! SWI_vector_installed) 2418 ARMul_OSHandleSWI (state, SWI_Breakpoint); 2419 else 2420 { 2421 /* BKPT - normally this will cause an abort, but on the 2422 XScale we must check the DCSR. */ 2423 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); 2424 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT)) 2425 break; 2426 } 2427 2428 /* Force the next instruction to be refetched. */ 2429 state->NextInstr = RESUME; 2430 break; 2431 } 2432 } 2433 if (DESTReg == 15) 2434 { 2435 /* MSR reg to CPSR. */ 2436 UNDEF_MSRPC; 2437 temp = DPRegRHS; 2438 #ifdef MODET 2439 /* Don't allow TBIT to be set by MSR. */ 2440 temp &= ~ TBIT; 2441 #endif 2442 ARMul_FixCPSR (state, instr, temp); 2443 } 2444 #ifdef MODE32 2445 else if (state->is_v6 2446 && handle_v6_insn (state, instr)) 2447 break; 2448 #endif 2449 else 2450 UNDEF_Test; 2451 2452 break; 2453 2454 case 0x13: /* TEQP reg */ 2455 #ifdef MODET 2456 if ((BITS (4, 11) & 0xF9) == 0x9) 2457 /* LDR register offset, write-back, down, pre indexed. */ 2458 LHPREDOWNWB (); 2459 /* Continue with remaining instruction decode. */ 2460 #endif 2461 if (DESTReg == 15) 2462 { 2463 /* TEQP reg */ 2464 #ifdef MODE32 2465 state->Cpsr = GETSPSR (state->Bank); 2466 ARMul_CPSRAltered (state); 2467 #else 2468 rhs = DPRegRHS; 2469 temp = LHS ^ rhs; 2470 SETR15PSR (temp); 2471 #endif 2472 } 2473 else 2474 { 2475 /* TEQ Reg. */ 2476 rhs = DPSRegRHS; 2477 dest = LHS ^ rhs; 2478 ARMul_NegZero (state, dest); 2479 } 2480 break; 2481 2482 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */ 2483 if (state->is_v5e) 2484 { 2485 if (BIT (4) == 0 && BIT (7) == 1) 2486 { 2487 /* ElSegundo SMLALxy insn. */ 2488 ARMdword op1 = state->Reg[BITS (0, 3)]; 2489 ARMdword op2 = state->Reg[BITS (8, 11)]; 2490 ARMdword dest; 2491 2492 if (BIT (5)) 2493 op1 >>= 16; 2494 if (BIT (6)) 2495 op2 >>= 16; 2496 op1 &= 0xFFFF; 2497 if (op1 & 0x8000) 2498 op1 -= 65536; 2499 op2 &= 0xFFFF; 2500 if (op2 & 0x8000) 2501 op2 -= 65536; 2502 2503 dest = (ARMdword) state->Reg[BITS (16, 19)] << 32; 2504 dest |= state->Reg[BITS (12, 15)]; 2505 dest += op1 * op2; 2506 state->Reg[BITS (12, 15)] = dest; 2507 state->Reg[BITS (16, 19)] = dest >> 32; 2508 break; 2509 } 2510 2511 if (BITS (4, 11) == 5) 2512 { 2513 /* ElSegundo QDADD insn. */ 2514 ARMword op1 = state->Reg[BITS (0, 3)]; 2515 ARMword op2 = state->Reg[BITS (16, 19)]; 2516 ARMword op2d = op2 + op2; 2517 ARMword result; 2518 2519 if (AddOverflow (op2, op2, op2d)) 2520 { 2521 SETS; 2522 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 2523 } 2524 2525 result = op1 + op2d; 2526 if (AddOverflow (op1, op2d, result)) 2527 { 2528 SETS; 2529 result = POS (result) ? 0x80000000 : 0x7fffffff; 2530 } 2531 2532 state->Reg[BITS (12, 15)] = result; 2533 break; 2534 } 2535 } 2536 #ifdef MODET 2537 if (BITS (4, 7) == 0xB) 2538 { 2539 /* STRH immediate offset, no write-back, down, pre indexed. */ 2540 SHPREDOWN (); 2541 break; 2542 } 2543 if (BITS (4, 7) == 0xD) 2544 { 2545 Handle_Load_Double (state, instr); 2546 break; 2547 } 2548 if (BITS (4, 7) == 0xF) 2549 { 2550 Handle_Store_Double (state, instr); 2551 break; 2552 } 2553 #endif 2554 if (BITS (4, 11) == 9) 2555 { 2556 /* SWP */ 2557 UNDEF_SWPPC; 2558 temp = LHS; 2559 BUSUSEDINCPCS; 2560 #ifndef MODE32 2561 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) 2562 { 2563 INTERNALABORT (temp); 2564 (void) ARMul_LoadByte (state, temp); 2565 (void) ARMul_LoadByte (state, temp); 2566 } 2567 else 2568 #endif 2569 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]); 2570 if (state->abortSig || state->Aborted) 2571 TAKEABORT; 2572 } 2573 else if ((BITS (0, 11) == 0) && (LHSReg == 15)) 2574 { 2575 /* MRS SPSR */ 2576 UNDEF_MRSPC; 2577 DEST = GETSPSR (state->Bank); 2578 } 2579 #ifdef MODE32 2580 else if (state->is_v6 2581 && handle_v6_insn (state, instr)) 2582 break; 2583 #endif 2584 else 2585 UNDEF_Test; 2586 2587 break; 2588 2589 case 0x15: /* CMPP reg. */ 2590 #ifdef MODET 2591 if ((BITS (4, 7) & 0x9) == 0x9) 2592 /* LDR immediate offset, no write-back, down, pre indexed. */ 2593 LHPREDOWN (); 2594 /* Continue with remaining instruction decode. */ 2595 #endif 2596 if (DESTReg == 15) 2597 { 2598 /* CMPP reg. */ 2599 #ifdef MODE32 2600 state->Cpsr = GETSPSR (state->Bank); 2601 ARMul_CPSRAltered (state); 2602 #else 2603 rhs = DPRegRHS; 2604 temp = LHS - rhs; 2605 SETR15PSR (temp); 2606 #endif 2607 } 2608 else 2609 { 2610 /* CMP reg. */ 2611 lhs = LHS; 2612 rhs = DPRegRHS; 2613 dest = lhs - rhs; 2614 ARMul_NegZero (state, dest); 2615 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2616 { 2617 ARMul_SubCarry (state, lhs, rhs, dest); 2618 ARMul_SubOverflow (state, lhs, rhs, dest); 2619 } 2620 else 2621 { 2622 CLEARC; 2623 CLEARV; 2624 } 2625 } 2626 break; 2627 2628 case 0x16: /* CMN reg and MSR reg to SPSR */ 2629 if (state->is_v5e) 2630 { 2631 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0) 2632 { 2633 /* ElSegundo SMULxy insn. */ 2634 ARMword op1 = state->Reg[BITS (0, 3)]; 2635 ARMword op2 = state->Reg[BITS (8, 11)]; 2636 2637 if (BIT (5)) 2638 op1 >>= 16; 2639 if (BIT (6)) 2640 op2 >>= 16; 2641 op1 &= 0xFFFF; 2642 op2 &= 0xFFFF; 2643 if (op1 & 0x8000) 2644 op1 -= 65536; 2645 if (op2 & 0x8000) 2646 op2 -= 65536; 2647 2648 state->Reg[BITS (16, 19)] = op1 * op2; 2649 break; 2650 } 2651 2652 if (BITS (4, 11) == 5) 2653 { 2654 /* ElSegundo QDSUB insn. */ 2655 ARMword op1 = state->Reg[BITS (0, 3)]; 2656 ARMword op2 = state->Reg[BITS (16, 19)]; 2657 ARMword op2d = op2 + op2; 2658 ARMword result; 2659 2660 if (AddOverflow (op2, op2, op2d)) 2661 { 2662 SETS; 2663 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 2664 } 2665 2666 result = op1 - op2d; 2667 if (SubOverflow (op1, op2d, result)) 2668 { 2669 SETS; 2670 result = POS (result) ? 0x80000000 : 0x7fffffff; 2671 } 2672 2673 state->Reg[BITS (12, 15)] = result; 2674 break; 2675 } 2676 } 2677 2678 if (state->is_v5) 2679 { 2680 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF) 2681 { 2682 /* ARM5 CLZ insn. */ 2683 ARMword op1 = state->Reg[BITS (0, 3)]; 2684 int result = 32; 2685 2686 if (op1) 2687 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1) 2688 result++; 2689 2690 state->Reg[BITS (12, 15)] = result; 2691 break; 2692 } 2693 } 2694 #ifdef MODET 2695 if (BITS (4, 7) == 0xB) 2696 { 2697 /* STRH immediate offset, write-back, down, pre indexed. */ 2698 SHPREDOWNWB (); 2699 break; 2700 } 2701 if (BITS (4, 7) == 0xD) 2702 { 2703 Handle_Load_Double (state, instr); 2704 break; 2705 } 2706 if (BITS (4, 7) == 0xF) 2707 { 2708 Handle_Store_Double (state, instr); 2709 break; 2710 } 2711 #endif 2712 if (DESTReg == 15) 2713 { 2714 /* MSR */ 2715 UNDEF_MSRPC; 2716 ARMul_FixSPSR (state, instr, DPRegRHS); 2717 } 2718 else 2719 { 2720 #ifdef MODE32 2721 if (state->is_v6 2722 && handle_v6_insn (state, instr)) 2723 break; 2724 #endif 2725 UNDEF_Test; 2726 } 2727 break; 2728 2729 case 0x17: /* CMNP reg */ 2730 #ifdef MODET 2731 if ((BITS (4, 7) & 0x9) == 0x9) 2732 /* LDR immediate offset, write-back, down, pre indexed. */ 2733 LHPREDOWNWB (); 2734 /* Continue with remaining instruction decoding. */ 2735 #endif 2736 if (DESTReg == 15) 2737 { 2738 #ifdef MODE32 2739 state->Cpsr = GETSPSR (state->Bank); 2740 ARMul_CPSRAltered (state); 2741 #else 2742 rhs = DPRegRHS; 2743 temp = LHS + rhs; 2744 SETR15PSR (temp); 2745 #endif 2746 break; 2747 } 2748 else 2749 { 2750 /* CMN reg. */ 2751 lhs = LHS; 2752 rhs = DPRegRHS; 2753 dest = lhs + rhs; 2754 ASSIGNZ (dest == 0); 2755 if ((lhs | rhs) >> 30) 2756 { 2757 /* Possible C,V,N to set. */ 2758 ASSIGNN (NEG (dest)); 2759 ARMul_AddCarry (state, lhs, rhs, dest); 2760 ARMul_AddOverflow (state, lhs, rhs, dest); 2761 } 2762 else 2763 { 2764 CLEARN; 2765 CLEARC; 2766 CLEARV; 2767 } 2768 } 2769 break; 2770 2771 case 0x18: /* ORR reg */ 2772 #ifdef MODET 2773 if (BITS (4, 11) == 0xB) 2774 { 2775 /* STRH register offset, no write-back, up, pre indexed. */ 2776 SHPREUP (); 2777 break; 2778 } 2779 if (BITS (4, 7) == 0xD) 2780 { 2781 Handle_Load_Double (state, instr); 2782 break; 2783 } 2784 if (BITS (4, 7) == 0xF) 2785 { 2786 Handle_Store_Double (state, instr); 2787 break; 2788 } 2789 #endif 2790 rhs = DPRegRHS; 2791 dest = LHS | rhs; 2792 WRITEDEST (dest); 2793 break; 2794 2795 case 0x19: /* ORRS reg */ 2796 #ifdef MODET 2797 if ((BITS (4, 11) & 0xF9) == 0x9) 2798 /* LDR register offset, no write-back, up, pre indexed. */ 2799 LHPREUP (); 2800 /* Continue with remaining instruction decoding. */ 2801 #endif 2802 rhs = DPSRegRHS; 2803 dest = LHS | rhs; 2804 WRITESDEST (dest); 2805 break; 2806 2807 case 0x1a: /* MOV reg */ 2808 #ifdef MODET 2809 if (BITS (4, 11) == 0xB) 2810 { 2811 /* STRH register offset, write-back, up, pre indexed. */ 2812 SHPREUPWB (); 2813 break; 2814 } 2815 if (BITS (4, 7) == 0xD) 2816 { 2817 Handle_Load_Double (state, instr); 2818 break; 2819 } 2820 if (BITS (4, 7) == 0xF) 2821 { 2822 Handle_Store_Double (state, instr); 2823 break; 2824 } 2825 #endif 2826 dest = DPRegRHS; 2827 WRITEDEST (dest); 2828 break; 2829 2830 case 0x1b: /* MOVS reg */ 2831 #ifdef MODET 2832 if ((BITS (4, 11) & 0xF9) == 0x9) 2833 /* LDR register offset, write-back, up, pre indexed. */ 2834 LHPREUPWB (); 2835 /* Continue with remaining instruction decoding. */ 2836 #endif 2837 dest = DPSRegRHS; 2838 WRITESDEST (dest); 2839 break; 2840 2841 case 0x1c: /* BIC reg */ 2842 #ifdef MODET 2843 if (BITS (4, 7) == 0xB) 2844 { 2845 /* STRH immediate offset, no write-back, up, pre indexed. */ 2846 SHPREUP (); 2847 break; 2848 } 2849 if (BITS (4, 7) == 0xD) 2850 { 2851 Handle_Load_Double (state, instr); 2852 break; 2853 } 2854 else if (BITS (4, 7) == 0xF) 2855 { 2856 Handle_Store_Double (state, instr); 2857 break; 2858 } 2859 #endif 2860 rhs = DPRegRHS; 2861 dest = LHS & ~rhs; 2862 WRITEDEST (dest); 2863 break; 2864 2865 case 0x1d: /* BICS reg */ 2866 #ifdef MODET 2867 if ((BITS (4, 7) & 0x9) == 0x9) 2868 /* LDR immediate offset, no write-back, up, pre indexed. */ 2869 LHPREUP (); 2870 /* Continue with instruction decoding. */ 2871 #endif 2872 rhs = DPSRegRHS; 2873 dest = LHS & ~rhs; 2874 WRITESDEST (dest); 2875 break; 2876 2877 case 0x1e: /* MVN reg */ 2878 #ifdef MODET 2879 if (BITS (4, 7) == 0xB) 2880 { 2881 /* STRH immediate offset, write-back, up, pre indexed. */ 2882 SHPREUPWB (); 2883 break; 2884 } 2885 if (BITS (4, 7) == 0xD) 2886 { 2887 Handle_Load_Double (state, instr); 2888 break; 2889 } 2890 if (BITS (4, 7) == 0xF) 2891 { 2892 Handle_Store_Double (state, instr); 2893 break; 2894 } 2895 #endif 2896 dest = ~DPRegRHS; 2897 WRITEDEST (dest); 2898 break; 2899 2900 case 0x1f: /* MVNS reg */ 2901 #ifdef MODET 2902 if ((BITS (4, 7) & 0x9) == 0x9) 2903 /* LDR immediate offset, write-back, up, pre indexed. */ 2904 LHPREUPWB (); 2905 /* Continue instruction decoding. */ 2906 #endif 2907 dest = ~DPSRegRHS; 2908 WRITESDEST (dest); 2909 break; 2910 2911 2912 /* Data Processing Immediate RHS Instructions. */ 2913 2914 case 0x20: /* AND immed */ 2915 dest = LHS & DPImmRHS; 2916 WRITEDEST (dest); 2917 break; 2918 2919 case 0x21: /* ANDS immed */ 2920 DPSImmRHS; 2921 dest = LHS & rhs; 2922 WRITESDEST (dest); 2923 break; 2924 2925 case 0x22: /* EOR immed */ 2926 dest = LHS ^ DPImmRHS; 2927 WRITEDEST (dest); 2928 break; 2929 2930 case 0x23: /* EORS immed */ 2931 DPSImmRHS; 2932 dest = LHS ^ rhs; 2933 WRITESDEST (dest); 2934 break; 2935 2936 case 0x24: /* SUB immed */ 2937 dest = LHS - DPImmRHS; 2938 WRITEDEST (dest); 2939 break; 2940 2941 case 0x25: /* SUBS immed */ 2942 lhs = LHS; 2943 rhs = DPImmRHS; 2944 dest = lhs - rhs; 2945 2946 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2947 { 2948 ARMul_SubCarry (state, lhs, rhs, dest); 2949 ARMul_SubOverflow (state, lhs, rhs, dest); 2950 } 2951 else 2952 { 2953 CLEARC; 2954 CLEARV; 2955 } 2956 WRITESDEST (dest); 2957 break; 2958 2959 case 0x26: /* RSB immed */ 2960 dest = DPImmRHS - LHS; 2961 WRITEDEST (dest); 2962 break; 2963 2964 case 0x27: /* RSBS immed */ 2965 lhs = LHS; 2966 rhs = DPImmRHS; 2967 dest = rhs - lhs; 2968 2969 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 2970 { 2971 ARMul_SubCarry (state, rhs, lhs, dest); 2972 ARMul_SubOverflow (state, rhs, lhs, dest); 2973 } 2974 else 2975 { 2976 CLEARC; 2977 CLEARV; 2978 } 2979 WRITESDEST (dest); 2980 break; 2981 2982 case 0x28: /* ADD immed */ 2983 dest = LHS + DPImmRHS; 2984 WRITEDEST (dest); 2985 break; 2986 2987 case 0x29: /* ADDS immed */ 2988 lhs = LHS; 2989 rhs = DPImmRHS; 2990 dest = lhs + rhs; 2991 ASSIGNZ (dest == 0); 2992 2993 if ((lhs | rhs) >> 30) 2994 { 2995 /* Possible C,V,N to set. */ 2996 ASSIGNN (NEG (dest)); 2997 ARMul_AddCarry (state, lhs, rhs, dest); 2998 ARMul_AddOverflow (state, lhs, rhs, dest); 2999 } 3000 else 3001 { 3002 CLEARN; 3003 CLEARC; 3004 CLEARV; 3005 } 3006 WRITESDEST (dest); 3007 break; 3008 3009 case 0x2a: /* ADC immed */ 3010 dest = LHS + DPImmRHS + CFLAG; 3011 WRITEDEST (dest); 3012 break; 3013 3014 case 0x2b: /* ADCS immed */ 3015 lhs = LHS; 3016 rhs = DPImmRHS; 3017 dest = lhs + rhs + CFLAG; 3018 ASSIGNZ (dest == 0); 3019 if ((lhs | rhs) >> 30) 3020 { 3021 /* Possible C,V,N to set. */ 3022 ASSIGNN (NEG (dest)); 3023 ARMul_AddCarry (state, lhs, rhs, dest); 3024 ARMul_AddOverflow (state, lhs, rhs, dest); 3025 } 3026 else 3027 { 3028 CLEARN; 3029 CLEARC; 3030 CLEARV; 3031 } 3032 WRITESDEST (dest); 3033 break; 3034 3035 case 0x2c: /* SBC immed */ 3036 dest = LHS - DPImmRHS - !CFLAG; 3037 WRITEDEST (dest); 3038 break; 3039 3040 case 0x2d: /* SBCS immed */ 3041 lhs = LHS; 3042 rhs = DPImmRHS; 3043 dest = lhs - rhs - !CFLAG; 3044 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 3045 { 3046 ARMul_SubCarry (state, lhs, rhs, dest); 3047 ARMul_SubOverflow (state, lhs, rhs, dest); 3048 } 3049 else 3050 { 3051 CLEARC; 3052 CLEARV; 3053 } 3054 WRITESDEST (dest); 3055 break; 3056 3057 case 0x2e: /* RSC immed */ 3058 dest = DPImmRHS - LHS - !CFLAG; 3059 WRITEDEST (dest); 3060 break; 3061 3062 case 0x2f: /* RSCS immed */ 3063 lhs = LHS; 3064 rhs = DPImmRHS; 3065 dest = rhs - lhs - !CFLAG; 3066 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) 3067 { 3068 ARMul_SubCarry (state, rhs, lhs, dest); 3069 ARMul_SubOverflow (state, rhs, lhs, dest); 3070 } 3071 else 3072 { 3073 CLEARC; 3074 CLEARV; 3075 } 3076 WRITESDEST (dest); 3077 break; 3078 3079 case 0x30: /* MOVW immed */ 3080 #ifdef MODE32 3081 if (state->is_v6 3082 && handle_v6_insn (state, instr)) 3083 break; 3084 #endif 3085 dest = BITS (0, 11); 3086 dest |= (BITS (16, 19) << 12); 3087 WRITEDEST (dest); 3088 break; 3089 3090 case 0x31: /* TSTP immed */ 3091 if (DESTReg == 15) 3092 { 3093 /* TSTP immed. */ 3094 #ifdef MODE32 3095 state->Cpsr = GETSPSR (state->Bank); 3096 ARMul_CPSRAltered (state); 3097 #else 3098 temp = LHS & DPImmRHS; 3099 SETR15PSR (temp); 3100 #endif 3101 } 3102 else 3103 { 3104 /* TST immed. */ 3105 DPSImmRHS; 3106 dest = LHS & rhs; 3107 ARMul_NegZero (state, dest); 3108 } 3109 break; 3110 3111 case 0x32: /* TEQ immed and MSR immed to CPSR */ 3112 if (DESTReg == 15) 3113 /* MSR immed to CPSR. */ 3114 ARMul_FixCPSR (state, instr, DPImmRHS); 3115 #ifdef MODE32 3116 else if (state->is_v6 3117 && handle_v6_insn (state, instr)) 3118 break; 3119 #endif 3120 else 3121 UNDEF_Test; 3122 break; 3123 3124 case 0x33: /* TEQP immed */ 3125 if (DESTReg == 15) 3126 { 3127 /* TEQP immed. */ 3128 #ifdef MODE32 3129 state->Cpsr = GETSPSR (state->Bank); 3130 ARMul_CPSRAltered (state); 3131 #else 3132 temp = LHS ^ DPImmRHS; 3133 SETR15PSR (temp); 3134 #endif 3135 } 3136 else 3137 { 3138 DPSImmRHS; /* TEQ immed */ 3139 dest = LHS ^ rhs; 3140 ARMul_NegZero (state, dest); 3141 } 3142 break; 3143 3144 case 0x34: /* MOVT immed */ 3145 #ifdef MODE32 3146 if (state->is_v6 3147 && handle_v6_insn (state, instr)) 3148 break; 3149 #endif 3150 DEST &= 0xFFFF; 3151 dest = BITS (0, 11); 3152 dest |= (BITS (16, 19) << 12); 3153 DEST |= (dest << 16); 3154 break; 3155 3156 case 0x35: /* CMPP immed */ 3157 if (DESTReg == 15) 3158 { 3159 /* CMPP immed. */ 3160 #ifdef MODE32 3161 state->Cpsr = GETSPSR (state->Bank); 3162 ARMul_CPSRAltered (state); 3163 #else 3164 temp = LHS - DPImmRHS; 3165 SETR15PSR (temp); 3166 #endif 3167 break; 3168 } 3169 else 3170 { 3171 /* CMP immed. */ 3172 lhs = LHS; 3173 rhs = DPImmRHS; 3174 dest = lhs - rhs; 3175 ARMul_NegZero (state, dest); 3176 3177 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 3178 { 3179 ARMul_SubCarry (state, lhs, rhs, dest); 3180 ARMul_SubOverflow (state, lhs, rhs, dest); 3181 } 3182 else 3183 { 3184 CLEARC; 3185 CLEARV; 3186 } 3187 } 3188 break; 3189 3190 case 0x36: /* CMN immed and MSR immed to SPSR */ 3191 if (DESTReg == 15) 3192 ARMul_FixSPSR (state, instr, DPImmRHS); 3193 #ifdef MODE32 3194 else if (state->is_v6 3195 && handle_v6_insn (state, instr)) 3196 break; 3197 #endif 3198 else 3199 UNDEF_Test; 3200 break; 3201 3202 case 0x37: /* CMNP immed. */ 3203 if (DESTReg == 15) 3204 { 3205 /* CMNP immed. */ 3206 #ifdef MODE32 3207 state->Cpsr = GETSPSR (state->Bank); 3208 ARMul_CPSRAltered (state); 3209 #else 3210 temp = LHS + DPImmRHS; 3211 SETR15PSR (temp); 3212 #endif 3213 break; 3214 } 3215 else 3216 { 3217 /* CMN immed. */ 3218 lhs = LHS; 3219 rhs = DPImmRHS; 3220 dest = lhs + rhs; 3221 ASSIGNZ (dest == 0); 3222 if ((lhs | rhs) >> 30) 3223 { 3224 /* Possible C,V,N to set. */ 3225 ASSIGNN (NEG (dest)); 3226 ARMul_AddCarry (state, lhs, rhs, dest); 3227 ARMul_AddOverflow (state, lhs, rhs, dest); 3228 } 3229 else 3230 { 3231 CLEARN; 3232 CLEARC; 3233 CLEARV; 3234 } 3235 } 3236 break; 3237 3238 case 0x38: /* ORR immed. */ 3239 dest = LHS | DPImmRHS; 3240 WRITEDEST (dest); 3241 break; 3242 3243 case 0x39: /* ORRS immed. */ 3244 DPSImmRHS; 3245 dest = LHS | rhs; 3246 WRITESDEST (dest); 3247 break; 3248 3249 case 0x3a: /* MOV immed. */ 3250 dest = DPImmRHS; 3251 WRITEDEST (dest); 3252 break; 3253 3254 case 0x3b: /* MOVS immed. */ 3255 DPSImmRHS; 3256 WRITESDEST (rhs); 3257 break; 3258 3259 case 0x3c: /* BIC immed. */ 3260 dest = LHS & ~DPImmRHS; 3261 WRITEDEST (dest); 3262 break; 3263 3264 case 0x3d: /* BICS immed. */ 3265 DPSImmRHS; 3266 dest = LHS & ~rhs; 3267 WRITESDEST (dest); 3268 break; 3269 3270 case 0x3e: /* MVN immed. */ 3271 dest = ~DPImmRHS; 3272 WRITEDEST (dest); 3273 break; 3274 3275 case 0x3f: /* MVNS immed. */ 3276 DPSImmRHS; 3277 WRITESDEST (~rhs); 3278 break; 3279 3280 3281 /* Single Data Transfer Immediate RHS Instructions. */ 3282 3283 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */ 3284 lhs = LHS; 3285 if (StoreWord (state, instr, lhs)) 3286 LSBase = lhs - LSImmRHS; 3287 break; 3288 3289 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */ 3290 lhs = LHS; 3291 if (LoadWord (state, instr, lhs)) 3292 LSBase = lhs - LSImmRHS; 3293 break; 3294 3295 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */ 3296 UNDEF_LSRBaseEQDestWb; 3297 UNDEF_LSRPCBaseWb; 3298 lhs = LHS; 3299 temp = lhs - LSImmRHS; 3300 state->NtransSig = LOW; 3301 if (StoreWord (state, instr, lhs)) 3302 LSBase = temp; 3303 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3304 break; 3305 3306 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */ 3307 UNDEF_LSRBaseEQDestWb; 3308 UNDEF_LSRPCBaseWb; 3309 lhs = LHS; 3310 state->NtransSig = LOW; 3311 if (LoadWord (state, instr, lhs)) 3312 LSBase = lhs - LSImmRHS; 3313 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3314 break; 3315 3316 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */ 3317 lhs = LHS; 3318 if (StoreByte (state, instr, lhs)) 3319 LSBase = lhs - LSImmRHS; 3320 break; 3321 3322 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */ 3323 lhs = LHS; 3324 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3325 LSBase = lhs - LSImmRHS; 3326 break; 3327 3328 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */ 3329 UNDEF_LSRBaseEQDestWb; 3330 UNDEF_LSRPCBaseWb; 3331 lhs = LHS; 3332 state->NtransSig = LOW; 3333 if (StoreByte (state, instr, lhs)) 3334 LSBase = lhs - LSImmRHS; 3335 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3336 break; 3337 3338 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */ 3339 UNDEF_LSRBaseEQDestWb; 3340 UNDEF_LSRPCBaseWb; 3341 lhs = LHS; 3342 state->NtransSig = LOW; 3343 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3344 LSBase = lhs - LSImmRHS; 3345 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3346 break; 3347 3348 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */ 3349 lhs = LHS; 3350 if (StoreWord (state, instr, lhs)) 3351 LSBase = lhs + LSImmRHS; 3352 break; 3353 3354 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */ 3355 lhs = LHS; 3356 if (LoadWord (state, instr, lhs)) 3357 LSBase = lhs + LSImmRHS; 3358 break; 3359 3360 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */ 3361 UNDEF_LSRBaseEQDestWb; 3362 UNDEF_LSRPCBaseWb; 3363 lhs = LHS; 3364 state->NtransSig = LOW; 3365 if (StoreWord (state, instr, lhs)) 3366 LSBase = lhs + LSImmRHS; 3367 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3368 break; 3369 3370 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */ 3371 UNDEF_LSRBaseEQDestWb; 3372 UNDEF_LSRPCBaseWb; 3373 lhs = LHS; 3374 state->NtransSig = LOW; 3375 if (LoadWord (state, instr, lhs)) 3376 LSBase = lhs + LSImmRHS; 3377 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3378 break; 3379 3380 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */ 3381 lhs = LHS; 3382 if (StoreByte (state, instr, lhs)) 3383 LSBase = lhs + LSImmRHS; 3384 break; 3385 3386 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */ 3387 lhs = LHS; 3388 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3389 LSBase = lhs + LSImmRHS; 3390 break; 3391 3392 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */ 3393 UNDEF_LSRBaseEQDestWb; 3394 UNDEF_LSRPCBaseWb; 3395 lhs = LHS; 3396 state->NtransSig = LOW; 3397 if (StoreByte (state, instr, lhs)) 3398 LSBase = lhs + LSImmRHS; 3399 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3400 break; 3401 3402 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */ 3403 UNDEF_LSRBaseEQDestWb; 3404 UNDEF_LSRPCBaseWb; 3405 lhs = LHS; 3406 state->NtransSig = LOW; 3407 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3408 LSBase = lhs + LSImmRHS; 3409 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3410 break; 3411 3412 3413 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */ 3414 (void) StoreWord (state, instr, LHS - LSImmRHS); 3415 break; 3416 3417 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */ 3418 (void) LoadWord (state, instr, LHS - LSImmRHS); 3419 break; 3420 3421 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */ 3422 UNDEF_LSRBaseEQDestWb; 3423 UNDEF_LSRPCBaseWb; 3424 temp = LHS - LSImmRHS; 3425 if (StoreWord (state, instr, temp)) 3426 LSBase = temp; 3427 break; 3428 3429 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */ 3430 UNDEF_LSRBaseEQDestWb; 3431 UNDEF_LSRPCBaseWb; 3432 temp = LHS - LSImmRHS; 3433 if (LoadWord (state, instr, temp)) 3434 LSBase = temp; 3435 break; 3436 3437 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */ 3438 (void) StoreByte (state, instr, LHS - LSImmRHS); 3439 break; 3440 3441 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */ 3442 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED); 3443 break; 3444 3445 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */ 3446 UNDEF_LSRBaseEQDestWb; 3447 UNDEF_LSRPCBaseWb; 3448 temp = LHS - LSImmRHS; 3449 if (StoreByte (state, instr, temp)) 3450 LSBase = temp; 3451 break; 3452 3453 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */ 3454 UNDEF_LSRBaseEQDestWb; 3455 UNDEF_LSRPCBaseWb; 3456 temp = LHS - LSImmRHS; 3457 if (LoadByte (state, instr, temp, LUNSIGNED)) 3458 LSBase = temp; 3459 break; 3460 3461 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */ 3462 (void) StoreWord (state, instr, LHS + LSImmRHS); 3463 break; 3464 3465 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */ 3466 (void) LoadWord (state, instr, LHS + LSImmRHS); 3467 break; 3468 3469 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */ 3470 UNDEF_LSRBaseEQDestWb; 3471 UNDEF_LSRPCBaseWb; 3472 temp = LHS + LSImmRHS; 3473 if (StoreWord (state, instr, temp)) 3474 LSBase = temp; 3475 break; 3476 3477 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */ 3478 UNDEF_LSRBaseEQDestWb; 3479 UNDEF_LSRPCBaseWb; 3480 temp = LHS + LSImmRHS; 3481 if (LoadWord (state, instr, temp)) 3482 LSBase = temp; 3483 break; 3484 3485 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */ 3486 (void) StoreByte (state, instr, LHS + LSImmRHS); 3487 break; 3488 3489 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */ 3490 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED); 3491 break; 3492 3493 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */ 3494 UNDEF_LSRBaseEQDestWb; 3495 UNDEF_LSRPCBaseWb; 3496 temp = LHS + LSImmRHS; 3497 if (StoreByte (state, instr, temp)) 3498 LSBase = temp; 3499 break; 3500 3501 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */ 3502 UNDEF_LSRBaseEQDestWb; 3503 UNDEF_LSRPCBaseWb; 3504 temp = LHS + LSImmRHS; 3505 if (LoadByte (state, instr, temp, LUNSIGNED)) 3506 LSBase = temp; 3507 break; 3508 3509 3510 /* Single Data Transfer Register RHS Instructions. */ 3511 3512 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */ 3513 if (BIT (4)) 3514 { 3515 #ifdef MODE32 3516 if (state->is_v6 3517 && handle_v6_insn (state, instr)) 3518 break; 3519 #endif 3520 ARMul_UndefInstr (state, instr); 3521 break; 3522 } 3523 UNDEF_LSRBaseEQOffWb; 3524 UNDEF_LSRBaseEQDestWb; 3525 UNDEF_LSRPCBaseWb; 3526 UNDEF_LSRPCOffWb; 3527 lhs = LHS; 3528 if (StoreWord (state, instr, lhs)) 3529 LSBase = lhs - LSRegRHS; 3530 break; 3531 3532 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */ 3533 if (BIT (4)) 3534 { 3535 #ifdef MODE32 3536 if (state->is_v6 3537 && handle_v6_insn (state, instr)) 3538 break; 3539 #endif 3540 ARMul_UndefInstr (state, instr); 3541 break; 3542 } 3543 UNDEF_LSRBaseEQOffWb; 3544 UNDEF_LSRBaseEQDestWb; 3545 UNDEF_LSRPCBaseWb; 3546 UNDEF_LSRPCOffWb; 3547 lhs = LHS; 3548 temp = lhs - LSRegRHS; 3549 if (LoadWord (state, instr, lhs)) 3550 LSBase = temp; 3551 break; 3552 3553 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */ 3554 if (BIT (4)) 3555 { 3556 #ifdef MODE32 3557 if (state->is_v6 3558 && handle_v6_insn (state, instr)) 3559 break; 3560 #endif 3561 ARMul_UndefInstr (state, instr); 3562 break; 3563 } 3564 UNDEF_LSRBaseEQOffWb; 3565 UNDEF_LSRBaseEQDestWb; 3566 UNDEF_LSRPCBaseWb; 3567 UNDEF_LSRPCOffWb; 3568 lhs = LHS; 3569 state->NtransSig = LOW; 3570 if (StoreWord (state, instr, lhs)) 3571 LSBase = lhs - LSRegRHS; 3572 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3573 break; 3574 3575 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */ 3576 if (BIT (4)) 3577 { 3578 #ifdef MODE32 3579 if (state->is_v6 3580 && handle_v6_insn (state, instr)) 3581 break; 3582 #endif 3583 ARMul_UndefInstr (state, instr); 3584 break; 3585 } 3586 UNDEF_LSRBaseEQOffWb; 3587 UNDEF_LSRBaseEQDestWb; 3588 UNDEF_LSRPCBaseWb; 3589 UNDEF_LSRPCOffWb; 3590 lhs = LHS; 3591 temp = lhs - LSRegRHS; 3592 state->NtransSig = LOW; 3593 if (LoadWord (state, instr, lhs)) 3594 LSBase = temp; 3595 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3596 break; 3597 3598 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */ 3599 if (BIT (4)) 3600 { 3601 #ifdef MODE32 3602 if (state->is_v6 3603 && handle_v6_insn (state, instr)) 3604 break; 3605 #endif 3606 ARMul_UndefInstr (state, instr); 3607 break; 3608 } 3609 UNDEF_LSRBaseEQOffWb; 3610 UNDEF_LSRBaseEQDestWb; 3611 UNDEF_LSRPCBaseWb; 3612 UNDEF_LSRPCOffWb; 3613 lhs = LHS; 3614 if (StoreByte (state, instr, lhs)) 3615 LSBase = lhs - LSRegRHS; 3616 break; 3617 3618 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */ 3619 if (BIT (4)) 3620 { 3621 #ifdef MODE32 3622 if (state->is_v6 3623 && handle_v6_insn (state, instr)) 3624 break; 3625 #endif 3626 ARMul_UndefInstr (state, instr); 3627 break; 3628 } 3629 UNDEF_LSRBaseEQOffWb; 3630 UNDEF_LSRBaseEQDestWb; 3631 UNDEF_LSRPCBaseWb; 3632 UNDEF_LSRPCOffWb; 3633 lhs = LHS; 3634 temp = lhs - LSRegRHS; 3635 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3636 LSBase = temp; 3637 break; 3638 3639 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */ 3640 if (BIT (4)) 3641 { 3642 #ifdef MODE32 3643 if (state->is_v6 3644 && handle_v6_insn (state, instr)) 3645 break; 3646 #endif 3647 ARMul_UndefInstr (state, instr); 3648 break; 3649 } 3650 UNDEF_LSRBaseEQOffWb; 3651 UNDEF_LSRBaseEQDestWb; 3652 UNDEF_LSRPCBaseWb; 3653 UNDEF_LSRPCOffWb; 3654 lhs = LHS; 3655 state->NtransSig = LOW; 3656 if (StoreByte (state, instr, lhs)) 3657 LSBase = lhs - LSRegRHS; 3658 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3659 break; 3660 3661 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */ 3662 if (BIT (4)) 3663 { 3664 #ifdef MODE32 3665 if (state->is_v6 3666 && handle_v6_insn (state, instr)) 3667 break; 3668 #endif 3669 ARMul_UndefInstr (state, instr); 3670 break; 3671 } 3672 UNDEF_LSRBaseEQOffWb; 3673 UNDEF_LSRBaseEQDestWb; 3674 UNDEF_LSRPCBaseWb; 3675 UNDEF_LSRPCOffWb; 3676 lhs = LHS; 3677 temp = lhs - LSRegRHS; 3678 state->NtransSig = LOW; 3679 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3680 LSBase = temp; 3681 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3682 break; 3683 3684 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 3685 if (BIT (4)) 3686 { 3687 #ifdef MODE32 3688 if (state->is_v6 3689 && handle_v6_insn (state, instr)) 3690 break; 3691 #endif 3692 ARMul_UndefInstr (state, instr); 3693 break; 3694 } 3695 UNDEF_LSRBaseEQOffWb; 3696 UNDEF_LSRBaseEQDestWb; 3697 UNDEF_LSRPCBaseWb; 3698 UNDEF_LSRPCOffWb; 3699 lhs = LHS; 3700 if (StoreWord (state, instr, lhs)) 3701 LSBase = lhs + LSRegRHS; 3702 break; 3703 3704 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */ 3705 if (BIT (4)) 3706 { 3707 #ifdef MODE32 3708 if (state->is_v6 3709 && handle_v6_insn (state, instr)) 3710 break; 3711 #endif 3712 ARMul_UndefInstr (state, instr); 3713 break; 3714 } 3715 UNDEF_LSRBaseEQOffWb; 3716 UNDEF_LSRBaseEQDestWb; 3717 UNDEF_LSRPCBaseWb; 3718 UNDEF_LSRPCOffWb; 3719 lhs = LHS; 3720 temp = lhs + LSRegRHS; 3721 if (LoadWord (state, instr, lhs)) 3722 LSBase = temp; 3723 break; 3724 3725 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */ 3726 if (BIT (4)) 3727 { 3728 #ifdef MODE32 3729 if (state->is_v6 3730 && handle_v6_insn (state, instr)) 3731 break; 3732 #endif 3733 ARMul_UndefInstr (state, instr); 3734 break; 3735 } 3736 UNDEF_LSRBaseEQOffWb; 3737 UNDEF_LSRBaseEQDestWb; 3738 UNDEF_LSRPCBaseWb; 3739 UNDEF_LSRPCOffWb; 3740 lhs = LHS; 3741 state->NtransSig = LOW; 3742 if (StoreWord (state, instr, lhs)) 3743 LSBase = lhs + LSRegRHS; 3744 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3745 break; 3746 3747 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */ 3748 if (BIT (4)) 3749 { 3750 #ifdef MODE32 3751 if (state->is_v6 3752 && handle_v6_insn (state, instr)) 3753 break; 3754 #endif 3755 ARMul_UndefInstr (state, instr); 3756 break; 3757 } 3758 UNDEF_LSRBaseEQOffWb; 3759 UNDEF_LSRBaseEQDestWb; 3760 UNDEF_LSRPCBaseWb; 3761 UNDEF_LSRPCOffWb; 3762 lhs = LHS; 3763 temp = lhs + LSRegRHS; 3764 state->NtransSig = LOW; 3765 if (LoadWord (state, instr, lhs)) 3766 LSBase = temp; 3767 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3768 break; 3769 3770 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */ 3771 if (BIT (4)) 3772 { 3773 #ifdef MODE32 3774 if (state->is_v6 3775 && handle_v6_insn (state, instr)) 3776 break; 3777 #endif 3778 ARMul_UndefInstr (state, instr); 3779 break; 3780 } 3781 UNDEF_LSRBaseEQOffWb; 3782 UNDEF_LSRBaseEQDestWb; 3783 UNDEF_LSRPCBaseWb; 3784 UNDEF_LSRPCOffWb; 3785 lhs = LHS; 3786 if (StoreByte (state, instr, lhs)) 3787 LSBase = lhs + LSRegRHS; 3788 break; 3789 3790 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */ 3791 if (BIT (4)) 3792 { 3793 #ifdef MODE32 3794 if (state->is_v6 3795 && handle_v6_insn (state, instr)) 3796 break; 3797 #endif 3798 ARMul_UndefInstr (state, instr); 3799 break; 3800 } 3801 UNDEF_LSRBaseEQOffWb; 3802 UNDEF_LSRBaseEQDestWb; 3803 UNDEF_LSRPCBaseWb; 3804 UNDEF_LSRPCOffWb; 3805 lhs = LHS; 3806 temp = lhs + LSRegRHS; 3807 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3808 LSBase = temp; 3809 break; 3810 3811 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */ 3812 if (BIT (4)) 3813 { 3814 #ifdef MODE32 3815 if (state->is_v6 3816 && handle_v6_insn (state, instr)) 3817 break; 3818 #endif 3819 ARMul_UndefInstr (state, instr); 3820 break; 3821 } 3822 UNDEF_LSRBaseEQOffWb; 3823 UNDEF_LSRBaseEQDestWb; 3824 UNDEF_LSRPCBaseWb; 3825 UNDEF_LSRPCOffWb; 3826 lhs = LHS; 3827 state->NtransSig = LOW; 3828 if (StoreByte (state, instr, lhs)) 3829 LSBase = lhs + LSRegRHS; 3830 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3831 break; 3832 3833 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */ 3834 if (BIT (4)) 3835 { 3836 #ifdef MODE32 3837 if (state->is_v6 3838 && handle_v6_insn (state, instr)) 3839 break; 3840 #endif 3841 ARMul_UndefInstr (state, instr); 3842 break; 3843 } 3844 UNDEF_LSRBaseEQOffWb; 3845 UNDEF_LSRBaseEQDestWb; 3846 UNDEF_LSRPCBaseWb; 3847 UNDEF_LSRPCOffWb; 3848 lhs = LHS; 3849 temp = lhs + LSRegRHS; 3850 state->NtransSig = LOW; 3851 if (LoadByte (state, instr, lhs, LUNSIGNED)) 3852 LSBase = temp; 3853 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 3854 break; 3855 3856 3857 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */ 3858 if (BIT (4)) 3859 { 3860 #ifdef MODE32 3861 if (state->is_v6 3862 && handle_v6_insn (state, instr)) 3863 break; 3864 #endif 3865 ARMul_UndefInstr (state, instr); 3866 break; 3867 } 3868 (void) StoreWord (state, instr, LHS - LSRegRHS); 3869 break; 3870 3871 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */ 3872 if (BIT (4)) 3873 { 3874 #ifdef MODE32 3875 if (state->is_v6 3876 && handle_v6_insn (state, instr)) 3877 break; 3878 #endif 3879 ARMul_UndefInstr (state, instr); 3880 break; 3881 } 3882 (void) LoadWord (state, instr, LHS - LSRegRHS); 3883 break; 3884 3885 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */ 3886 if (BIT (4)) 3887 { 3888 #ifdef MODE32 3889 if (state->is_v6 3890 && handle_v6_insn (state, instr)) 3891 break; 3892 #endif 3893 ARMul_UndefInstr (state, instr); 3894 break; 3895 } 3896 UNDEF_LSRBaseEQOffWb; 3897 UNDEF_LSRBaseEQDestWb; 3898 UNDEF_LSRPCBaseWb; 3899 UNDEF_LSRPCOffWb; 3900 temp = LHS - LSRegRHS; 3901 if (StoreWord (state, instr, temp)) 3902 LSBase = temp; 3903 break; 3904 3905 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */ 3906 if (BIT (4)) 3907 { 3908 #ifdef MODE32 3909 if (state->is_v6 3910 && handle_v6_insn (state, instr)) 3911 break; 3912 #endif 3913 ARMul_UndefInstr (state, instr); 3914 break; 3915 } 3916 UNDEF_LSRBaseEQOffWb; 3917 UNDEF_LSRBaseEQDestWb; 3918 UNDEF_LSRPCBaseWb; 3919 UNDEF_LSRPCOffWb; 3920 temp = LHS - LSRegRHS; 3921 if (LoadWord (state, instr, temp)) 3922 LSBase = temp; 3923 break; 3924 3925 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */ 3926 if (BIT (4)) 3927 { 3928 #ifdef MODE32 3929 if (state->is_v6 3930 && handle_v6_insn (state, instr)) 3931 break; 3932 #endif 3933 ARMul_UndefInstr (state, instr); 3934 break; 3935 } 3936 (void) StoreByte (state, instr, LHS - LSRegRHS); 3937 break; 3938 3939 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */ 3940 if (BIT (4)) 3941 { 3942 #ifdef MODE32 3943 if (state->is_v6 3944 && handle_v6_insn (state, instr)) 3945 break; 3946 #endif 3947 ARMul_UndefInstr (state, instr); 3948 break; 3949 } 3950 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED); 3951 break; 3952 3953 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */ 3954 if (BIT (4)) 3955 { 3956 #ifdef MODE32 3957 if (state->is_v6 3958 && handle_v6_insn (state, instr)) 3959 break; 3960 #endif 3961 ARMul_UndefInstr (state, instr); 3962 break; 3963 } 3964 UNDEF_LSRBaseEQOffWb; 3965 UNDEF_LSRBaseEQDestWb; 3966 UNDEF_LSRPCBaseWb; 3967 UNDEF_LSRPCOffWb; 3968 temp = LHS - LSRegRHS; 3969 if (StoreByte (state, instr, temp)) 3970 LSBase = temp; 3971 break; 3972 3973 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */ 3974 if (BIT (4)) 3975 { 3976 #ifdef MODE32 3977 if (state->is_v6 3978 && handle_v6_insn (state, instr)) 3979 break; 3980 #endif 3981 ARMul_UndefInstr (state, instr); 3982 break; 3983 } 3984 UNDEF_LSRBaseEQOffWb; 3985 UNDEF_LSRBaseEQDestWb; 3986 UNDEF_LSRPCBaseWb; 3987 UNDEF_LSRPCOffWb; 3988 temp = LHS - LSRegRHS; 3989 if (LoadByte (state, instr, temp, LUNSIGNED)) 3990 LSBase = temp; 3991 break; 3992 3993 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */ 3994 if (BIT (4)) 3995 { 3996 #ifdef MODE32 3997 if (state->is_v6 3998 && handle_v6_insn (state, instr)) 3999 break; 4000 #endif 4001 ARMul_UndefInstr (state, instr); 4002 break; 4003 } 4004 (void) StoreWord (state, instr, LHS + LSRegRHS); 4005 break; 4006 4007 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */ 4008 if (BIT (4)) 4009 { 4010 #ifdef MODE32 4011 if (state->is_v6 4012 && handle_v6_insn (state, instr)) 4013 break; 4014 #endif 4015 ARMul_UndefInstr (state, instr); 4016 break; 4017 } 4018 (void) LoadWord (state, instr, LHS + LSRegRHS); 4019 break; 4020 4021 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */ 4022 if (BIT (4)) 4023 { 4024 #ifdef MODE32 4025 if (state->is_v6 4026 && handle_v6_insn (state, instr)) 4027 break; 4028 #endif 4029 ARMul_UndefInstr (state, instr); 4030 break; 4031 } 4032 UNDEF_LSRBaseEQOffWb; 4033 UNDEF_LSRBaseEQDestWb; 4034 UNDEF_LSRPCBaseWb; 4035 UNDEF_LSRPCOffWb; 4036 temp = LHS + LSRegRHS; 4037 if (StoreWord (state, instr, temp)) 4038 LSBase = temp; 4039 break; 4040 4041 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */ 4042 if (BIT (4)) 4043 { 4044 #ifdef MODE32 4045 if (state->is_v6 4046 && handle_v6_insn (state, instr)) 4047 break; 4048 #endif 4049 ARMul_UndefInstr (state, instr); 4050 break; 4051 } 4052 UNDEF_LSRBaseEQOffWb; 4053 UNDEF_LSRBaseEQDestWb; 4054 UNDEF_LSRPCBaseWb; 4055 UNDEF_LSRPCOffWb; 4056 temp = LHS + LSRegRHS; 4057 if (LoadWord (state, instr, temp)) 4058 LSBase = temp; 4059 break; 4060 4061 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */ 4062 if (BIT (4)) 4063 { 4064 #ifdef MODE32 4065 if (state->is_v6 4066 && handle_v6_insn (state, instr)) 4067 break; 4068 #endif 4069 ARMul_UndefInstr (state, instr); 4070 break; 4071 } 4072 (void) StoreByte (state, instr, LHS + LSRegRHS); 4073 break; 4074 4075 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */ 4076 if (BIT (4)) 4077 { 4078 #ifdef MODE32 4079 if (state->is_v6 4080 && handle_v6_insn (state, instr)) 4081 break; 4082 #endif 4083 ARMul_UndefInstr (state, instr); 4084 break; 4085 } 4086 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED); 4087 break; 4088 4089 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */ 4090 if (BIT (4)) 4091 { 4092 #ifdef MODE32 4093 if (state->is_v6 4094 && handle_v6_insn (state, instr)) 4095 break; 4096 #endif 4097 ARMul_UndefInstr (state, instr); 4098 break; 4099 } 4100 UNDEF_LSRBaseEQOffWb; 4101 UNDEF_LSRBaseEQDestWb; 4102 UNDEF_LSRPCBaseWb; 4103 UNDEF_LSRPCOffWb; 4104 temp = LHS + LSRegRHS; 4105 if (StoreByte (state, instr, temp)) 4106 LSBase = temp; 4107 break; 4108 4109 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ 4110 if (BIT (4)) 4111 { 4112 /* Check for the special breakpoint opcode. 4113 This value should correspond to the value defined 4114 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */ 4115 if (BITS (0, 19) == 0xfdefe) 4116 { 4117 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint)) 4118 ARMul_Abort (state, ARMul_SWIV); 4119 } 4120 #ifdef MODE32 4121 else if (state->is_v6 4122 && handle_v6_insn (state, instr)) 4123 break; 4124 #endif 4125 else 4126 ARMul_UndefInstr (state, instr); 4127 break; 4128 } 4129 UNDEF_LSRBaseEQOffWb; 4130 UNDEF_LSRBaseEQDestWb; 4131 UNDEF_LSRPCBaseWb; 4132 UNDEF_LSRPCOffWb; 4133 temp = LHS + LSRegRHS; 4134 if (LoadByte (state, instr, temp, LUNSIGNED)) 4135 LSBase = temp; 4136 break; 4137 4138 4139 /* Multiple Data Transfer Instructions. */ 4140 4141 case 0x80: /* Store, No WriteBack, Post Dec. */ 4142 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 4143 break; 4144 4145 case 0x81: /* Load, No WriteBack, Post Dec. */ 4146 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 4147 break; 4148 4149 case 0x82: /* Store, WriteBack, Post Dec. */ 4150 temp = LSBase - LSMNumRegs; 4151 STOREMULT (instr, temp + 4L, temp); 4152 break; 4153 4154 case 0x83: /* Load, WriteBack, Post Dec. */ 4155 temp = LSBase - LSMNumRegs; 4156 LOADMULT (instr, temp + 4L, temp); 4157 break; 4158 4159 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */ 4160 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 4161 break; 4162 4163 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */ 4164 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L); 4165 break; 4166 4167 case 0x86: /* Store, Flags, WriteBack, Post Dec. */ 4168 temp = LSBase - LSMNumRegs; 4169 STORESMULT (instr, temp + 4L, temp); 4170 break; 4171 4172 case 0x87: /* Load, Flags, WriteBack, Post Dec. */ 4173 temp = LSBase - LSMNumRegs; 4174 LOADSMULT (instr, temp + 4L, temp); 4175 break; 4176 4177 case 0x88: /* Store, No WriteBack, Post Inc. */ 4178 STOREMULT (instr, LSBase, 0L); 4179 break; 4180 4181 case 0x89: /* Load, No WriteBack, Post Inc. */ 4182 LOADMULT (instr, LSBase, 0L); 4183 break; 4184 4185 case 0x8a: /* Store, WriteBack, Post Inc. */ 4186 temp = LSBase; 4187 STOREMULT (instr, temp, temp + LSMNumRegs); 4188 break; 4189 4190 case 0x8b: /* Load, WriteBack, Post Inc. */ 4191 temp = LSBase; 4192 LOADMULT (instr, temp, temp + LSMNumRegs); 4193 break; 4194 4195 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */ 4196 STORESMULT (instr, LSBase, 0L); 4197 break; 4198 4199 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */ 4200 LOADSMULT (instr, LSBase, 0L); 4201 break; 4202 4203 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */ 4204 temp = LSBase; 4205 STORESMULT (instr, temp, temp + LSMNumRegs); 4206 break; 4207 4208 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */ 4209 temp = LSBase; 4210 LOADSMULT (instr, temp, temp + LSMNumRegs); 4211 break; 4212 4213 case 0x90: /* Store, No WriteBack, Pre Dec. */ 4214 STOREMULT (instr, LSBase - LSMNumRegs, 0L); 4215 break; 4216 4217 case 0x91: /* Load, No WriteBack, Pre Dec. */ 4218 LOADMULT (instr, LSBase - LSMNumRegs, 0L); 4219 break; 4220 4221 case 0x92: /* Store, WriteBack, Pre Dec. */ 4222 temp = LSBase - LSMNumRegs; 4223 STOREMULT (instr, temp, temp); 4224 break; 4225 4226 case 0x93: /* Load, WriteBack, Pre Dec. */ 4227 temp = LSBase - LSMNumRegs; 4228 LOADMULT (instr, temp, temp); 4229 break; 4230 4231 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */ 4232 STORESMULT (instr, LSBase - LSMNumRegs, 0L); 4233 break; 4234 4235 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */ 4236 LOADSMULT (instr, LSBase - LSMNumRegs, 0L); 4237 break; 4238 4239 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */ 4240 temp = LSBase - LSMNumRegs; 4241 STORESMULT (instr, temp, temp); 4242 break; 4243 4244 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */ 4245 temp = LSBase - LSMNumRegs; 4246 LOADSMULT (instr, temp, temp); 4247 break; 4248 4249 case 0x98: /* Store, No WriteBack, Pre Inc. */ 4250 STOREMULT (instr, LSBase + 4L, 0L); 4251 break; 4252 4253 case 0x99: /* Load, No WriteBack, Pre Inc. */ 4254 LOADMULT (instr, LSBase + 4L, 0L); 4255 break; 4256 4257 case 0x9a: /* Store, WriteBack, Pre Inc. */ 4258 temp = LSBase; 4259 STOREMULT (instr, temp + 4L, temp + LSMNumRegs); 4260 break; 4261 4262 case 0x9b: /* Load, WriteBack, Pre Inc. */ 4263 temp = LSBase; 4264 LOADMULT (instr, temp + 4L, temp + LSMNumRegs); 4265 break; 4266 4267 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */ 4268 STORESMULT (instr, LSBase + 4L, 0L); 4269 break; 4270 4271 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */ 4272 LOADSMULT (instr, LSBase + 4L, 0L); 4273 break; 4274 4275 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */ 4276 temp = LSBase; 4277 STORESMULT (instr, temp + 4L, temp + LSMNumRegs); 4278 break; 4279 4280 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */ 4281 temp = LSBase; 4282 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs); 4283 break; 4284 4285 4286 /* Branch forward. */ 4287 case 0xa0: 4288 case 0xa1: 4289 case 0xa2: 4290 case 0xa3: 4291 case 0xa4: 4292 case 0xa5: 4293 case 0xa6: 4294 case 0xa7: 4295 state->Reg[15] = pc + 8 + POSBRANCH; 4296 FLUSHPIPE; 4297 break; 4298 4299 4300 /* Branch backward. */ 4301 case 0xa8: 4302 case 0xa9: 4303 case 0xaa: 4304 case 0xab: 4305 case 0xac: 4306 case 0xad: 4307 case 0xae: 4308 case 0xaf: 4309 state->Reg[15] = pc + 8 + NEGBRANCH; 4310 FLUSHPIPE; 4311 break; 4312 4313 /* Branch and Link forward. */ 4314 case 0xb0: 4315 case 0xb1: 4316 case 0xb2: 4317 case 0xb3: 4318 case 0xb4: 4319 case 0xb5: 4320 case 0xb6: 4321 case 0xb7: 4322 /* Put PC into Link. */ 4323 #ifdef MODE32 4324 state->Reg[14] = pc + 4; 4325 #else 4326 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 4327 #endif 4328 state->Reg[15] = pc + 8 + POSBRANCH; 4329 FLUSHPIPE; 4330 if (trace_funcs) 4331 fprintf (stderr, " pc changed to %x\n", state->Reg[15]); 4332 break; 4333 4334 /* Branch and Link backward. */ 4335 case 0xb8: 4336 case 0xb9: 4337 case 0xba: 4338 case 0xbb: 4339 case 0xbc: 4340 case 0xbd: 4341 case 0xbe: 4342 case 0xbf: 4343 /* Put PC into Link. */ 4344 #ifdef MODE32 4345 state->Reg[14] = pc + 4; 4346 #else 4347 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; 4348 #endif 4349 state->Reg[15] = pc + 8 + NEGBRANCH; 4350 FLUSHPIPE; 4351 if (trace_funcs) 4352 fprintf (stderr, " pc changed to %x\n", state->Reg[15]); 4353 break; 4354 4355 /* Co-Processor Data Transfers. */ 4356 case 0xc4: 4357 if (state->is_v5) 4358 { 4359 if (CPNum == 10 || CPNum == 11) 4360 handle_VFP_move (state, instr); 4361 /* Reading from R15 is UNPREDICTABLE. */ 4362 else if (BITS (12, 15) == 15 || BITS (16, 19) == 15) 4363 ARMul_UndefInstr (state, instr); 4364 /* Is access to coprocessor 0 allowed ? */ 4365 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 4366 ARMul_UndefInstr (state, instr); 4367 /* Special treatment for XScale coprocessors. */ 4368 else if (state->is_XScale) 4369 { 4370 /* Only opcode 0 is supported. */ 4371 if (BITS (4, 7) != 0x00) 4372 ARMul_UndefInstr (state, instr); 4373 /* Only coporcessor 0 is supported. */ 4374 else if (CPNum != 0x00) 4375 ARMul_UndefInstr (state, instr); 4376 /* Only accumulator 0 is supported. */ 4377 else if (BITS (0, 3) != 0x00) 4378 ARMul_UndefInstr (state, instr); 4379 else 4380 { 4381 /* XScale MAR insn. Move two registers into accumulator. */ 4382 state->Accumulator = state->Reg[BITS (12, 15)]; 4383 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32; 4384 } 4385 } 4386 else 4387 /* FIXME: Not sure what to do for other v5 processors. */ 4388 ARMul_UndefInstr (state, instr); 4389 break; 4390 } 4391 /* Drop through. */ 4392 4393 case 0xc0: /* Store , No WriteBack , Post Dec. */ 4394 ARMul_STC (state, instr, LHS); 4395 break; 4396 4397 case 0xc5: 4398 if (state->is_v5) 4399 { 4400 if (CPNum == 10 || CPNum == 11) 4401 handle_VFP_move (state, instr); 4402 /* Writes to R15 are UNPREDICATABLE. */ 4403 else if (DESTReg == 15 || LHSReg == 15) 4404 ARMul_UndefInstr (state, instr); 4405 /* Is access to the coprocessor allowed ? */ 4406 else if (! CP_ACCESS_ALLOWED (state, CPNum)) 4407 ARMul_UndefInstr (state, instr); 4408 /* Special handling for XScale coprcoessors. */ 4409 else if (state->is_XScale) 4410 { 4411 /* Only opcode 0 is supported. */ 4412 if (BITS (4, 7) != 0x00) 4413 ARMul_UndefInstr (state, instr); 4414 /* Only coprocessor 0 is supported. */ 4415 else if (CPNum != 0x00) 4416 ARMul_UndefInstr (state, instr); 4417 /* Only accumulator 0 is supported. */ 4418 else if (BITS (0, 3) != 0x00) 4419 ARMul_UndefInstr (state, instr); 4420 else 4421 { 4422 /* XScale MRA insn. Move accumulator into two registers. */ 4423 ARMword t1 = (state->Accumulator >> 32) & 255; 4424 4425 if (t1 & 128) 4426 t1 -= 256; 4427 4428 state->Reg[BITS (12, 15)] = state->Accumulator; 4429 state->Reg[BITS (16, 19)] = t1; 4430 break; 4431 } 4432 } 4433 else 4434 /* FIXME: Not sure what to do for other v5 processors. */ 4435 ARMul_UndefInstr (state, instr); 4436 break; 4437 } 4438 /* Drop through. */ 4439 4440 case 0xc1: /* Load , No WriteBack , Post Dec. */ 4441 ARMul_LDC (state, instr, LHS); 4442 break; 4443 4444 case 0xc2: 4445 case 0xc6: /* Store , WriteBack , Post Dec. */ 4446 lhs = LHS; 4447 state->Base = lhs - LSCOff; 4448 ARMul_STC (state, instr, lhs); 4449 break; 4450 4451 case 0xc3: 4452 case 0xc7: /* Load , WriteBack , Post Dec. */ 4453 lhs = LHS; 4454 state->Base = lhs - LSCOff; 4455 ARMul_LDC (state, instr, lhs); 4456 break; 4457 4458 case 0xc8: 4459 case 0xcc: /* Store , No WriteBack , Post Inc. */ 4460 ARMul_STC (state, instr, LHS); 4461 break; 4462 4463 case 0xc9: 4464 case 0xcd: /* Load , No WriteBack , Post Inc. */ 4465 ARMul_LDC (state, instr, LHS); 4466 break; 4467 4468 case 0xca: 4469 case 0xce: /* Store , WriteBack , Post Inc. */ 4470 lhs = LHS; 4471 state->Base = lhs + LSCOff; 4472 ARMul_STC (state, instr, LHS); 4473 break; 4474 4475 case 0xcb: 4476 case 0xcf: /* Load , WriteBack , Post Inc. */ 4477 lhs = LHS; 4478 state->Base = lhs + LSCOff; 4479 ARMul_LDC (state, instr, LHS); 4480 break; 4481 4482 case 0xd0: 4483 case 0xd4: /* Store , No WriteBack , Pre Dec. */ 4484 ARMul_STC (state, instr, LHS - LSCOff); 4485 break; 4486 4487 case 0xd1: 4488 case 0xd5: /* Load , No WriteBack , Pre Dec. */ 4489 ARMul_LDC (state, instr, LHS - LSCOff); 4490 break; 4491 4492 case 0xd2: 4493 case 0xd6: /* Store , WriteBack , Pre Dec. */ 4494 lhs = LHS - LSCOff; 4495 state->Base = lhs; 4496 ARMul_STC (state, instr, lhs); 4497 break; 4498 4499 case 0xd3: 4500 case 0xd7: /* Load , WriteBack , Pre Dec. */ 4501 lhs = LHS - LSCOff; 4502 state->Base = lhs; 4503 ARMul_LDC (state, instr, lhs); 4504 break; 4505 4506 case 0xd8: 4507 case 0xdc: /* Store , No WriteBack , Pre Inc. */ 4508 ARMul_STC (state, instr, LHS + LSCOff); 4509 break; 4510 4511 case 0xd9: 4512 case 0xdd: /* Load , No WriteBack , Pre Inc. */ 4513 ARMul_LDC (state, instr, LHS + LSCOff); 4514 break; 4515 4516 case 0xda: 4517 case 0xde: /* Store , WriteBack , Pre Inc. */ 4518 lhs = LHS + LSCOff; 4519 state->Base = lhs; 4520 ARMul_STC (state, instr, lhs); 4521 break; 4522 4523 case 0xdb: 4524 case 0xdf: /* Load , WriteBack , Pre Inc. */ 4525 lhs = LHS + LSCOff; 4526 state->Base = lhs; 4527 ARMul_LDC (state, instr, lhs); 4528 break; 4529 4530 4531 /* Co-Processor Register Transfers (MCR) and Data Ops. */ 4532 4533 case 0xe2: 4534 if (! CP_ACCESS_ALLOWED (state, CPNum)) 4535 { 4536 ARMul_UndefInstr (state, instr); 4537 break; 4538 } 4539 if (state->is_XScale) 4540 switch (BITS (18, 19)) 4541 { 4542 case 0x0: 4543 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 4544 { 4545 /* XScale MIA instruction. Signed multiplication of 4546 two 32 bit values and addition to 40 bit accumulator. */ 4547 ARMsdword Rm = state->Reg[MULLHSReg]; 4548 ARMsdword Rs = state->Reg[MULACCReg]; 4549 4550 if (Rm & (1 << 31)) 4551 Rm -= 1ULL << 32; 4552 if (Rs & (1 << 31)) 4553 Rs -= 1ULL << 32; 4554 state->Accumulator += Rm * Rs; 4555 goto donext; 4556 } 4557 break; 4558 4559 case 0x2: 4560 if (BITS (4, 11) == 1 && BITS (16, 17) == 0) 4561 { 4562 /* XScale MIAPH instruction. */ 4563 ARMword t1 = state->Reg[MULLHSReg] >> 16; 4564 ARMword t2 = state->Reg[MULACCReg] >> 16; 4565 ARMword t3 = state->Reg[MULLHSReg] & 0xffff; 4566 ARMword t4 = state->Reg[MULACCReg] & 0xffff; 4567 ARMsdword t5; 4568 4569 if (t1 & (1 << 15)) 4570 t1 -= 1 << 16; 4571 if (t2 & (1 << 15)) 4572 t2 -= 1 << 16; 4573 if (t3 & (1 << 15)) 4574 t3 -= 1 << 16; 4575 if (t4 & (1 << 15)) 4576 t4 -= 1 << 16; 4577 t1 *= t2; 4578 t5 = t1; 4579 if (t5 & (1 << 31)) 4580 t5 -= 1ULL << 32; 4581 state->Accumulator += t5; 4582 t3 *= t4; 4583 t5 = t3; 4584 if (t5 & (1 << 31)) 4585 t5 -= 1ULL << 32; 4586 state->Accumulator += t5; 4587 goto donext; 4588 } 4589 break; 4590 4591 case 0x3: 4592 if (BITS (4, 11) == 1) 4593 { 4594 /* XScale MIAxy instruction. */ 4595 ARMword t1; 4596 ARMword t2; 4597 ARMsdword t5; 4598 4599 if (BIT (17)) 4600 t1 = state->Reg[MULLHSReg] >> 16; 4601 else 4602 t1 = state->Reg[MULLHSReg] & 0xffff; 4603 4604 if (BIT (16)) 4605 t2 = state->Reg[MULACCReg] >> 16; 4606 else 4607 t2 = state->Reg[MULACCReg] & 0xffff; 4608 4609 if (t1 & (1 << 15)) 4610 t1 -= 1 << 16; 4611 if (t2 & (1 << 15)) 4612 t2 -= 1 << 16; 4613 t1 *= t2; 4614 t5 = t1; 4615 if (t5 & (1 << 31)) 4616 t5 -= 1ULL << 32; 4617 state->Accumulator += t5; 4618 goto donext; 4619 } 4620 break; 4621 4622 default: 4623 break; 4624 } 4625 /* Drop through. */ 4626 4627 case 0xe0: 4628 case 0xe4: 4629 case 0xe6: 4630 case 0xe8: 4631 case 0xea: 4632 case 0xec: 4633 case 0xee: 4634 if (BIT (4)) 4635 { 4636 if (CPNum == 10 || CPNum == 11) 4637 handle_VFP_move (state, instr); 4638 /* MCR. */ 4639 else if (DESTReg == 15) 4640 { 4641 UNDEF_MCRPC; 4642 #ifdef MODE32 4643 ARMul_MCR (state, instr, state->Reg[15] + isize); 4644 #else 4645 ARMul_MCR (state, instr, ECC | ER15INT | EMODE | 4646 ((state->Reg[15] + isize) & R15PCBITS)); 4647 #endif 4648 } 4649 else 4650 ARMul_MCR (state, instr, DEST); 4651 } 4652 else 4653 /* CDP Part 1. */ 4654 ARMul_CDP (state, instr); 4655 break; 4656 4657 4658 /* Co-Processor Register Transfers (MRC) and Data Ops. */ 4659 case 0xe1: 4660 case 0xe3: 4661 case 0xe5: 4662 case 0xe7: 4663 case 0xe9: 4664 case 0xeb: 4665 case 0xed: 4666 case 0xef: 4667 if (BIT (4)) 4668 { 4669 if (CPNum == 10 || CPNum == 11) 4670 { 4671 switch (BITS (20, 27)) 4672 { 4673 case 0xEF: 4674 if (BITS (16, 19) == 0x1 4675 && BITS (0, 11) == 0xA10) 4676 { 4677 /* VMRS */ 4678 if (DESTReg == 15) 4679 { 4680 ARMul_SetCPSR (state, (state->FPSCR & 0xF0000000) 4681 | (ARMul_GetCPSR (state) & 0x0FFFFFFF)); 4682 4683 if (trace) 4684 fprintf (stderr, " VFP: VMRS: set flags to %c%c%c%c\n", 4685 ARMul_GetCPSR (state) & NBIT ? 'N' : '-', 4686 ARMul_GetCPSR (state) & ZBIT ? 'Z' : '-', 4687 ARMul_GetCPSR (state) & CBIT ? 'C' : '-', 4688 ARMul_GetCPSR (state) & VBIT ? 'V' : '-'); 4689 } 4690 else 4691 { 4692 state->Reg[DESTReg] = state->FPSCR; 4693 4694 if (trace) 4695 fprintf (stderr, " VFP: VMRS: r%d = %x\n", DESTReg, state->Reg[DESTReg]); 4696 } 4697 } 4698 else 4699 fprintf (stderr, "SIM: VFP: Unimplemented: Compare op\n"); 4700 break; 4701 4702 case 0xE0: 4703 case 0xE1: 4704 /* VMOV reg <-> single precision. */ 4705 if (BITS (0,6) != 0x10 || BITS (8,11) != 0xA) 4706 fprintf (stderr, "SIM: VFP: Unimplemented: move op\n"); 4707 else if (BIT (20)) 4708 state->Reg[BITS (12, 15)] = VFP_uword (BITS (16, 19) << 1 | BIT (7)); 4709 else 4710 VFP_uword (BITS (16, 19) << 1 | BIT (7)) = state->Reg[BITS (12, 15)]; 4711 break; 4712 4713 default: 4714 fprintf (stderr, "SIM: VFP: Unimplemented: CDP op\n"); 4715 break; 4716 } 4717 } 4718 else 4719 { 4720 /* MRC */ 4721 temp = ARMul_MRC (state, instr); 4722 if (DESTReg == 15) 4723 { 4724 ASSIGNN ((temp & NBIT) != 0); 4725 ASSIGNZ ((temp & ZBIT) != 0); 4726 ASSIGNC ((temp & CBIT) != 0); 4727 ASSIGNV ((temp & VBIT) != 0); 4728 } 4729 else 4730 DEST = temp; 4731 } 4732 } 4733 else 4734 /* CDP Part 2. */ 4735 ARMul_CDP (state, instr); 4736 break; 4737 4738 4739 /* SWI instruction. */ 4740 case 0xf0: 4741 case 0xf1: 4742 case 0xf2: 4743 case 0xf3: 4744 case 0xf4: 4745 case 0xf5: 4746 case 0xf6: 4747 case 0xf7: 4748 case 0xf8: 4749 case 0xf9: 4750 case 0xfa: 4751 case 0xfb: 4752 case 0xfc: 4753 case 0xfd: 4754 case 0xfe: 4755 case 0xff: 4756 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) 4757 { 4758 /* A prefetch abort. */ 4759 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); 4760 ARMul_Abort (state, ARMul_PrefetchAbortV); 4761 break; 4762 } 4763 4764 if (!ARMul_OSHandleSWI (state, BITS (0, 23))) 4765 ARMul_Abort (state, ARMul_SWIV); 4766 4767 break; 4768 } 4769 } 4770 4771 #ifdef MODET 4772 donext: 4773 #endif 4774 4775 if (state->Emulate == ONCE) 4776 state->Emulate = STOP; 4777 /* If we have changed mode, allow the PC to advance before stopping. */ 4778 else if (state->Emulate == CHANGEMODE) 4779 continue; 4780 else if (state->Emulate != RUN) 4781 break; 4782 } 4783 while (!stop_simulator); 4784 4785 state->decoded = decoded; 4786 state->loaded = loaded; 4787 state->pc = pc; 4788 4789 return pc; 4790 } 4791 4792 /* This routine evaluates most Data Processing register RHS's with the S 4793 bit clear. It is intended to be called from the macro DPRegRHS, which 4794 filters the common case of an unshifted register with in line code. */ 4795 4796 static ARMword 4797 GetDPRegRHS (ARMul_State * state, ARMword instr) 4798 { 4799 ARMword shamt, base; 4800 4801 base = RHSReg; 4802 if (BIT (4)) 4803 { 4804 /* Shift amount in a register. */ 4805 UNDEF_Shift; 4806 INCPC; 4807 #ifndef MODE32 4808 if (base == 15) 4809 base = ECC | ER15INT | R15PC | EMODE; 4810 else 4811 #endif 4812 base = state->Reg[base]; 4813 ARMul_Icycles (state, 1, 0L); 4814 shamt = state->Reg[BITS (8, 11)] & 0xff; 4815 switch ((int) BITS (5, 6)) 4816 { 4817 case LSL: 4818 if (shamt == 0) 4819 return (base); 4820 else if (shamt >= 32) 4821 return (0); 4822 else 4823 return (base << shamt); 4824 case LSR: 4825 if (shamt == 0) 4826 return (base); 4827 else if (shamt >= 32) 4828 return (0); 4829 else 4830 return (base >> shamt); 4831 case ASR: 4832 if (shamt == 0) 4833 return (base); 4834 else if (shamt >= 32) 4835 return ((ARMword) ((ARMsword) base >> 31L)); 4836 else 4837 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4838 case ROR: 4839 shamt &= 0x1f; 4840 if (shamt == 0) 4841 return (base); 4842 else 4843 return ((base << (32 - shamt)) | (base >> shamt)); 4844 } 4845 } 4846 else 4847 { 4848 /* Shift amount is a constant. */ 4849 #ifndef MODE32 4850 if (base == 15) 4851 base = ECC | ER15INT | R15PC | EMODE; 4852 else 4853 #endif 4854 base = state->Reg[base]; 4855 shamt = BITS (7, 11); 4856 switch ((int) BITS (5, 6)) 4857 { 4858 case LSL: 4859 return (base << shamt); 4860 case LSR: 4861 if (shamt == 0) 4862 return (0); 4863 else 4864 return (base >> shamt); 4865 case ASR: 4866 if (shamt == 0) 4867 return ((ARMword) ((ARMsword) base >> 31L)); 4868 else 4869 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4870 case ROR: 4871 if (shamt == 0) 4872 /* It's an RRX. */ 4873 return ((base >> 1) | (CFLAG << 31)); 4874 else 4875 return ((base << (32 - shamt)) | (base >> shamt)); 4876 } 4877 } 4878 4879 return 0; 4880 } 4881 4882 /* This routine evaluates most Logical Data Processing register RHS's 4883 with the S bit set. It is intended to be called from the macro 4884 DPSRegRHS, which filters the common case of an unshifted register 4885 with in line code. */ 4886 4887 static ARMword 4888 GetDPSRegRHS (ARMul_State * state, ARMword instr) 4889 { 4890 ARMword shamt, base; 4891 4892 base = RHSReg; 4893 if (BIT (4)) 4894 { 4895 /* Shift amount in a register. */ 4896 UNDEF_Shift; 4897 INCPC; 4898 #ifndef MODE32 4899 if (base == 15) 4900 base = ECC | ER15INT | R15PC | EMODE; 4901 else 4902 #endif 4903 base = state->Reg[base]; 4904 ARMul_Icycles (state, 1, 0L); 4905 shamt = state->Reg[BITS (8, 11)] & 0xff; 4906 switch ((int) BITS (5, 6)) 4907 { 4908 case LSL: 4909 if (shamt == 0) 4910 return (base); 4911 else if (shamt == 32) 4912 { 4913 ASSIGNC (base & 1); 4914 return (0); 4915 } 4916 else if (shamt > 32) 4917 { 4918 CLEARC; 4919 return (0); 4920 } 4921 else 4922 { 4923 ASSIGNC ((base >> (32 - shamt)) & 1); 4924 return (base << shamt); 4925 } 4926 case LSR: 4927 if (shamt == 0) 4928 return (base); 4929 else if (shamt == 32) 4930 { 4931 ASSIGNC (base >> 31); 4932 return (0); 4933 } 4934 else if (shamt > 32) 4935 { 4936 CLEARC; 4937 return (0); 4938 } 4939 else 4940 { 4941 ASSIGNC ((base >> (shamt - 1)) & 1); 4942 return (base >> shamt); 4943 } 4944 case ASR: 4945 if (shamt == 0) 4946 return (base); 4947 else if (shamt >= 32) 4948 { 4949 ASSIGNC (base >> 31L); 4950 return ((ARMword) ((ARMsword) base >> 31L)); 4951 } 4952 else 4953 { 4954 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 4955 return ((ARMword) ((ARMsword) base >> (int) shamt)); 4956 } 4957 case ROR: 4958 if (shamt == 0) 4959 return (base); 4960 shamt &= 0x1f; 4961 if (shamt == 0) 4962 { 4963 ASSIGNC (base >> 31); 4964 return (base); 4965 } 4966 else 4967 { 4968 ASSIGNC ((base >> (shamt - 1)) & 1); 4969 return ((base << (32 - shamt)) | (base >> shamt)); 4970 } 4971 } 4972 } 4973 else 4974 { 4975 /* Shift amount is a constant. */ 4976 #ifndef MODE32 4977 if (base == 15) 4978 base = ECC | ER15INT | R15PC | EMODE; 4979 else 4980 #endif 4981 base = state->Reg[base]; 4982 shamt = BITS (7, 11); 4983 4984 switch ((int) BITS (5, 6)) 4985 { 4986 case LSL: 4987 ASSIGNC ((base >> (32 - shamt)) & 1); 4988 return (base << shamt); 4989 case LSR: 4990 if (shamt == 0) 4991 { 4992 ASSIGNC (base >> 31); 4993 return (0); 4994 } 4995 else 4996 { 4997 ASSIGNC ((base >> (shamt - 1)) & 1); 4998 return (base >> shamt); 4999 } 5000 case ASR: 5001 if (shamt == 0) 5002 { 5003 ASSIGNC (base >> 31L); 5004 return ((ARMword) ((ARMsword) base >> 31L)); 5005 } 5006 else 5007 { 5008 ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1); 5009 return ((ARMword) ((ARMsword) base >> (int) shamt)); 5010 } 5011 case ROR: 5012 if (shamt == 0) 5013 { 5014 /* It's an RRX. */ 5015 shamt = CFLAG; 5016 ASSIGNC (base & 1); 5017 return ((base >> 1) | (shamt << 31)); 5018 } 5019 else 5020 { 5021 ASSIGNC ((base >> (shamt - 1)) & 1); 5022 return ((base << (32 - shamt)) | (base >> shamt)); 5023 } 5024 } 5025 } 5026 5027 return 0; 5028 } 5029 5030 /* This routine handles writes to register 15 when the S bit is not set. */ 5031 5032 static void 5033 WriteR15 (ARMul_State * state, ARMword src) 5034 { 5035 /* The ARM documentation states that the two least significant bits 5036 are discarded when setting PC, except in the cases handled by 5037 WriteR15Branch() below. It's probably an oversight: in THUMB 5038 mode, the second least significant bit should probably not be 5039 discarded. */ 5040 #ifdef MODET 5041 if (TFLAG) 5042 src &= 0xfffffffe; 5043 else 5044 #endif 5045 src &= 0xfffffffc; 5046 5047 #ifdef MODE32 5048 state->Reg[15] = src & PCBITS; 5049 #else 5050 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE; 5051 ARMul_R15Altered (state); 5052 #endif 5053 5054 FLUSHPIPE; 5055 if (trace_funcs) 5056 fprintf (stderr, " pc changed to %x\n", state->Reg[15]); 5057 } 5058 5059 /* This routine handles writes to register 15 when the S bit is set. */ 5060 5061 static void 5062 WriteSR15 (ARMul_State * state, ARMword src) 5063 { 5064 #ifdef MODE32 5065 if (state->Bank > 0) 5066 { 5067 state->Cpsr = state->Spsr[state->Bank]; 5068 ARMul_CPSRAltered (state); 5069 } 5070 #ifdef MODET 5071 if (TFLAG) 5072 src &= 0xfffffffe; 5073 else 5074 #endif 5075 src &= 0xfffffffc; 5076 state->Reg[15] = src & PCBITS; 5077 #else 5078 #ifdef MODET 5079 if (TFLAG) 5080 /* ARMul_R15Altered would have to support it. */ 5081 abort (); 5082 else 5083 #endif 5084 src &= 0xfffffffc; 5085 5086 if (state->Bank == USERBANK) 5087 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; 5088 else 5089 state->Reg[15] = src; 5090 5091 ARMul_R15Altered (state); 5092 #endif 5093 FLUSHPIPE; 5094 if (trace_funcs) 5095 fprintf (stderr, " pc changed to %x\n", state->Reg[15]); 5096 } 5097 5098 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM 5099 will switch to Thumb mode if the least significant bit is set. */ 5100 5101 static void 5102 WriteR15Branch (ARMul_State * state, ARMword src) 5103 { 5104 #ifdef MODET 5105 if (src & 1) 5106 { 5107 /* Thumb bit. */ 5108 SETT; 5109 state->Reg[15] = src & 0xfffffffe; 5110 } 5111 else 5112 { 5113 CLEART; 5114 state->Reg[15] = src & 0xfffffffc; 5115 } 5116 FLUSHPIPE; 5117 if (trace_funcs) 5118 fprintf (stderr, " pc changed to %x\n", state->Reg[15]); 5119 #else 5120 WriteR15 (state, src); 5121 #endif 5122 } 5123 5124 /* Before ARM_v5 LDR and LDM of pc did not change mode. */ 5125 5126 static void 5127 WriteR15Load (ARMul_State * state, ARMword src) 5128 { 5129 if (state->is_v5) 5130 WriteR15Branch (state, src); 5131 else 5132 WriteR15 (state, src); 5133 } 5134 5135 /* This routine evaluates most Load and Store register RHS's. It is 5136 intended to be called from the macro LSRegRHS, which filters the 5137 common case of an unshifted register with in line code. */ 5138 5139 static ARMword 5140 GetLSRegRHS (ARMul_State * state, ARMword instr) 5141 { 5142 ARMword shamt, base; 5143 5144 base = RHSReg; 5145 #ifndef MODE32 5146 if (base == 15) 5147 /* Now forbidden, but ... */ 5148 base = ECC | ER15INT | R15PC | EMODE; 5149 else 5150 #endif 5151 base = state->Reg[base]; 5152 5153 shamt = BITS (7, 11); 5154 switch ((int) BITS (5, 6)) 5155 { 5156 case LSL: 5157 return (base << shamt); 5158 case LSR: 5159 if (shamt == 0) 5160 return (0); 5161 else 5162 return (base >> shamt); 5163 case ASR: 5164 if (shamt == 0) 5165 return ((ARMword) ((ARMsword) base >> 31L)); 5166 else 5167 return ((ARMword) ((ARMsword) base >> (int) shamt)); 5168 case ROR: 5169 if (shamt == 0) 5170 /* It's an RRX. */ 5171 return ((base >> 1) | (CFLAG << 31)); 5172 else 5173 return ((base << (32 - shamt)) | (base >> shamt)); 5174 default: 5175 break; 5176 } 5177 return 0; 5178 } 5179 5180 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */ 5181 5182 static ARMword 5183 GetLS7RHS (ARMul_State * state, ARMword instr) 5184 { 5185 if (BIT (22) == 0) 5186 { 5187 /* Register. */ 5188 #ifndef MODE32 5189 if (RHSReg == 15) 5190 /* Now forbidden, but ... */ 5191 return ECC | ER15INT | R15PC | EMODE; 5192 #endif 5193 return state->Reg[RHSReg]; 5194 } 5195 5196 /* Immediate. */ 5197 return BITS (0, 3) | (BITS (8, 11) << 4); 5198 } 5199 5200 /* This function does the work of loading a word for a LDR instruction. */ 5201 5202 static unsigned 5203 LoadWord (ARMul_State * state, ARMword instr, ARMword address) 5204 { 5205 ARMword dest; 5206 5207 BUSUSEDINCPCS; 5208 #ifndef MODE32 5209 if (ADDREXCEPT (address)) 5210 INTERNALABORT (address); 5211 #endif 5212 5213 dest = ARMul_LoadWordN (state, address); 5214 5215 if (state->Aborted) 5216 { 5217 TAKEABORT; 5218 return state->lateabtSig; 5219 } 5220 if (address & 3) 5221 dest = ARMul_Align (state, address, dest); 5222 WRITEDESTB (dest); 5223 ARMul_Icycles (state, 1, 0L); 5224 5225 return (DESTReg != LHSReg); 5226 } 5227 5228 #ifdef MODET 5229 /* This function does the work of loading a halfword. */ 5230 5231 static unsigned 5232 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, 5233 int signextend) 5234 { 5235 ARMword dest; 5236 5237 BUSUSEDINCPCS; 5238 #ifndef MODE32 5239 if (ADDREXCEPT (address)) 5240 INTERNALABORT (address); 5241 #endif 5242 dest = ARMul_LoadHalfWord (state, address); 5243 if (state->Aborted) 5244 { 5245 TAKEABORT; 5246 return state->lateabtSig; 5247 } 5248 UNDEF_LSRBPC; 5249 if (signextend) 5250 if (dest & 1 << (16 - 1)) 5251 dest = (dest & ((1 << 16) - 1)) - (1 << 16); 5252 5253 WRITEDEST (dest); 5254 ARMul_Icycles (state, 1, 0L); 5255 return (DESTReg != LHSReg); 5256 } 5257 5258 #endif /* MODET */ 5259 5260 /* This function does the work of loading a byte for a LDRB instruction. */ 5261 5262 static unsigned 5263 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) 5264 { 5265 ARMword dest; 5266 5267 BUSUSEDINCPCS; 5268 #ifndef MODE32 5269 if (ADDREXCEPT (address)) 5270 INTERNALABORT (address); 5271 #endif 5272 dest = ARMul_LoadByte (state, address); 5273 if (state->Aborted) 5274 { 5275 TAKEABORT; 5276 return state->lateabtSig; 5277 } 5278 UNDEF_LSRBPC; 5279 if (signextend) 5280 if (dest & 1 << (8 - 1)) 5281 dest = (dest & ((1 << 8) - 1)) - (1 << 8); 5282 5283 WRITEDEST (dest); 5284 ARMul_Icycles (state, 1, 0L); 5285 5286 return (DESTReg != LHSReg); 5287 } 5288 5289 /* This function does the work of loading two words for a LDRD instruction. */ 5290 5291 static void 5292 Handle_Load_Double (ARMul_State * state, ARMword instr) 5293 { 5294 ARMword dest_reg; 5295 ARMword addr_reg; 5296 ARMword write_back = BIT (21); 5297 ARMword immediate = BIT (22); 5298 ARMword add_to_base = BIT (23); 5299 ARMword pre_indexed = BIT (24); 5300 ARMword offset; 5301 ARMword addr; 5302 ARMword sum; 5303 ARMword base; 5304 ARMword value1; 5305 ARMword value2; 5306 5307 BUSUSEDINCPCS; 5308 5309 /* If the writeback bit is set, the pre-index bit must be clear. */ 5310 if (write_back && ! pre_indexed) 5311 { 5312 ARMul_UndefInstr (state, instr); 5313 return; 5314 } 5315 5316 /* Extract the base address register. */ 5317 addr_reg = LHSReg; 5318 5319 /* Extract the destination register and check it. */ 5320 dest_reg = DESTReg; 5321 5322 /* Destination register must be even. */ 5323 if ((dest_reg & 1) 5324 /* Destination register cannot be LR. */ 5325 || (dest_reg == 14)) 5326 { 5327 ARMul_UndefInstr (state, instr); 5328 return; 5329 } 5330 5331 /* Compute the base address. */ 5332 base = state->Reg[addr_reg]; 5333 5334 /* Compute the offset. */ 5335 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 5336 5337 /* Compute the sum of the two. */ 5338 if (add_to_base) 5339 sum = base + offset; 5340 else 5341 sum = base - offset; 5342 5343 /* If this is a pre-indexed mode use the sum. */ 5344 if (pre_indexed) 5345 addr = sum; 5346 else 5347 addr = base; 5348 5349 if (state->is_v6 && (addr & 0x3) == 0) 5350 /* Word alignment is enough for v6. */ 5351 ; 5352 /* The address must be aligned on a 8 byte boundary. */ 5353 else if (addr & 0x7) 5354 { 5355 #ifdef ABORTS 5356 ARMul_DATAABORT (addr); 5357 #else 5358 ARMul_UndefInstr (state, instr); 5359 #endif 5360 return; 5361 } 5362 5363 /* For pre indexed or post indexed addressing modes, 5364 check that the destination registers do not overlap 5365 the address registers. */ 5366 if ((! pre_indexed || write_back) 5367 && ( addr_reg == dest_reg 5368 || addr_reg == dest_reg + 1)) 5369 { 5370 ARMul_UndefInstr (state, instr); 5371 return; 5372 } 5373 5374 /* Load the words. */ 5375 value1 = ARMul_LoadWordN (state, addr); 5376 value2 = ARMul_LoadWordN (state, addr + 4); 5377 5378 /* Check for data aborts. */ 5379 if (state->Aborted) 5380 { 5381 TAKEABORT; 5382 return; 5383 } 5384 5385 ARMul_Icycles (state, 2, 0L); 5386 5387 /* Store the values. */ 5388 state->Reg[dest_reg] = value1; 5389 state->Reg[dest_reg + 1] = value2; 5390 5391 /* Do the post addressing and writeback. */ 5392 if (! pre_indexed) 5393 addr = sum; 5394 5395 if (! pre_indexed || write_back) 5396 state->Reg[addr_reg] = addr; 5397 } 5398 5399 /* This function does the work of storing two words for a STRD instruction. */ 5400 5401 static void 5402 Handle_Store_Double (ARMul_State * state, ARMword instr) 5403 { 5404 ARMword src_reg; 5405 ARMword addr_reg; 5406 ARMword write_back = BIT (21); 5407 ARMword immediate = BIT (22); 5408 ARMword add_to_base = BIT (23); 5409 ARMword pre_indexed = BIT (24); 5410 ARMword offset; 5411 ARMword addr; 5412 ARMword sum; 5413 ARMword base; 5414 5415 BUSUSEDINCPCS; 5416 5417 /* If the writeback bit is set, the pre-index bit must be clear. */ 5418 if (write_back && ! pre_indexed) 5419 { 5420 ARMul_UndefInstr (state, instr); 5421 return; 5422 } 5423 5424 /* Extract the base address register. */ 5425 addr_reg = LHSReg; 5426 5427 /* Base register cannot be PC. */ 5428 if (addr_reg == 15) 5429 { 5430 ARMul_UndefInstr (state, instr); 5431 return; 5432 } 5433 5434 /* Extract the source register. */ 5435 src_reg = DESTReg; 5436 5437 /* Source register must be even. */ 5438 if (src_reg & 1) 5439 { 5440 ARMul_UndefInstr (state, instr); 5441 return; 5442 } 5443 5444 /* Compute the base address. */ 5445 base = state->Reg[addr_reg]; 5446 5447 /* Compute the offset. */ 5448 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg]; 5449 5450 /* Compute the sum of the two. */ 5451 if (add_to_base) 5452 sum = base + offset; 5453 else 5454 sum = base - offset; 5455 5456 /* If this is a pre-indexed mode use the sum. */ 5457 if (pre_indexed) 5458 addr = sum; 5459 else 5460 addr = base; 5461 5462 /* The address must be aligned on a 8 byte boundary. */ 5463 if (state->is_v6 && (addr & 0x3) == 0) 5464 /* Word alignment is enough for v6. */ 5465 ; 5466 else if (addr & 0x7) 5467 { 5468 #ifdef ABORTS 5469 ARMul_DATAABORT (addr); 5470 #else 5471 ARMul_UndefInstr (state, instr); 5472 #endif 5473 return; 5474 } 5475 5476 /* For pre indexed or post indexed addressing modes, 5477 check that the destination registers do not overlap 5478 the address registers. */ 5479 if ((! pre_indexed || write_back) 5480 && ( addr_reg == src_reg 5481 || addr_reg == src_reg + 1)) 5482 { 5483 ARMul_UndefInstr (state, instr); 5484 return; 5485 } 5486 5487 /* Load the words. */ 5488 ARMul_StoreWordN (state, addr, state->Reg[src_reg]); 5489 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]); 5490 5491 if (state->Aborted) 5492 { 5493 TAKEABORT; 5494 return; 5495 } 5496 5497 /* Do the post addressing and writeback. */ 5498 if (! pre_indexed) 5499 addr = sum; 5500 5501 if (! pre_indexed || write_back) 5502 state->Reg[addr_reg] = addr; 5503 } 5504 5505 /* This function does the work of storing a word from a STR instruction. */ 5506 5507 static unsigned 5508 StoreWord (ARMul_State * state, ARMword instr, ARMword address) 5509 { 5510 BUSUSEDINCPCN; 5511 #ifndef MODE32 5512 if (DESTReg == 15) 5513 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 5514 #endif 5515 #ifdef MODE32 5516 ARMul_StoreWordN (state, address, DEST); 5517 #else 5518 if (VECTORACCESS (address) || ADDREXCEPT (address)) 5519 { 5520 INTERNALABORT (address); 5521 (void) ARMul_LoadWordN (state, address); 5522 } 5523 else 5524 ARMul_StoreWordN (state, address, DEST); 5525 #endif 5526 if (state->Aborted) 5527 { 5528 TAKEABORT; 5529 return state->lateabtSig; 5530 } 5531 return TRUE; 5532 } 5533 5534 #ifdef MODET 5535 /* This function does the work of storing a byte for a STRH instruction. */ 5536 5537 static unsigned 5538 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) 5539 { 5540 BUSUSEDINCPCN; 5541 5542 #ifndef MODE32 5543 if (DESTReg == 15) 5544 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 5545 #endif 5546 5547 #ifdef MODE32 5548 ARMul_StoreHalfWord (state, address, DEST); 5549 #else 5550 if (VECTORACCESS (address) || ADDREXCEPT (address)) 5551 { 5552 INTERNALABORT (address); 5553 (void) ARMul_LoadHalfWord (state, address); 5554 } 5555 else 5556 ARMul_StoreHalfWord (state, address, DEST); 5557 #endif 5558 5559 if (state->Aborted) 5560 { 5561 TAKEABORT; 5562 return state->lateabtSig; 5563 } 5564 return TRUE; 5565 } 5566 5567 #endif /* MODET */ 5568 5569 /* This function does the work of storing a byte for a STRB instruction. */ 5570 5571 static unsigned 5572 StoreByte (ARMul_State * state, ARMword instr, ARMword address) 5573 { 5574 BUSUSEDINCPCN; 5575 #ifndef MODE32 5576 if (DESTReg == 15) 5577 state->Reg[15] = ECC | ER15INT | R15PC | EMODE; 5578 #endif 5579 #ifdef MODE32 5580 ARMul_StoreByte (state, address, DEST); 5581 #else 5582 if (VECTORACCESS (address) || ADDREXCEPT (address)) 5583 { 5584 INTERNALABORT (address); 5585 (void) ARMul_LoadByte (state, address); 5586 } 5587 else 5588 ARMul_StoreByte (state, address, DEST); 5589 #endif 5590 if (state->Aborted) 5591 { 5592 TAKEABORT; 5593 return state->lateabtSig; 5594 } 5595 UNDEF_LSRBPC; 5596 return TRUE; 5597 } 5598 5599 /* This function does the work of loading the registers listed in an LDM 5600 instruction, when the S bit is clear. The code here is always increment 5601 after, it's up to the caller to get the input address correct and to 5602 handle base register modification. */ 5603 5604 static void 5605 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) 5606 { 5607 ARMword dest, temp; 5608 5609 UNDEF_LSMNoRegs; 5610 UNDEF_LSMPCBase; 5611 UNDEF_LSMBaseInListWb; 5612 BUSUSEDINCPCS; 5613 #ifndef MODE32 5614 if (ADDREXCEPT (address)) 5615 INTERNALABORT (address); 5616 #endif 5617 if (BIT (21) && LHSReg != 15) 5618 LSBase = WBBase; 5619 5620 /* N cycle first. */ 5621 for (temp = 0; !BIT (temp); temp++) 5622 ; 5623 5624 dest = ARMul_LoadWordN (state, address); 5625 5626 if (!state->abortSig && !state->Aborted) 5627 state->Reg[temp++] = dest; 5628 else if (!state->Aborted) 5629 { 5630 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5631 state->Aborted = ARMul_DataAbortV; 5632 } 5633 5634 /* S cycles from here on. */ 5635 for (; temp < 16; temp ++) 5636 if (BIT (temp)) 5637 { 5638 /* Load this register. */ 5639 address += 4; 5640 dest = ARMul_LoadWordS (state, address); 5641 5642 if (!state->abortSig && !state->Aborted) 5643 state->Reg[temp] = dest; 5644 else if (!state->Aborted) 5645 { 5646 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5647 state->Aborted = ARMul_DataAbortV; 5648 } 5649 } 5650 5651 if (BIT (15) && !state->Aborted) 5652 /* PC is in the reg list. */ 5653 WriteR15Load (state, PC); 5654 5655 /* To write back the final register. */ 5656 ARMul_Icycles (state, 1, 0L); 5657 5658 if (state->Aborted) 5659 { 5660 if (BIT (21) && LHSReg != 15) 5661 LSBase = WBBase; 5662 TAKEABORT; 5663 } 5664 } 5665 5666 /* This function does the work of loading the registers listed in an LDM 5667 instruction, when the S bit is set. The code here is always increment 5668 after, it's up to the caller to get the input address correct and to 5669 handle base register modification. */ 5670 5671 static void 5672 LoadSMult (ARMul_State * state, 5673 ARMword instr, 5674 ARMword address, 5675 ARMword WBBase) 5676 { 5677 ARMword dest, temp; 5678 5679 UNDEF_LSMNoRegs; 5680 UNDEF_LSMPCBase; 5681 UNDEF_LSMBaseInListWb; 5682 5683 BUSUSEDINCPCS; 5684 5685 #ifndef MODE32 5686 if (ADDREXCEPT (address)) 5687 INTERNALABORT (address); 5688 #endif 5689 5690 if (BIT (21) && LHSReg != 15) 5691 LSBase = WBBase; 5692 5693 if (!BIT (15) && state->Bank != USERBANK) 5694 { 5695 /* Temporary reg bank switch. */ 5696 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 5697 UNDEF_LSMUserBankWb; 5698 } 5699 5700 /* N cycle first. */ 5701 for (temp = 0; !BIT (temp); temp ++) 5702 ; 5703 5704 dest = ARMul_LoadWordN (state, address); 5705 5706 if (!state->abortSig) 5707 state->Reg[temp++] = dest; 5708 else if (!state->Aborted) 5709 { 5710 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5711 state->Aborted = ARMul_DataAbortV; 5712 } 5713 5714 /* S cycles from here on. */ 5715 for (; temp < 16; temp++) 5716 if (BIT (temp)) 5717 { 5718 /* Load this register. */ 5719 address += 4; 5720 dest = ARMul_LoadWordS (state, address); 5721 5722 if (!state->abortSig && !state->Aborted) 5723 state->Reg[temp] = dest; 5724 else if (!state->Aborted) 5725 { 5726 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5727 state->Aborted = ARMul_DataAbortV; 5728 } 5729 } 5730 5731 if (BIT (15) && !state->Aborted) 5732 { 5733 /* PC is in the reg list. */ 5734 #ifdef MODE32 5735 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 5736 { 5737 state->Cpsr = GETSPSR (state->Bank); 5738 ARMul_CPSRAltered (state); 5739 } 5740 5741 WriteR15 (state, PC); 5742 #else 5743 if (state->Mode == USER26MODE || state->Mode == USER32MODE) 5744 { 5745 /* Protect bits in user mode. */ 5746 ASSIGNN ((state->Reg[15] & NBIT) != 0); 5747 ASSIGNZ ((state->Reg[15] & ZBIT) != 0); 5748 ASSIGNC ((state->Reg[15] & CBIT) != 0); 5749 ASSIGNV ((state->Reg[15] & VBIT) != 0); 5750 } 5751 else 5752 ARMul_R15Altered (state); 5753 5754 FLUSHPIPE; 5755 #endif 5756 } 5757 5758 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE) 5759 /* Restore the correct bank. */ 5760 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 5761 5762 /* To write back the final register. */ 5763 ARMul_Icycles (state, 1, 0L); 5764 5765 if (state->Aborted) 5766 { 5767 if (BIT (21) && LHSReg != 15) 5768 LSBase = WBBase; 5769 5770 TAKEABORT; 5771 } 5772 } 5773 5774 /* This function does the work of storing the registers listed in an STM 5775 instruction, when the S bit is clear. The code here is always increment 5776 after, it's up to the caller to get the input address correct and to 5777 handle base register modification. */ 5778 5779 static void 5780 StoreMult (ARMul_State * state, 5781 ARMword instr, 5782 ARMword address, 5783 ARMword WBBase) 5784 { 5785 ARMword temp; 5786 5787 UNDEF_LSMNoRegs; 5788 UNDEF_LSMPCBase; 5789 UNDEF_LSMBaseInListWb; 5790 5791 if (!TFLAG) 5792 /* N-cycle, increment the PC and update the NextInstr state. */ 5793 BUSUSEDINCPCN; 5794 5795 #ifndef MODE32 5796 if (VECTORACCESS (address) || ADDREXCEPT (address)) 5797 INTERNALABORT (address); 5798 5799 if (BIT (15)) 5800 PATCHR15; 5801 #endif 5802 5803 /* N cycle first. */ 5804 for (temp = 0; !BIT (temp); temp ++) 5805 ; 5806 5807 #ifdef MODE32 5808 ARMul_StoreWordN (state, address, state->Reg[temp++]); 5809 #else 5810 if (state->Aborted) 5811 { 5812 (void) ARMul_LoadWordN (state, address); 5813 5814 /* Fake the Stores as Loads. */ 5815 for (; temp < 16; temp++) 5816 if (BIT (temp)) 5817 { 5818 /* Save this register. */ 5819 address += 4; 5820 (void) ARMul_LoadWordS (state, address); 5821 } 5822 5823 if (BIT (21) && LHSReg != 15) 5824 LSBase = WBBase; 5825 TAKEABORT; 5826 return; 5827 } 5828 else 5829 ARMul_StoreWordN (state, address, state->Reg[temp++]); 5830 #endif 5831 5832 if (state->abortSig && !state->Aborted) 5833 { 5834 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5835 state->Aborted = ARMul_DataAbortV; 5836 } 5837 5838 if (BIT (21) && LHSReg != 15) 5839 LSBase = WBBase; 5840 5841 /* S cycles from here on. */ 5842 for (; temp < 16; temp ++) 5843 if (BIT (temp)) 5844 { 5845 /* Save this register. */ 5846 address += 4; 5847 5848 ARMul_StoreWordS (state, address, state->Reg[temp]); 5849 5850 if (state->abortSig && !state->Aborted) 5851 { 5852 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5853 state->Aborted = ARMul_DataAbortV; 5854 } 5855 } 5856 5857 if (state->Aborted) 5858 TAKEABORT; 5859 } 5860 5861 /* This function does the work of storing the registers listed in an STM 5862 instruction when the S bit is set. The code here is always increment 5863 after, it's up to the caller to get the input address correct and to 5864 handle base register modification. */ 5865 5866 static void 5867 StoreSMult (ARMul_State * state, 5868 ARMword instr, 5869 ARMword address, 5870 ARMword WBBase) 5871 { 5872 ARMword temp; 5873 5874 UNDEF_LSMNoRegs; 5875 UNDEF_LSMPCBase; 5876 UNDEF_LSMBaseInListWb; 5877 5878 BUSUSEDINCPCN; 5879 5880 #ifndef MODE32 5881 if (VECTORACCESS (address) || ADDREXCEPT (address)) 5882 INTERNALABORT (address); 5883 5884 if (BIT (15)) 5885 PATCHR15; 5886 #endif 5887 5888 if (state->Bank != USERBANK) 5889 { 5890 /* Force User Bank. */ 5891 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); 5892 UNDEF_LSMUserBankWb; 5893 } 5894 5895 for (temp = 0; !BIT (temp); temp++) 5896 ; /* N cycle first. */ 5897 5898 #ifdef MODE32 5899 ARMul_StoreWordN (state, address, state->Reg[temp++]); 5900 #else 5901 if (state->Aborted) 5902 { 5903 (void) ARMul_LoadWordN (state, address); 5904 5905 for (; temp < 16; temp++) 5906 /* Fake the Stores as Loads. */ 5907 if (BIT (temp)) 5908 { 5909 /* Save this register. */ 5910 address += 4; 5911 5912 (void) ARMul_LoadWordS (state, address); 5913 } 5914 5915 if (BIT (21) && LHSReg != 15) 5916 LSBase = WBBase; 5917 5918 TAKEABORT; 5919 return; 5920 } 5921 else 5922 ARMul_StoreWordN (state, address, state->Reg[temp++]); 5923 #endif 5924 5925 if (state->abortSig && !state->Aborted) 5926 { 5927 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5928 state->Aborted = ARMul_DataAbortV; 5929 } 5930 5931 /* S cycles from here on. */ 5932 for (; temp < 16; temp++) 5933 if (BIT (temp)) 5934 { 5935 /* Save this register. */ 5936 address += 4; 5937 5938 ARMul_StoreWordS (state, address, state->Reg[temp]); 5939 5940 if (state->abortSig && !state->Aborted) 5941 { 5942 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); 5943 state->Aborted = ARMul_DataAbortV; 5944 } 5945 } 5946 5947 if (state->Mode != USER26MODE && state->Mode != USER32MODE) 5948 /* Restore the correct bank. */ 5949 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); 5950 5951 if (BIT (21) && LHSReg != 15) 5952 LSBase = WBBase; 5953 5954 if (state->Aborted) 5955 TAKEABORT; 5956 } 5957 5958 /* This function does the work of adding two 32bit values 5959 together, and calculating if a carry has occurred. */ 5960 5961 static ARMword 5962 Add32 (ARMword a1, ARMword a2, int *carry) 5963 { 5964 ARMword result = (a1 + a2); 5965 unsigned int uresult = (unsigned int) result; 5966 unsigned int ua1 = (unsigned int) a1; 5967 5968 /* If (result == RdLo) and (state->Reg[nRdLo] == 0), 5969 or (result > RdLo) then we have no carry. */ 5970 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) 5971 *carry = 1; 5972 else 5973 *carry = 0; 5974 5975 return result; 5976 } 5977 5978 /* This function does the work of multiplying 5979 two 32bit values to give a 64bit result. */ 5980 5981 static unsigned 5982 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) 5983 { 5984 /* Operand register numbers. */ 5985 int nRdHi, nRdLo, nRs, nRm; 5986 ARMword RdHi = 0, RdLo = 0, Rm; 5987 /* Cycle count. */ 5988 int scount; 5989 5990 nRdHi = BITS (16, 19); 5991 nRdLo = BITS (12, 15); 5992 nRs = BITS (8, 11); 5993 nRm = BITS (0, 3); 5994 5995 /* Needed to calculate the cycle count. */ 5996 Rm = state->Reg[nRm]; 5997 5998 /* Check for illegal operand combinations first. */ 5999 if ( nRdHi != 15 6000 && nRdLo != 15 6001 && nRs != 15 6002 && nRm != 15 6003 && nRdHi != nRdLo) 6004 { 6005 /* Intermediate results. */ 6006 ARMword lo, mid1, mid2, hi; 6007 int carry; 6008 ARMword Rs = state->Reg[nRs]; 6009 int sign = 0; 6010 6011 #ifdef MODE32 6012 if (state->is_v6) 6013 ; 6014 else 6015 #endif 6016 /* BAD code can trigger this result. So only complain if debugging. */ 6017 if (state->Debug && (nRdHi == nRm || nRdLo == nRm)) 6018 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS: %d %d %d\n", 6019 nRdHi, nRdLo, nRm); 6020 if (msigned) 6021 { 6022 /* Compute sign of result and adjust operands if necessary. */ 6023 sign = (Rm ^ Rs) & 0x80000000; 6024 6025 if (((ARMsword) Rm) < 0) 6026 Rm = -Rm; 6027 6028 if (((ARMsword) Rs) < 0) 6029 Rs = -Rs; 6030 } 6031 6032 /* We can split the 32x32 into four 16x16 operations. This 6033 ensures that we do not lose precision on 32bit only hosts. */ 6034 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); 6035 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 6036 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); 6037 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); 6038 6039 /* We now need to add all of these results together, taking 6040 care to propogate the carries from the additions. */ 6041 RdLo = Add32 (lo, (mid1 << 16), &carry); 6042 RdHi = carry; 6043 RdLo = Add32 (RdLo, (mid2 << 16), &carry); 6044 RdHi += 6045 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); 6046 6047 if (sign) 6048 { 6049 /* Negate result if necessary. */ 6050 RdLo = ~RdLo; 6051 RdHi = ~RdHi; 6052 if (RdLo == 0xFFFFFFFF) 6053 { 6054 RdLo = 0; 6055 RdHi += 1; 6056 } 6057 else 6058 RdLo += 1; 6059 } 6060 6061 state->Reg[nRdLo] = RdLo; 6062 state->Reg[nRdHi] = RdHi; 6063 } 6064 else if (state->Debug) 6065 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n"); 6066 6067 if (scc) 6068 /* Ensure that both RdHi and RdLo are used to compute Z, 6069 but don't let RdLo's sign bit make it to N. */ 6070 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 6071 6072 /* The cycle count depends on whether the instruction is a signed or 6073 unsigned multiply, and what bits are clear in the multiplier. */ 6074 if (msigned && (Rm & ((unsigned) 1 << 31))) 6075 /* Invert the bits to make the check against zero. */ 6076 Rm = ~Rm; 6077 6078 if ((Rm & 0xFFFFFF00) == 0) 6079 scount = 1; 6080 else if ((Rm & 0xFFFF0000) == 0) 6081 scount = 2; 6082 else if ((Rm & 0xFF000000) == 0) 6083 scount = 3; 6084 else 6085 scount = 4; 6086 6087 return 2 + scount; 6088 } 6089 6090 /* This function does the work of multiplying two 32bit 6091 values and adding a 64bit value to give a 64bit result. */ 6092 6093 static unsigned 6094 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) 6095 { 6096 unsigned scount; 6097 ARMword RdLo, RdHi; 6098 int nRdHi, nRdLo; 6099 int carry = 0; 6100 6101 nRdHi = BITS (16, 19); 6102 nRdLo = BITS (12, 15); 6103 6104 RdHi = state->Reg[nRdHi]; 6105 RdLo = state->Reg[nRdLo]; 6106 6107 scount = Multiply64 (state, instr, msigned, LDEFAULT); 6108 6109 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry); 6110 RdHi = (RdHi + state->Reg[nRdHi]) + carry; 6111 6112 state->Reg[nRdLo] = RdLo; 6113 state->Reg[nRdHi] = RdHi; 6114 6115 if (scc) 6116 /* Ensure that both RdHi and RdLo are used to compute Z, 6117 but don't let RdLo's sign bit make it to N. */ 6118 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); 6119 6120 /* Extra cycle for addition. */ 6121 return scount + 1; 6122 } 6123