fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 2920 lines 47 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/arm/opcodes.c * 7 * Created: 2004-11-03 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2011 Hampa Hug <hampa@hampa.ch> * 9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> * 10 *****************************************************************************/ 11 12/***************************************************************************** 13 * This program is free software. You can redistribute it and / or modify it * 14 * under the terms of the GNU General Public License version 2 as published * 15 * by the Free Software Foundation. * 16 * * 17 * This program is distributed in the hope that it will be useful, but * 18 * WITHOUT ANY WARRANTY, without even the implied warranty of * 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 20 * Public License for more details. * 21 *****************************************************************************/ 22 23/***************************************************************************** 24 * This software was developed at the Computer Engineering and Networks * 25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. * 26 *****************************************************************************/ 27 28 29#include "arm.h" 30#include "internal.h" 31 32 33/* 34 * Count the number of 1 bits in v. 35 */ 36static 37unsigned arm_bitcnt32 (unsigned long v) 38{ 39 unsigned n; 40 41 n = 0; 42 while (v != 0) { 43 n += 1; 44 v &= v - 1; 45 } 46 47 return (n); 48} 49 50/* 51 * Write a new value to CPSR and adjust the register mapping and execution 52 * mode. 53 */ 54int arm_write_cpsr (arm_t *c, uint32_t val, int prvchk) 55{ 56 if (prvchk) { 57 if (arm_get_cpsr_m (c) == ARM_MODE_USR) { 58 return (1); 59 } 60 } 61 62 arm_set_reg_map (c, val & 0x1f); 63 arm_set_cpsr (c, val); 64 65 c->privileged = ((val & 0x1f) != ARM_MODE_USR); 66 67 arm_tbuf_flush (c); 68 69 return (0); 70} 71 72/* 73 * Set the N and Z condition codes according to a 32 bit result 74 */ 75static 76void arm_set_cc_nz (arm_t *c, uint32_t val) 77{ 78 uint32_t cc; 79 80 val &= 0xffffffff; 81 cc = 0; 82 83 if (val == 0) { 84 cc |= ARM_PSR_Z; 85 } 86 else if (val & 0x80000000) { 87 cc |= ARM_PSR_N; 88 } 89 90 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N); 91 c->cpsr |= cc; 92} 93 94/* 95 * Set the condition codes after an addition 96 */ 97static 98void arm_set_cc_add (arm_t *c, uint32_t d, uint32_t s1, uint32_t s2) 99{ 100 uint32_t cc; 101 102 cc = 0; 103 104 if (d == 0) { 105 cc |= ARM_PSR_Z; 106 } 107 else if (d & 0x80000000) { 108 cc |= ARM_PSR_N; 109 } 110 111 if ((d < s1) || ((d == s1) && (s2 != 0))) { 112 cc |= ARM_PSR_C; 113 } 114 115 if ((d ^ s1) & (d ^ s2) & 0x80000000) { 116 cc |= ARM_PSR_V; 117 } 118 119 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N | ARM_PSR_C | ARM_PSR_V); 120 c->cpsr |= cc; 121} 122 123/* 124 * Set the condition codes after a subtraction 125 */ 126static 127void arm_set_cc_sub (arm_t *c, uint32_t d, uint32_t s1, uint32_t s2) 128{ 129 uint32_t cc; 130 131 cc = 0; 132 133 if (d == 0) { 134 cc |= ARM_PSR_Z; 135 } 136 else if (d & 0x80000000) { 137 cc |= ARM_PSR_N; 138 } 139 140 if (!((d > s1) || ((d == s1) && (s2 != 0)))) { 141 cc |= ARM_PSR_C; 142 } 143 144 if ((d ^ s1) & (s1 ^ s2) & 0x80000000) { 145 cc |= ARM_PSR_V; 146 } 147 148 c->cpsr &= ~(ARM_PSR_Z | ARM_PSR_N | ARM_PSR_C | ARM_PSR_V); 149 c->cpsr |= cc; 150} 151 152static 153uint32_t arm_set_psr_field (uint32_t psr, uint32_t val, unsigned fld) 154{ 155 if (fld & 0x01) { 156 psr &= 0xffffff00; 157 psr |= val & 0x000000ff; 158 } 159 160 if (fld & 0x02) { 161 psr &= 0xffff00ff; 162 psr |= val & 0x0000ff00; 163 } 164 165 if (fld & 0x04) { 166 psr &= 0xff00ffff; 167 psr |= val & 0x00ff0000; 168 } 169 170 if (fld & 0x08) { 171 psr &= 0x00ffffff; 172 psr |= val & 0xff000000; 173 } 174 175 return (psr); 176} 177 178/* 179 * Check if condition cond is met 180 */ 181int arm_check_cond (arm_t *c, unsigned cond) 182{ 183 switch (cond & 0x0f) { 184 case 0x00: /* eq */ 185 return (arm_get_cc_z (c)); 186 187 case 0x01: /* ne */ 188 return (!arm_get_cc_z (c)); 189 190 case 0x02: /* cs */ 191 return (arm_get_cc_c (c)); 192 193 case 0x03: /* cc */ 194 return (!arm_get_cc_c (c)); 195 196 case 0x04: /* mi */ 197 return (arm_get_cc_n (c)); 198 199 case 0x05: /* pl */ 200 return (!arm_get_cc_n (c)); 201 202 case 0x06: /* vs */ 203 return (arm_get_cc_v (c)); 204 205 case 0x07: /* vc */ 206 return (!arm_get_cc_v (c)); 207 208 case 0x08: /* hi */ 209 return (arm_get_cc_c (c) && !arm_get_cc_z (c)); 210 211 case 0x09: /* ls */ 212 return (!arm_get_cc_c (c) || arm_get_cc_z (c)); 213 214 case 0x0a: /* ge */ 215 return (arm_get_cc_n (c) == arm_get_cc_v (c)); 216 217 case 0x0b: /* lt */ 218 return (arm_get_cc_n (c) != arm_get_cc_v (c)); 219 220 case 0x0c: /* gt */ 221 return (!arm_get_cc_z (c) && (arm_get_cc_n (c) == arm_get_cc_v (c))); 222 223 case 0x0d: /* le */ 224 return (arm_get_cc_z (c) || (arm_get_cc_n (c) != arm_get_cc_v (c))); 225 226 case 0x0e: /* al */ 227 return (1); 228 229 case 0x0f: /* nv */ 230 return (0); 231 } 232 233 return (0); 234} 235 236static 237uint32_t arm_get_sh (arm_t *c, uint32_t ir, uint32_t *cry) 238{ 239 unsigned n; 240 uint32_t v, tmp; 241 242 if (cry == NULL) { 243 cry = &tmp; 244 } 245 246 if (arm_get_bit (ir, 25)) { 247 /* 32 bit immediate */ 248 249 v = (ir & 0xff); 250 n = (ir >> 7) & 0x1e; 251 252 if (n == 0) { 253 *cry = arm_get_cc_c (c); 254 } 255 else { 256 v = ((v >> n) | (v << (32 - n))) & 0xffffffff; 257 *cry = ((v & 0x80000000) != 0); 258 } 259 260 return (v); 261 } 262 263 v = arm_get_rm (c, c->ir); 264 265 if (arm_get_bit (ir, 4)) { 266 /* register shifts */ 267 268 if (arm_get_bit (ir, 7)) { 269 /* extension */ 270 *cry = 0; 271 return (0); 272 } 273 274 n = arm_get_rs (c, c->ir) & 0xff; 275 276 switch (arm_get_bits (ir, 5, 2)) { 277 case 0x00: /* lsl */ 278 if (n == 0) { 279 *cry = arm_get_cc_c (c); 280 } 281 else if (n <= 32) { 282 *cry = (v >> (32 - n)) & 0x01; 283 v = (n < 32) ? (v << n) : 0; 284 } 285 else { 286 *cry = 0; 287 v = 0; 288 } 289 return (v); 290 291 case 0x01: /* lsr */ 292 if (n == 0) { 293 *cry = arm_get_cc_c (c); 294 } 295 else if (n <= 32) { 296 *cry = (v >> (n - 1)) & 0x01; 297 v = (n < 32) ? (v >> n) : 0; 298 } 299 else { 300 *cry = 0; 301 v = 0; 302 } 303 return (v); 304 305 case 0x02: /* asr */ 306 if (n == 0) { 307 *cry = arm_get_cc_c (c); 308 } 309 else if (n < 32) { 310 *cry = (v >> (n - 1)) & 0x01; 311 if (v & 0x80000000) { 312 v = v >> n; 313 v |= (0xffffffff << (32 - n)) & 0xffffffff; 314 } 315 else { 316 v = v >> n; 317 } 318 } 319 else { 320 *cry = (v >> 31) & 0x01; 321 v = *cry ? 0xffffffffUL : 0x00000000UL; 322 } 323 return (v); 324 325 case 0x03: /* ror */ 326 if (n == 0) { 327 *cry = arm_get_cc_c (c); 328 } 329 else if ((n & 0x1f) == 0) { 330 *cry = (v >> 31) & 0x01; 331 } 332 else { 333 n &= 0x1f; 334 *cry = (v >> (n - 1)) & 0x01; 335 v = (v >> n) | (v << (32 - n)); 336 } 337 return (v); 338 } 339 } 340 else { 341 /* immediate shifts */ 342 343 n = arm_get_bits (ir, 7, 5); 344 345 switch (arm_get_bits (ir, 5, 2)) { 346 case 0x00: /* lsl */ 347 if (n == 0) { 348 *cry = arm_get_cc_c (c); 349 } 350 else { 351 *cry = (v >> (32 - n)) & 0x01; 352 v = (v << n) & 0xffffffff; 353 } 354 return (v); 355 356 case 0x01: /* lsr */ 357 if (n == 0) { 358 *cry = (v >> 31) & 0x01; 359 v = 0; 360 } 361 else { 362 *cry = (v >> (n - 1)) & 0x01; 363 v = v >> n; 364 } 365 return (v); 366 367 case 0x02: /* asr */ 368 if (n == 0) { 369 *cry = (v >> 31) & 0x01; 370 v = *cry ? 0xffffffffUL : 0x00000000UL; 371 } 372 else { 373 *cry = (v >> (n - 1)) & 0x01; 374 v = arm_asr32 (v, n); 375 } 376 return (v); 377 378 case 0x03: /* ror */ 379 if (n == 0) { 380 *cry = v & 0x01; 381 v = (v >> 1) | (arm_get_cc_c (c) << 31); 382 } 383 else { 384 *cry = (v >> (n - 1)) & 0x01; 385 v = (v >> n) | (v << (32 - n)); 386 } 387 return (v); 388 } 389 } 390 391 *cry = 0; 392 393 return (0); 394} 395 396 397void op_undefined (arm_t *c) 398{ 399 if (c->log_undef != NULL) { 400 c->log_undef (c->log_ext, c->ir); 401 } 402 403 arm_set_clk (c, 0, 1); 404 405 arm_exception_undefined (c); 406} 407 408/* 00 09: mul[cond] rn, rm, rs */ 409static 410void op00_09 (arm_t *c) 411{ 412 uint32_t d, s1, s2; 413 414 s1 = arm_get_rm (c, c->ir); 415 s2 = arm_get_rs (c, c->ir); 416 417 d = (s1 * s2) & 0xffffffff; 418 419 arm_set_rn (c, c->ir, d); 420 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 421} 422 423/* 00 0b: str[cond][h|sh|sb|d] rd, addressing_mode */ 424static 425void op00_0b (arm_t *c) 426{ 427 int p, u, w, s, h; 428 uint32_t val, base, index; 429 430 p = arm_get_bit (c->ir, 24); 431 u = arm_get_bit (c->ir, 23); 432 w = arm_get_bit (c->ir, 21); 433 s = arm_get_bit (c->ir, 6); 434 h = arm_get_bit (c->ir, 5); 435 436 base = arm_get_rn (c, c->ir); 437 438 /* get index */ 439 if (arm_get_bit (c->ir, 22)) { 440 index = arm_get_bits (c->ir, 8, 4) << 4; 441 index |= arm_get_bits (c->ir, 0, 4); 442 } 443 else { 444 index = arm_get_rm (c, c->ir); 445 } 446 447 /* pre-index */ 448 if (p) { 449 base += u ? index : (~index + 1); 450 base &= 0xffffffff; 451 } 452 453 val = arm_get_rd (c, c->ir); 454 455 if (s) { 456 /* ldrd/strd */ 457 458 if (arm_ir_rd (c->ir) & 1) { 459 op_undefined (c); 460 return; 461 } 462 463 base &= 0xfffffff8; 464 465 if (h) { 466 if (arm_dstore32 (c, base, val)) { 467 return; 468 } 469 470 val = arm_get_gpr (c, (arm_ir_rd (c->ir) + 1) & 0x0f); 471 472 if (arm_dstore32 (c, base + 4, val)) { 473 return; 474 } 475 } 476 else { 477 uint32_t val2; 478 479 if (arm_dload32 (c, base, &val)) { 480 return; 481 } 482 483 if (arm_dload32 (c, base + 4, &val2)) { 484 return; 485 } 486 487 arm_set_rd (c, c->ir, val); 488 arm_set_gpr (c, (arm_ir_rd (c->ir) + 1) & 0xff, val2); 489 } 490 } 491 else if (h) { 492 if (arm_dstore16 (c, base & 0xfffffffe, val)) { 493 return; 494 } 495 } 496 else { 497 if (arm_dstore8 (c, base, val)) { 498 return; 499 } 500 } 501 502 /* post-index */ 503 if (p == 0) { 504 base += u ? index : (~index + 1); 505 base &= 0xffffffff; 506 } 507 508 /* base register writeback */ 509 if ((p == 0) || (w == 1)) { 510 arm_set_rn (c, c->ir, base); 511 } 512 513 arm_set_clk (c, 4, 1); 514} 515 516/* 00 ext */ 517static 518void op00_ext (arm_t *c) 519{ 520 switch (arm_get_shext (c->ir)) { 521 case 0x09: 522 op00_09 (c); 523 break; 524 525 default: 526 op00_0b (c); 527 break; 528 } 529} 530 531/* 00: and[cond] rd, rn, shifter_operand */ 532static 533void op00 (arm_t *c) 534{ 535 uint32_t s1, s2, d; 536 537 if (arm_is_shext (c->ir)) { 538 op00_ext (c); 539 return; 540 } 541 542 s1 = arm_get_rn (c, c->ir); 543 s2 = arm_get_sh (c, c->ir, NULL); 544 545 d = s1 & s2; 546 547 arm_set_rd (c, c->ir, d); 548 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 549} 550 551/* 01 09: mul[cond]s rn, rm, rs */ 552static 553void op01_09 (arm_t *c) 554{ 555 uint32_t d, s1, s2; 556 557 s1 = arm_get_rm (c, c->ir); 558 s2 = arm_get_rs (c, c->ir); 559 560 d = (s1 * s2) & 0xffffffff; 561 562 arm_set_rn (c, c->ir, d); 563 arm_set_cc_nz (c, d); 564 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 565} 566 567/* 01 0b: ldr[cond][h|sh|sb] rd, addressing_mode */ 568static 569void op01_0b (arm_t *c) 570{ 571 int p, u, w, s, h; 572 uint32_t val, base, index; 573 574 p = arm_get_bit (c->ir, 24); 575 u = arm_get_bit (c->ir, 23); 576 w = arm_get_bit (c->ir, 21); 577 s = arm_get_bit (c->ir, 6); 578 h = arm_get_bit (c->ir, 5); 579 580 base = arm_get_rn (c, c->ir); 581 582 /* get index */ 583 if (arm_get_bit (c->ir, 22)) { 584 index = arm_get_bits (c->ir, 8, 4) << 4; 585 index |= arm_get_bits (c->ir, 0, 4); 586 } 587 else { 588 index = arm_get_rm (c, c->ir); 589 } 590 591 /* pre-index */ 592 if (p) { 593 base += u ? index : (~index + 1); 594 base &= 0xffffffff; 595 } 596 597 if (h) { 598 uint16_t tmp; 599 600 if (arm_dload16 (c, base & 0xfffffffe, &tmp)) { 601 return; 602 } 603 604 if (s) { 605 val = arm_exts (tmp, 16); 606 } 607 else { 608 val = arm_extu (tmp, 16); 609 } 610 } 611 else { 612 uint8_t tmp; 613 614 if (arm_dload8 (c, base, &tmp)) { 615 return; 616 } 617 618 if (s) { 619 val = arm_exts (tmp, 8); 620 } 621 else { 622 val = arm_extu (tmp, 8); 623 } 624 } 625 626 arm_set_rd (c, c->ir, val); 627 628 /* post-index */ 629 if (p == 0) { 630 base += u ? index : (~index + 1); 631 base &= 0xffffffff; 632 } 633 634 /* base register writeback */ 635 if ((p == 0) || (w == 1)) { 636 arm_set_rn (c, c->ir, base); 637 } 638 639 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 640} 641 642/* 01 ext */ 643static 644void op01_ext (arm_t *c) 645{ 646 switch (arm_get_shext (c->ir)) { 647 case 0x09: 648 op01_09 (c); 649 break; 650 651 default: 652 op01_0b (c); 653 break; 654 } 655} 656 657/* 01: and[cond]s rd, rn, shifter_operand */ 658static 659void op01 (arm_t *c) 660{ 661 uint32_t s1, s2, d, shc; 662 663 if (arm_is_shext (c->ir)) { 664 op01_ext (c); 665 return; 666 } 667 668 s1 = arm_get_rn (c, c->ir); 669 s2 = arm_get_sh (c, c->ir, &shc); 670 671 d = s1 & s2; 672 673 arm_set_rd (c, c->ir, d); 674 675 if (arm_rd_is_pc (c->ir)) { 676 arm_write_cpsr (c, arm_get_spsr (c), 1); 677 arm_set_clk (c, 0, 1); 678 } 679 else { 680 arm_set_cc_nz (c, d); 681 arm_set_cc_c (c, shc); 682 arm_set_clk (c, 4, 1); 683 } 684} 685 686/* 02 09: mla[cond] rn, rm, rs, rd */ 687static 688void op02_09 (arm_t *c) 689{ 690 uint32_t s1, s2, s3, d; 691 692 s1 = arm_get_rm (c, c->ir); 693 s2 = arm_get_rs (c, c->ir); 694 s3 = arm_get_rd (c, c->ir); 695 696 d = (s1 * s2 + s3) & 0xffffffff; 697 698 arm_set_rn (c, c->ir, d); 699 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 700} 701 702/* 02 ext */ 703static 704void op02_ext (arm_t *c) 705{ 706 switch (arm_get_shext (c->ir)) { 707 case 0x09: 708 op02_09 (c); 709 break; 710 711 default: 712 op00_0b (c); 713 break; 714 } 715} 716 717/* 02: eor[cond] rd, rn, shifter_operand */ 718static 719void op02 (arm_t *c) 720{ 721 uint32_t s1, s2, d; 722 723 if (arm_is_shext (c->ir)) { 724 op02_ext (c); 725 return; 726 } 727 728 s1 = arm_get_rn (c, c->ir); 729 s2 = arm_get_sh (c, c->ir, NULL); 730 731 d = s1 ^ s2; 732 733 arm_set_rd (c, c->ir, d); 734 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 735} 736 737/* 03 09: mla[cond]s rn, rm, rs, rd */ 738static 739void op03_09 (arm_t *c) 740{ 741 uint32_t s1, s2, s3, d; 742 743 s1 = arm_get_rm (c, c->ir); 744 s2 = arm_get_rs (c, c->ir); 745 s3 = arm_get_rd (c, c->ir); 746 747 d = (s1 * s2 + s3) & 0xffffffff; 748 749 arm_set_rn (c, c->ir, d); 750 arm_set_cc_nz (c, d); 751 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 752} 753 754/* 03 ext */ 755static 756void op03_ext (arm_t *c) 757{ 758 switch (arm_get_shext (c->ir)) { 759 case 0x09: 760 op03_09 (c); 761 break; 762 763 default: 764 op01_0b (c); 765 break; 766 } 767} 768 769/* 03: eor[cond]s rd, rn, shifter_operand */ 770static 771void op03 (arm_t *c) 772{ 773 uint32_t s1, s2, d, shc; 774 775 if (arm_is_shext (c->ir)) { 776 op03_ext (c); 777 return; 778 } 779 780 s1 = arm_get_rn (c, c->ir); 781 s2 = arm_get_sh (c, c->ir, &shc); 782 783 d = s1 ^ s2; 784 785 arm_set_rd (c, c->ir, d); 786 787 if (arm_rd_is_pc (c->ir)) { 788 arm_write_cpsr (c, arm_get_spsr (c), 1); 789 arm_set_clk (c, 0, 1); 790 } 791 else { 792 arm_set_cc_nz (c, d); 793 arm_set_cc_c (c, shc); 794 arm_set_clk (c, 4, 1); 795 } 796} 797 798/* 04 ext */ 799static 800void op04_ext (arm_t *c) 801{ 802 switch (arm_get_shext (c->ir)) { 803 case 0x09: 804 op_undefined (c); 805 break; 806 807 default: 808 op00_0b (c); 809 break; 810 } 811} 812 813/* 04: sub[cond] rd, rn, shifter_operand */ 814static 815void op04 (arm_t *c) 816{ 817 uint32_t s1, s2, d; 818 819 if (arm_is_shext (c->ir)) { 820 op04_ext (c); 821 return; 822 } 823 824 s1 = arm_get_rn (c, c->ir); 825 s2 = arm_get_sh (c, c->ir, NULL); 826 827 d = (s1 - s2) & 0xffffffff; 828 829 arm_set_rd (c, c->ir, d); 830 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 831} 832 833/* 05 ext */ 834static 835void op05_ext (arm_t *c) 836{ 837 switch (arm_get_shext (c->ir)) { 838 case 0x09: 839 op_undefined (c); 840 break; 841 842 default: 843 op01_0b (c); 844 break; 845 } 846} 847 848/* 05: sub[cond]s rd, rn, shifter_operand */ 849static 850void op05 (arm_t *c) 851{ 852 uint32_t s1, s2, d; 853 854 if (arm_is_shext (c->ir)) { 855 op05_ext (c); 856 return; 857 } 858 859 s1 = arm_get_rn (c, c->ir); 860 s2 = arm_get_sh (c, c->ir, NULL); 861 862 d = (s1 - s2) & 0xffffffff; 863 864 arm_set_rd (c, c->ir, d); 865 866 if (arm_rd_is_pc (c->ir)) { 867 arm_write_cpsr (c, arm_get_spsr (c), 1); 868 arm_set_clk (c, 0, 1); 869 } 870 else { 871 arm_set_cc_sub (c, d, s1, s2); 872 arm_set_clk (c, 4, 1); 873 } 874} 875 876/* 06 ext */ 877static 878void op06_ext (arm_t *c) 879{ 880 switch (arm_get_shext (c->ir)) { 881 case 0x09: 882 op_undefined (c); 883 break; 884 885 default: 886 op00_0b (c); 887 break; 888 } 889} 890 891/* 06: rsb[cond] rd, rn, shifter_operand */ 892static 893void op06 (arm_t *c) 894{ 895 uint32_t s1, s2, d; 896 897 if (arm_is_shext (c->ir)) { 898 op06_ext (c); 899 return; 900 } 901 902 s2 = arm_get_rn (c, c->ir); 903 s1 = arm_get_sh (c, c->ir, NULL); 904 905 d = (s1 - s2) & 0xffffffff; 906 907 arm_set_rd (c, c->ir, d); 908 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 909} 910 911/* 07 ext */ 912static 913void op07_ext (arm_t *c) 914{ 915 switch (arm_get_shext (c->ir)) { 916 case 0x09: 917 op_undefined (c); 918 break; 919 920 default: 921 op01_0b (c); 922 break; 923 } 924} 925 926/* 07: rsb[cond]s rd, rn, shifter_operand */ 927static 928void op07 (arm_t *c) 929{ 930 uint32_t s1, s2, d; 931 932 if (arm_is_shext (c->ir)) { 933 op07_ext (c); 934 return; 935 } 936 937 s2 = arm_get_rn (c, c->ir); 938 s1 = arm_get_sh (c, c->ir, NULL); 939 940 d = (s1 - s2) & 0xffffffff; 941 942 arm_set_rd (c, c->ir, d); 943 944 if (arm_rd_is_pc (c->ir)) { 945 arm_write_cpsr (c, arm_get_spsr (c), 1); 946 arm_set_clk (c, 0, 1); 947 } 948 else { 949 arm_set_cc_sub (c, d, s1, s2); 950 arm_set_clk (c, 4, 1); 951 } 952} 953 954/* 08 09: umull[cond] rdlo, rdhi, rm, rs */ 955static 956void op08_09 (arm_t *c) 957{ 958 uint32_t d1, d2, s1, s2; 959 uint64_t d; 960 961 s1 = arm_get_rm (c, c->ir); 962 s2 = arm_get_rs (c, c->ir); 963 964 d = (uint64_t) s1 * (uint64_t) s2; 965 d1 = d & 0xffffffff; 966 d2 = (d >> 32) & 0xffffffff; 967 968 arm_set_rn (c, c->ir, d2); 969 arm_set_rd (c, c->ir, d1); 970 971 arm_set_clk (c, 4, 1); 972} 973 974/* 08 ext */ 975static 976void op08_ext (arm_t *c) 977{ 978 switch (arm_get_shext (c->ir)) { 979 case 0x09: 980 op08_09 (c); 981 break; 982 983 default: 984 op00_0b (c); 985 break; 986 } 987} 988 989/* 08: add[cond] rd, rn, shifter_operand */ 990static 991void op08 (arm_t *c) 992{ 993 uint32_t s1, s2, d; 994 995 if (arm_is_shext (c->ir)) { 996 op08_ext (c); 997 return; 998 } 999 1000 s1 = arm_get_rn (c, c->ir); 1001 s2 = arm_get_sh (c, c->ir, NULL); 1002 1003 d = (s1 + s2) & 0xffffffffUL; 1004 1005 arm_set_rd (c, c->ir, d); 1006 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1007} 1008 1009/* 09 09: umull[cond]s rdlo, rdhi, rm, rs */ 1010static 1011void op09_09 (arm_t *c) 1012{ 1013 uint32_t d1, d2, s1, s2; 1014 uint64_t d; 1015 1016 s1 = arm_get_rm (c, c->ir); 1017 s2 = arm_get_rs (c, c->ir); 1018 1019 d = (uint64_t) s1 * (uint64_t) s2; 1020 d1 = d & 0xffffffff; 1021 d2 = (d >> 32) & 0xffffffff; 1022 1023 arm_set_rn (c, c->ir, d2); 1024 arm_set_rd (c, c->ir, d1); 1025 arm_set_cc_nz (c, d2); 1026 1027 arm_set_clk (c, 4, 1); 1028} 1029 1030/* 09 ext */ 1031static 1032void op09_ext (arm_t *c) 1033{ 1034 switch (arm_get_shext (c->ir)) { 1035 case 0x09: 1036 op09_09 (c); 1037 break; 1038 1039 default: 1040 op01_0b (c); 1041 break; 1042 } 1043} 1044 1045/* 09: add[cond]s rd, rn, shifter_operand */ 1046static 1047void op09 (arm_t *c) 1048{ 1049 uint32_t s1, s2, d; 1050 1051 if (arm_is_shext (c->ir)) { 1052 op09_ext (c); 1053 return; 1054 } 1055 1056 s1 = arm_get_rn (c, c->ir); 1057 s2 = arm_get_sh (c, c->ir, NULL); 1058 1059 d = (s1 + s2) & 0xffffffff; 1060 1061 arm_set_rd (c, c->ir, d); 1062 1063 if (arm_rd_is_pc (c->ir)) { 1064 arm_write_cpsr (c, arm_get_spsr (c), 1); 1065 arm_set_clk (c, 0, 1); 1066 } 1067 else { 1068 arm_set_cc_add (c, d, s1, s2); 1069 arm_set_clk (c, 4, 1); 1070 } 1071} 1072 1073/* 0A 09: umlal[cond] rdlo, rdhi, rm, rs */ 1074static 1075void op0a_09 (arm_t *c) 1076{ 1077 uint32_t s1, s2, d1, d2; 1078 uint64_t d; 1079 1080 s1 = arm_get_rm (c, c->ir); 1081 s2 = arm_get_rs (c, c->ir); 1082 d1 = arm_get_rd (c, c->ir); 1083 d2 = arm_get_rn (c, c->ir); 1084 1085 d = (uint64_t) s1 * (uint64_t) s2; 1086 1087 d += d1; 1088 d += (uint64_t) d2 << 32; 1089 1090 d1 = d & 0xffffffff; 1091 d2 = (d >> 32) & 0xffffffff; 1092 1093 arm_set_rd (c, c->ir, d1); 1094 arm_set_rn (c, c->ir, d2); 1095 1096 arm_set_clk (c, 4, 1); 1097} 1098 1099/* 0A ext */ 1100static 1101void op0a_ext (arm_t *c) 1102{ 1103 switch (arm_get_shext (c->ir)) { 1104 case 0x09: 1105 op0a_09 (c); 1106 break; 1107 1108 default: 1109 op00_0b (c); 1110 break; 1111 } 1112} 1113 1114/* 0A: adc[cond] rd, rn, shifter_operand */ 1115static 1116void op0a (arm_t *c) 1117{ 1118 uint32_t s1, s2, s3, d; 1119 1120 if (arm_is_shext (c->ir)) { 1121 op0a_ext (c); 1122 return; 1123 } 1124 1125 s1 = arm_get_rn (c, c->ir); 1126 s2 = arm_get_sh (c, c->ir, NULL); 1127 s3 = arm_get_cc_c (c); 1128 1129 d = (s1 + s2 + s3) & 0xffffffffUL; 1130 1131 arm_set_rd (c, c->ir, d); 1132 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1133} 1134 1135/* 0B 09: umlal[cond]s rdlo, rdhi, rm, rs */ 1136static 1137void op0b_09 (arm_t *c) 1138{ 1139 uint32_t s1, s2, d1, d2; 1140 uint64_t d; 1141 1142 s1 = arm_get_rm (c, c->ir); 1143 s2 = arm_get_rs (c, c->ir); 1144 d1 = arm_get_rd (c, c->ir); 1145 d2 = arm_get_rn (c, c->ir); 1146 1147 d = (uint64_t) s1 * (uint64_t) s2; 1148 1149 d += d1; 1150 d += (uint64_t) d2 << 32; 1151 1152 d1 = d & 0xffffffff; 1153 d2 = (d >> 32) & 0xffffffff; 1154 1155 arm_set_rd (c, c->ir, d1); 1156 arm_set_rn (c, c->ir, d2); 1157 arm_set_cc_nz (c, d2); 1158 1159 arm_set_clk (c, 4, 1); 1160} 1161 1162/* 0B ext */ 1163static 1164void op0b_ext (arm_t *c) 1165{ 1166 switch (arm_get_shext (c->ir)) { 1167 case 0x09: 1168 op0b_09 (c); 1169 break; 1170 1171 default: 1172 op01_0b (c); 1173 break; 1174 } 1175} 1176 1177/* 0B: adc[cond]s rd, rn, shifter_operand */ 1178static 1179void op0b (arm_t *c) 1180{ 1181 uint32_t s1, s2, s3, d; 1182 1183 if (arm_is_shext (c->ir)) { 1184 op0b_ext (c); 1185 return; 1186 } 1187 1188 s1 = arm_get_rn (c, c->ir); 1189 s2 = arm_get_sh (c, c->ir, NULL); 1190 s3 = arm_get_cc_c (c); 1191 1192 d = (s1 + s2 + s3) & 0xffffffff; 1193 1194 arm_set_rd (c, c->ir, d); 1195 1196 if (arm_rd_is_pc (c->ir)) { 1197 arm_write_cpsr (c, arm_get_spsr (c), 1); 1198 arm_set_clk (c, 0, 1); 1199 } 1200 else { 1201 arm_set_cc_add (c, d, s1, s2); 1202 arm_set_clk (c, 4, 1); 1203 } 1204} 1205 1206/* 0C 09: smull[cond] rdlo, rdhi, rm, rs */ 1207static 1208void op0c_09 (arm_t *c) 1209{ 1210 int sign; 1211 uint32_t d1, d2, s1, s2; 1212 uint64_t d; 1213 1214 s1 = arm_get_rm (c, c->ir); 1215 s2 = arm_get_rs (c, c->ir); 1216 1217 sign = ((s1 ^ s2) & 0x80000000) != 0; 1218 1219 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff; 1220 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff; 1221 1222 d = (uint64_t) s1 * (uint64_t) s2; 1223 1224 if (sign) { 1225 d = ~d + 1; 1226 } 1227 1228 d1 = d & 0xffffffff; 1229 d2 = (d >> 32) & 0xffffffff; 1230 1231 arm_set_rd (c, c->ir, d1); 1232 arm_set_rn (c, c->ir, d2); 1233 1234 arm_set_clk (c, 4, 1); 1235} 1236 1237/* 0C ext */ 1238static 1239void op0c_ext (arm_t *c) 1240{ 1241 switch (arm_get_shext (c->ir)) { 1242 case 0x09: 1243 op0c_09 (c); 1244 break; 1245 1246 default: 1247 op00_0b (c); 1248 break; 1249 } 1250} 1251 1252/* 0C: sbc[cond] rd, rn, shifter_operand */ 1253static 1254void op0c (arm_t *c) 1255{ 1256 uint32_t s1, s2, s3, d; 1257 1258 if (arm_is_shext (c->ir)) { 1259 op0c_ext (c); 1260 return; 1261 } 1262 1263 s1 = arm_get_rn (c, c->ir); 1264 s2 = arm_get_sh (c, c->ir, NULL); 1265 s3 = !arm_get_cc_c (c); 1266 1267 d = (s1 - s2 - s3) & 0xffffffff; 1268 1269 arm_set_rd (c, c->ir, d); 1270 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1271} 1272 1273/* 0D 09: smull[cond]s rdlo, rdhi, rm, rs */ 1274static 1275void op0d_09 (arm_t *c) 1276{ 1277 int sign; 1278 uint32_t d1, d2, s1, s2; 1279 uint64_t d; 1280 1281 s1 = arm_get_rm (c, c->ir); 1282 s2 = arm_get_rs (c, c->ir); 1283 1284 sign = ((s1 ^ s2) & 0x80000000) != 0; 1285 1286 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff; 1287 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff; 1288 1289 d = (uint64_t) s1 * (uint64_t) s2; 1290 1291 if (sign) { 1292 d = ~d + 1; 1293 } 1294 1295 d1 = d & 0xffffffff; 1296 d2 = (d >> 32) & 0xffffffff; 1297 1298 arm_set_rd (c, c->ir, d1); 1299 arm_set_rn (c, c->ir, d2); 1300 arm_set_cc_nz (c, d2); 1301 1302 arm_set_clk (c, 4, 1); 1303} 1304 1305/* 0D ext */ 1306static 1307void op0d_ext (arm_t *c) 1308{ 1309 switch (arm_get_shext (c->ir)) { 1310 case 0x09: 1311 op0d_09 (c); 1312 break; 1313 1314 default: 1315 op01_0b (c); 1316 break; 1317 } 1318} 1319 1320/* 0D: sbc[cond]s rd, rn, shifter_operand */ 1321static 1322void op0d (arm_t *c) 1323{ 1324 uint32_t s1, s2, s3, d; 1325 1326 if (arm_is_shext (c->ir)) { 1327 op0d_ext (c); 1328 return; 1329 } 1330 1331 s1 = arm_get_rn (c, c->ir); 1332 s2 = arm_get_sh (c, c->ir, NULL); 1333 s3 = !arm_get_cc_c (c); 1334 1335 d = (s1 - s2 - s3) & 0xffffffff; 1336 1337 arm_set_rd (c, c->ir, d); 1338 1339 if (arm_rd_is_pc (c->ir)) { 1340 arm_write_cpsr (c, arm_get_spsr (c), 1); 1341 arm_set_clk (c, 0, 1); 1342 } 1343 else { 1344 arm_set_cc_sub (c, d, s1, s2); 1345 arm_set_clk (c, 4, 1); 1346 } 1347} 1348 1349/* 0E 09: smlal[cond] rdlo, rdhi, rm, rs */ 1350static 1351void op0e_09 (arm_t *c) 1352{ 1353 int sign; 1354 uint32_t s1, s2, d1, d2; 1355 uint64_t d; 1356 1357 s1 = arm_get_rm (c, c->ir); 1358 s2 = arm_get_rs (c, c->ir); 1359 d1 = arm_get_rd (c, c->ir); 1360 d2 = arm_get_rn (c, c->ir); 1361 1362 sign = ((s1 ^ s2) & 0x80000000) != 0; 1363 1364 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff; 1365 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff; 1366 1367 d = (uint64_t) s1 * (uint64_t) s2; 1368 1369 if (sign) { 1370 d = ~d + 1; 1371 } 1372 1373 d += d1; 1374 d += (uint64_t) d2 << 32; 1375 1376 d1 = d & 0xffffffff; 1377 d2 = (d >> 32) & 0xffffffff; 1378 1379 arm_set_rd (c, c->ir, d1); 1380 arm_set_rn (c, c->ir, d2); 1381 1382 arm_set_clk (c, 4, 1); 1383} 1384 1385/* 0E ext */ 1386static 1387void op0e_ext (arm_t *c) 1388{ 1389 switch (arm_get_shext (c->ir)) { 1390 case 0x09: 1391 op0e_09 (c); 1392 break; 1393 1394 default: 1395 op00_0b (c); 1396 break; 1397 } 1398} 1399 1400/* 0E: rsc[cond] rd, rn, shifter_operand */ 1401static 1402void op0e (arm_t *c) 1403{ 1404 uint32_t s1, s2, s3, d; 1405 1406 if (arm_is_shext (c->ir)) { 1407 op0e_ext (c); 1408 return; 1409 } 1410 1411 s2 = arm_get_rn (c, c->ir); 1412 s1 = arm_get_sh (c, c->ir, NULL); 1413 s3 = !arm_get_cc_c (c); 1414 1415 d = (s1 - s2 - s3) & 0xffffffffUL; 1416 1417 arm_set_rd (c, c->ir, d); 1418 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1419} 1420 1421/* 0F 09: smlal[cond]s rdlo, rdhi, rm, rs */ 1422static 1423void op0f_09 (arm_t *c) 1424{ 1425 int sign; 1426 uint32_t s1, s2, d1, d2; 1427 uint64_t d; 1428 1429 s1 = arm_get_rm (c, c->ir); 1430 s2 = arm_get_rs (c, c->ir); 1431 d1 = arm_get_rd (c, c->ir); 1432 d2 = arm_get_rn (c, c->ir); 1433 1434 sign = ((s1 ^ s2) & 0x80000000) != 0; 1435 1436 s1 = ((s1 & 0x80000000) ? (~s1 + 1) : s1) & 0xffffffff; 1437 s2 = ((s2 & 0x80000000) ? (~s2 + 1) : s2) & 0xffffffff; 1438 1439 d = (uint64_t) s1 * (uint64_t) s2; 1440 1441 if (sign) { 1442 d = ~d + 1; 1443 } 1444 1445 d += d1; 1446 d += (uint64_t) d2 << 32; 1447 1448 d1 = d & 0xffffffff; 1449 d2 = (d >> 32) & 0xffffffff; 1450 1451 arm_set_rd (c, c->ir, d1); 1452 arm_set_rn (c, c->ir, d2); 1453 arm_set_cc_nz (c, d2); 1454 1455 arm_set_clk (c, 4, 1); 1456} 1457 1458/* 0F ext */ 1459static 1460void op0f_ext (arm_t *c) 1461{ 1462 switch (arm_get_shext (c->ir)) { 1463 case 0x09: 1464 op0f_09 (c); 1465 break; 1466 1467 default: 1468 op01_0b (c); 1469 break; 1470 } 1471} 1472 1473/* 0F: rsc[cond]s rd, rn, shifter_operand */ 1474static 1475void op0f (arm_t *c) 1476{ 1477 uint32_t s1, s2, s3, d; 1478 1479 if (arm_is_shext (c->ir)) { 1480 op0f_ext (c); 1481 return; 1482 } 1483 1484 s2 = arm_get_rn (c, c->ir); 1485 s1 = arm_get_sh (c, c->ir, NULL); 1486 s3 = !arm_get_cc_c (c); 1487 1488 d = (s1 - s2 - s3) & 0xffffffff; 1489 1490 arm_set_rd (c, c->ir, d); 1491 1492 if (arm_rd_is_pc (c->ir)) { 1493 arm_write_cpsr (c, arm_get_spsr (c), 1); 1494 arm_set_clk (c, 0, 1); 1495 } 1496 else { 1497 arm_set_cc_sub (c, d, s1, s2); 1498 arm_set_clk (c, 4, 1); 1499 } 1500} 1501 1502/* 10 00: mrs[cond] rd, cpsr */ 1503static 1504void op10_00 (arm_t *c) 1505{ 1506 arm_set_rd (c, c->ir, arm_get_cpsr (c)); 1507 arm_set_clk (c, 4, 1); 1508} 1509 1510/* 10 09: swp[cond] rd, rm, rn */ 1511static 1512void op10_09 (arm_t *c) 1513{ 1514 uint32_t addr, d, s; 1515 1516 addr = arm_get_rn (c, c->ir); 1517 s = arm_get_rm (c, c->ir); 1518 1519 if (arm_dload32 (c, addr & 0xfffffffc, &d)) { 1520 return; 1521 } 1522 1523 if (addr & 0x03) { 1524 d = arm_ror32 (d, (addr & 0x03) << 3); 1525 } 1526 1527 if (arm_dstore32 (c, addr & 0xfffffffc, s)) { 1528 return; 1529 } 1530 1531 arm_set_rd (c, c->ir, d); 1532 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1533} 1534 1535/* 10 */ 1536static 1537void op10 (arm_t *c) 1538{ 1539 switch (arm_get_bits (c->ir, 4, 4)) { 1540 case 0x00: 1541 op10_00 (c); 1542 break; 1543 1544 case 0x09: 1545 op10_09 (c); 1546 break; 1547 1548 case 0x0b: 1549 case 0x0d: 1550 case 0x0f: 1551 op00_0b (c); 1552 break; 1553 1554 default: 1555 op_undefined (c); 1556 break; 1557 } 1558} 1559 1560/* 11 ext */ 1561static 1562void op11_ext (arm_t *c) 1563{ 1564 switch (arm_get_shext (c->ir)) { 1565 case 0x09: 1566 op_undefined (c); 1567 break; 1568 1569 default: 1570 op01_0b (c); 1571 break; 1572 } 1573} 1574 1575/* 11: tst[cond] rn, shifter_operand */ 1576static 1577void op11 (arm_t *c) 1578{ 1579 uint32_t s1, s2, d, shc; 1580 1581 if (arm_is_shext (c->ir)) { 1582 op11_ext (c); 1583 return; 1584 } 1585 1586 s1 = arm_get_rn (c, c->ir); 1587 s2 = arm_get_sh (c, c->ir, &shc); 1588 1589 d = s1 & s2; 1590 1591 arm_set_cc_nz (c, d); 1592 arm_set_cc_c (c, shc); 1593 arm_set_clk (c, 4, 1); 1594} 1595 1596/* 12 00: msr[cond] fields, rm */ 1597static 1598void op12_00 (arm_t *c) 1599{ 1600 unsigned fld; 1601 uint32_t val; 1602 1603 fld = arm_get_bits (c->ir, 16, 4); 1604 1605 if (arm_is_privileged (c) == 0) { 1606 fld &= 0x08; 1607 } 1608 1609 val = arm_get_rm (c, c->ir); 1610 1611 if (arm_get_bit (c->ir, 22)) { 1612 val = arm_set_psr_field (arm_get_spsr (c), val, fld); 1613 arm_set_spsr (c, val); 1614 } 1615 else { 1616 val = arm_set_psr_field (arm_get_cpsr (c), val, fld); 1617 arm_write_cpsr (c, val, 0); 1618 } 1619 1620 arm_set_clk (c, 4, 1); 1621} 1622 1623/* 12 01: bx rm */ 1624static 1625void op12_01 (arm_t *c) 1626{ 1627 uint32_t d; 1628 1629 d = arm_get_rm (c, c->ir); 1630 1631 if (d & 1) { 1632 /* branch to thumb instruction set */ 1633 op_undefined (c); 1634 return; 1635 } 1636 1637 arm_set_pc (c, d & 0xfffffffc); 1638 1639 arm_set_clk (c, 0, 1); 1640} 1641 1642/* 12 03: blx rm */ 1643static 1644void op12_03 (arm_t *c) 1645{ 1646 uint32_t d; 1647 1648 d = arm_get_rm (c, c->ir); 1649 1650 if (d & 1) { 1651 /* branch to thumb instruction set */ 1652 op_undefined (c); 1653 return; 1654 } 1655 1656 arm_set_lr (c, (arm_get_pc (c) + 4) & 0xffffffff); 1657 arm_set_pc (c, d & 0xfffffffc); 1658 1659 arm_set_clk (c, 0, 1); 1660} 1661 1662/* 12 07: bkpt uimm16 */ 1663static 1664void op12_07 (arm_t *c) 1665{ 1666 arm_set_clk (c, 0, 1); 1667 arm_exception_prefetch_abort (c); 1668} 1669 1670/* 12 */ 1671static 1672void op12 (arm_t *c) 1673{ 1674 switch (c->ir & 0x0ff000f0) { 1675 case 0x01200000: 1676 op12_00 (c); 1677 break; 1678 1679 case 0x01200010: 1680 op12_01 (c); 1681 break; 1682 1683 case 0x01200030: 1684 op12_03 (c); 1685 break; 1686 1687 case 0x01200070: 1688 op12_07 (c); 1689 break; 1690 1691 case 0x012000b0: 1692 case 0x012000d0: 1693 case 0x012000f0: 1694 op00_0b (c); 1695 break; 1696 1697 default: 1698 op_undefined (c); 1699 break; 1700 } 1701} 1702 1703/* 13 ext */ 1704static 1705void op13_ext (arm_t *c) 1706{ 1707 switch (arm_get_shext (c->ir)) { 1708 case 0x09: 1709 op_undefined (c); 1710 break; 1711 1712 default: 1713 op01_0b (c); 1714 break; 1715 } 1716} 1717 1718/* 13: teq[cond] rn, shifter_operand */ 1719static 1720void op13 (arm_t *c) 1721{ 1722 uint32_t s1, s2, d, shc; 1723 1724 if (arm_is_shext (c->ir)) { 1725 op13_ext (c); 1726 return; 1727 } 1728 1729 s1 = arm_get_rn (c, c->ir); 1730 s2 = arm_get_sh (c, c->ir, &shc); 1731 1732 d = s1 ^ s2; 1733 1734 arm_set_cc_nz (c, d); 1735 arm_set_cc_c (c, shc); 1736 arm_set_clk (c, 4, 1); 1737} 1738 1739/* 14 00: mrs[cond] rd, spsr */ 1740static 1741void op14_00 (arm_t *c) 1742{ 1743 arm_set_rd (c, c->ir, arm_get_spsr (c)); 1744 arm_set_clk (c, 4, 1); 1745} 1746 1747/* 14 09: swp[cond]b rd, rm, rn */ 1748static 1749void op14_09 (arm_t *c) 1750{ 1751 uint32_t addr, s; 1752 uint8_t d; 1753 1754 addr = arm_get_rn (c, c->ir); 1755 s = arm_get_rm (c, c->ir); 1756 1757 if (arm_dload8 (c, addr, &d)) { 1758 return; 1759 } 1760 1761 if (arm_dstore8 (c, addr, s & 0xff)) { 1762 return; 1763 } 1764 1765 arm_set_rd (c, c->ir, d & 0xff); 1766 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1767} 1768 1769/* 14 */ 1770static 1771void op14 (arm_t *c) 1772{ 1773 switch (arm_get_bits (c->ir, 4, 4)) { 1774 case 0x00: 1775 op14_00 (c); 1776 break; 1777 1778 case 0x09: 1779 op14_09 (c); 1780 break; 1781 1782 case 0x0b: 1783 case 0x0d: 1784 case 0x0f: 1785 op00_0b (c); 1786 break; 1787 1788 default: 1789 op_undefined (c); 1790 break; 1791 } 1792} 1793 1794/* 15 ext */ 1795static 1796void op15_ext (arm_t *c) 1797{ 1798 switch (arm_get_shext (c->ir)) { 1799 case 0x09: 1800 op_undefined (c); 1801 break; 1802 1803 default: 1804 op01_0b (c); 1805 break; 1806 } 1807} 1808 1809/* 15: cmp[cond] rn, shifter_operand */ 1810static 1811void op15 (arm_t *c) 1812{ 1813 uint32_t s1, s2, d; 1814 1815 if (arm_is_shext (c->ir)) { 1816 op15_ext (c); 1817 return; 1818 } 1819 1820 s1 = arm_get_rn (c, c->ir); 1821 s2 = arm_get_sh (c, c->ir, NULL); 1822 1823 d = (s1 - s2) & 0xffffffff; 1824 1825 arm_set_cc_sub (c, d, s1, s2); 1826 arm_set_clk (c, 4, 1); 1827} 1828 1829/* 16 01: clz rd, rm */ 1830static 1831void op16_01 (arm_t *c) 1832{ 1833 if (arm_get_bits (c->ir, 4, 4) == 0x01) { 1834 uint32_t d, s; 1835 1836 s = arm_get_rm (c, c->ir); 1837 1838 if (s == 0) { 1839 d = 32; 1840 } 1841 else { 1842 d = 0; 1843 while ((s & 0x80000000) == 0) { 1844 d += 1; 1845 s <<= 1; 1846 } 1847 } 1848 1849 arm_set_rd (c, c->ir, d); 1850 arm_set_clk (c, 4, 1); 1851 } 1852 else { 1853 op_undefined (c); 1854 } 1855} 1856 1857/* 16 08: smulxy[cond] rd, rm, rs */ 1858static 1859void op16_08 (arm_t *c) 1860{ 1861 int sign; 1862 uint32_t d, s1, s2; 1863 1864 s1 = arm_get_rm (c, c->ir); 1865 s2 = arm_get_rs (c, c->ir); 1866 1867 if (arm_get_bit (c->ir, 5)) { 1868 s1 = s1 >> 16; 1869 } 1870 1871 if (arm_get_bit (c->ir, 6)) { 1872 s2 = s2 >> 16; 1873 } 1874 1875 sign = ((s1 ^ s2) & 0x8000) != 0; 1876 1877 s1 = ((s1 & 0x8000) ? (~s1 + 1) : s1) & 0xffff; 1878 s2 = ((s2 & 0x8000) ? (~s2 + 1) : s2) & 0xffff; 1879 1880 d = s1 * s2; 1881 1882 if (sign) { 1883 d = (~d + 1) & 0xffffffff; 1884 } 1885 1886 arm_set_rn (c, c->ir, d); 1887 arm_set_clk (c, 4, 1); 1888} 1889 1890/* 16 */ 1891static 1892void op16 (arm_t *c) 1893{ 1894 switch (c->ir & 0x0ff000f0) { 1895 case 0x01600000: 1896 op12_00 (c); 1897 break; 1898 1899 case 0x01600010: 1900 op16_01 (c); 1901 break; 1902 1903 case 0x01600080: 1904 case 0x016000a0: 1905 case 0x016000c0: 1906 case 0x016000e0: 1907 op16_08 (c); 1908 break; 1909 1910 case 0x016000b0: 1911 case 0x016000d0: 1912 case 0x016000f0: 1913 op00_0b (c); 1914 break; 1915 1916 default: 1917 op_undefined (c); 1918 break; 1919 } 1920} 1921 1922/* 17 ext */ 1923static 1924void op17_ext (arm_t *c) 1925{ 1926 switch (arm_get_shext (c->ir)) { 1927 case 0x09: 1928 op_undefined (c); 1929 break; 1930 1931 default: 1932 op01_0b (c); 1933 break; 1934 } 1935} 1936 1937/* 17: cmn[cond] rn, shifter_operand */ 1938static 1939void op17 (arm_t *c) 1940{ 1941 uint32_t s1, s2, d; 1942 1943 if (arm_is_shext (c->ir)) { 1944 op17_ext (c); 1945 return; 1946 } 1947 1948 s1 = arm_get_rn (c, c->ir); 1949 s2 = arm_get_sh (c, c->ir, NULL); 1950 1951 d = (s1 + s2) & 0xffffffff; 1952 1953 arm_set_cc_add (c, d, s1, s2); 1954 arm_set_clk (c, 4, 1); 1955} 1956 1957/* 18 ext */ 1958static 1959void op18_ext (arm_t *c) 1960{ 1961 switch (arm_get_shext (c->ir)) { 1962 case 0x09: 1963 op_undefined (c); 1964 break; 1965 1966 default: 1967 op00_0b (c); 1968 break; 1969 } 1970} 1971 1972/* 18: orr[cond] rd, rn, shifter_operand */ 1973static 1974void op18 (arm_t *c) 1975{ 1976 uint32_t d, s1, s2; 1977 1978 if (arm_is_shext (c->ir)) { 1979 op18_ext (c); 1980 return; 1981 } 1982 1983 s1 = arm_get_rn (c, c->ir); 1984 s2 = arm_get_sh (c, c->ir, NULL); 1985 1986 d = s1 | s2; 1987 1988 arm_set_rd (c, c->ir, d); 1989 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 1990} 1991 1992/* 19 ext */ 1993static 1994void op19_ext (arm_t *c) 1995{ 1996 switch (arm_get_shext (c->ir)) { 1997 case 0x09: 1998 op_undefined (c); 1999 break; 2000 2001 default: 2002 op01_0b (c); 2003 break; 2004 } 2005} 2006 2007/* 19: orr[cond]s rd, rn, shifter_operand */ 2008static 2009void op19 (arm_t *c) 2010{ 2011 uint32_t s1, s2, d, shc; 2012 2013 if (arm_is_shext (c->ir)) { 2014 op19_ext (c); 2015 return; 2016 } 2017 2018 s1 = arm_get_rn (c, c->ir); 2019 s2 = arm_get_sh (c, c->ir, &shc); 2020 2021 d = s1 | s2; 2022 2023 arm_set_rd (c, c->ir, d); 2024 2025 if (arm_rd_is_pc (c->ir)) { 2026 arm_write_cpsr (c, arm_get_spsr (c), 1); 2027 arm_set_clk (c, 0, 1); 2028 } 2029 else { 2030 arm_set_cc_nz (c, d); 2031 arm_set_cc_c (c, shc); 2032 arm_set_clk (c, 4, 1); 2033 } 2034} 2035 2036/* 1A ext */ 2037static 2038void op1a_ext (arm_t *c) 2039{ 2040 switch (arm_get_shext (c->ir)) { 2041 case 0x09: 2042 op_undefined (c); 2043 break; 2044 2045 default: 2046 op00_0b (c); 2047 break; 2048 } 2049} 2050 2051/* 1A: mov[cond] rd, shifter_operand */ 2052static 2053void op1a (arm_t *c) 2054{ 2055 uint32_t d; 2056 2057 if (arm_is_shext (c->ir)) { 2058 op1a_ext (c); 2059 return; 2060 } 2061 2062 d = arm_get_sh (c, c->ir, NULL); 2063 2064 arm_set_rd (c, c->ir, d); 2065 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 2066} 2067 2068/* 1B ext */ 2069static 2070void op1b_ext (arm_t *c) 2071{ 2072 switch (arm_get_shext (c->ir)) { 2073 case 0x09: 2074 op_undefined (c); 2075 break; 2076 2077 default: 2078 op01_0b (c); 2079 break; 2080 } 2081} 2082 2083/* 1B: mov[cond]s rd, shifter_operand */ 2084static 2085void op1b (arm_t *c) 2086{ 2087 uint32_t d, shc; 2088 2089 if (arm_is_shext (c->ir)) { 2090 op1b_ext (c); 2091 return; 2092 } 2093 2094 d = arm_get_sh (c, c->ir, &shc); 2095 2096 arm_set_rd (c, c->ir, d); 2097 2098 if (arm_rd_is_pc (c->ir)) { 2099 arm_write_cpsr (c, arm_get_spsr (c), 1); 2100 arm_set_clk (c, 0, 1); 2101 } 2102 else { 2103 arm_set_cc_nz (c, d); 2104 arm_set_cc_c (c, shc); 2105 arm_set_clk (c, 4, 1); 2106 } 2107} 2108 2109/* 1C ext */ 2110static 2111void op1c_ext (arm_t *c) 2112{ 2113 switch (arm_get_shext (c->ir)) { 2114 case 0x09: 2115 op_undefined (c); 2116 break; 2117 2118 default: 2119 op00_0b (c); 2120 break; 2121 } 2122} 2123 2124/* 1C: bic[cond] rd, rn, shifter_operand */ 2125static 2126void op1c (arm_t *c) 2127{ 2128 uint32_t s1, s2, d; 2129 2130 if (arm_is_shext (c->ir)) { 2131 op1c_ext (c); 2132 return; 2133 } 2134 2135 s1 = arm_get_rn (c, c->ir); 2136 s2 = arm_get_sh (c, c->ir, NULL); 2137 2138 d = s1 & ~s2; 2139 2140 arm_set_rd (c, c->ir, d); 2141 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 2142} 2143 2144/* 1D ext */ 2145static 2146void op1d_ext (arm_t *c) 2147{ 2148 switch (arm_get_shext (c->ir)) { 2149 case 0x09: 2150 op_undefined (c); 2151 break; 2152 2153 default: 2154 op01_0b (c); 2155 break; 2156 } 2157} 2158 2159/* 1d: bic[cond]s rd, rn, shifter_operand */ 2160static 2161void op1d (arm_t *c) 2162{ 2163 uint32_t s1, s2, d, shc; 2164 2165 if (arm_is_shext (c->ir)) { 2166 op1d_ext (c); 2167 return; 2168 } 2169 2170 s1 = arm_get_rn (c, c->ir); 2171 s2 = arm_get_sh (c, c->ir, &shc); 2172 2173 d = s1 & ~s2; 2174 2175 arm_set_rd (c, c->ir, d); 2176 2177 if (arm_rd_is_pc (c->ir)) { 2178 arm_write_cpsr (c, arm_get_spsr (c), 1); 2179 arm_set_clk (c, 0, 1); 2180 } 2181 else { 2182 arm_set_cc_nz (c, d); 2183 arm_set_cc_c (c, shc); 2184 arm_set_clk (c, 4, 1); 2185 } 2186} 2187 2188/* 1E ext */ 2189static 2190void op1e_ext (arm_t *c) 2191{ 2192 switch (arm_get_shext (c->ir)) { 2193 case 0x09: 2194 op_undefined (c); 2195 break; 2196 2197 default: 2198 op00_0b (c); 2199 break; 2200 } 2201} 2202 2203/* 1E: mvn[cond] rd, shifter_operand */ 2204static 2205void op1e (arm_t *c) 2206{ 2207 uint32_t d; 2208 2209 if (arm_is_shext (c->ir)) { 2210 op1e_ext (c); 2211 return; 2212 } 2213 2214 d = arm_get_sh (c, c->ir, NULL); 2215 2216 d = ~d & 0xffffffff; 2217 2218 arm_set_rd (c, c->ir, d); 2219 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 2220} 2221 2222/* 1F ext */ 2223static 2224void op1f_ext (arm_t *c) 2225{ 2226 switch (arm_get_shext (c->ir)) { 2227 case 0x09: 2228 op_undefined (c); 2229 break; 2230 2231 default: 2232 op01_0b (c); 2233 break; 2234 } 2235} 2236 2237/* 1F: mvn[cond]s rd, shifter_operand */ 2238static 2239void op1f (arm_t *c) 2240{ 2241 uint32_t d, shc; 2242 2243 if (arm_is_shext (c->ir)) { 2244 op1f_ext (c); 2245 return; 2246 } 2247 2248 d = arm_get_sh (c, c->ir, &shc); 2249 2250 d = ~d & 0xffffffff; 2251 2252 arm_set_rd (c, c->ir, d); 2253 2254 if (arm_rd_is_pc (c->ir)) { 2255 arm_write_cpsr (c, arm_get_spsr (c), 1); 2256 arm_set_clk (c, 0, 1); 2257 } 2258 else { 2259 arm_set_cc_nz (c, d); 2260 arm_set_cc_c (c, shc); 2261 arm_set_clk (c, 4, 1); 2262 } 2263} 2264 2265/* 32: msr[cond] fields, #imm */ 2266static 2267void op32 (arm_t *c) 2268{ 2269 unsigned fld, rot; 2270 uint32_t val; 2271 2272 fld = arm_get_bits (c->ir, 16, 4); 2273 rot = 2 * arm_get_bits (c->ir, 8, 4); 2274 2275 if (arm_is_privileged (c) == 0) { 2276 fld &= 0x08; 2277 } 2278 2279 val = arm_get_bits (c->ir, 0, 8); 2280 val = arm_ror32 (val, rot); 2281 2282 if (arm_get_bit (c->ir, 22)) { 2283 val = arm_set_psr_field (arm_get_spsr (c), val, fld); 2284 arm_set_spsr (c, val); 2285 } 2286 else { 2287 val = arm_set_psr_field (arm_get_cpsr (c), val, fld); 2288 arm_write_cpsr (c, val, 0); 2289 } 2290 2291 arm_set_clk (c, 4, 1); 2292} 2293 2294/* 40: str[cond][b][t] rd, [rn], address */ 2295static 2296void op40 (arm_t *c) 2297{ 2298 int p, u, b, w, t; 2299 uint32_t val, base, index; 2300 2301 p = arm_get_bit (c->ir, 24); 2302 u = arm_get_bit (c->ir, 23); 2303 b = arm_get_bit (c->ir, 22); 2304 w = arm_get_bit (c->ir, 21); 2305 t = (p == 0) && (w == 1); 2306 2307 base = arm_get_rn (c, c->ir); 2308 2309 /* get index */ 2310 if (arm_get_bit (c->ir, 25)) { 2311 unsigned n; 2312 2313 index = arm_get_rm (c, c->ir); 2314 n = arm_get_bits (c->ir, 7, 5); 2315 2316 switch (arm_get_bits (c->ir, 5, 2)) { 2317 case 0x00: /* lsl */ 2318 index = index << n; 2319 break; 2320 2321 case 0x01: /* lsr */ 2322 index = (n == 0) ? 0 : (index >> n); 2323 break; 2324 2325 case 0x02: /* asr */ 2326 if (n == 0) { 2327 if (index & 0x80000000) { 2328 index = 0xffffffff; 2329 } 2330 else { 2331 index = 0x00000000; 2332 } 2333 } 2334 else { 2335 index = arm_asr32 (index, n); 2336 } 2337 break; 2338 2339 case 0x03: /* ror / rrx */ 2340 if (n == 0) { 2341 index = (index >> 1) | (arm_get_cc_c (c) << 31); 2342 } 2343 else { 2344 index = (index >> n) | (index << (32 - n)); 2345 } 2346 } 2347 } 2348 else { 2349 index = arm_extu (c->ir, 12); 2350 } 2351 2352 /* pre-index */ 2353 if (p) { 2354 base += u ? index : (~index + 1); 2355 base &= 0xffffffff; 2356 } 2357 2358 val = arm_get_rd (c, c->ir); 2359 2360 if (b) { 2361 if (t) { 2362 if (arm_dstore8_t (c, base, val)) { 2363 return; 2364 } 2365 } 2366 else { 2367 if (arm_dstore8 (c, base, val)) { 2368 return; 2369 } 2370 } 2371 } 2372 else { 2373 if (t) { 2374 if (arm_dstore32_t (c, base, val)) { 2375 return; 2376 } 2377 } 2378 else { 2379 if (arm_dstore32 (c, base, val)) { 2380 return; 2381 } 2382 } 2383 } 2384 2385 /* post-index */ 2386 if (p == 0) { 2387 base += u ? index : (~index + 1); 2388 base &= 0xffffffff; 2389 } 2390 2391 /* base register writeback */ 2392 if ((p == 0) || (w == 1)) { 2393 arm_set_rn (c, c->ir, base); 2394 } 2395 2396 arm_set_clk (c, 4, 1); 2397} 2398 2399/* 41: ldr[cond][b][t] rd, [rn], address */ 2400static 2401void op41 (arm_t *c) 2402{ 2403 int p, u, b, w, t; 2404 uint32_t val, base, index; 2405 2406 p = arm_get_bit (c->ir, 24); 2407 u = arm_get_bit (c->ir, 23); 2408 b = arm_get_bit (c->ir, 22); 2409 w = arm_get_bit (c->ir, 21); 2410 t = (p == 0) && (w == 1); 2411 2412 base = arm_get_rn (c, c->ir); 2413 2414 /* get index */ 2415 if (arm_get_bit (c->ir, 25)) { 2416 unsigned n; 2417 2418 index = arm_get_rm (c, c->ir); 2419 n = arm_get_bits (c->ir, 7, 5); 2420 2421 switch (arm_get_bits (c->ir, 5, 2)) { 2422 case 0x00: /* lsl */ 2423 index = index << n; 2424 break; 2425 2426 case 0x01: /* lsr */ 2427 index = (n == 0) ? 0 : (index >> n); 2428 break; 2429 2430 case 0x02: /* asr */ 2431 if (n == 0) { 2432 if (index & 0x80000000) { 2433 index = 0xffffffff; 2434 } 2435 else { 2436 index = 0x00000000; 2437 } 2438 } 2439 else { 2440 index = arm_asr32 (index, n); 2441 } 2442 break; 2443 2444 case 0x03: /* ror / rrx */ 2445 if (n == 0) { 2446 index = (index >> 1) | (arm_get_cc_c (c) << 31); 2447 } 2448 else { 2449 index = (index >> n) | (index << (32 - n)); 2450 } 2451 } 2452 } 2453 else { 2454 index = arm_extu (c->ir, 12); 2455 } 2456 2457 /* pre-index */ 2458 if (p) { 2459 base += u ? index : (~index + 1); 2460 base &= 0xffffffff; 2461 } 2462 2463 if (b) { 2464 uint8_t tmp; 2465 2466 if (t) { 2467 if (arm_dload8_t (c, base, &tmp)) { 2468 return; 2469 } 2470 } 2471 else { 2472 if (arm_dload8 (c, base, &tmp)) { 2473 return; 2474 } 2475 } 2476 2477 val = tmp & 0xff; 2478 } 2479 else { 2480 if (t) { 2481 if (arm_dload32_t (c, base & 0xfffffffc, &val)) { 2482 return; 2483 } 2484 } 2485 else { 2486 if (arm_dload32 (c, base & 0xfffffffc, &val)) { 2487 return; 2488 } 2489 } 2490 2491 if (base & 0x03) { 2492 val = arm_ror32 (val, (base & 0x03) << 3); 2493 } 2494 } 2495 2496 arm_set_rd (c, c->ir, val); 2497 2498 /* post-index */ 2499 if (p == 0) { 2500 base += u ? index : (~index + 1); 2501 base &= 0xffffffff; 2502 } 2503 2504 /* base register writeback */ 2505 if ((p == 0) || (w == 1)) { 2506 arm_set_rn (c, c->ir, base); 2507 } 2508 2509 arm_set_clk (c, arm_rd_is_pc (c->ir) ? 0 : 4, 1); 2510} 2511 2512/* 80: stm[cond][mode] rn[!], registers[^] */ 2513static 2514void op80 (arm_t *c) 2515{ 2516 int p, u, s, w; 2517 unsigned i; 2518 unsigned regs, regn; 2519 unsigned mode; 2520 uint32_t addr, base, writeback; 2521 uint32_t val; 2522 2523 p = arm_get_bit (c->ir, 24); 2524 u = arm_get_bit (c->ir, 23); 2525 s = arm_get_bit (c->ir, 22); 2526 w = arm_get_bit (c->ir, 21); 2527 2528 regs = arm_get_bits (c->ir, 0, 16); 2529 regn = arm_bitcnt32 (regs); 2530 mode = arm_get_cpsr_m (c); 2531 base = arm_get_rn (c, c->ir); 2532 2533 if (u) { 2534 writeback = base + 4 * regn; 2535 2536 if (p) { 2537 /* ib */ 2538 addr = base + 4; 2539 } 2540 else { 2541 /* ia */ 2542 addr = base; 2543 } 2544 } 2545 else { 2546 writeback = base - 4 * regn; 2547 2548 if (p) { 2549 /* db */ 2550 addr = base - 4 * regn; 2551 } 2552 else { 2553 /* da */ 2554 addr = base - 4 * regn + 4; 2555 } 2556 } 2557 2558 if (s) { 2559 /* access user mode registers */ 2560 arm_set_reg_map (c, ARM_MODE_USR); 2561 } 2562 2563 for (i = 0; i < 16; i++) { 2564 if (regs & (1U << i)) { 2565 val = arm_get_reg_pc (c, i, 8); 2566 2567 if (arm_dstore32 (c, addr & 0xfffffffc, val)) { 2568 return; 2569 } 2570 2571 addr += 4; 2572 } 2573 } 2574 2575 if (s) { 2576 arm_set_reg_map (c, mode); 2577 } 2578 2579 if (w) { 2580 arm_set_rn (c, c->ir, writeback); 2581 } 2582 2583 arm_set_clk (c, 4, 1); 2584} 2585 2586/* 81: ldm[cond][mode] rn[!], registers[^] */ 2587static 2588void op81 (arm_t *c) 2589{ 2590 int p, u, s, w; 2591 unsigned i; 2592 unsigned regs, regn; 2593 unsigned mode; 2594 uint32_t addr, base, writeback; 2595 uint32_t val; 2596 2597 p = arm_get_bit (c->ir, 24); 2598 u = arm_get_bit (c->ir, 23); 2599 s = arm_get_bit (c->ir, 22); 2600 w = arm_get_bit (c->ir, 21); 2601 2602 regs = arm_get_bits (c->ir, 0, 16); 2603 regn = arm_bitcnt32 (regs); 2604 mode = arm_get_cpsr_m (c); 2605 base = arm_get_rn (c, c->ir); 2606 2607 if (u) { 2608 writeback = base + 4 * regn; 2609 2610 if (p) { 2611 /* ib */ 2612 addr = base + 4; 2613 } 2614 else { 2615 /* ia */ 2616 addr = base; 2617 } 2618 } 2619 else { 2620 writeback = base - 4 * regn; 2621 2622 if (p) { 2623 /* db */ 2624 addr = base - 4 * regn; 2625 } 2626 else { 2627 /* da */ 2628 addr = base - 4 * regn + 4; 2629 } 2630 } 2631 2632 if (s && !(regs & 0x8000)) { 2633 /* access user mode registers */ 2634 arm_set_reg_map (c, ARM_MODE_USR); 2635 } 2636 2637 for (i = 0; i < 16; i++) { 2638 if (regs & (1U << i)) { 2639 if (arm_dload32 (c, addr & 0xfffffffc, &val)) { 2640 return; 2641 } 2642 2643 if (i == arm_ir_rn (c->ir)) { 2644 /* defer modification of base register */ 2645 base = val; 2646 } 2647 else { 2648 arm_set_gpr (c, i, val); 2649 } 2650 2651 addr += 4; 2652 } 2653 } 2654 2655 arm_set_rn (c, c->ir, base); 2656 2657 if (s) { 2658 if (regs & 0x8000) { 2659 arm_write_cpsr (c, arm_get_spsr (c), 1); 2660 } 2661 else { 2662 arm_set_reg_map (c, mode); 2663 } 2664 } 2665 2666 if (w) { 2667 arm_set_rn (c, c->ir, writeback); 2668 } 2669 2670 arm_set_clk (c, (regs & 0x8000) ? 0 : 4, 1); 2671} 2672 2673/* A0: b[cond] target */ 2674static 2675void opa0 (arm_t *c) 2676{ 2677 uint32_t d; 2678 2679 d = arm_exts (c->ir, 24); 2680 d = (arm_get_pc (c) + (d << 2) + 8) & 0xffffffff; 2681 2682 arm_set_pc (c, d); 2683 2684 arm_set_clk (c, 0, 1); 2685} 2686 2687/* B0: bl[cond] target */ 2688static 2689void opb0 (arm_t *c) 2690{ 2691 uint32_t d; 2692 2693 d = arm_exts (c->ir, 24); 2694 d = (arm_get_pc (c) + (d << 2) + 8) & 0xffffffff; 2695 2696 arm_set_lr (c, (arm_get_pc (c) + 4) & 0xffffffff); 2697 arm_set_pc (c, d); 2698 2699 arm_set_clk (c, 0, 1); 2700} 2701 2702/* C4: mcrr[cond] coproc, opcode, rd, rn, crm */ 2703static 2704void opc4 (arm_t *c) 2705{ 2706 int r; 2707 unsigned cop; 2708 2709 cop = arm_get_bits (c->ir, 8, 4); 2710 2711 if (arm_copr_check (c, cop) == 0) { 2712 r = c->copr[cop]->exec (c, c->copr[cop]); 2713 } 2714 else { 2715 r = 1; 2716 } 2717 2718 if (cop == 0) { 2719 /* hack */ 2720 arm_set_clk (c, 4, 1); 2721 return; 2722 } 2723 2724 if (r) { 2725 arm_set_clk (c, 0, 1); 2726 arm_exception_undefined (c); 2727 return; 2728 } 2729} 2730 2731/* C5: mrrc[cond] coproc, opcode, rd, rn, crm */ 2732static 2733void opc5 (arm_t *c) 2734{ 2735 int r; 2736 unsigned cop; 2737 2738 cop = arm_get_bits (c->ir, 8, 4); 2739 2740 if (arm_copr_check (c, cop) == 0) { 2741 r = c->copr[cop]->exec (c, c->copr[cop]); 2742 } 2743 else { 2744 r = 1; 2745 } 2746 2747 if (cop == 0) { 2748 /* hack */ 2749 arm_set_clk (c, 4, 1); 2750 return; 2751 } 2752 2753 if (r) { 2754 arm_set_clk (c, 0, 1); 2755 arm_exception_undefined (c); 2756 return; 2757 } 2758} 2759 2760/* E0 00: cdp[cond] coproc, opcode1, crd, crn, crm, opcode2 */ 2761static 2762void ope0_00 (arm_t *c) 2763{ 2764 int r; 2765 unsigned cop; 2766 2767 cop = arm_get_bits (c->ir, 8, 4); 2768 2769 if (arm_copr_check (c, cop) == 0) { 2770 r = c->copr[cop]->exec (c, c->copr[cop]); 2771 } 2772 else { 2773 r = 1; 2774 } 2775 2776 if (r) { 2777 arm_set_clk (c, 0, 1); 2778 arm_exception_undefined (c); 2779 return; 2780 } 2781 2782 arm_set_clk (c, 4, 1); 2783} 2784 2785/* E0 01: mcr[cond] coproc, opcode1, rd, crn, crm, opcode2 */ 2786static 2787void ope0_01 (arm_t *c) 2788{ 2789 int r; 2790 unsigned cop; 2791 2792 cop = arm_get_bits (c->ir, 8, 4); 2793 2794 if (arm_copr_check (c, cop) == 0) { 2795 r = c->copr[cop]->exec (c, c->copr[cop]); 2796 } 2797 else { 2798 r = 1; 2799 } 2800 2801 if (r) { 2802 arm_set_clk (c, 0, 1); 2803 arm_exception_undefined (c); 2804 return; 2805 } 2806} 2807 2808/* E0 11: mrc[cond] coproc, opcode1, rd, crn, crm, opcode2 */ 2809static 2810void ope0_11 (arm_t *c) 2811{ 2812 int r; 2813 unsigned cop; 2814 2815 cop = arm_get_bits (c->ir, 8, 4); 2816 2817 if (arm_copr_check (c, cop) == 0) { 2818 r = c->copr[cop]->exec (c, c->copr[cop]); 2819 } 2820 else { 2821 r = 1; 2822 } 2823 2824 if (cop == 0) { 2825 /* hack */ 2826 arm_set_clk (c, 4, 1); 2827 return; 2828 } 2829 2830 if (r) { 2831 arm_set_clk (c, 0, 1); 2832 arm_exception_undefined (c); 2833 return; 2834 } 2835} 2836 2837/* E0 */ 2838static 2839void ope0 (arm_t *c) 2840{ 2841 switch (c->ir & 0x00100010) { 2842 case 0x00000000: 2843 case 0x00100000: 2844 ope0_00 (c); 2845 break; 2846 2847 case 0x00000010: 2848 ope0_01 (c); 2849 break; 2850 2851 case 0x00100010: 2852 ope0_11 (c); 2853 break; 2854 2855 default: 2856 op_undefined (c); 2857 break; 2858 } 2859} 2860 2861/* F0: swi[cond] immediate */ 2862static 2863void opf0 (arm_t *c) 2864{ 2865 arm_set_clk (c, 0, 1); 2866 2867 arm_exception_swi (c); 2868} 2869 2870 2871static 2872arm_opcode_f arm_opcodes[256] = { 2873 op00, op01, op02, op03, op04, op05, op06, op07, /* 00 */ 2874 op08, op09, op0a, op0b, op0c, op0d, op0e, op0f, 2875 op10, op11, op12, op13, op14, op15, op16, op17, /* 10 */ 2876 op18, op19, op1a, op1b, op1c, op1d, op1e, op1f, 2877 op00, op01, op02, op03, op04, op05, op06, op07, /* 20 */ 2878 op08, op09, op0a, op0b, op0c, op0d, op0e, op0f, 2879 NULL, op11, op32, op13, NULL, op15, NULL, op17, /* 30 */ 2880 op18, op19, op1a, op1b, op1c, op1d, op1e, op1f, 2881 op40, op41, op40, op41, op40, op41, op40, op41, /* 40 */ 2882 op40, op41, op40, op41, op40, op41, op40, op41, 2883 op40, op41, op40, op41, op40, op41, op40, op41, /* 50 */ 2884 op40, op41, op40, op41, op40, op41, op40, op41, 2885 op40, op41, op40, op41, op40, op41, op40, op41, /* 60 */ 2886 op40, op41, op40, op41, op40, op41, op40, op41, 2887 op40, op41, op40, op41, op40, op41, op40, op41, /* 70 */ 2888 op40, op41, op40, op41, op40, op41, op40, op41, 2889 op80, op81, op80, op81, op80, op81, op80, op81, /* 80 */ 2890 op80, op81, op80, op81, op80, op81, op80, op81, 2891 op80, op81, op80, op81, op80, op81, op80, op81, /* 90 */ 2892 op80, op81, op80, op81, op80, op81, op80, op81, 2893 opa0, opa0, opa0, opa0, opa0, opa0, opa0, opa0, /* a0 */ 2894 opa0, opa0, opa0, opa0, opa0, opa0, opa0, opa0, 2895 opb0, opb0, opb0, opb0, opb0, opb0, opb0, opb0, /* b0 */ 2896 opb0, opb0, opb0, opb0, opb0, opb0, opb0, opb0, 2897 NULL, NULL, NULL, NULL, opc4, opc5, NULL, NULL, /* c0 */ 2898 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2899 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* d0 */ 2900 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2901 ope0, ope0, ope0, ope0, ope0, ope0, ope0, ope0, /* e0 */ 2902 ope0, ope0, ope0, ope0, ope0, ope0, ope0, ope0, 2903 opf0, opf0, opf0, opf0, opf0, opf0, opf0, opf0, /* f0 */ 2904 opf0, opf0, opf0, opf0, opf0, opf0, opf0, opf0 2905}; 2906 2907 2908void arm_set_opcodes (arm_t *c) 2909{ 2910 unsigned i; 2911 2912 for (i = 0; i < 256; i++) { 2913 if (arm_opcodes[i] != NULL) { 2914 c->opcodes[i] = arm_opcodes[i]; 2915 } 2916 else { 2917 c->opcodes[i] = op_undefined; 2918 } 2919 } 2920}