|
|
1.1 ! root 1: /* ! 2: * Tiny Code Generator for QEMU ! 3: * ! 4: * Copyright (c) 2008 Fabrice Bellard ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: ! 25: #define TCG_CT_CONST_U32 0x100 ! 26: ! 27: static uint8_t *tb_ret_addr; ! 28: ! 29: #define FAST_PATH ! 30: ! 31: #if TARGET_PHYS_ADDR_BITS == 32 ! 32: #define LD_ADDEND LWZ ! 33: #else ! 34: #define LD_ADDEND LD ! 35: #endif ! 36: ! 37: #if TARGET_LONG_BITS == 32 ! 38: #define LD_ADDR LWZU ! 39: #define CMP_L 0 ! 40: #else ! 41: #define LD_ADDR LDU ! 42: #define CMP_L (1<<21) ! 43: #endif ! 44: ! 45: #ifndef NDEBUG ! 46: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ! 47: "r0", ! 48: "r1", ! 49: "rp", ! 50: "r3", ! 51: "r4", ! 52: "r5", ! 53: "r6", ! 54: "r7", ! 55: "r8", ! 56: "r9", ! 57: "r10", ! 58: "r11", ! 59: "r12", ! 60: "r13", ! 61: "r14", ! 62: "r15", ! 63: "r16", ! 64: "r17", ! 65: "r18", ! 66: "r19", ! 67: "r20", ! 68: "r21", ! 69: "r22", ! 70: "r23", ! 71: "r24", ! 72: "r25", ! 73: "r26", ! 74: "r27", ! 75: "r28", ! 76: "r29", ! 77: "r30", ! 78: "r31" ! 79: }; ! 80: #endif ! 81: ! 82: static const int tcg_target_reg_alloc_order[] = { ! 83: TCG_REG_R14, ! 84: TCG_REG_R15, ! 85: TCG_REG_R16, ! 86: TCG_REG_R17, ! 87: TCG_REG_R18, ! 88: TCG_REG_R19, ! 89: TCG_REG_R20, ! 90: TCG_REG_R21, ! 91: TCG_REG_R22, ! 92: TCG_REG_R23, ! 93: TCG_REG_R28, ! 94: TCG_REG_R29, ! 95: TCG_REG_R30, ! 96: TCG_REG_R31, ! 97: TCG_REG_R3, ! 98: TCG_REG_R4, ! 99: TCG_REG_R5, ! 100: TCG_REG_R6, ! 101: TCG_REG_R7, ! 102: TCG_REG_R8, ! 103: TCG_REG_R9, ! 104: TCG_REG_R10, ! 105: TCG_REG_R11, ! 106: TCG_REG_R12, ! 107: TCG_REG_R13, ! 108: TCG_REG_R0, ! 109: TCG_REG_R1, ! 110: TCG_REG_R2, ! 111: TCG_REG_R24, ! 112: TCG_REG_R25, ! 113: TCG_REG_R26, ! 114: TCG_REG_R27 ! 115: }; ! 116: ! 117: static const int tcg_target_call_iarg_regs[] = { ! 118: TCG_REG_R3, ! 119: TCG_REG_R4, ! 120: TCG_REG_R5, ! 121: TCG_REG_R6, ! 122: TCG_REG_R7, ! 123: TCG_REG_R8, ! 124: TCG_REG_R9, ! 125: TCG_REG_R10 ! 126: }; ! 127: ! 128: static const int tcg_target_call_oarg_regs[2] = { ! 129: TCG_REG_R3 ! 130: }; ! 131: ! 132: static const int tcg_target_callee_save_regs[] = { ! 133: TCG_REG_R14, ! 134: TCG_REG_R15, ! 135: TCG_REG_R16, ! 136: TCG_REG_R17, ! 137: TCG_REG_R18, ! 138: TCG_REG_R19, ! 139: TCG_REG_R20, ! 140: TCG_REG_R21, ! 141: TCG_REG_R22, ! 142: TCG_REG_R23, ! 143: TCG_REG_R24, ! 144: TCG_REG_R25, ! 145: TCG_REG_R26, ! 146: /* TCG_REG_R27, */ /* currently used for the global env, so no ! 147: need to save */ ! 148: TCG_REG_R28, ! 149: TCG_REG_R29, ! 150: TCG_REG_R30, ! 151: TCG_REG_R31 ! 152: }; ! 153: ! 154: static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) ! 155: { ! 156: tcg_target_long disp; ! 157: ! 158: disp = target - (tcg_target_long) pc; ! 159: if ((disp << 38) >> 38 != disp) ! 160: tcg_abort (); ! 161: ! 162: return disp & 0x3fffffc; ! 163: } ! 164: ! 165: static void reloc_pc24 (void *pc, tcg_target_long target) ! 166: { ! 167: *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc) ! 168: | reloc_pc24_val (pc, target); ! 169: } ! 170: ! 171: static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) ! 172: { ! 173: tcg_target_long disp; ! 174: ! 175: disp = target - (tcg_target_long) pc; ! 176: if (disp != (int16_t) disp) ! 177: tcg_abort (); ! 178: ! 179: return disp & 0xfffc; ! 180: } ! 181: ! 182: static void reloc_pc14 (void *pc, tcg_target_long target) ! 183: { ! 184: *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc) ! 185: | reloc_pc14_val (pc, target); ! 186: } ! 187: ! 188: static void patch_reloc (uint8_t *code_ptr, int type, ! 189: tcg_target_long value, tcg_target_long addend) ! 190: { ! 191: value += addend; ! 192: switch (type) { ! 193: case R_PPC_REL14: ! 194: reloc_pc14 (code_ptr, value); ! 195: break; ! 196: case R_PPC_REL24: ! 197: reloc_pc24 (code_ptr, value); ! 198: break; ! 199: default: ! 200: tcg_abort (); ! 201: } ! 202: } ! 203: ! 204: /* maximum number of register used for input function arguments */ ! 205: static int tcg_target_get_call_iarg_regs_count (int flags) ! 206: { ! 207: return ARRAY_SIZE (tcg_target_call_iarg_regs); ! 208: } ! 209: ! 210: /* parse target specific constraints */ ! 211: static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) ! 212: { ! 213: const char *ct_str; ! 214: ! 215: ct_str = *pct_str; ! 216: switch (ct_str[0]) { ! 217: case 'A': case 'B': case 'C': case 'D': ! 218: ct->ct |= TCG_CT_REG; ! 219: tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A'); ! 220: break; ! 221: case 'r': ! 222: ct->ct |= TCG_CT_REG; ! 223: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); ! 224: break; ! 225: case 'L': /* qemu_ld constraint */ ! 226: ct->ct |= TCG_CT_REG; ! 227: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); ! 228: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ! 229: #ifdef CONFIG_SOFTMMU ! 230: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); ! 231: #endif ! 232: break; ! 233: case 'S': /* qemu_st constraint */ ! 234: ct->ct |= TCG_CT_REG; ! 235: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); ! 236: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ! 237: #ifdef CONFIG_SOFTMMU ! 238: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); ! 239: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5); ! 240: #endif ! 241: break; ! 242: case 'Z': ! 243: ct->ct |= TCG_CT_CONST_U32; ! 244: break; ! 245: default: ! 246: return -1; ! 247: } ! 248: ct_str++; ! 249: *pct_str = ct_str; ! 250: return 0; ! 251: } ! 252: ! 253: /* test if a constant matches the constraint */ ! 254: static int tcg_target_const_match (tcg_target_long val, ! 255: const TCGArgConstraint *arg_ct) ! 256: { ! 257: int ct; ! 258: ! 259: ct = arg_ct->ct; ! 260: if (ct & TCG_CT_CONST) ! 261: return 1; ! 262: else if ((ct & TCG_CT_CONST_U32) && (val == (uint32_t) val)) ! 263: return 1; ! 264: return 0; ! 265: } ! 266: ! 267: #define OPCD(opc) ((opc)<<26) ! 268: #define XO19(opc) (OPCD(19)|((opc)<<1)) ! 269: #define XO30(opc) (OPCD(30)|((opc)<<2)) ! 270: #define XO31(opc) (OPCD(31)|((opc)<<1)) ! 271: #define XO58(opc) (OPCD(58)|(opc)) ! 272: #define XO62(opc) (OPCD(62)|(opc)) ! 273: ! 274: #define B OPCD( 18) ! 275: #define BC OPCD( 16) ! 276: #define LBZ OPCD( 34) ! 277: #define LHZ OPCD( 40) ! 278: #define LHA OPCD( 42) ! 279: #define LWZ OPCD( 32) ! 280: #define STB OPCD( 38) ! 281: #define STH OPCD( 44) ! 282: #define STW OPCD( 36) ! 283: ! 284: #define STD XO62( 0) ! 285: #define STDU XO62( 1) ! 286: #define STDX XO31(149) ! 287: ! 288: #define LD XO58( 0) ! 289: #define LDX XO31( 21) ! 290: #define LDU XO58( 1) ! 291: #define LWA XO58( 2) ! 292: #define LWAX XO31(341) ! 293: ! 294: #define ADDI OPCD( 14) ! 295: #define ADDIS OPCD( 15) ! 296: #define ORI OPCD( 24) ! 297: #define ORIS OPCD( 25) ! 298: #define XORI OPCD( 26) ! 299: #define XORIS OPCD( 27) ! 300: #define ANDI OPCD( 28) ! 301: #define ANDIS OPCD( 29) ! 302: #define MULLI OPCD( 7) ! 303: #define CMPLI OPCD( 10) ! 304: #define CMPI OPCD( 11) ! 305: ! 306: #define LWZU OPCD( 33) ! 307: #define STWU OPCD( 37) ! 308: ! 309: #define RLWINM OPCD( 21) ! 310: ! 311: #define RLDICL XO30( 0) ! 312: #define RLDICR XO30( 1) ! 313: #define RLDIMI XO30( 3) ! 314: ! 315: #define BCLR XO19( 16) ! 316: #define BCCTR XO19(528) ! 317: #define CRAND XO19(257) ! 318: #define CRANDC XO19(129) ! 319: #define CRNAND XO19(225) ! 320: #define CROR XO19(449) ! 321: ! 322: #define EXTSB XO31(954) ! 323: #define EXTSH XO31(922) ! 324: #define EXTSW XO31(986) ! 325: #define ADD XO31(266) ! 326: #define ADDE XO31(138) ! 327: #define ADDC XO31( 10) ! 328: #define AND XO31( 28) ! 329: #define SUBF XO31( 40) ! 330: #define SUBFC XO31( 8) ! 331: #define SUBFE XO31(136) ! 332: #define OR XO31(444) ! 333: #define XOR XO31(316) ! 334: #define MULLW XO31(235) ! 335: #define MULHWU XO31( 11) ! 336: #define DIVW XO31(491) ! 337: #define DIVWU XO31(459) ! 338: #define CMP XO31( 0) ! 339: #define CMPL XO31( 32) ! 340: #define LHBRX XO31(790) ! 341: #define LWBRX XO31(534) ! 342: #define STHBRX XO31(918) ! 343: #define STWBRX XO31(662) ! 344: #define MFSPR XO31(339) ! 345: #define MTSPR XO31(467) ! 346: #define SRAWI XO31(824) ! 347: #define NEG XO31(104) ! 348: ! 349: #define MULLD XO31(233) ! 350: #define MULHD XO31( 73) ! 351: #define MULHDU XO31( 9) ! 352: #define DIVD XO31(489) ! 353: #define DIVDU XO31(457) ! 354: ! 355: #define LBZX XO31( 87) ! 356: #define LHZX XO31(276) ! 357: #define LHAX XO31(343) ! 358: #define LWZX XO31( 23) ! 359: #define STBX XO31(215) ! 360: #define STHX XO31(407) ! 361: #define STWX XO31(151) ! 362: ! 363: #define SPR(a,b) ((((a)<<5)|(b))<<11) ! 364: #define LR SPR(8, 0) ! 365: #define CTR SPR(9, 0) ! 366: ! 367: #define SLW XO31( 24) ! 368: #define SRW XO31(536) ! 369: #define SRAW XO31(792) ! 370: ! 371: #define SLD XO31( 27) ! 372: #define SRD XO31(539) ! 373: #define SRAD XO31(794) ! 374: #define SRADI XO31(413<<1) ! 375: ! 376: #define LMW OPCD( 46) ! 377: #define STMW OPCD( 47) ! 378: ! 379: #define TW XO31( 4) ! 380: #define TRAP (TW | TO (31)) ! 381: ! 382: #define RT(r) ((r)<<21) ! 383: #define RS(r) ((r)<<21) ! 384: #define RA(r) ((r)<<16) ! 385: #define RB(r) ((r)<<11) ! 386: #define TO(t) ((t)<<21) ! 387: #define SH(s) ((s)<<11) ! 388: #define MB(b) ((b)<<6) ! 389: #define ME(e) ((e)<<1) ! 390: #define BO(o) ((o)<<21) ! 391: #define MB64(b) ((b)<<5) ! 392: ! 393: #define LK 1 ! 394: ! 395: #define TAB(t,a,b) (RT(t) | RA(a) | RB(b)) ! 396: #define SAB(s,a,b) (RS(s) | RA(a) | RB(b)) ! 397: ! 398: #define BF(n) ((n)<<23) ! 399: #define BI(n, c) (((c)+((n)*4))<<16) ! 400: #define BT(n, c) (((c)+((n)*4))<<21) ! 401: #define BA(n, c) (((c)+((n)*4))<<16) ! 402: #define BB(n, c) (((c)+((n)*4))<<11) ! 403: ! 404: #define BO_COND_TRUE BO (12) ! 405: #define BO_COND_FALSE BO ( 4) ! 406: #define BO_ALWAYS BO (20) ! 407: ! 408: enum { ! 409: CR_LT, ! 410: CR_GT, ! 411: CR_EQ, ! 412: CR_SO ! 413: }; ! 414: ! 415: static const uint32_t tcg_to_bc[10] = { ! 416: [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, ! 417: [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, ! 418: [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, ! 419: [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE, ! 420: [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE, ! 421: [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE, ! 422: [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE, ! 423: [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE, ! 424: [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE, ! 425: [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, ! 426: }; ! 427: ! 428: static void tcg_out_mov (TCGContext *s, int ret, int arg) ! 429: { ! 430: tcg_out32 (s, OR | SAB (arg, ret, arg)); ! 431: } ! 432: ! 433: static void tcg_out_rld (TCGContext *s, int op, int ra, int rs, int sh, int mb) ! 434: { ! 435: sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1); ! 436: mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f)); ! 437: tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb); ! 438: } ! 439: ! 440: static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg) ! 441: { ! 442: if (arg == (int16_t) arg) ! 443: tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff)); ! 444: else { ! 445: tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff)); ! 446: if (arg & 0xffff) ! 447: tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff)); ! 448: } ! 449: } ! 450: ! 451: static void tcg_out_movi (TCGContext *s, TCGType type, ! 452: int ret, tcg_target_long arg) ! 453: { ! 454: int32_t arg32 = arg; ! 455: ! 456: if (type == TCG_TYPE_I32 || arg == arg32) { ! 457: tcg_out_movi32 (s, ret, arg32); ! 458: } ! 459: else { ! 460: if ((uint64_t) arg >> 32) { ! 461: uint16_t h16 = arg >> 16; ! 462: uint16_t l16 = arg; ! 463: ! 464: tcg_out_movi32 (s, ret, arg >> 32); ! 465: tcg_out_rld (s, RLDICR, ret, ret, 32, 31); ! 466: if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16); ! 467: if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16); ! 468: } ! 469: else { ! 470: tcg_out_movi32 (s, ret, arg32); ! 471: if (arg32 < 0) ! 472: tcg_out_rld (s, RLDICL, ret, ret, 0, 32); ! 473: } ! 474: } ! 475: } ! 476: ! 477: static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) ! 478: { ! 479: int reg; ! 480: ! 481: if (const_arg) { ! 482: reg = 2; ! 483: tcg_out_movi (s, TCG_TYPE_I64, reg, arg); ! 484: } ! 485: else reg = arg; ! 486: ! 487: tcg_out32 (s, LD | RT (0) | RA (reg)); ! 488: tcg_out32 (s, MTSPR | RA (0) | CTR); ! 489: tcg_out32 (s, LD | RT (11) | RA (reg) | 16); ! 490: tcg_out32 (s, LD | RT (2) | RA (reg) | 8); ! 491: tcg_out32 (s, BCCTR | BO_ALWAYS | LK); ! 492: } ! 493: ! 494: static void tcg_out_ldst (TCGContext *s, int ret, int addr, ! 495: int offset, int op1, int op2) ! 496: { ! 497: if (offset == (int16_t) offset) ! 498: tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff)); ! 499: else { ! 500: tcg_out_movi (s, TCG_TYPE_I64, 0, offset); ! 501: tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0)); ! 502: } ! 503: } ! 504: ! 505: static void tcg_out_ldsta (TCGContext *s, int ret, int addr, ! 506: int offset, int op1, int op2) ! 507: { ! 508: if (offset == (int16_t) (offset & ~3)) ! 509: tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff)); ! 510: else { ! 511: tcg_out_movi (s, TCG_TYPE_I64, 0, offset); ! 512: tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0)); ! 513: } ! 514: } ! 515: ! 516: static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) ! 517: { ! 518: tcg_target_long disp; ! 519: ! 520: disp = target - (tcg_target_long) s->code_ptr; ! 521: if ((disp << 38) >> 38 == disp) ! 522: tcg_out32 (s, B | (disp & 0x3fffffc) | mask); ! 523: else { ! 524: tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); ! 525: tcg_out32 (s, MTSPR | RS (0) | CTR); ! 526: tcg_out32 (s, BCCTR | BO_ALWAYS | mask); ! 527: } ! 528: } ! 529: ! 530: #if defined (CONFIG_SOFTMMU) ! 531: ! 532: #include "../../softmmu_defs.h" ! 533: ! 534: static void *qemu_ld_helpers[4] = { ! 535: __ldb_mmu, ! 536: __ldw_mmu, ! 537: __ldl_mmu, ! 538: __ldq_mmu, ! 539: }; ! 540: ! 541: static void *qemu_st_helpers[4] = { ! 542: __stb_mmu, ! 543: __stw_mmu, ! 544: __stl_mmu, ! 545: __stq_mmu, ! 546: }; ! 547: ! 548: static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, ! 549: int addr_reg, int s_bits, int offset) ! 550: { ! 551: #if TARGET_LONG_BITS == 32 ! 552: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); ! 553: ! 554: tcg_out32 (s, (RLWINM ! 555: | RA (r0) ! 556: | RS (addr_reg) ! 557: | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)) ! 558: | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS)) ! 559: | ME (31 - CPU_TLB_ENTRY_BITS) ! 560: ) ! 561: ); ! 562: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0)); ! 563: tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset)); ! 564: tcg_out32 (s, (RLWINM ! 565: | RA (r2) ! 566: | RS (addr_reg) ! 567: | SH (0) ! 568: | MB ((32 - s_bits) & 31) ! 569: | ME (31 - TARGET_PAGE_BITS) ! 570: ) ! 571: ); ! 572: #else ! 573: tcg_out_rld (s, RLDICL, r0, addr_reg, ! 574: 64 - TARGET_PAGE_BITS, ! 575: 64 - CPU_TLB_BITS); ! 576: tcg_out_rld (s, RLDICR, r0, r0, ! 577: CPU_TLB_ENTRY_BITS, ! 578: 63 - CPU_TLB_ENTRY_BITS); ! 579: ! 580: tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0)); ! 581: tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset); ! 582: ! 583: if (!s_bits) { ! 584: tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS); ! 585: } ! 586: else { ! 587: tcg_out_rld (s, RLDICL, r2, addr_reg, ! 588: 64 - TARGET_PAGE_BITS, ! 589: TARGET_PAGE_BITS - s_bits); ! 590: tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0); ! 591: } ! 592: #endif ! 593: } ! 594: #endif ! 595: ! 596: static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) ! 597: { ! 598: int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; ! 599: #ifdef CONFIG_SOFTMMU ! 600: int r2; ! 601: void *label1_ptr, *label2_ptr; ! 602: #endif ! 603: ! 604: data_reg = *args++; ! 605: addr_reg = *args++; ! 606: mem_index = *args; ! 607: s_bits = opc & 3; ! 608: ! 609: #ifdef CONFIG_SOFTMMU ! 610: r0 = 3; ! 611: r1 = 4; ! 612: r2 = 0; ! 613: ! 614: tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits, ! 615: offsetof (CPUState, tlb_table[mem_index][0].addr_read)); ! 616: ! 617: tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); ! 618: ! 619: label1_ptr = s->code_ptr; ! 620: #ifdef FAST_PATH ! 621: tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); ! 622: #endif ! 623: ! 624: /* slow path */ ! 625: tcg_out_mov (s, 3, addr_reg); ! 626: tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index); ! 627: ! 628: tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); ! 629: ! 630: switch (opc) { ! 631: case 0|4: ! 632: tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); ! 633: break; ! 634: case 1|4: ! 635: tcg_out32 (s, EXTSH | RA (data_reg) | RS (3)); ! 636: break; ! 637: case 2|4: ! 638: tcg_out32 (s, EXTSW | RA (data_reg) | RS (3)); ! 639: break; ! 640: case 0: ! 641: case 1: ! 642: case 2: ! 643: case 3: ! 644: if (data_reg != 3) ! 645: tcg_out_mov (s, data_reg, 3); ! 646: break; ! 647: } ! 648: label2_ptr = s->code_ptr; ! 649: tcg_out32 (s, B); ! 650: ! 651: /* label1: fast path */ ! 652: #ifdef FAST_PATH ! 653: reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); ! 654: #endif ! 655: ! 656: /* r0 now contains &env->tlb_table[mem_index][index].addr_read */ ! 657: tcg_out32 (s, (LD_ADDEND ! 658: | RT (r0) ! 659: | RA (r0) ! 660: | (offsetof (CPUTLBEntry, addend) ! 661: - offsetof (CPUTLBEntry, addr_read)) ! 662: )); ! 663: /* r0 = env->tlb_table[mem_index][index].addend */ ! 664: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); ! 665: /* r0 = env->tlb_table[mem_index][index].addend + addr */ ! 666: ! 667: #else /* !CONFIG_SOFTMMU */ ! 668: #if TARGET_LONG_BITS == 32 ! 669: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); ! 670: #endif ! 671: r0 = addr_reg; ! 672: r1 = 3; ! 673: #endif ! 674: ! 675: #ifdef TARGET_WORDS_BIGENDIAN ! 676: bswap = 0; ! 677: #else ! 678: bswap = 1; ! 679: #endif ! 680: switch (opc) { ! 681: default: ! 682: case 0: ! 683: tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); ! 684: break; ! 685: case 0|4: ! 686: tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); ! 687: tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg)); ! 688: break; ! 689: case 1: ! 690: if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); ! 691: else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0)); ! 692: break; ! 693: case 1|4: ! 694: if (bswap) { ! 695: tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); ! 696: tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg)); ! 697: } ! 698: else tcg_out32 (s, LHA | RT (data_reg) | RA (r0)); ! 699: break; ! 700: case 2: ! 701: if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); ! 702: else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0)); ! 703: break; ! 704: case 2|4: ! 705: if (bswap) { ! 706: tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); ! 707: tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg)); ! 708: } ! 709: else tcg_out32 (s, LWA | RT (data_reg)| RA (r0)); ! 710: break; ! 711: case 3: ! 712: if (bswap) { ! 713: tcg_out_movi32 (s, 0, 4); ! 714: tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); ! 715: tcg_out32 (s, LWBRX | RT ( r1) | RA (r0)); ! 716: tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0); ! 717: } ! 718: else tcg_out32 (s, LD | RT (data_reg) | RA (r0)); ! 719: break; ! 720: } ! 721: ! 722: #ifdef CONFIG_SOFTMMU ! 723: reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); ! 724: #endif ! 725: } ! 726: ! 727: static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) ! 728: { ! 729: int addr_reg, r0, r1, data_reg, mem_index, bswap; ! 730: #ifdef CONFIG_SOFTMMU ! 731: int r2; ! 732: void *label1_ptr, *label2_ptr; ! 733: #endif ! 734: ! 735: data_reg = *args++; ! 736: addr_reg = *args++; ! 737: mem_index = *args; ! 738: ! 739: #ifdef CONFIG_SOFTMMU ! 740: r0 = 3; ! 741: r1 = 4; ! 742: r2 = 0; ! 743: ! 744: tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc, ! 745: offsetof (CPUState, tlb_table[mem_index][0].addr_write)); ! 746: ! 747: tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); ! 748: ! 749: label1_ptr = s->code_ptr; ! 750: #ifdef FAST_PATH ! 751: tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); ! 752: #endif ! 753: ! 754: /* slow path */ ! 755: tcg_out_mov (s, 3, addr_reg); ! 756: tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc))); ! 757: tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index); ! 758: ! 759: tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1); ! 760: ! 761: label2_ptr = s->code_ptr; ! 762: tcg_out32 (s, B); ! 763: ! 764: /* label1: fast path */ ! 765: #ifdef FAST_PATH ! 766: reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); ! 767: #endif ! 768: ! 769: tcg_out32 (s, (LD_ADDEND ! 770: | RT (r0) ! 771: | RA (r0) ! 772: | (offsetof (CPUTLBEntry, addend) ! 773: - offsetof (CPUTLBEntry, addr_write)) ! 774: )); ! 775: /* r0 = env->tlb_table[mem_index][index].addend */ ! 776: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); ! 777: /* r0 = env->tlb_table[mem_index][index].addend + addr */ ! 778: ! 779: #else /* !CONFIG_SOFTMMU */ ! 780: #if TARGET_LONG_BITS == 32 ! 781: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); ! 782: #endif ! 783: r1 = 3; ! 784: r0 = addr_reg; ! 785: #endif ! 786: ! 787: #ifdef TARGET_WORDS_BIGENDIAN ! 788: bswap = 0; ! 789: #else ! 790: bswap = 1; ! 791: #endif ! 792: switch (opc) { ! 793: case 0: ! 794: tcg_out32 (s, STB | RS (data_reg) | RA (r0)); ! 795: break; ! 796: case 1: ! 797: if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0)); ! 798: else tcg_out32 (s, STH | RS (data_reg) | RA (r0)); ! 799: break; ! 800: case 2: ! 801: if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); ! 802: else tcg_out32 (s, STW | RS (data_reg) | RA (r0)); ! 803: break; ! 804: case 3: ! 805: if (bswap) { ! 806: tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); ! 807: tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); ! 808: tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0); ! 809: tcg_out32 (s, STWBRX | RS (0) | RA (0) | RB (r1)); ! 810: } ! 811: else tcg_out32 (s, STD | RS (data_reg) | RA (r0)); ! 812: break; ! 813: } ! 814: ! 815: #ifdef CONFIG_SOFTMMU ! 816: reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); ! 817: #endif ! 818: } ! 819: ! 820: void tcg_target_qemu_prologue (TCGContext *s) ! 821: { ! 822: int i, frame_size; ! 823: uint64_t addr; ! 824: ! 825: frame_size = 0 ! 826: + 8 /* back chain */ ! 827: + 8 /* CR */ ! 828: + 8 /* LR */ ! 829: + 8 /* compiler doubleword */ ! 830: + 8 /* link editor doubleword */ ! 831: + 8 /* TOC save area */ ! 832: + TCG_STATIC_CALL_ARGS_SIZE ! 833: + ARRAY_SIZE (tcg_target_callee_save_regs) * 8 ! 834: ; ! 835: frame_size = (frame_size + 15) & ~15; ! 836: ! 837: /* First emit adhoc function descriptor */ ! 838: addr = (uint64_t) s->code_ptr + 24; ! 839: tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */ ! 840: s->code_ptr += 16; /* skip TOC and environment pointer */ ! 841: ! 842: /* Prologue */ ! 843: tcg_out32 (s, MFSPR | RT (0) | LR); ! 844: tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff)); ! 845: for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) ! 846: tcg_out32 (s, (STD ! 847: | RS (tcg_target_callee_save_regs[i]) ! 848: | RA (1) ! 849: | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) ! 850: ) ! 851: ); ! 852: tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16)); ! 853: ! 854: tcg_out32 (s, MTSPR | RS (3) | CTR); ! 855: tcg_out32 (s, BCCTR | BO_ALWAYS); ! 856: ! 857: /* Epilogue */ ! 858: tb_ret_addr = s->code_ptr; ! 859: ! 860: for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) ! 861: tcg_out32 (s, (LD ! 862: | RT (tcg_target_callee_save_regs[i]) ! 863: | RA (1) ! 864: | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) ! 865: ) ! 866: ); ! 867: tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16)); ! 868: tcg_out32 (s, MTSPR | RS (0) | LR); ! 869: tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); ! 870: tcg_out32 (s, BCLR | BO_ALWAYS); ! 871: } ! 872: ! 873: static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, ! 874: tcg_target_long arg2) ! 875: { ! 876: if (type == TCG_TYPE_I32) ! 877: tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); ! 878: else ! 879: tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX); ! 880: } ! 881: ! 882: static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1, ! 883: tcg_target_long arg2) ! 884: { ! 885: if (type == TCG_TYPE_I32) ! 886: tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); ! 887: else ! 888: tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX); ! 889: } ! 890: ! 891: static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si) ! 892: { ! 893: if (!si && rt == ra) ! 894: return; ! 895: ! 896: if (si == (int16_t) si) ! 897: tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff)); ! 898: else { ! 899: uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15); ! 900: tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h); ! 901: tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff)); ! 902: } ! 903: } ! 904: ! 905: static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si) ! 906: { ! 907: /* XXX: suboptimal */ ! 908: if (si == (int16_t) si ! 909: || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0)) ! 910: ppc_addi32 (s, rt, ra, si); ! 911: else { ! 912: tcg_out_movi (s, TCG_TYPE_I64, 0, si); ! 913: tcg_out32 (s, ADD | RT (rt) | RA (ra)); ! 914: } ! 915: } ! 916: ! 917: static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val) ! 918: { ! 919: ppc_addi64 (s, reg, reg, val); ! 920: } ! 921: ! 922: static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, ! 923: int const_arg2, int cr, int arch64) ! 924: { ! 925: int imm; ! 926: uint32_t op; ! 927: ! 928: switch (cond) { ! 929: case TCG_COND_EQ: ! 930: case TCG_COND_NE: ! 931: if (const_arg2) { ! 932: if ((int16_t) arg2 == arg2) { ! 933: op = CMPI; ! 934: imm = 1; ! 935: break; ! 936: } ! 937: else if ((uint16_t) arg2 == arg2) { ! 938: op = CMPLI; ! 939: imm = 1; ! 940: break; ! 941: } ! 942: } ! 943: op = CMPL; ! 944: imm = 0; ! 945: break; ! 946: ! 947: case TCG_COND_LT: ! 948: case TCG_COND_GE: ! 949: case TCG_COND_LE: ! 950: case TCG_COND_GT: ! 951: if (const_arg2) { ! 952: if ((int16_t) arg2 == arg2) { ! 953: op = CMPI; ! 954: imm = 1; ! 955: break; ! 956: } ! 957: } ! 958: op = CMP; ! 959: imm = 0; ! 960: break; ! 961: ! 962: case TCG_COND_LTU: ! 963: case TCG_COND_GEU: ! 964: case TCG_COND_LEU: ! 965: case TCG_COND_GTU: ! 966: if (const_arg2) { ! 967: if ((uint16_t) arg2 == arg2) { ! 968: op = CMPLI; ! 969: imm = 1; ! 970: break; ! 971: } ! 972: } ! 973: op = CMPL; ! 974: imm = 0; ! 975: break; ! 976: ! 977: default: ! 978: tcg_abort (); ! 979: } ! 980: op |= BF (cr) | (arch64 << 21); ! 981: ! 982: if (imm) ! 983: tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); ! 984: else { ! 985: if (const_arg2) { ! 986: tcg_out_movi (s, TCG_TYPE_I64, 0, arg2); ! 987: tcg_out32 (s, op | RA (arg1) | RB (0)); ! 988: } ! 989: else ! 990: tcg_out32 (s, op | RA (arg1) | RB (arg2)); ! 991: } ! 992: ! 993: } ! 994: ! 995: static void tcg_out_bc (TCGContext *s, int bc, int label_index) ! 996: { ! 997: TCGLabel *l = &s->labels[label_index]; ! 998: ! 999: if (l->has_value) ! 1000: tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value)); ! 1001: else { ! 1002: uint16_t val = *(uint16_t *) &s->code_ptr[2]; ! 1003: ! 1004: /* Thanks to Andrzej Zaborowski */ ! 1005: tcg_out32 (s, bc | (val & 0xfffc)); ! 1006: tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); ! 1007: } ! 1008: } ! 1009: ! 1010: static void tcg_out_brcond (TCGContext *s, int cond, ! 1011: TCGArg arg1, TCGArg arg2, int const_arg2, ! 1012: int label_index, int arch64) ! 1013: { ! 1014: tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64); ! 1015: tcg_out_bc (s, tcg_to_bc[cond], label_index); ! 1016: } ! 1017: ! 1018: void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr) ! 1019: { ! 1020: TCGContext s; ! 1021: unsigned long patch_size; ! 1022: ! 1023: s.code_ptr = (uint8_t *) jmp_addr; ! 1024: tcg_out_b (&s, 0, addr); ! 1025: patch_size = s.code_ptr - (uint8_t *) jmp_addr; ! 1026: flush_icache_range (jmp_addr, jmp_addr + patch_size); ! 1027: } ! 1028: ! 1029: static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args, ! 1030: const int *const_args) ! 1031: { ! 1032: int c; ! 1033: ! 1034: switch (opc) { ! 1035: case INDEX_op_exit_tb: ! 1036: tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]); ! 1037: tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr); ! 1038: break; ! 1039: case INDEX_op_goto_tb: ! 1040: if (s->tb_jmp_offset) { ! 1041: /* direct jump method */ ! 1042: ! 1043: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; ! 1044: s->code_ptr += 28; ! 1045: } ! 1046: else { ! 1047: tcg_abort (); ! 1048: } ! 1049: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ! 1050: break; ! 1051: case INDEX_op_br: ! 1052: { ! 1053: TCGLabel *l = &s->labels[args[0]]; ! 1054: ! 1055: if (l->has_value) { ! 1056: tcg_out_b (s, 0, l->u.value); ! 1057: } ! 1058: else { ! 1059: uint32_t val = *(uint32_t *) s->code_ptr; ! 1060: ! 1061: /* Thanks to Andrzej Zaborowski */ ! 1062: tcg_out32 (s, B | (val & 0x3fffffc)); ! 1063: tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0); ! 1064: } ! 1065: } ! 1066: break; ! 1067: case INDEX_op_call: ! 1068: tcg_out_call (s, args[0], const_args[0]); ! 1069: break; ! 1070: case INDEX_op_jmp: ! 1071: if (const_args[0]) { ! 1072: tcg_out_b (s, 0, args[0]); ! 1073: } ! 1074: else { ! 1075: tcg_out32 (s, MTSPR | RS (args[0]) | CTR); ! 1076: tcg_out32 (s, BCCTR | BO_ALWAYS); ! 1077: } ! 1078: break; ! 1079: case INDEX_op_movi_i32: ! 1080: tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]); ! 1081: break; ! 1082: case INDEX_op_movi_i64: ! 1083: tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]); ! 1084: break; ! 1085: case INDEX_op_ld8u_i32: ! 1086: case INDEX_op_ld8u_i64: ! 1087: tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); ! 1088: break; ! 1089: case INDEX_op_ld8s_i32: ! 1090: case INDEX_op_ld8s_i64: ! 1091: tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); ! 1092: tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0])); ! 1093: break; ! 1094: case INDEX_op_ld16u_i32: ! 1095: case INDEX_op_ld16u_i64: ! 1096: tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX); ! 1097: break; ! 1098: case INDEX_op_ld16s_i32: ! 1099: case INDEX_op_ld16s_i64: ! 1100: tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX); ! 1101: break; ! 1102: case INDEX_op_ld_i32: ! 1103: case INDEX_op_ld32u_i64: ! 1104: tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX); ! 1105: break; ! 1106: case INDEX_op_ld32s_i64: ! 1107: tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX); ! 1108: break; ! 1109: case INDEX_op_ld_i64: ! 1110: tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX); ! 1111: break; ! 1112: case INDEX_op_st8_i32: ! 1113: case INDEX_op_st8_i64: ! 1114: tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX); ! 1115: break; ! 1116: case INDEX_op_st16_i32: ! 1117: case INDEX_op_st16_i64: ! 1118: tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX); ! 1119: break; ! 1120: case INDEX_op_st_i32: ! 1121: case INDEX_op_st32_i64: ! 1122: tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX); ! 1123: break; ! 1124: case INDEX_op_st_i64: ! 1125: tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX); ! 1126: break; ! 1127: ! 1128: case INDEX_op_add_i32: ! 1129: if (const_args[2]) ! 1130: ppc_addi32 (s, args[0], args[1], args[2]); ! 1131: else ! 1132: tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); ! 1133: break; ! 1134: case INDEX_op_sub_i32: ! 1135: if (const_args[2]) ! 1136: ppc_addi32 (s, args[0], args[1], -args[2]); ! 1137: else ! 1138: tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); ! 1139: break; ! 1140: ! 1141: case INDEX_op_and_i64: ! 1142: case INDEX_op_and_i32: ! 1143: if (const_args[2]) { ! 1144: if ((args[2] & 0xffff) == args[2]) ! 1145: tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]); ! 1146: else if ((args[2] & 0xffff0000) == args[2]) ! 1147: tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0]) ! 1148: | ((args[2] >> 16) & 0xffff)); ! 1149: else { ! 1150: tcg_out_movi (s, (opc == INDEX_op_and_i32 ! 1151: ? TCG_TYPE_I32 ! 1152: : TCG_TYPE_I64), ! 1153: 0, args[2]); ! 1154: tcg_out32 (s, AND | SAB (args[1], args[0], 0)); ! 1155: } ! 1156: } ! 1157: else ! 1158: tcg_out32 (s, AND | SAB (args[1], args[0], args[2])); ! 1159: break; ! 1160: case INDEX_op_or_i64: ! 1161: case INDEX_op_or_i32: ! 1162: if (const_args[2]) { ! 1163: if (args[2] & 0xffff) { ! 1164: tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) ! 1165: | (args[2] & 0xffff)); ! 1166: if (args[2] >> 16) ! 1167: tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) ! 1168: | ((args[2] >> 16) & 0xffff)); ! 1169: } ! 1170: else { ! 1171: tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0]) ! 1172: | ((args[2] >> 16) & 0xffff)); ! 1173: } ! 1174: } ! 1175: else ! 1176: tcg_out32 (s, OR | SAB (args[1], args[0], args[2])); ! 1177: break; ! 1178: case INDEX_op_xor_i64: ! 1179: case INDEX_op_xor_i32: ! 1180: if (const_args[2]) { ! 1181: if ((args[2] & 0xffff) == args[2]) ! 1182: tcg_out32 (s, XORI | RS (args[1]) | RA (args[0]) ! 1183: | (args[2] & 0xffff)); ! 1184: else if ((args[2] & 0xffff0000) == args[2]) ! 1185: tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0]) ! 1186: | ((args[2] >> 16) & 0xffff)); ! 1187: else { ! 1188: tcg_out_movi (s, (opc == INDEX_op_and_i32 ! 1189: ? TCG_TYPE_I32 ! 1190: : TCG_TYPE_I64), ! 1191: 0, args[2]); ! 1192: tcg_out32 (s, XOR | SAB (args[1], args[0], 0)); ! 1193: } ! 1194: } ! 1195: else ! 1196: tcg_out32 (s, XOR | SAB (args[1], args[0], args[2])); ! 1197: break; ! 1198: ! 1199: case INDEX_op_mul_i32: ! 1200: if (const_args[2]) { ! 1201: if (args[2] == (int16_t) args[2]) ! 1202: tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1]) ! 1203: | (args[2] & 0xffff)); ! 1204: else { ! 1205: tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]); ! 1206: tcg_out32 (s, MULLW | TAB (args[0], args[1], 0)); ! 1207: } ! 1208: } ! 1209: else ! 1210: tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2])); ! 1211: break; ! 1212: ! 1213: case INDEX_op_div_i32: ! 1214: tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2])); ! 1215: break; ! 1216: ! 1217: case INDEX_op_divu_i32: ! 1218: tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2])); ! 1219: break; ! 1220: ! 1221: case INDEX_op_rem_i32: ! 1222: tcg_out32 (s, DIVW | TAB (0, args[1], args[2])); ! 1223: tcg_out32 (s, MULLW | TAB (0, 0, args[2])); ! 1224: tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); ! 1225: break; ! 1226: ! 1227: case INDEX_op_remu_i32: ! 1228: tcg_out32 (s, DIVWU | TAB (0, args[1], args[2])); ! 1229: tcg_out32 (s, MULLW | TAB (0, 0, args[2])); ! 1230: tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); ! 1231: break; ! 1232: ! 1233: case INDEX_op_shl_i32: ! 1234: if (const_args[2]) { ! 1235: tcg_out32 (s, (RLWINM ! 1236: | RA (args[0]) ! 1237: | RS (args[1]) ! 1238: | SH (args[2]) ! 1239: | MB (0) ! 1240: | ME (31 - args[2]) ! 1241: ) ! 1242: ); ! 1243: } ! 1244: else ! 1245: tcg_out32 (s, SLW | SAB (args[1], args[0], args[2])); ! 1246: break; ! 1247: case INDEX_op_shr_i32: ! 1248: if (const_args[2]) { ! 1249: tcg_out32 (s, (RLWINM ! 1250: | RA (args[0]) ! 1251: | RS (args[1]) ! 1252: | SH (32 - args[2]) ! 1253: | MB (args[2]) ! 1254: | ME (31) ! 1255: ) ! 1256: ); ! 1257: } ! 1258: else ! 1259: tcg_out32 (s, SRW | SAB (args[1], args[0], args[2])); ! 1260: break; ! 1261: case INDEX_op_sar_i32: ! 1262: if (const_args[2]) ! 1263: tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2])); ! 1264: else ! 1265: tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2])); ! 1266: break; ! 1267: ! 1268: case INDEX_op_brcond_i32: ! 1269: tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0); ! 1270: break; ! 1271: ! 1272: case INDEX_op_brcond_i64: ! 1273: tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1); ! 1274: break; ! 1275: ! 1276: case INDEX_op_neg_i32: ! 1277: case INDEX_op_neg_i64: ! 1278: tcg_out32 (s, NEG | RT (args[0]) | RA (args[1])); ! 1279: break; ! 1280: ! 1281: case INDEX_op_add_i64: ! 1282: if (const_args[2]) ! 1283: ppc_addi64 (s, args[0], args[1], args[2]); ! 1284: else ! 1285: tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); ! 1286: break; ! 1287: case INDEX_op_sub_i64: ! 1288: if (const_args[2]) ! 1289: ppc_addi64 (s, args[0], args[1], -args[2]); ! 1290: else ! 1291: tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); ! 1292: break; ! 1293: ! 1294: case INDEX_op_shl_i64: ! 1295: if (const_args[2]) ! 1296: tcg_out_rld (s, RLDICR, args[0], args[1], args[2], 63 - args[2]); ! 1297: else ! 1298: tcg_out32 (s, SLD | SAB (args[1], args[0], args[2])); ! 1299: break; ! 1300: case INDEX_op_shr_i64: ! 1301: if (const_args[2]) ! 1302: tcg_out_rld (s, RLDICL, args[0], args[1], 64 - args[2], args[2]); ! 1303: else ! 1304: tcg_out32 (s, SRD | SAB (args[1], args[0], args[2])); ! 1305: break; ! 1306: case INDEX_op_sar_i64: ! 1307: if (const_args[2]) { ! 1308: int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1); ! 1309: tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh); ! 1310: } ! 1311: else ! 1312: tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2])); ! 1313: break; ! 1314: ! 1315: case INDEX_op_mul_i64: ! 1316: tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2])); ! 1317: break; ! 1318: case INDEX_op_div_i64: ! 1319: tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2])); ! 1320: break; ! 1321: case INDEX_op_divu_i64: ! 1322: tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2])); ! 1323: break; ! 1324: case INDEX_op_rem_i64: ! 1325: tcg_out32 (s, DIVD | TAB (0, args[1], args[2])); ! 1326: tcg_out32 (s, MULLD | TAB (0, 0, args[2])); ! 1327: tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); ! 1328: break; ! 1329: case INDEX_op_remu_i64: ! 1330: tcg_out32 (s, DIVDU | TAB (0, args[1], args[2])); ! 1331: tcg_out32 (s, MULLD | TAB (0, 0, args[2])); ! 1332: tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); ! 1333: break; ! 1334: ! 1335: case INDEX_op_qemu_ld8u: ! 1336: tcg_out_qemu_ld (s, args, 0); ! 1337: break; ! 1338: case INDEX_op_qemu_ld8s: ! 1339: tcg_out_qemu_ld (s, args, 0 | 4); ! 1340: break; ! 1341: case INDEX_op_qemu_ld16u: ! 1342: tcg_out_qemu_ld (s, args, 1); ! 1343: break; ! 1344: case INDEX_op_qemu_ld16s: ! 1345: tcg_out_qemu_ld (s, args, 1 | 4); ! 1346: break; ! 1347: case INDEX_op_qemu_ld32u: ! 1348: tcg_out_qemu_ld (s, args, 2); ! 1349: break; ! 1350: case INDEX_op_qemu_ld32s: ! 1351: tcg_out_qemu_ld (s, args, 2 | 4); ! 1352: break; ! 1353: case INDEX_op_qemu_ld64: ! 1354: tcg_out_qemu_ld (s, args, 3); ! 1355: break; ! 1356: case INDEX_op_qemu_st8: ! 1357: tcg_out_qemu_st (s, args, 0); ! 1358: break; ! 1359: case INDEX_op_qemu_st16: ! 1360: tcg_out_qemu_st (s, args, 1); ! 1361: break; ! 1362: case INDEX_op_qemu_st32: ! 1363: tcg_out_qemu_st (s, args, 2); ! 1364: break; ! 1365: case INDEX_op_qemu_st64: ! 1366: tcg_out_qemu_st (s, args, 3); ! 1367: break; ! 1368: ! 1369: case INDEX_op_ext8s_i32: ! 1370: case INDEX_op_ext8s_i64: ! 1371: c = EXTSB; ! 1372: goto gen_ext; ! 1373: case INDEX_op_ext16s_i32: ! 1374: case INDEX_op_ext16s_i64: ! 1375: c = EXTSH; ! 1376: goto gen_ext; ! 1377: case INDEX_op_ext32s_i64: ! 1378: c = EXTSW; ! 1379: goto gen_ext; ! 1380: gen_ext: ! 1381: tcg_out32 (s, c | RS (args[1]) | RA (args[0])); ! 1382: break; ! 1383: ! 1384: default: ! 1385: tcg_dump_ops (s, stderr); ! 1386: tcg_abort (); ! 1387: } ! 1388: } ! 1389: ! 1390: static const TCGTargetOpDef ppc_op_defs[] = { ! 1391: { INDEX_op_exit_tb, { } }, ! 1392: { INDEX_op_goto_tb, { } }, ! 1393: { INDEX_op_call, { "ri" } }, ! 1394: { INDEX_op_jmp, { "ri" } }, ! 1395: { INDEX_op_br, { } }, ! 1396: ! 1397: { INDEX_op_mov_i32, { "r", "r" } }, ! 1398: { INDEX_op_mov_i64, { "r", "r" } }, ! 1399: { INDEX_op_movi_i32, { "r" } }, ! 1400: { INDEX_op_movi_i64, { "r" } }, ! 1401: ! 1402: { INDEX_op_ld8u_i32, { "r", "r" } }, ! 1403: { INDEX_op_ld8s_i32, { "r", "r" } }, ! 1404: { INDEX_op_ld16u_i32, { "r", "r" } }, ! 1405: { INDEX_op_ld16s_i32, { "r", "r" } }, ! 1406: { INDEX_op_ld_i32, { "r", "r" } }, ! 1407: { INDEX_op_ld_i64, { "r", "r" } }, ! 1408: { INDEX_op_st8_i32, { "r", "r" } }, ! 1409: { INDEX_op_st8_i64, { "r", "r" } }, ! 1410: { INDEX_op_st16_i32, { "r", "r" } }, ! 1411: { INDEX_op_st16_i64, { "r", "r" } }, ! 1412: { INDEX_op_st_i32, { "r", "r" } }, ! 1413: { INDEX_op_st_i64, { "r", "r" } }, ! 1414: { INDEX_op_st32_i64, { "r", "r" } }, ! 1415: ! 1416: { INDEX_op_ld8u_i64, { "r", "r" } }, ! 1417: { INDEX_op_ld8s_i64, { "r", "r" } }, ! 1418: { INDEX_op_ld16u_i64, { "r", "r" } }, ! 1419: { INDEX_op_ld16s_i64, { "r", "r" } }, ! 1420: { INDEX_op_ld32u_i64, { "r", "r" } }, ! 1421: { INDEX_op_ld32s_i64, { "r", "r" } }, ! 1422: { INDEX_op_ld_i64, { "r", "r" } }, ! 1423: ! 1424: { INDEX_op_add_i32, { "r", "r", "ri" } }, ! 1425: { INDEX_op_mul_i32, { "r", "r", "ri" } }, ! 1426: { INDEX_op_div_i32, { "r", "r", "r" } }, ! 1427: { INDEX_op_divu_i32, { "r", "r", "r" } }, ! 1428: { INDEX_op_rem_i32, { "r", "r", "r" } }, ! 1429: { INDEX_op_remu_i32, { "r", "r", "r" } }, ! 1430: { INDEX_op_sub_i32, { "r", "r", "ri" } }, ! 1431: { INDEX_op_and_i32, { "r", "r", "ri" } }, ! 1432: { INDEX_op_or_i32, { "r", "r", "ri" } }, ! 1433: { INDEX_op_xor_i32, { "r", "r", "ri" } }, ! 1434: ! 1435: { INDEX_op_shl_i32, { "r", "r", "ri" } }, ! 1436: { INDEX_op_shr_i32, { "r", "r", "ri" } }, ! 1437: { INDEX_op_sar_i32, { "r", "r", "ri" } }, ! 1438: ! 1439: { INDEX_op_brcond_i32, { "r", "ri" } }, ! 1440: { INDEX_op_brcond_i64, { "r", "ri" } }, ! 1441: ! 1442: { INDEX_op_neg_i32, { "r", "r" } }, ! 1443: ! 1444: { INDEX_op_add_i64, { "r", "r", "ri" } }, ! 1445: { INDEX_op_sub_i64, { "r", "r", "ri" } }, ! 1446: { INDEX_op_and_i64, { "r", "r", "rZ" } }, ! 1447: { INDEX_op_or_i64, { "r", "r", "rZ" } }, ! 1448: { INDEX_op_xor_i64, { "r", "r", "rZ" } }, ! 1449: ! 1450: { INDEX_op_shl_i64, { "r", "r", "ri" } }, ! 1451: { INDEX_op_shr_i64, { "r", "r", "ri" } }, ! 1452: { INDEX_op_sar_i64, { "r", "r", "ri" } }, ! 1453: ! 1454: { INDEX_op_mul_i64, { "r", "r", "r" } }, ! 1455: { INDEX_op_div_i64, { "r", "r", "r" } }, ! 1456: { INDEX_op_divu_i64, { "r", "r", "r" } }, ! 1457: { INDEX_op_rem_i64, { "r", "r", "r" } }, ! 1458: { INDEX_op_remu_i64, { "r", "r", "r" } }, ! 1459: ! 1460: { INDEX_op_neg_i64, { "r", "r" } }, ! 1461: ! 1462: { INDEX_op_qemu_ld8u, { "r", "L" } }, ! 1463: { INDEX_op_qemu_ld8s, { "r", "L" } }, ! 1464: { INDEX_op_qemu_ld16u, { "r", "L" } }, ! 1465: { INDEX_op_qemu_ld16s, { "r", "L" } }, ! 1466: { INDEX_op_qemu_ld32u, { "r", "L" } }, ! 1467: { INDEX_op_qemu_ld32s, { "r", "L" } }, ! 1468: { INDEX_op_qemu_ld64, { "r", "L" } }, ! 1469: ! 1470: { INDEX_op_qemu_st8, { "S", "S" } }, ! 1471: { INDEX_op_qemu_st16, { "S", "S" } }, ! 1472: { INDEX_op_qemu_st32, { "S", "S" } }, ! 1473: { INDEX_op_qemu_st64, { "S", "S", "S" } }, ! 1474: ! 1475: { INDEX_op_ext8s_i32, { "r", "r" } }, ! 1476: { INDEX_op_ext16s_i32, { "r", "r" } }, ! 1477: { INDEX_op_ext8s_i64, { "r", "r" } }, ! 1478: { INDEX_op_ext16s_i64, { "r", "r" } }, ! 1479: { INDEX_op_ext32s_i64, { "r", "r" } }, ! 1480: ! 1481: { -1 }, ! 1482: }; ! 1483: ! 1484: void tcg_target_init (TCGContext *s) ! 1485: { ! 1486: tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); ! 1487: tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); ! 1488: tcg_regset_set32 (tcg_target_call_clobber_regs, 0, ! 1489: (1 << TCG_REG_R0) | ! 1490: (1 << TCG_REG_R3) | ! 1491: (1 << TCG_REG_R4) | ! 1492: (1 << TCG_REG_R5) | ! 1493: (1 << TCG_REG_R6) | ! 1494: (1 << TCG_REG_R7) | ! 1495: (1 << TCG_REG_R8) | ! 1496: (1 << TCG_REG_R9) | ! 1497: (1 << TCG_REG_R10) | ! 1498: (1 << TCG_REG_R11) | ! 1499: (1 << TCG_REG_R12) ! 1500: ); ! 1501: ! 1502: tcg_regset_clear (s->reserved_regs); ! 1503: tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0); ! 1504: tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1); ! 1505: tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2); ! 1506: tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13); ! 1507: ! 1508: tcg_add_target_add_op_defs (ppc_op_defs); ! 1509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.