fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1108 lines 18 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/ppc405/opcodes.c * 7 * Created: 2003-11-08 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2003-2018 Hampa Hug <hampa@hampa.ch> * 9 * Copyright: (C) 2003-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 "ppc405.h" 30#include "internal.h" 31 32 33static inline 34uint32_t p405_get_mask (unsigned mb, unsigned me) 35{ 36 uint32_t msk; 37 38 if (mb <= me) { 39 msk = ((2UL << (me - mb)) - 1) << (31 - me); 40 } 41 else { 42 msk = ((2UL << me) - 1) << (31 - me); 43 msk |= (2UL << (31 - mb)) - 1; 44 } 45 46 return (msk); 47} 48 49uint64_t p405_mul (uint32_t s1, uint32_t s2) 50{ 51 int ss1, ss2; 52 uint64_t ret; 53 54 ss1 = (s1 & 0x80000000UL) != 0; 55 ss2 = (s2 & 0x80000000UL) != 0; 56 57 if (ss1) { 58 s1 = (~s1 + 1) & 0xffffffffUL; 59 } 60 61 if (ss2) { 62 s2 = (~s2 + 1) & 0xffffffffUL; 63 } 64 65 ret = (uint64_t) s1 * (uint64_t) s2; 66 67 if (ss1 != ss2) { 68 ret = (~ret + 1) & 0xffffffffffffffffULL; 69 } 70 71 return (ret); 72} 73 74/* 75 * Byte reverse a 16 bit value 76 */ 77uint16_t p405_br16 (uint16_t x) 78{ 79 return (((x & 0xff) << 8) | ((x >> 8) & 0xff)); 80} 81 82/* 83 * Byte reverse a 32 bit value 84 */ 85uint32_t p405_br32 (uint32_t x) 86{ 87 return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff)); 88} 89 90void p405_op_branch (p405_t *c, uint32_t dst, unsigned bo, unsigned bi, int aa, int lk) 91{ 92 int bo0, bo1, bo2, bo3, crb; 93 94 bo0 = (bo & 0x10) != 0; 95 bo1 = (bo & 0x08) != 0; 96 bo2 = (bo & 0x04) != 0; 97 bo3 = (bo & 0x02) != 0; 98 99 crb = (c->cr & (0x80000000UL >> bi)) != 0; 100 101 if (bo2 == 0) { 102 c->ctr = (c->ctr - 1) & 0xffffffffUL; 103 } 104 105 if (lk) { 106 p405_set_lr (c, (c->pc + 4) & 0xffffffffUL); 107 } 108 109 if ((bo2 || ((c->ctr == 0) == bo3)) && (bo0 || (crb == bo1))) { 110 if (aa) { 111 c->pc = dst; 112 } 113 else { 114 c->pc = (c->pc + dst) & 0xffffffffUL; 115 } 116 } 117 else { 118 c->pc = (c->pc + 4) & 0xffffffffUL; 119 } 120 121 p405_set_clk (c, 0, 1); 122} 123 124/* generic cr bit op */ 125void p405_op_crop (p405_t *c, unsigned bt, unsigned ba, unsigned bb, unsigned booltab) 126{ 127 unsigned msk; 128 uint32_t mt, ma, mb; 129 130 if (c->ir & P405_IR_RC) { 131 p405_op_undefined (c); 132 return; 133 } 134 135 mt = 0x80000000UL >> bt; 136 ma = 0x80000000UL >> ba; 137 mb = 0x80000000UL >> bb; 138 139 msk = (c->cr & ma) ? 0x04 : 0x01; 140 141 if (c->cr & mb) { 142 msk = msk << 1; 143 } 144 145 if (booltab & msk) { 146 c->cr |= mt; 147 } 148 else { 149 c->cr &= ~mt; 150 } 151 152 p405_set_clk (c, 4, 1); 153} 154 155/* generic load string word */ 156void p405_op_lsw (p405_t *c, unsigned rt, unsigned ra, unsigned rb, uint32_t ea, unsigned cnt) 157{ 158 unsigned i; 159 unsigned shl, rfinal, clk; 160 uint8_t val; 161 uint32_t msk; 162 163 rfinal = (rt + (cnt + 3) / 4 - 1) & 0x1f; 164 165 msk = 0; 166 shl = 24; 167 168 clk = ((ea & 0x03) == 0) ? 0 : 1; 169 170 for (i = 0; i < cnt; i++) { 171 if ((ea & 0x03) == 0) { 172 clk += 1; 173 } 174 175 if (((rt != ra) && (rt != rb)) || (rt == rfinal)) { 176 if (p405_dload8 (c, ea, &val)) { 177 return; 178 } 179 180 p405_set_gpr (c, rt, (p405_get_gpr (c, rt) & msk) | ((uint32_t) val << shl)); 181 } 182 183 if (shl == 0) { 184 msk = 0; 185 shl = 24; 186 rt = (rt + 1) & 0x1f; 187 } 188 else { 189 msk = (msk >> 8) | 0xff000000UL; 190 shl -= 8; 191 } 192 193 ea += 1; 194 } 195 196 p405_set_clk (c, 4, (clk > 0) ? clk : 1); 197} 198 199/* generic store string word */ 200void p405_op_stsw (p405_t *c, unsigned rs, uint32_t ea, unsigned cnt) 201{ 202 unsigned i; 203 unsigned sh, clk; 204 205 sh = 24; 206 207 clk = ((ea & 0x03) == 0) ? 0 : 1; 208 209 for (i = 0; i < cnt; i++) { 210 if ((ea & 0x03) == 0) { 211 clk += 1; 212 } 213 214 if (p405_dstore8 (c, ea, (p405_get_gpr (c, rs) >> sh) & 0xff)) { 215 return; 216 } 217 218 if (sh == 0) { 219 sh = 24; 220 rs = (rs + 1) & 0x1f; 221 } 222 else { 223 sh -= 8; 224 } 225 226 ea += 1; 227 } 228 229 p405_set_clk (c, 4, (clk > 0) ? clk : 1); 230} 231 232void p405_op_undefined (p405_t *c) 233{ 234 p405_undefined (c); 235 p405_exception_program (c, P405_ESR_PIL); 236 p405_set_clk (c, 0, 1); 237} 238 239/*****************************************************************************/ 240 241/* 03: twi to, ra, simm16 */ 242static 243void op_03 (p405_t *c) 244{ 245 int cond; 246 unsigned to; 247 uint32_t ra1, im1, ra2, im2; 248 249 to = p405_bits (c->ir, 6, 5); 250 ra1 = p405_get_ra (c, c->ir); 251 im1 = p405_sext (c->ir, 16); 252 253 ra2 = (ra1 + 0x80000000UL) & 0xffffffffUL; 254 im2 = (im1 + 0x80000000UL) & 0xffffffffUL; 255 256 if ((to & 0x10) && (ra2 < im2)) { 257 cond = 1; 258 } 259 else if ((to & 0x08) && (ra2 > im2)) { 260 cond = 1; 261 } 262 else if ((to & 0x04) && (ra1 == im2)) { 263 cond = 1; 264 } 265 else if ((to & 0x02) && (ra1 < im1)) { 266 cond = 1; 267 } 268 else if ((to & 0x01) && (ra1 > im1)) { 269 cond = 1; 270 } 271 else { 272 cond = 0; 273 } 274 275 if (cond) { 276 p405_exception_program (c, P405_ESR_PTR); 277 } 278 else { 279 p405_set_clk (c, 4, 1); 280 } 281} 282 283/* 07: mulli rt, ra, simm16 */ 284static 285void op_07 (p405_t *c) 286{ 287 uint64_t rt; 288 289 rt = p405_mul (p405_get_ra (c, c->ir), p405_sext (c->ir, 16)); 290 p405_set_rt (c, c->ir, rt & 0xffffffffUL); 291 292 p405_set_clk (c, 4, 1); 293} 294 295/* 08: subfic rt, ra, simm16 */ 296static 297void op_08 (p405_t *c) 298{ 299 uint32_t rt, s1, s2; 300 301 s1 = p405_get_simm16 (c->ir); 302 s2 = p405_get_ra (c, c->ir); 303 304 rt = (s1 - s2) & 0xffffffff; 305 306 p405_set_rt (c, c->ir, rt); 307 308 p405_set_xer_ca (c, rt <= s1); 309 310 p405_set_clk (c, 4, 1); 311} 312 313/* 0A: cmpli bf, ra, uimm16 */ 314static 315void op_0a (p405_t *c) 316{ 317 unsigned f; 318 uint32_t d, s1, s2; 319 320 s1 = p405_get_ra (c, c->ir); 321 s2 = p405_get_uimm16 (c->ir); 322 323 f = (c->ir >> 23) & 0x07; 324 325 if (s1 < s2) { 326 d = P405_CR_LT; 327 } 328 else if (s1 > s2) { 329 d = P405_CR_GT; 330 } 331 else { 332 d = P405_CR_EQ; 333 } 334 335 if (p405_get_xer_so (c)) { 336 d |= P405_CR_SO; 337 } 338 339 f = 4 * (7 - f); 340 341 c->cr &= ~(0x0fUL << f); 342 c->cr |= d << f; 343 344 p405_set_clk (c, 4, 1); 345} 346 347/* 0B: cmpi bf, ra, simm16 */ 348static 349void op_0b (p405_t *c) 350{ 351 unsigned f; 352 uint32_t d, s1, s2; 353 354 s1 = p405_get_ra (c, c->ir); 355 s2 = p405_get_simm16 (c->ir); 356 357 s1 ^= 0x80000000; 358 s2 ^= 0x80000000; 359 360 f = (c->ir >> 23) & 0x07; 361 362 if (s1 < s2) { 363 d = P405_CR_LT; 364 } 365 else if (s1 > s2) { 366 d = P405_CR_GT; 367 } 368 else { 369 d = P405_CR_EQ; 370 } 371 372 if (p405_get_xer_so (c)) { 373 d |= P405_CR_SO; 374 } 375 376 f = 4 * (7 - f); 377 378 c->cr &= ~(0x0fUL << f); 379 c->cr |= d << f; 380 381 p405_set_clk (c, 4, 1); 382} 383 384/* 0C: addic rt, ra, simm16 */ 385static 386void op_0c (p405_t *c) 387{ 388 uint32_t rt, s1, s2; 389 390 s1 = p405_get_ra (c, c->ir); 391 s2 = p405_get_simm16 (c->ir); 392 393 rt = (s1 + s2) & 0xffffffff; 394 395 p405_set_rt (c, c->ir, rt); 396 397 p405_set_xer_ca (c, rt < s1); 398 399 p405_set_clk (c, 4, 1); 400} 401 402/* 0D: addic. rt, ra, simm16 */ 403static 404void op_0d (p405_t *c) 405{ 406 uint32_t rt, s1, s2; 407 408 s1 = p405_get_ra (c, c->ir); 409 s2 = p405_get_simm16 (c->ir); 410 411 rt = (s1 + s2) & 0xffffffff; 412 413 p405_set_rt (c, c->ir, rt); 414 415 p405_set_xer_ca (c, rt < s1); 416 p405_set_cr0 (c, rt); 417 418 p405_set_clk (c, 4, 1); 419} 420 421/* 0E: addi rt, ra0, simm16 */ 422static 423void op_0e (p405_t *c) 424{ 425 uint32_t rt, s1, s2; 426 427 s1 = p405_get_ra0 (c, c->ir); 428 s2 = p405_get_simm16 (c->ir); 429 430 rt = s1 + s2; 431 432 p405_set_rt (c, c->ir, rt); 433 434 p405_set_clk (c, 4, 1); 435} 436 437/* 0F: addis rt, ra0, imm16 */ 438static 439void op_0f (p405_t *c) 440{ 441 uint32_t rt, s1, s2; 442 443 s1 = p405_get_ra0 (c, c->ir); 444 s2 = p405_get_uimm16 (c->ir); 445 446 rt = s1 + (s2 << 16); 447 448 p405_set_rt (c, c->ir, rt); 449 450 p405_set_clk (c, 4, 1); 451} 452 453/* 10: bc/bca/bcl/bcla target */ 454static 455void op_10 (p405_t *c) 456{ 457 p405_op_branch (c, 458 p405_sext (c->ir & 0xfffcUL, 16), 459 (c->ir >> 21) & 0x1f, (c->ir >> 16) & 0x1f, 460 (c->ir & P405_IR_AA) != 0, (c->ir & P405_IR_LK) != 0 461 ); 462} 463 464/* 11: sc */ 465static 466void op_11 (p405_t *c) 467{ 468 /* hook */ 469 if ((c->ir & 0x00ff0000) == 0x00ce0000) { 470 if (c->hook != NULL) { 471 c->hook (c->hook_ext, c->ir); 472 } 473 474 p405_set_clk (c, 4, 1); 475 476 return; 477 } 478 479 if (p405_check_reserved (c, 0x03fffffdUL)) { 480 return; 481 } 482 483 p405_exception_syscall (c); 484 485/* p405_set_clk (c, 0, 1); */ 486} 487 488/* 12: b/ba/bl/bla target */ 489static 490void op_12 (p405_t *c) 491{ 492 uint32_t li; 493 494 li = p405_sext (c->ir, 26) & 0xfffffffcUL; 495 496 if (c->ir & 0x01) { 497 p405_set_lr (c, (c->pc + 4) & 0xffffffffUL); 498 } 499 500 if (c->ir & 0x02) { 501 c->pc = li; 502 } 503 else { 504 c->pc = (c->pc + li) & 0xffffffffUL; 505 } 506 507 p405_set_clk (c, 0, 1); 508} 509 510/* 14: rlwimi[.] ra, rs, sh, mb, me */ 511static 512void op_14 (p405_t *c) 513{ 514 uint32_t ra, rs, msk; 515 unsigned sh, mb, me; 516 517 ra = p405_get_ra (c, c->ir); 518 rs = p405_get_rs (c, c->ir); 519 sh = (c->ir >> 11) & 0x1f; 520 mb = (c->ir >> 6) & 0x1f; 521 me = (c->ir >> 1) & 0x1f; 522 523 if (sh != 0) { 524 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL; 525 } 526 527 msk = p405_get_mask (mb, me); 528 529 ra = (rs & msk) | (ra & ~msk); 530 531 p405_set_ra (c, c->ir, ra); 532 533 if (p405_get_ir_rc (c->ir)) { 534 p405_set_cr0 (c, ra); 535 } 536 537 p405_set_clk (c, 4, 1); 538} 539 540/* 15: rlwinm[.] ra, rs, sh, mb, me */ 541static 542void op_15 (p405_t *c) 543{ 544 uint32_t ra, rs; 545 unsigned sh, mb, me; 546 547 ra = p405_get_ra (c, c->ir); 548 rs = p405_get_rs (c, c->ir); 549 sh = (c->ir >> 11) & 0x1f; 550 mb = (c->ir >> 6) & 0x1f; 551 me = (c->ir >> 1) & 0x1f; 552 553 if (sh != 0) { 554 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL; 555 } 556 557 ra = rs & p405_get_mask (mb, me); 558 559 p405_set_ra (c, c->ir, ra); 560 561 if (p405_get_ir_rc (c->ir)) { 562 p405_set_cr0 (c, ra); 563 } 564 565 p405_set_clk (c, 4, 1); 566} 567 568/* 17: rlwnm[.] ra, rs, rb, mb, me */ 569static 570void op_17 (p405_t *c) 571{ 572 uint32_t ra, rs; 573 unsigned sh, mb, me; 574 575 ra = p405_get_ra (c, c->ir); 576 rs = p405_get_rs (c, c->ir); 577 sh = p405_get_rb (c, c->ir) & 0x1f; 578 mb = (c->ir >> 6) & 0x1f; 579 me = (c->ir >> 1) & 0x1f; 580 581 if (sh != 0) { 582 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL; 583 } 584 585 ra = rs & p405_get_mask (mb, me); 586 587 p405_set_ra (c, c->ir, ra); 588 589 if (p405_get_ir_rc (c->ir)) { 590 p405_set_cr0 (c, ra); 591 } 592 593 p405_set_clk (c, 4, 1); 594} 595 596/* 18: ori ra, rs, uimm16 */ 597static 598void op_18 (p405_t *c) 599{ 600 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) | p405_uext (c->ir, 16)); 601 p405_set_clk (c, 4, 1); 602} 603 604/* 19: oris ra, rs, uimm16 */ 605static 606void op_19 (p405_t *c) 607{ 608 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) | (p405_uext (c->ir, 16) << 16)); 609 p405_set_clk (c, 4, 1); 610} 611 612/* 1A: xori ra, rs, uimm16 */ 613static 614void op_1a (p405_t *c) 615{ 616 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) ^ p405_uext (c->ir, 16)); 617 p405_set_clk (c, 4, 1); 618} 619 620/* 1B: xoris ra, rs, uimm16 */ 621static 622void op_1b (p405_t *c) 623{ 624 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) ^ (p405_uext (c->ir, 16) << 16)); 625 p405_set_clk (c, 4, 1); 626} 627 628/* 1C: andi. ra, rs, uimm16 */ 629static 630void op_1c (p405_t *c) 631{ 632 uint32_t rt, s1, s2; 633 634 s1 = p405_get_rs (c, c->ir); 635 s2 = p405_get_uimm16 (c->ir); 636 637 rt = s1 & s2; 638 639 p405_set_ra (c, c->ir, rt); 640 641 p405_set_cr0 (c, rt); 642 643 p405_set_clk (c, 4, 1); 644} 645 646/* 1D: andis. ra, rs, uimm16 */ 647static 648void op_1d (p405_t *c) 649{ 650 uint32_t rt, s1, s2; 651 652 s1 = p405_get_rs (c, c->ir); 653 s2 = p405_get_uimm16 (c->ir); 654 655 rt = s1 & (s2 << 16); 656 657 p405_set_ra (c, c->ir, rt); 658 659 p405_set_cr0 (c, rt); 660 661 p405_set_clk (c, 4, 1); 662} 663 664/* 20: lwz rt, ra0, simm16 */ 665static 666void op_20 (p405_t *c) 667{ 668 uint32_t rt, ea; 669 670 if (p405_get_ea (c, &ea, 0, 0)) { 671 return; 672 } 673 674 if (p405_dload32 (c, ea, &rt)) { 675 return; 676 } 677 678 p405_set_rt (c, c->ir, rt); 679 680 p405_set_clk (c, 4, 1); 681} 682 683/* 21: lwzu rt, ra, simm16 */ 684static 685void op_21 (p405_t *c) 686{ 687 uint32_t rt, ea; 688 689 if (p405_get_ea (c, &ea, 0, 1)) { 690 return; 691 } 692 693 if (p405_dload32 (c, ea, &rt)) { 694 return; 695 } 696 697 p405_set_ra (c, c->ir, ea); 698 p405_set_rt (c, c->ir, rt); 699 700 p405_set_clk (c, 4, 1); 701} 702 703/* 22: lbz rt, ra0, simm16 */ 704static 705void op_22 (p405_t *c) 706{ 707 uint8_t rt; 708 uint32_t ea; 709 710 if (p405_get_ea (c, &ea, 0, 0)) { 711 return; 712 } 713 714 if (p405_dload8 (c, ea, &rt)) { 715 return; 716 } 717 718 p405_set_rt (c, c->ir, p405_uext (rt, 8)); 719 720 p405_set_clk (c, 4, 1); 721} 722 723/* 23: lbzu rt, ra, simm16 */ 724static 725void op_23 (p405_t *c) 726{ 727 uint8_t rt; 728 uint32_t ea; 729 730 if (p405_get_ea (c, &ea, 0, 1)) { 731 return; 732 } 733 734 if (p405_dload8 (c, ea, &rt)) { 735 return; 736 } 737 738 p405_set_ra (c, c->ir, ea); 739 p405_set_rt (c, c->ir, p405_uext (rt, 8)); 740 741 p405_set_clk (c, 4, 1); 742} 743 744/* 24: stw rs, ra0, simm16 */ 745static 746void op_24 (p405_t *c) 747{ 748 uint32_t ea; 749 750 if (p405_get_ea (c, &ea, 0, 0)) { 751 return; 752 } 753 754 if (p405_dstore32 (c, ea, p405_get_rs (c, c->ir))) { 755 return; 756 } 757 758 p405_set_clk (c, 4, 1); 759} 760 761/* 25: stwu rs, ra, simm16 */ 762static 763void op_25 (p405_t *c) 764{ 765 uint32_t ea; 766 767 if (p405_get_ea (c, &ea, 0, 1)) { 768 return; 769 } 770 771 if (p405_dstore32 (c, ea, p405_get_rs (c, c->ir))) { 772 return; 773 } 774 775 p405_set_ra (c, c->ir, ea); 776 777 p405_set_clk (c, 4, 1); 778} 779 780/* 26: stb rs, ra0, simm16 */ 781static 782void op_26 (p405_t *c) 783{ 784 uint32_t ea; 785 786 if (p405_get_ea (c, &ea, 0, 0)) { 787 return; 788 } 789 790 if (p405_dstore8 (c, ea, p405_uext (p405_get_rs (c, c->ir), 8))) { 791 return; 792 } 793 794 p405_set_clk (c, 4, 1); 795} 796 797/* 27: stbu rs, ra, simm16 */ 798static 799void op_27 (p405_t *c) 800{ 801 uint32_t ea; 802 803 if (p405_get_ea (c, &ea, 0, 1)) { 804 return; 805 } 806 807 if (p405_dstore8 (c, ea, p405_uext (p405_get_rs (c, c->ir), 8))) { 808 return; 809 } 810 811 p405_set_ra (c, c->ir, ea); 812 813 p405_set_clk (c, 4, 1); 814} 815 816/* 28: lhz rt, ra0, simm16 */ 817static 818void op_28 (p405_t *c) 819{ 820 uint16_t rt; 821 uint32_t ea; 822 823 if (p405_get_ea (c, &ea, 0, 0)) { 824 return; 825 } 826 827 if (p405_dload16 (c, ea, &rt)) { 828 return; 829 } 830 831 p405_set_rt (c, c->ir, p405_uext (rt, 16)); 832 833 p405_set_clk (c, 4, 1); 834} 835 836/* 29: lhzu rt, ra, simm16 */ 837static 838void op_29 (p405_t *c) 839{ 840 uint16_t rt; 841 uint32_t ea; 842 843 if (p405_get_ea (c, &ea, 0, 1)) { 844 return; 845 } 846 847 if (p405_dload16 (c, ea, &rt)) { 848 return; 849 } 850 851 p405_set_ra (c, c->ir, ea); 852 p405_set_rt (c, c->ir, p405_uext (rt, 16)); 853 854 p405_set_clk (c, 4, 1); 855} 856 857/* 2A: lha rt, ra0, simm16 */ 858static 859void op_2a (p405_t *c) 860{ 861 uint16_t rt; 862 uint32_t ea; 863 864 if (p405_get_ea (c, &ea, 0, 0)) { 865 return; 866 } 867 868 if (p405_dload16 (c, ea, &rt)) { 869 return; 870 } 871 872 p405_set_rt (c, c->ir, p405_sext (rt, 16)); 873 874 p405_set_clk (c, 4, 1); 875} 876 877/* 2B: lhau rt, ra, simm16 */ 878static 879void op_2b (p405_t *c) 880{ 881 uint16_t rt; 882 uint32_t ea; 883 884 if (p405_get_ea (c, &ea, 0, 1)) { 885 return; 886 } 887 888 if (p405_dload16 (c, ea, &rt)) { 889 return; 890 } 891 892 p405_set_ra (c, c->ir, ea); 893 p405_set_rt (c, c->ir, p405_sext (rt, 16)); 894 895 p405_set_clk (c, 4, 1); 896} 897 898/* 2C: sth rs, ra0, simm16 */ 899static 900void op_2c (p405_t *c) 901{ 902 uint32_t ea; 903 904 if (p405_get_ea (c, &ea, 0, 0)) { 905 return; 906 } 907 908 if (p405_dstore16 (c, ea, p405_uext (p405_get_rs (c, c->ir), 16))) { 909 return; 910 } 911 912 p405_set_clk (c, 4, 1); 913} 914 915/* 2D: sthu rs, ra, simm16 */ 916static 917void op_2d (p405_t *c) 918{ 919 uint32_t ea; 920 921 if (p405_get_ea (c, &ea, 0, 1)) { 922 return; 923 } 924 925 if (p405_dstore16 (c, ea, p405_uext (p405_get_rs (c, c->ir), 16))) { 926 return; 927 } 928 929 p405_set_ra (c, c->ir, ea); 930 931 p405_set_clk (c, 4, 1); 932} 933 934/* 2E: lmw rt, ra, simm16 */ 935static 936void op_2e (p405_t *c) 937{ 938 unsigned rt, ra, cnt; 939 uint32_t val; 940 uint32_t ea; 941 942 if (p405_get_ea (c, &ea, 0, 0)) { 943 return; 944 } 945 946 rt = p405_get_ir_rt (c->ir); 947 ra = p405_get_ir_ra (c->ir); 948 949 if (ra >= rt) { 950 p405_op_undefined (c); 951 return; 952 } 953 954 cnt = 32 - rt; 955 956 while (rt <= 31) { 957 if ((rt != ra) || (rt == 31)) { 958 if (p405_dload32 (c, ea, &val)) { 959 return; 960 } 961 962 p405_set_gpr (c, rt, val); 963 } 964 965 rt += 1; 966 ea += 4; 967 } 968 969 p405_set_clk (c, 4, cnt); 970} 971 972/* 2F: stmw rs, ra, simm16 */ 973static 974void op_2f (p405_t *c) 975{ 976 unsigned rs, cnt; 977 uint32_t ea; 978 979 if (p405_get_ea (c, &ea, 0, 0)) { 980 return; 981 } 982 983 rs = p405_get_ir_rs (c->ir); 984 985 cnt = 32 - rs; 986 987 while (rs <= 31) { 988 if (p405_dstore32 (c, ea, p405_get_gpr (c, rs))) { 989 return; 990 } 991 992 rs += 1; 993 ea += 4; 994 } 995 996 p405_set_clk (c, 4, cnt); 997} 998 999/* 30: lfs */ 1000static 1001void op_30 (p405_t *c) 1002{ 1003 p405_set_clk (c, 0, 1); 1004 p405_exception_program_fpu (c); 1005} 1006 1007/* 31: lfsu */ 1008static 1009void op_31 (p405_t *c) 1010{ 1011 p405_set_clk (c, 0, 1); 1012 p405_exception_program_fpu (c); 1013} 1014 1015/* 32: lfd */ 1016static 1017void op_32 (p405_t *c) 1018{ 1019 p405_set_clk (c, 0, 1); 1020 p405_exception_program_fpu (c); 1021} 1022 1023/* 33: lfdu */ 1024static 1025void op_33 (p405_t *c) 1026{ 1027 p405_set_clk (c, 0, 1); 1028 p405_exception_program_fpu (c); 1029} 1030 1031/* 34: stfs */ 1032static 1033void op_34 (p405_t *c) 1034{ 1035 p405_set_clk (c, 0, 1); 1036 p405_exception_program_fpu (c); 1037} 1038 1039/* 35: stfsu */ 1040static 1041void op_35 (p405_t *c) 1042{ 1043 p405_set_clk (c, 0, 1); 1044 p405_exception_program_fpu (c); 1045} 1046 1047/* 36: stfd */ 1048static 1049void op_36 (p405_t *c) 1050{ 1051 p405_set_clk (c, 0, 1); 1052 p405_exception_program_fpu (c); 1053} 1054 1055/* 37: stfdu */ 1056static 1057void op_37 (p405_t *c) 1058{ 1059 p405_set_clk (c, 0, 1); 1060 p405_exception_program_fpu (c); 1061} 1062 1063/* 3B: single precision floating point instructions */ 1064static 1065void op_3b (p405_t *c) 1066{ 1067 p405_set_clk (c, 0, 1); 1068 p405_exception_program_fpu (c); 1069} 1070 1071/* 3F: double precision floating point instructions */ 1072static 1073void op_3f (p405_t *c) 1074{ 1075 p405_set_clk (c, 0, 1); 1076 p405_exception_program_fpu (c); 1077} 1078 1079 1080static 1081p405_opcode_f p405_opcodes[64] = { 1082 NULL, NULL, NULL, &op_03, NULL, NULL, NULL, &op_07, /* 00 */ 1083 &op_08, NULL, &op_0a, &op_0b, &op_0c, &op_0d, &op_0e, &op_0f, 1084 &op_10, &op_11, &op_12, NULL, &op_14, &op_15, NULL, &op_17, /* 10 */ 1085 &op_18, &op_19, &op_1a, &op_1b, &op_1c, &op_1d, NULL, NULL, 1086 &op_20, &op_21, &op_22, &op_23, &op_24, &op_25, &op_26, &op_27, /* 20 */ 1087 &op_28, &op_29, &op_2a, &op_2b, &op_2c, &op_2d, &op_2e, &op_2f, 1088 &op_30, &op_31, &op_32, &op_33, &op_34, &op_35, &op_36, &op_37, /* 30 */ 1089 NULL, NULL, NULL, &op_3b, NULL, NULL, NULL, &op_3f 1090}; 1091 1092 1093void p405_set_opcodes (p405_t *c) 1094{ 1095 unsigned i; 1096 1097 for (i = 0; i < 64; i++) { 1098 if (p405_opcodes[i] != NULL) { 1099 c->opcodes.op[i] = p405_opcodes[i]; 1100 } 1101 else { 1102 c->opcodes.op[i] = &p405_op_undefined; 1103 } 1104 } 1105 1106 p405_set_opcode13 (c); 1107 p405_set_opcode1f (c); 1108}