|
|
1.1 ! root 1: /* ! 2: * PowerPC emulation micro-operations for qemu. ! 3: * ! 4: * Copyright (c) 2003-2005 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: ! 21: //#define DEBUG_OP ! 22: ! 23: #include "config.h" ! 24: #include "exec.h" ! 25: ! 26: #define regs (env) ! 27: #define Ts0 (int32_t)T0 ! 28: #define Ts1 (int32_t)T1 ! 29: #define Ts2 (int32_t)T2 ! 30: ! 31: #define FT0 (env->ft0) ! 32: #define FT1 (env->ft1) ! 33: #define FT2 (env->ft2) ! 34: ! 35: #define PPC_OP(name) void glue(op_, name)(void) ! 36: ! 37: #define REG 0 ! 38: #include "op_template.h" ! 39: ! 40: #define REG 1 ! 41: #include "op_template.h" ! 42: ! 43: #define REG 2 ! 44: #include "op_template.h" ! 45: ! 46: #define REG 3 ! 47: #include "op_template.h" ! 48: ! 49: #define REG 4 ! 50: #include "op_template.h" ! 51: ! 52: #define REG 5 ! 53: #include "op_template.h" ! 54: ! 55: #define REG 6 ! 56: #include "op_template.h" ! 57: ! 58: #define REG 7 ! 59: #include "op_template.h" ! 60: ! 61: #define REG 8 ! 62: #include "op_template.h" ! 63: ! 64: #define REG 9 ! 65: #include "op_template.h" ! 66: ! 67: #define REG 10 ! 68: #include "op_template.h" ! 69: ! 70: #define REG 11 ! 71: #include "op_template.h" ! 72: ! 73: #define REG 12 ! 74: #include "op_template.h" ! 75: ! 76: #define REG 13 ! 77: #include "op_template.h" ! 78: ! 79: #define REG 14 ! 80: #include "op_template.h" ! 81: ! 82: #define REG 15 ! 83: #include "op_template.h" ! 84: ! 85: #define REG 16 ! 86: #include "op_template.h" ! 87: ! 88: #define REG 17 ! 89: #include "op_template.h" ! 90: ! 91: #define REG 18 ! 92: #include "op_template.h" ! 93: ! 94: #define REG 19 ! 95: #include "op_template.h" ! 96: ! 97: #define REG 20 ! 98: #include "op_template.h" ! 99: ! 100: #define REG 21 ! 101: #include "op_template.h" ! 102: ! 103: #define REG 22 ! 104: #include "op_template.h" ! 105: ! 106: #define REG 23 ! 107: #include "op_template.h" ! 108: ! 109: #define REG 24 ! 110: #include "op_template.h" ! 111: ! 112: #define REG 25 ! 113: #include "op_template.h" ! 114: ! 115: #define REG 26 ! 116: #include "op_template.h" ! 117: ! 118: #define REG 27 ! 119: #include "op_template.h" ! 120: ! 121: #define REG 28 ! 122: #include "op_template.h" ! 123: ! 124: #define REG 29 ! 125: #include "op_template.h" ! 126: ! 127: #define REG 30 ! 128: #include "op_template.h" ! 129: ! 130: #define REG 31 ! 131: #include "op_template.h" ! 132: ! 133: /* PowerPC state maintenance operations */ ! 134: /* set_Rc0 */ ! 135: PPC_OP(set_Rc0) ! 136: { ! 137: uint32_t tmp; ! 138: ! 139: if (Ts0 < 0) { ! 140: tmp = 0x08; ! 141: } else if (Ts0 > 0) { ! 142: tmp = 0x04; ! 143: } else { ! 144: tmp = 0x02; ! 145: } ! 146: tmp |= xer_ov; ! 147: env->crf[0] = tmp; ! 148: RETURN(); ! 149: } ! 150: ! 151: /* reset_Rc0 */ ! 152: PPC_OP(reset_Rc0) ! 153: { ! 154: env->crf[0] = 0x02 | xer_ov; ! 155: RETURN(); ! 156: } ! 157: ! 158: /* set_Rc0_1 */ ! 159: PPC_OP(set_Rc0_1) ! 160: { ! 161: env->crf[0] = 0x04 | xer_ov; ! 162: RETURN(); ! 163: } ! 164: ! 165: /* Set Rc1 (for floating point arithmetic) */ ! 166: PPC_OP(set_Rc1) ! 167: { ! 168: env->crf[1] = regs->fpscr[7]; ! 169: RETURN(); ! 170: } ! 171: ! 172: /* Constants load */ ! 173: PPC_OP(set_T0) ! 174: { ! 175: T0 = PARAM(1); ! 176: RETURN(); ! 177: } ! 178: ! 179: PPC_OP(set_T1) ! 180: { ! 181: T1 = PARAM(1); ! 182: RETURN(); ! 183: } ! 184: ! 185: PPC_OP(set_T2) ! 186: { ! 187: T2 = PARAM(1); ! 188: RETURN(); ! 189: } ! 190: ! 191: /* Generate exceptions */ ! 192: PPC_OP(raise_exception_err) ! 193: { ! 194: do_raise_exception_err(PARAM(1), PARAM(2)); ! 195: } ! 196: ! 197: PPC_OP(raise_exception) ! 198: { ! 199: do_raise_exception(PARAM(1)); ! 200: } ! 201: ! 202: PPC_OP(update_nip) ! 203: { ! 204: env->nip = PARAM(1); ! 205: } ! 206: ! 207: /* Segment registers load and store with immediate index */ ! 208: PPC_OP(load_srin) ! 209: { ! 210: T0 = regs->sr[T1 >> 28]; ! 211: RETURN(); ! 212: } ! 213: ! 214: PPC_OP(store_srin) ! 215: { ! 216: do_store_sr(env, ((uint32_t)T1 >> 28), T0); ! 217: RETURN(); ! 218: } ! 219: ! 220: PPC_OP(load_sdr1) ! 221: { ! 222: T0 = regs->sdr1; ! 223: RETURN(); ! 224: } ! 225: ! 226: PPC_OP(store_sdr1) ! 227: { ! 228: do_store_sdr1(env, T0); ! 229: RETURN(); ! 230: } ! 231: ! 232: PPC_OP(exit_tb) ! 233: { ! 234: EXIT_TB(); ! 235: } ! 236: ! 237: /* Load/store special registers */ ! 238: PPC_OP(load_cr) ! 239: { ! 240: T0 = do_load_cr(env); ! 241: RETURN(); ! 242: } ! 243: ! 244: PPC_OP(store_cr) ! 245: { ! 246: do_store_cr(env, T0, PARAM(1)); ! 247: RETURN(); ! 248: } ! 249: ! 250: PPC_OP(load_xer_cr) ! 251: { ! 252: T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1); ! 253: RETURN(); ! 254: } ! 255: ! 256: PPC_OP(clear_xer_cr) ! 257: { ! 258: xer_so = 0; ! 259: xer_ov = 0; ! 260: xer_ca = 0; ! 261: RETURN(); ! 262: } ! 263: ! 264: PPC_OP(load_xer_bc) ! 265: { ! 266: T1 = xer_bc; ! 267: RETURN(); ! 268: } ! 269: ! 270: PPC_OP(load_xer) ! 271: { ! 272: T0 = do_load_xer(env); ! 273: RETURN(); ! 274: } ! 275: ! 276: PPC_OP(store_xer) ! 277: { ! 278: do_store_xer(env, T0); ! 279: RETURN(); ! 280: } ! 281: ! 282: PPC_OP(load_msr) ! 283: { ! 284: T0 = do_load_msr(env); ! 285: RETURN(); ! 286: } ! 287: ! 288: PPC_OP(store_msr) ! 289: { ! 290: do_store_msr(env, T0); ! 291: RETURN(); ! 292: } ! 293: ! 294: /* SPR */ ! 295: PPC_OP(load_spr) ! 296: { ! 297: T0 = regs->spr[PARAM(1)]; ! 298: RETURN(); ! 299: } ! 300: ! 301: PPC_OP(store_spr) ! 302: { ! 303: regs->spr[PARAM(1)] = T0; ! 304: RETURN(); ! 305: } ! 306: ! 307: PPC_OP(load_lr) ! 308: { ! 309: T0 = regs->lr; ! 310: RETURN(); ! 311: } ! 312: ! 313: PPC_OP(store_lr) ! 314: { ! 315: regs->lr = T0; ! 316: RETURN(); ! 317: } ! 318: ! 319: PPC_OP(load_ctr) ! 320: { ! 321: T0 = regs->ctr; ! 322: RETURN(); ! 323: } ! 324: ! 325: PPC_OP(store_ctr) ! 326: { ! 327: regs->ctr = T0; ! 328: RETURN(); ! 329: } ! 330: ! 331: PPC_OP(load_tbl) ! 332: { ! 333: T0 = cpu_ppc_load_tbl(regs); ! 334: RETURN(); ! 335: } ! 336: ! 337: PPC_OP(load_tbu) ! 338: { ! 339: T0 = cpu_ppc_load_tbu(regs); ! 340: RETURN(); ! 341: } ! 342: ! 343: PPC_OP(store_tbl) ! 344: { ! 345: cpu_ppc_store_tbl(regs, T0); ! 346: RETURN(); ! 347: } ! 348: ! 349: PPC_OP(store_tbu) ! 350: { ! 351: cpu_ppc_store_tbu(regs, T0); ! 352: RETURN(); ! 353: } ! 354: ! 355: PPC_OP(load_decr) ! 356: { ! 357: T0 = cpu_ppc_load_decr(regs); ! 358: } ! 359: ! 360: PPC_OP(store_decr) ! 361: { ! 362: cpu_ppc_store_decr(regs, T0); ! 363: RETURN(); ! 364: } ! 365: ! 366: PPC_OP(load_ibat) ! 367: { ! 368: T0 = regs->IBAT[PARAM(1)][PARAM(2)]; ! 369: } ! 370: ! 371: void op_store_ibatu (void) ! 372: { ! 373: do_store_ibatu(env, PARAM1, T0); ! 374: RETURN(); ! 375: } ! 376: ! 377: void op_store_ibatl (void) ! 378: { ! 379: #if 1 ! 380: env->IBAT[1][PARAM1] = T0; ! 381: #else ! 382: do_store_ibatl(env, PARAM1, T0); ! 383: #endif ! 384: RETURN(); ! 385: } ! 386: ! 387: PPC_OP(load_dbat) ! 388: { ! 389: T0 = regs->DBAT[PARAM(1)][PARAM(2)]; ! 390: } ! 391: ! 392: void op_store_dbatu (void) ! 393: { ! 394: do_store_dbatu(env, PARAM1, T0); ! 395: RETURN(); ! 396: } ! 397: ! 398: void op_store_dbatl (void) ! 399: { ! 400: #if 1 ! 401: env->DBAT[1][PARAM1] = T0; ! 402: #else ! 403: do_store_dbatl(env, PARAM1, T0); ! 404: #endif ! 405: RETURN(); ! 406: } ! 407: ! 408: /* FPSCR */ ! 409: PPC_OP(load_fpscr) ! 410: { ! 411: FT0 = do_load_fpscr(env); ! 412: RETURN(); ! 413: } ! 414: ! 415: PPC_OP(store_fpscr) ! 416: { ! 417: do_store_fpscr(env, FT0, PARAM1); ! 418: RETURN(); ! 419: } ! 420: ! 421: PPC_OP(reset_scrfx) ! 422: { ! 423: regs->fpscr[7] &= ~0x8; ! 424: RETURN(); ! 425: } ! 426: ! 427: /* crf operations */ ! 428: PPC_OP(getbit_T0) ! 429: { ! 430: T0 = (T0 >> PARAM(1)) & 1; ! 431: RETURN(); ! 432: } ! 433: ! 434: PPC_OP(getbit_T1) ! 435: { ! 436: T1 = (T1 >> PARAM(1)) & 1; ! 437: RETURN(); ! 438: } ! 439: ! 440: PPC_OP(setcrfbit) ! 441: { ! 442: T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); ! 443: RETURN(); ! 444: } ! 445: ! 446: /* Branch */ ! 447: #define EIP regs->nip ! 448: ! 449: PPC_OP(setlr) ! 450: { ! 451: regs->lr = PARAM1; ! 452: } ! 453: ! 454: PPC_OP(b) ! 455: { ! 456: JUMP_TB(b1, PARAM1, 0, PARAM2); ! 457: } ! 458: ! 459: PPC_OP(b_T1) ! 460: { ! 461: regs->nip = T1 & ~3; ! 462: } ! 463: ! 464: PPC_OP(btest) ! 465: { ! 466: if (T0) { ! 467: JUMP_TB(btest, PARAM1, 0, PARAM2); ! 468: } else { ! 469: JUMP_TB(btest, PARAM1, 1, PARAM3); ! 470: } ! 471: RETURN(); ! 472: } ! 473: ! 474: PPC_OP(btest_T1) ! 475: { ! 476: if (T0) { ! 477: regs->nip = T1 & ~3; ! 478: } else { ! 479: regs->nip = PARAM1; ! 480: } ! 481: RETURN(); ! 482: } ! 483: ! 484: PPC_OP(movl_T1_ctr) ! 485: { ! 486: T1 = regs->ctr; ! 487: } ! 488: ! 489: PPC_OP(movl_T1_lr) ! 490: { ! 491: T1 = regs->lr; ! 492: } ! 493: ! 494: /* tests with result in T0 */ ! 495: ! 496: PPC_OP(test_ctr) ! 497: { ! 498: T0 = regs->ctr; ! 499: } ! 500: ! 501: PPC_OP(test_ctr_true) ! 502: { ! 503: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0); ! 504: } ! 505: ! 506: PPC_OP(test_ctr_false) ! 507: { ! 508: T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0); ! 509: } ! 510: ! 511: PPC_OP(test_ctrz) ! 512: { ! 513: T0 = (regs->ctr == 0); ! 514: } ! 515: ! 516: PPC_OP(test_ctrz_true) ! 517: { ! 518: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0); ! 519: } ! 520: ! 521: PPC_OP(test_ctrz_false) ! 522: { ! 523: T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0); ! 524: } ! 525: ! 526: PPC_OP(test_true) ! 527: { ! 528: T0 = (T0 & PARAM(1)); ! 529: } ! 530: ! 531: PPC_OP(test_false) ! 532: { ! 533: T0 = ((T0 & PARAM(1)) == 0); ! 534: } ! 535: ! 536: /* CTR maintenance */ ! 537: PPC_OP(dec_ctr) ! 538: { ! 539: regs->ctr--; ! 540: RETURN(); ! 541: } ! 542: ! 543: /*** Integer arithmetic ***/ ! 544: /* add */ ! 545: PPC_OP(add) ! 546: { ! 547: T0 += T1; ! 548: RETURN(); ! 549: } ! 550: ! 551: void do_addo (void); ! 552: void op_addo (void) ! 553: { ! 554: do_addo(); ! 555: RETURN(); ! 556: } ! 557: ! 558: /* add carrying */ ! 559: PPC_OP(addc) ! 560: { ! 561: T2 = T0; ! 562: T0 += T1; ! 563: if (T0 < T2) { ! 564: xer_ca = 1; ! 565: } else { ! 566: xer_ca = 0; ! 567: } ! 568: RETURN(); ! 569: } ! 570: ! 571: void do_addco (void); ! 572: void op_addco (void) ! 573: { ! 574: do_addco(); ! 575: RETURN(); ! 576: } ! 577: ! 578: /* add extended */ ! 579: void do_adde (void); ! 580: void op_adde (void) ! 581: { ! 582: do_adde(); ! 583: } ! 584: ! 585: void do_addeo (void); ! 586: PPC_OP(addeo) ! 587: { ! 588: do_addeo(); ! 589: RETURN(); ! 590: } ! 591: ! 592: /* add immediate */ ! 593: PPC_OP(addi) ! 594: { ! 595: T0 += PARAM(1); ! 596: RETURN(); ! 597: } ! 598: ! 599: /* add immediate carrying */ ! 600: PPC_OP(addic) ! 601: { ! 602: T1 = T0; ! 603: T0 += PARAM(1); ! 604: if (T0 < T1) { ! 605: xer_ca = 1; ! 606: } else { ! 607: xer_ca = 0; ! 608: } ! 609: RETURN(); ! 610: } ! 611: ! 612: /* add to minus one extended */ ! 613: PPC_OP(addme) ! 614: { ! 615: T1 = T0; ! 616: T0 += xer_ca + (-1); ! 617: if (T1 != 0) ! 618: xer_ca = 1; ! 619: RETURN(); ! 620: } ! 621: ! 622: void do_addmeo (void); ! 623: void op_addmeo (void) ! 624: { ! 625: do_addmeo(); ! 626: RETURN(); ! 627: } ! 628: ! 629: /* add to zero extended */ ! 630: PPC_OP(addze) ! 631: { ! 632: T1 = T0; ! 633: T0 += xer_ca; ! 634: if (T0 < T1) { ! 635: xer_ca = 1; ! 636: } else { ! 637: xer_ca = 0; ! 638: } ! 639: RETURN(); ! 640: } ! 641: ! 642: void do_addzeo (void); ! 643: void op_addzeo (void) ! 644: { ! 645: do_addzeo(); ! 646: RETURN(); ! 647: } ! 648: ! 649: /* divide word */ ! 650: PPC_OP(divw) ! 651: { ! 652: if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) { ! 653: T0 = (int32_t)((-1) * (T0 >> 31)); ! 654: } else { ! 655: T0 = (Ts0 / Ts1); ! 656: } ! 657: RETURN(); ! 658: } ! 659: ! 660: void do_divwo (void); ! 661: void op_divwo (void) ! 662: { ! 663: do_divwo(); ! 664: RETURN(); ! 665: } ! 666: ! 667: /* divide word unsigned */ ! 668: PPC_OP(divwu) ! 669: { ! 670: if (T1 == 0) { ! 671: T0 = 0; ! 672: } else { ! 673: T0 /= T1; ! 674: } ! 675: RETURN(); ! 676: } ! 677: ! 678: void do_divwuo (void); ! 679: void op_divwuo (void) ! 680: { ! 681: do_divwuo(); ! 682: RETURN(); ! 683: } ! 684: ! 685: /* multiply high word */ ! 686: PPC_OP(mulhw) ! 687: { ! 688: T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32; ! 689: RETURN(); ! 690: } ! 691: ! 692: /* multiply high word unsigned */ ! 693: PPC_OP(mulhwu) ! 694: { ! 695: T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32; ! 696: RETURN(); ! 697: } ! 698: ! 699: /* multiply low immediate */ ! 700: PPC_OP(mulli) ! 701: { ! 702: T0 = (Ts0 * SPARAM(1)); ! 703: RETURN(); ! 704: } ! 705: ! 706: /* multiply low word */ ! 707: PPC_OP(mullw) ! 708: { ! 709: T0 *= T1; ! 710: RETURN(); ! 711: } ! 712: ! 713: void do_mullwo (void); ! 714: void op_mullwo (void) ! 715: { ! 716: do_mullwo(); ! 717: RETURN(); ! 718: } ! 719: ! 720: /* negate */ ! 721: PPC_OP(neg) ! 722: { ! 723: if (T0 != 0x80000000) { ! 724: T0 = -Ts0; ! 725: } ! 726: RETURN(); ! 727: } ! 728: ! 729: void do_nego (void); ! 730: void op_nego (void) ! 731: { ! 732: do_nego(); ! 733: RETURN(); ! 734: } ! 735: ! 736: /* substract from */ ! 737: PPC_OP(subf) ! 738: { ! 739: T0 = T1 - T0; ! 740: RETURN(); ! 741: } ! 742: ! 743: void do_subfo (void); ! 744: void op_subfo (void) ! 745: { ! 746: do_subfo(); ! 747: RETURN(); ! 748: } ! 749: ! 750: /* substract from carrying */ ! 751: PPC_OP(subfc) ! 752: { ! 753: T0 = T1 - T0; ! 754: if (T0 <= T1) { ! 755: xer_ca = 1; ! 756: } else { ! 757: xer_ca = 0; ! 758: } ! 759: RETURN(); ! 760: } ! 761: ! 762: void do_subfco (void); ! 763: void op_subfco (void) ! 764: { ! 765: do_subfco(); ! 766: RETURN(); ! 767: } ! 768: ! 769: /* substract from extended */ ! 770: void do_subfe (void); ! 771: void op_subfe (void) ! 772: { ! 773: do_subfe(); ! 774: RETURN(); ! 775: } ! 776: ! 777: void do_subfeo (void); ! 778: PPC_OP(subfeo) ! 779: { ! 780: do_subfeo(); ! 781: RETURN(); ! 782: } ! 783: ! 784: /* substract from immediate carrying */ ! 785: PPC_OP(subfic) ! 786: { ! 787: T0 = PARAM(1) + ~T0 + 1; ! 788: if (T0 <= PARAM(1)) { ! 789: xer_ca = 1; ! 790: } else { ! 791: xer_ca = 0; ! 792: } ! 793: RETURN(); ! 794: } ! 795: ! 796: /* substract from minus one extended */ ! 797: PPC_OP(subfme) ! 798: { ! 799: T0 = ~T0 + xer_ca - 1; ! 800: ! 801: if (T0 != -1) ! 802: xer_ca = 1; ! 803: RETURN(); ! 804: } ! 805: ! 806: void do_subfmeo (void); ! 807: void op_subfmeo (void) ! 808: { ! 809: do_subfmeo(); ! 810: RETURN(); ! 811: } ! 812: ! 813: /* substract from zero extended */ ! 814: PPC_OP(subfze) ! 815: { ! 816: T1 = ~T0; ! 817: T0 = T1 + xer_ca; ! 818: if (T0 < T1) { ! 819: xer_ca = 1; ! 820: } else { ! 821: xer_ca = 0; ! 822: } ! 823: RETURN(); ! 824: } ! 825: ! 826: void do_subfzeo (void); ! 827: void op_subfzeo (void) ! 828: { ! 829: do_subfzeo(); ! 830: RETURN(); ! 831: } ! 832: ! 833: /*** Integer comparison ***/ ! 834: /* compare */ ! 835: PPC_OP(cmp) ! 836: { ! 837: if (Ts0 < Ts1) { ! 838: T0 = 0x08; ! 839: } else if (Ts0 > Ts1) { ! 840: T0 = 0x04; ! 841: } else { ! 842: T0 = 0x02; ! 843: } ! 844: RETURN(); ! 845: } ! 846: ! 847: /* compare immediate */ ! 848: PPC_OP(cmpi) ! 849: { ! 850: if (Ts0 < SPARAM(1)) { ! 851: T0 = 0x08; ! 852: } else if (Ts0 > SPARAM(1)) { ! 853: T0 = 0x04; ! 854: } else { ! 855: T0 = 0x02; ! 856: } ! 857: RETURN(); ! 858: } ! 859: ! 860: /* compare logical */ ! 861: PPC_OP(cmpl) ! 862: { ! 863: if (T0 < T1) { ! 864: T0 = 0x08; ! 865: } else if (T0 > T1) { ! 866: T0 = 0x04; ! 867: } else { ! 868: T0 = 0x02; ! 869: } ! 870: RETURN(); ! 871: } ! 872: ! 873: /* compare logical immediate */ ! 874: PPC_OP(cmpli) ! 875: { ! 876: if (T0 < PARAM(1)) { ! 877: T0 = 0x08; ! 878: } else if (T0 > PARAM(1)) { ! 879: T0 = 0x04; ! 880: } else { ! 881: T0 = 0x02; ! 882: } ! 883: RETURN(); ! 884: } ! 885: ! 886: /*** Integer logical ***/ ! 887: /* and */ ! 888: PPC_OP(and) ! 889: { ! 890: T0 &= T1; ! 891: RETURN(); ! 892: } ! 893: ! 894: /* andc */ ! 895: PPC_OP(andc) ! 896: { ! 897: T0 &= ~T1; ! 898: RETURN(); ! 899: } ! 900: ! 901: /* andi. */ ! 902: PPC_OP(andi_) ! 903: { ! 904: T0 &= PARAM(1); ! 905: RETURN(); ! 906: } ! 907: ! 908: /* count leading zero */ ! 909: PPC_OP(cntlzw) ! 910: { ! 911: T1 = T0; ! 912: for (T0 = 32; T1 > 0; T0--) ! 913: T1 = T1 >> 1; ! 914: RETURN(); ! 915: } ! 916: ! 917: /* eqv */ ! 918: PPC_OP(eqv) ! 919: { ! 920: T0 = ~(T0 ^ T1); ! 921: RETURN(); ! 922: } ! 923: ! 924: /* extend sign byte */ ! 925: PPC_OP(extsb) ! 926: { ! 927: T0 = (int32_t)((int8_t)(Ts0)); ! 928: RETURN(); ! 929: } ! 930: ! 931: /* extend sign half word */ ! 932: PPC_OP(extsh) ! 933: { ! 934: T0 = (int32_t)((int16_t)(Ts0)); ! 935: RETURN(); ! 936: } ! 937: ! 938: /* nand */ ! 939: PPC_OP(nand) ! 940: { ! 941: T0 = ~(T0 & T1); ! 942: RETURN(); ! 943: } ! 944: ! 945: /* nor */ ! 946: PPC_OP(nor) ! 947: { ! 948: T0 = ~(T0 | T1); ! 949: RETURN(); ! 950: } ! 951: ! 952: /* or */ ! 953: PPC_OP(or) ! 954: { ! 955: T0 |= T1; ! 956: RETURN(); ! 957: } ! 958: ! 959: /* orc */ ! 960: PPC_OP(orc) ! 961: { ! 962: T0 |= ~T1; ! 963: RETURN(); ! 964: } ! 965: ! 966: /* ori */ ! 967: PPC_OP(ori) ! 968: { ! 969: T0 |= PARAM(1); ! 970: RETURN(); ! 971: } ! 972: ! 973: /* xor */ ! 974: PPC_OP(xor) ! 975: { ! 976: T0 ^= T1; ! 977: RETURN(); ! 978: } ! 979: ! 980: /* xori */ ! 981: PPC_OP(xori) ! 982: { ! 983: T0 ^= PARAM(1); ! 984: RETURN(); ! 985: } ! 986: ! 987: /*** Integer rotate ***/ ! 988: /* rotate left word immediate then mask insert */ ! 989: PPC_OP(rlwimi) ! 990: { ! 991: T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3)); ! 992: RETURN(); ! 993: } ! 994: ! 995: /* rotate left immediate then and with mask insert */ ! 996: PPC_OP(rotlwi) ! 997: { ! 998: T0 = rotl(T0, PARAM(1)); ! 999: RETURN(); ! 1000: } ! 1001: ! 1002: PPC_OP(slwi) ! 1003: { ! 1004: T0 = T0 << PARAM(1); ! 1005: RETURN(); ! 1006: } ! 1007: ! 1008: PPC_OP(srwi) ! 1009: { ! 1010: T0 = T0 >> PARAM(1); ! 1011: RETURN(); ! 1012: } ! 1013: ! 1014: /* rotate left word then and with mask insert */ ! 1015: PPC_OP(rlwinm) ! 1016: { ! 1017: T0 = rotl(T0, PARAM(1)) & PARAM(2); ! 1018: RETURN(); ! 1019: } ! 1020: ! 1021: PPC_OP(rotl) ! 1022: { ! 1023: T0 = rotl(T0, T1); ! 1024: RETURN(); ! 1025: } ! 1026: ! 1027: PPC_OP(rlwnm) ! 1028: { ! 1029: T0 = rotl(T0, T1) & PARAM(1); ! 1030: RETURN(); ! 1031: } ! 1032: ! 1033: /*** Integer shift ***/ ! 1034: /* shift left word */ ! 1035: PPC_OP(slw) ! 1036: { ! 1037: if (T1 & 0x20) { ! 1038: T0 = 0; ! 1039: } else { ! 1040: T0 = T0 << T1; ! 1041: } ! 1042: RETURN(); ! 1043: } ! 1044: ! 1045: /* shift right algebraic word */ ! 1046: void op_sraw (void) ! 1047: { ! 1048: do_sraw(); ! 1049: RETURN(); ! 1050: } ! 1051: ! 1052: /* shift right algebraic word immediate */ ! 1053: PPC_OP(srawi) ! 1054: { ! 1055: T1 = T0; ! 1056: T0 = (Ts0 >> PARAM(1)); ! 1057: if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) { ! 1058: xer_ca = 1; ! 1059: } else { ! 1060: xer_ca = 0; ! 1061: } ! 1062: RETURN(); ! 1063: } ! 1064: ! 1065: /* shift right word */ ! 1066: PPC_OP(srw) ! 1067: { ! 1068: if (T1 & 0x20) { ! 1069: T0 = 0; ! 1070: } else { ! 1071: T0 = T0 >> T1; ! 1072: } ! 1073: RETURN(); ! 1074: } ! 1075: ! 1076: /*** Floating-Point arithmetic ***/ ! 1077: /* fadd - fadd. */ ! 1078: PPC_OP(fadd) ! 1079: { ! 1080: FT0 += FT1; ! 1081: RETURN(); ! 1082: } ! 1083: ! 1084: /* fsub - fsub. */ ! 1085: PPC_OP(fsub) ! 1086: { ! 1087: FT0 -= FT1; ! 1088: RETURN(); ! 1089: } ! 1090: ! 1091: /* fmul - fmul. */ ! 1092: PPC_OP(fmul) ! 1093: { ! 1094: FT0 *= FT1; ! 1095: RETURN(); ! 1096: } ! 1097: ! 1098: /* fdiv - fdiv. */ ! 1099: PPC_OP(fdiv) ! 1100: { ! 1101: FT0 = float64_div(FT0, FT1, &env->fp_status); ! 1102: RETURN(); ! 1103: } ! 1104: ! 1105: /* fsqrt - fsqrt. */ ! 1106: PPC_OP(fsqrt) ! 1107: { ! 1108: do_fsqrt(); ! 1109: RETURN(); ! 1110: } ! 1111: ! 1112: /* fres - fres. */ ! 1113: PPC_OP(fres) ! 1114: { ! 1115: do_fres(); ! 1116: RETURN(); ! 1117: } ! 1118: ! 1119: /* frsqrte - frsqrte. */ ! 1120: PPC_OP(frsqrte) ! 1121: { ! 1122: do_frsqrte(); ! 1123: RETURN(); ! 1124: } ! 1125: ! 1126: /* fsel - fsel. */ ! 1127: PPC_OP(fsel) ! 1128: { ! 1129: do_fsel(); ! 1130: RETURN(); ! 1131: } ! 1132: ! 1133: /*** Floating-Point multiply-and-add ***/ ! 1134: /* fmadd - fmadd. */ ! 1135: PPC_OP(fmadd) ! 1136: { ! 1137: FT0 = (FT0 * FT1) + FT2; ! 1138: RETURN(); ! 1139: } ! 1140: ! 1141: /* fmsub - fmsub. */ ! 1142: PPC_OP(fmsub) ! 1143: { ! 1144: FT0 = (FT0 * FT1) - FT2; ! 1145: RETURN(); ! 1146: } ! 1147: ! 1148: /* fnmadd - fnmadd. - fnmadds - fnmadds. */ ! 1149: PPC_OP(fnmadd) ! 1150: { ! 1151: do_fnmadd(); ! 1152: RETURN(); ! 1153: } ! 1154: ! 1155: /* fnmsub - fnmsub. */ ! 1156: PPC_OP(fnmsub) ! 1157: { ! 1158: do_fnmsub(); ! 1159: RETURN(); ! 1160: } ! 1161: ! 1162: /*** Floating-Point round & convert ***/ ! 1163: /* frsp - frsp. */ ! 1164: PPC_OP(frsp) ! 1165: { ! 1166: FT0 = (float)FT0; ! 1167: RETURN(); ! 1168: } ! 1169: ! 1170: /* fctiw - fctiw. */ ! 1171: PPC_OP(fctiw) ! 1172: { ! 1173: do_fctiw(); ! 1174: RETURN(); ! 1175: } ! 1176: ! 1177: /* fctiwz - fctiwz. */ ! 1178: PPC_OP(fctiwz) ! 1179: { ! 1180: do_fctiwz(); ! 1181: RETURN(); ! 1182: } ! 1183: ! 1184: ! 1185: /*** Floating-Point compare ***/ ! 1186: /* fcmpu */ ! 1187: PPC_OP(fcmpu) ! 1188: { ! 1189: do_fcmpu(); ! 1190: RETURN(); ! 1191: } ! 1192: ! 1193: /* fcmpo */ ! 1194: PPC_OP(fcmpo) ! 1195: { ! 1196: do_fcmpo(); ! 1197: RETURN(); ! 1198: } ! 1199: ! 1200: /*** Floating-point move ***/ ! 1201: /* fabs */ ! 1202: PPC_OP(fabs) ! 1203: { ! 1204: FT0 = float64_abs(FT0); ! 1205: RETURN(); ! 1206: } ! 1207: ! 1208: /* fnabs */ ! 1209: PPC_OP(fnabs) ! 1210: { ! 1211: FT0 = float64_abs(FT0); ! 1212: FT0 = float64_chs(FT0); ! 1213: RETURN(); ! 1214: } ! 1215: ! 1216: /* fneg */ ! 1217: PPC_OP(fneg) ! 1218: { ! 1219: FT0 = float64_chs(FT0); ! 1220: RETURN(); ! 1221: } ! 1222: ! 1223: /* Load and store */ ! 1224: #define MEMSUFFIX _raw ! 1225: #include "op_mem.h" ! 1226: #if !defined(CONFIG_USER_ONLY) ! 1227: #define MEMSUFFIX _user ! 1228: #include "op_mem.h" ! 1229: ! 1230: #define MEMSUFFIX _kernel ! 1231: #include "op_mem.h" ! 1232: #endif ! 1233: ! 1234: /* Special op to check and maybe clear reservation */ ! 1235: PPC_OP(check_reservation) ! 1236: { ! 1237: if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003)) ! 1238: env->reserve = -1; ! 1239: RETURN(); ! 1240: } ! 1241: ! 1242: /* Return from interrupt */ ! 1243: void do_rfi (void); ! 1244: void op_rfi (void) ! 1245: { ! 1246: do_rfi(); ! 1247: RETURN(); ! 1248: } ! 1249: ! 1250: /* Trap word */ ! 1251: void do_tw (uint32_t cmp, int flags); ! 1252: void op_tw (void) ! 1253: { ! 1254: do_tw(T1, PARAM(1)); ! 1255: RETURN(); ! 1256: } ! 1257: ! 1258: void op_twi (void) ! 1259: { ! 1260: do_tw(PARAM(1), PARAM(2)); ! 1261: RETURN(); ! 1262: } ! 1263: ! 1264: /* Instruction cache block invalidate */ ! 1265: PPC_OP(icbi) ! 1266: { ! 1267: do_icbi(); ! 1268: RETURN(); ! 1269: } ! 1270: ! 1271: /* tlbia */ ! 1272: PPC_OP(tlbia) ! 1273: { ! 1274: do_tlbia(); ! 1275: RETURN(); ! 1276: } ! 1277: ! 1278: /* tlbie */ ! 1279: PPC_OP(tlbie) ! 1280: { ! 1281: do_tlbie(); ! 1282: RETURN(); ! 1283: } ! 1284: ! 1285: void op_store_pir (void) ! 1286: { ! 1287: env->spr[SPR_PIR] = T0 & 0x0000000FUL; ! 1288: RETURN(); ! 1289: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.