|
|
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: #ifndef NDEBUG ! 26: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ! 27: "%g0", ! 28: "%g1", ! 29: "%g2", ! 30: "%g3", ! 31: "%g4", ! 32: "%g5", ! 33: "%g6", ! 34: "%g7", ! 35: "%o0", ! 36: "%o1", ! 37: "%o2", ! 38: "%o3", ! 39: "%o4", ! 40: "%o5", ! 41: "%o6", ! 42: "%o7", ! 43: "%l0", ! 44: "%l1", ! 45: "%l2", ! 46: "%l3", ! 47: "%l4", ! 48: "%l5", ! 49: "%l6", ! 50: "%l7", ! 51: "%i0", ! 52: "%i1", ! 53: "%i2", ! 54: "%i3", ! 55: "%i4", ! 56: "%i5", ! 57: "%i6", ! 58: "%i7", ! 59: }; ! 60: #endif ! 61: ! 62: static const int tcg_target_reg_alloc_order[] = { ! 63: TCG_REG_L0, ! 64: TCG_REG_L1, ! 65: TCG_REG_L2, ! 66: TCG_REG_L3, ! 67: TCG_REG_L4, ! 68: TCG_REG_L5, ! 69: TCG_REG_L6, ! 70: TCG_REG_L7, ! 71: TCG_REG_I0, ! 72: TCG_REG_I1, ! 73: TCG_REG_I2, ! 74: TCG_REG_I3, ! 75: TCG_REG_I4, ! 76: }; ! 77: ! 78: static const int tcg_target_call_iarg_regs[6] = { ! 79: TCG_REG_O0, ! 80: TCG_REG_O1, ! 81: TCG_REG_O2, ! 82: TCG_REG_O3, ! 83: TCG_REG_O4, ! 84: TCG_REG_O5, ! 85: }; ! 86: ! 87: static const int tcg_target_call_oarg_regs[2] = { ! 88: TCG_REG_O0, ! 89: TCG_REG_O1, ! 90: }; ! 91: ! 92: static inline int check_fit_tl(tcg_target_long val, unsigned int bits) ! 93: { ! 94: return (val << ((sizeof(tcg_target_long) * 8 - bits)) ! 95: >> (sizeof(tcg_target_long) * 8 - bits)) == val; ! 96: } ! 97: ! 98: static inline int check_fit_i32(uint32_t val, unsigned int bits) ! 99: { ! 100: return ((val << (32 - bits)) >> (32 - bits)) == val; ! 101: } ! 102: ! 103: static void patch_reloc(uint8_t *code_ptr, int type, ! 104: tcg_target_long value, tcg_target_long addend) ! 105: { ! 106: value += addend; ! 107: switch (type) { ! 108: case R_SPARC_32: ! 109: if (value != (uint32_t)value) ! 110: tcg_abort(); ! 111: *(uint32_t *)code_ptr = value; ! 112: break; ! 113: case R_SPARC_WDISP22: ! 114: value -= (long)code_ptr; ! 115: value >>= 2; ! 116: if (!check_fit_tl(value, 22)) ! 117: tcg_abort(); ! 118: *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value; ! 119: break; ! 120: default: ! 121: tcg_abort(); ! 122: } ! 123: } ! 124: ! 125: /* maximum number of register used for input function arguments */ ! 126: static inline int tcg_target_get_call_iarg_regs_count(int flags) ! 127: { ! 128: return 6; ! 129: } ! 130: ! 131: /* parse target specific constraints */ ! 132: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ! 133: { ! 134: const char *ct_str; ! 135: ! 136: ct_str = *pct_str; ! 137: switch (ct_str[0]) { ! 138: case 'r': ! 139: case 'L': /* qemu_ld/st constraint */ ! 140: ct->ct |= TCG_CT_REG; ! 141: tcg_regset_set32(ct->u.regs, 0, 0xffffffff); ! 142: // Helper args ! 143: tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); ! 144: tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); ! 145: tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); ! 146: break; ! 147: case 'I': ! 148: ct->ct |= TCG_CT_CONST_S11; ! 149: break; ! 150: case 'J': ! 151: ct->ct |= TCG_CT_CONST_S13; ! 152: break; ! 153: default: ! 154: return -1; ! 155: } ! 156: ct_str++; ! 157: *pct_str = ct_str; ! 158: return 0; ! 159: } ! 160: ! 161: /* test if a constant matches the constraint */ ! 162: static inline int tcg_target_const_match(tcg_target_long val, ! 163: const TCGArgConstraint *arg_ct) ! 164: { ! 165: int ct; ! 166: ! 167: ct = arg_ct->ct; ! 168: if (ct & TCG_CT_CONST) ! 169: return 1; ! 170: else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) ! 171: return 1; ! 172: else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) ! 173: return 1; ! 174: else ! 175: return 0; ! 176: } ! 177: ! 178: #define INSN_OP(x) ((x) << 30) ! 179: #define INSN_OP2(x) ((x) << 22) ! 180: #define INSN_OP3(x) ((x) << 19) ! 181: #define INSN_OPF(x) ((x) << 5) ! 182: #define INSN_RD(x) ((x) << 25) ! 183: #define INSN_RS1(x) ((x) << 14) ! 184: #define INSN_RS2(x) (x) ! 185: #define INSN_ASI(x) ((x) << 5) ! 186: ! 187: #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) ! 188: #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) ! 189: ! 190: #define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) ! 191: #define COND_N 0x0 ! 192: #define COND_E 0x1 ! 193: #define COND_LE 0x2 ! 194: #define COND_L 0x3 ! 195: #define COND_LEU 0x4 ! 196: #define COND_CS 0x5 ! 197: #define COND_NEG 0x6 ! 198: #define COND_VS 0x7 ! 199: #define COND_A 0x8 ! 200: #define COND_NE 0x9 ! 201: #define COND_G 0xa ! 202: #define COND_GE 0xb ! 203: #define COND_GU 0xc ! 204: #define COND_CC 0xd ! 205: #define COND_POS 0xe ! 206: #define COND_VC 0xf ! 207: #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) ! 208: ! 209: #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) ! 210: #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) ! 211: #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) ! 212: #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12)) ! 213: #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) ! 214: #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04)) ! 215: #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14)) ! 216: #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) ! 217: #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) ! 218: #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) ! 219: #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e)) ! 220: #define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f)) ! 221: #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09)) ! 222: #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d)) ! 223: #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d)) ! 224: ! 225: #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25)) ! 226: #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26)) ! 227: #define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27)) ! 228: ! 229: #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12)) ! 230: #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12)) ! 231: #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12)) ! 232: ! 233: #define WRY (INSN_OP(2) | INSN_OP3(0x30)) ! 234: #define JMPL (INSN_OP(2) | INSN_OP3(0x38)) ! 235: #define SAVE (INSN_OP(2) | INSN_OP3(0x3c)) ! 236: #define RESTORE (INSN_OP(2) | INSN_OP3(0x3d)) ! 237: #define SETHI (INSN_OP(0) | INSN_OP2(0x4)) ! 238: #define CALL INSN_OP(1) ! 239: #define LDUB (INSN_OP(3) | INSN_OP3(0x01)) ! 240: #define LDSB (INSN_OP(3) | INSN_OP3(0x09)) ! 241: #define LDUH (INSN_OP(3) | INSN_OP3(0x02)) ! 242: #define LDSH (INSN_OP(3) | INSN_OP3(0x0a)) ! 243: #define LDUW (INSN_OP(3) | INSN_OP3(0x00)) ! 244: #define LDSW (INSN_OP(3) | INSN_OP3(0x08)) ! 245: #define LDX (INSN_OP(3) | INSN_OP3(0x0b)) ! 246: #define STB (INSN_OP(3) | INSN_OP3(0x05)) ! 247: #define STH (INSN_OP(3) | INSN_OP3(0x06)) ! 248: #define STW (INSN_OP(3) | INSN_OP3(0x04)) ! 249: #define STX (INSN_OP(3) | INSN_OP3(0x0e)) ! 250: #define LDUBA (INSN_OP(3) | INSN_OP3(0x11)) ! 251: #define LDSBA (INSN_OP(3) | INSN_OP3(0x19)) ! 252: #define LDUHA (INSN_OP(3) | INSN_OP3(0x12)) ! 253: #define LDSHA (INSN_OP(3) | INSN_OP3(0x1a)) ! 254: #define LDUWA (INSN_OP(3) | INSN_OP3(0x10)) ! 255: #define LDSWA (INSN_OP(3) | INSN_OP3(0x18)) ! 256: #define LDXA (INSN_OP(3) | INSN_OP3(0x1b)) ! 257: #define STBA (INSN_OP(3) | INSN_OP3(0x15)) ! 258: #define STHA (INSN_OP(3) | INSN_OP3(0x16)) ! 259: #define STWA (INSN_OP(3) | INSN_OP3(0x14)) ! 260: #define STXA (INSN_OP(3) | INSN_OP3(0x1e)) ! 261: ! 262: #ifndef ASI_PRIMARY_LITTLE ! 263: #define ASI_PRIMARY_LITTLE 0x88 ! 264: #endif ! 265: ! 266: static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2, ! 267: int op) ! 268: { ! 269: tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | ! 270: INSN_RS2(rs2)); ! 271: } ! 272: ! 273: static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1, ! 274: uint32_t offset, int op) ! 275: { ! 276: tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | ! 277: INSN_IMM13(offset)); ! 278: } ! 279: ! 280: static inline void tcg_out_mov(TCGContext *s, int ret, int arg) ! 281: { ! 282: tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); ! 283: } ! 284: ! 285: static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg) ! 286: { ! 287: tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10)); ! 288: } ! 289: ! 290: static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg) ! 291: { ! 292: tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR); ! 293: } ! 294: ! 295: static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg) ! 296: { ! 297: if (check_fit_tl(arg, 12)) ! 298: tcg_out_movi_imm13(s, ret, arg); ! 299: else { ! 300: tcg_out_sethi(s, ret, arg); ! 301: if (arg & 0x3ff) ! 302: tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR); ! 303: } ! 304: } ! 305: ! 306: static inline void tcg_out_movi(TCGContext *s, TCGType type, ! 307: int ret, tcg_target_long arg) ! 308: { ! 309: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 310: if (!check_fit_tl(arg, 32) && (arg & ~0xffffffffULL) != 0) { ! 311: tcg_out_movi_imm32(s, TCG_REG_I4, arg >> 32); ! 312: tcg_out_arithi(s, TCG_REG_I4, TCG_REG_I4, 32, SHIFT_SLLX); ! 313: tcg_out_movi_imm32(s, ret, arg); ! 314: tcg_out_arith(s, ret, ret, TCG_REG_I4, ARITH_OR); ! 315: } else if (check_fit_tl(arg, 12)) ! 316: tcg_out_movi_imm13(s, ret, arg); ! 317: else { ! 318: tcg_out_sethi(s, ret, arg); ! 319: if (arg & 0x3ff) ! 320: tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR); ! 321: } ! 322: #else ! 323: tcg_out_movi_imm32(s, ret, arg); ! 324: #endif ! 325: } ! 326: ! 327: static inline void tcg_out_ld_raw(TCGContext *s, int ret, ! 328: tcg_target_long arg) ! 329: { ! 330: tcg_out_sethi(s, ret, arg); ! 331: tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) | ! 332: INSN_IMM13(arg & 0x3ff)); ! 333: } ! 334: ! 335: static inline void tcg_out_ld_ptr(TCGContext *s, int ret, ! 336: tcg_target_long arg) ! 337: { ! 338: if (!check_fit_tl(arg, 10)) ! 339: tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL); ! 340: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 341: tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) | ! 342: INSN_IMM13(arg & 0x3ff)); ! 343: #else ! 344: tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) | ! 345: INSN_IMM13(arg & 0x3ff)); ! 346: #endif ! 347: } ! 348: ! 349: static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op) ! 350: { ! 351: if (check_fit_tl(offset, 13)) ! 352: tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | ! 353: INSN_IMM13(offset)); ! 354: else { ! 355: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); ! 356: tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) | ! 357: INSN_RS2(addr)); ! 358: } ! 359: } ! 360: ! 361: static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr, ! 362: int offset, int op, int asi) ! 363: { ! 364: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); ! 365: tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) | ! 366: INSN_ASI(asi) | INSN_RS2(addr)); ! 367: } ! 368: ! 369: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, ! 370: int arg1, tcg_target_long arg2) ! 371: { ! 372: if (type == TCG_TYPE_I32) ! 373: tcg_out_ldst(s, ret, arg1, arg2, LDUW); ! 374: else ! 375: tcg_out_ldst(s, ret, arg1, arg2, LDX); ! 376: } ! 377: ! 378: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, ! 379: int arg1, tcg_target_long arg2) ! 380: { ! 381: if (type == TCG_TYPE_I32) ! 382: tcg_out_ldst(s, arg, arg1, arg2, STW); ! 383: else ! 384: tcg_out_ldst(s, arg, arg1, arg2, STX); ! 385: } ! 386: ! 387: static inline void tcg_out_sety(TCGContext *s, tcg_target_long val) ! 388: { ! 389: if (val == 0 || val == -1) ! 390: tcg_out32(s, WRY | INSN_IMM13(val)); ! 391: else ! 392: fprintf(stderr, "unimplemented sety %ld\n", (long)val); ! 393: } ! 394: ! 395: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) ! 396: { ! 397: if (val != 0) { ! 398: if (check_fit_tl(val, 13)) ! 399: tcg_out_arithi(s, reg, reg, val, ARITH_ADD); ! 400: else { ! 401: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val); ! 402: tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD); ! 403: } ! 404: } ! 405: } ! 406: ! 407: static inline void tcg_out_andi(TCGContext *s, int reg, tcg_target_long val) ! 408: { ! 409: if (val != 0) { ! 410: if (check_fit_tl(val, 13)) ! 411: tcg_out_arithi(s, reg, reg, val, ARITH_AND); ! 412: else { ! 413: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, val); ! 414: tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_AND); ! 415: } ! 416: } ! 417: } ! 418: ! 419: static inline void tcg_out_nop(TCGContext *s) ! 420: { ! 421: tcg_out_sethi(s, TCG_REG_G0, 0); ! 422: } ! 423: ! 424: static void tcg_out_branch(TCGContext *s, int opc, int label_index) ! 425: { ! 426: int32_t val; ! 427: TCGLabel *l = &s->labels[label_index]; ! 428: ! 429: if (l->has_value) { ! 430: val = l->u.value - (tcg_target_long)s->code_ptr; ! 431: tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) ! 432: | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); ! 433: } else { ! 434: tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0); ! 435: tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0)); ! 436: } ! 437: } ! 438: ! 439: static const uint8_t tcg_cond_to_bcond[10] = { ! 440: [TCG_COND_EQ] = COND_E, ! 441: [TCG_COND_NE] = COND_NE, ! 442: [TCG_COND_LT] = COND_L, ! 443: [TCG_COND_GE] = COND_GE, ! 444: [TCG_COND_LE] = COND_LE, ! 445: [TCG_COND_GT] = COND_G, ! 446: [TCG_COND_LTU] = COND_CS, ! 447: [TCG_COND_GEU] = COND_CC, ! 448: [TCG_COND_LEU] = COND_LEU, ! 449: [TCG_COND_GTU] = COND_GU, ! 450: }; ! 451: ! 452: static void tcg_out_brcond(TCGContext *s, int cond, ! 453: TCGArg arg1, TCGArg arg2, int const_arg2, ! 454: int label_index) ! 455: { ! 456: if (const_arg2 && arg2 == 0) ! 457: /* orcc %g0, r, %g0 */ ! 458: tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC); ! 459: else ! 460: /* subcc r1, r2, %g0 */ ! 461: tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC); ! 462: tcg_out_branch(s, tcg_cond_to_bcond[cond], label_index); ! 463: tcg_out_nop(s); ! 464: } ! 465: ! 466: /* Generate global QEMU prologue and epilogue code */ ! 467: void tcg_target_qemu_prologue(TCGContext *s) ! 468: { ! 469: tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | ! 470: INSN_IMM13(-TCG_TARGET_STACK_MINFRAME)); ! 471: tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) | ! 472: INSN_RS2(TCG_REG_G0)); ! 473: tcg_out_nop(s); ! 474: } ! 475: ! 476: #if defined(CONFIG_SOFTMMU) ! 477: ! 478: #include "../../softmmu_defs.h" ! 479: ! 480: static const void * const qemu_ld_helpers[4] = { ! 481: __ldb_mmu, ! 482: __ldw_mmu, ! 483: __ldl_mmu, ! 484: __ldq_mmu, ! 485: }; ! 486: ! 487: static const void * const qemu_st_helpers[4] = { ! 488: __stb_mmu, ! 489: __stw_mmu, ! 490: __stl_mmu, ! 491: __stq_mmu, ! 492: }; ! 493: #endif ! 494: ! 495: #if TARGET_LONG_BITS == 32 ! 496: #define TARGET_LD_OP LDUW ! 497: #else ! 498: #define TARGET_LD_OP LDX ! 499: #endif ! 500: ! 501: #if TARGET_PHYS_ADDR_BITS == 32 ! 502: #define TARGET_ADDEND_LD_OP LDUW ! 503: #else ! 504: #define TARGET_ADDEND_LD_OP LDX ! 505: #endif ! 506: ! 507: #ifdef __arch64__ ! 508: #define HOST_LD_OP LDX ! 509: #define HOST_ST_OP STX ! 510: #define HOST_SLL_OP SHIFT_SLLX ! 511: #define HOST_SRA_OP SHIFT_SRAX ! 512: #else ! 513: #define HOST_LD_OP LDUW ! 514: #define HOST_ST_OP STW ! 515: #define HOST_SLL_OP SHIFT_SLL ! 516: #define HOST_SRA_OP SHIFT_SRA ! 517: #endif ! 518: ! 519: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, ! 520: int opc) ! 521: { ! 522: int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; ! 523: #if defined(CONFIG_SOFTMMU) ! 524: uint32_t *label1_ptr, *label2_ptr; ! 525: #endif ! 526: ! 527: data_reg = *args++; ! 528: addr_reg = *args++; ! 529: mem_index = *args; ! 530: s_bits = opc & 3; ! 531: ! 532: arg0 = TCG_REG_O0; ! 533: arg1 = TCG_REG_O1; ! 534: arg2 = TCG_REG_O2; ! 535: ! 536: #if defined(CONFIG_SOFTMMU) ! 537: /* srl addr_reg, x, arg1 */ ! 538: tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, ! 539: SHIFT_SRL); ! 540: /* and addr_reg, x, arg0 */ ! 541: tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), ! 542: ARITH_AND); ! 543: ! 544: /* and arg1, x, arg1 */ ! 545: tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ! 546: ! 547: /* add arg1, x, arg1 */ ! 548: tcg_out_addi(s, arg1, offsetof(CPUState, ! 549: tlb_table[mem_index][0].addr_read)); ! 550: ! 551: /* add env, arg1, arg1 */ ! 552: tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); ! 553: ! 554: /* ld [arg1], arg2 */ ! 555: tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) | ! 556: INSN_RS2(TCG_REG_G0)); ! 557: ! 558: /* subcc arg0, arg2, %g0 */ ! 559: tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC); ! 560: ! 561: /* will become: ! 562: be label1 */ ! 563: label1_ptr = (uint32_t *)s->code_ptr; ! 564: tcg_out32(s, 0); ! 565: ! 566: /* mov (delay slot) */ ! 567: tcg_out_mov(s, arg0, addr_reg); ! 568: ! 569: /* mov */ ! 570: tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); ! 571: ! 572: /* XXX: move that code at the end of the TB */ ! 573: /* qemu_ld_helper[s_bits](arg0, arg1) */ ! 574: tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits] ! 575: - (tcg_target_ulong)s->code_ptr) >> 2) ! 576: & 0x3fffffff)); ! 577: /* Store AREG0 in stack to avoid ugly glibc bugs that mangle ! 578: global registers */ ! 579: // delay slot ! 580: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 581: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP); ! 582: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 583: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP); ! 584: ! 585: /* data_reg = sign_extend(arg0) */ ! 586: switch(opc) { ! 587: case 0 | 4: ! 588: /* sll arg0, 24/56, data_reg */ ! 589: tcg_out_arithi(s, data_reg, arg0, (int)sizeof(tcg_target_long) * 8 - 8, ! 590: HOST_SLL_OP); ! 591: /* sra data_reg, 24/56, data_reg */ ! 592: tcg_out_arithi(s, data_reg, data_reg, ! 593: (int)sizeof(tcg_target_long) * 8 - 8, HOST_SRA_OP); ! 594: break; ! 595: case 1 | 4: ! 596: /* sll arg0, 16/48, data_reg */ ! 597: tcg_out_arithi(s, data_reg, arg0, ! 598: (int)sizeof(tcg_target_long) * 8 - 16, HOST_SLL_OP); ! 599: /* sra data_reg, 16/48, data_reg */ ! 600: tcg_out_arithi(s, data_reg, data_reg, ! 601: (int)sizeof(tcg_target_long) * 8 - 16, HOST_SRA_OP); ! 602: break; ! 603: case 2 | 4: ! 604: /* sll arg0, 32, data_reg */ ! 605: tcg_out_arithi(s, data_reg, arg0, 32, HOST_SLL_OP); ! 606: /* sra data_reg, 32, data_reg */ ! 607: tcg_out_arithi(s, data_reg, data_reg, 32, HOST_SRA_OP); ! 608: break; ! 609: case 0: ! 610: case 1: ! 611: case 2: ! 612: case 3: ! 613: default: ! 614: /* mov */ ! 615: tcg_out_mov(s, data_reg, arg0); ! 616: break; ! 617: } ! 618: ! 619: /* will become: ! 620: ba label2 */ ! 621: label2_ptr = (uint32_t *)s->code_ptr; ! 622: tcg_out32(s, 0); ! 623: ! 624: /* nop (delay slot */ ! 625: tcg_out_nop(s); ! 626: ! 627: /* label1: */ ! 628: *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) | ! 629: INSN_OFF22((unsigned long)s->code_ptr - ! 630: (unsigned long)label1_ptr)); ! 631: ! 632: /* ld [arg1 + x], arg1 */ ! 633: tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - ! 634: offsetof(CPUTLBEntry, addr_read), TARGET_ADDEND_LD_OP); ! 635: ! 636: #if TARGET_LONG_BITS == 32 ! 637: /* and addr_reg, x, arg0 */ ! 638: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff); ! 639: tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND); ! 640: /* add arg0, arg1, arg0 */ ! 641: tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD); ! 642: #else ! 643: /* add addr_reg, arg1, arg0 */ ! 644: tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); ! 645: #endif ! 646: ! 647: #else ! 648: arg0 = addr_reg; ! 649: #endif ! 650: ! 651: switch(opc) { ! 652: case 0: ! 653: /* ldub [arg0], data_reg */ ! 654: tcg_out_ldst(s, data_reg, arg0, 0, LDUB); ! 655: break; ! 656: case 0 | 4: ! 657: /* ldsb [arg0], data_reg */ ! 658: tcg_out_ldst(s, data_reg, arg0, 0, LDSB); ! 659: break; ! 660: case 1: ! 661: #ifdef TARGET_WORDS_BIGENDIAN ! 662: /* lduh [arg0], data_reg */ ! 663: tcg_out_ldst(s, data_reg, arg0, 0, LDUH); ! 664: #else ! 665: /* lduha [arg0] ASI_PRIMARY_LITTLE, data_reg */ ! 666: tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUHA, ASI_PRIMARY_LITTLE); ! 667: #endif ! 668: break; ! 669: case 1 | 4: ! 670: #ifdef TARGET_WORDS_BIGENDIAN ! 671: /* ldsh [arg0], data_reg */ ! 672: tcg_out_ldst(s, data_reg, arg0, 0, LDSH); ! 673: #else ! 674: /* ldsha [arg0] ASI_PRIMARY_LITTLE, data_reg */ ! 675: tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSHA, ASI_PRIMARY_LITTLE); ! 676: #endif ! 677: break; ! 678: case 2: ! 679: #ifdef TARGET_WORDS_BIGENDIAN ! 680: /* lduw [arg0], data_reg */ ! 681: tcg_out_ldst(s, data_reg, arg0, 0, LDUW); ! 682: #else ! 683: /* lduwa [arg0] ASI_PRIMARY_LITTLE, data_reg */ ! 684: tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUWA, ASI_PRIMARY_LITTLE); ! 685: #endif ! 686: break; ! 687: case 2 | 4: ! 688: #ifdef TARGET_WORDS_BIGENDIAN ! 689: /* ldsw [arg0], data_reg */ ! 690: tcg_out_ldst(s, data_reg, arg0, 0, LDSW); ! 691: #else ! 692: /* ldswa [arg0] ASI_PRIMARY_LITTLE, data_reg */ ! 693: tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSWA, ASI_PRIMARY_LITTLE); ! 694: #endif ! 695: break; ! 696: case 3: ! 697: #ifdef TARGET_WORDS_BIGENDIAN ! 698: /* ldx [arg0], data_reg */ ! 699: tcg_out_ldst(s, data_reg, arg0, 0, LDX); ! 700: #else ! 701: /* ldxa [arg0] ASI_PRIMARY_LITTLE, data_reg */ ! 702: tcg_out_ldst_asi(s, data_reg, arg0, 0, LDXA, ASI_PRIMARY_LITTLE); ! 703: #endif ! 704: break; ! 705: default: ! 706: tcg_abort(); ! 707: } ! 708: ! 709: #if defined(CONFIG_SOFTMMU) ! 710: /* label2: */ ! 711: *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) | ! 712: INSN_OFF22((unsigned long)s->code_ptr - ! 713: (unsigned long)label2_ptr)); ! 714: #endif ! 715: } ! 716: ! 717: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, ! 718: int opc) ! 719: { ! 720: int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; ! 721: #if defined(CONFIG_SOFTMMU) ! 722: uint32_t *label1_ptr, *label2_ptr; ! 723: #endif ! 724: ! 725: data_reg = *args++; ! 726: addr_reg = *args++; ! 727: mem_index = *args; ! 728: ! 729: s_bits = opc; ! 730: ! 731: arg0 = TCG_REG_O0; ! 732: arg1 = TCG_REG_O1; ! 733: arg2 = TCG_REG_O2; ! 734: ! 735: #if defined(CONFIG_SOFTMMU) ! 736: /* srl addr_reg, x, arg1 */ ! 737: tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, ! 738: SHIFT_SRL); ! 739: ! 740: /* and addr_reg, x, arg0 */ ! 741: tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), ! 742: ARITH_AND); ! 743: ! 744: /* and arg1, x, arg1 */ ! 745: tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ! 746: ! 747: /* add arg1, x, arg1 */ ! 748: tcg_out_addi(s, arg1, offsetof(CPUState, ! 749: tlb_table[mem_index][0].addr_write)); ! 750: ! 751: /* add env, arg1, arg1 */ ! 752: tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); ! 753: ! 754: /* ld [arg1], arg2 */ ! 755: tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) | ! 756: INSN_RS2(TCG_REG_G0)); ! 757: ! 758: /* subcc arg0, arg2, %g0 */ ! 759: tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC); ! 760: ! 761: /* will become: ! 762: be label1 */ ! 763: label1_ptr = (uint32_t *)s->code_ptr; ! 764: tcg_out32(s, 0); ! 765: ! 766: /* mov (delay slot) */ ! 767: tcg_out_mov(s, arg0, addr_reg); ! 768: ! 769: /* mov */ ! 770: tcg_out_mov(s, arg1, data_reg); ! 771: ! 772: /* mov */ ! 773: tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); ! 774: ! 775: /* XXX: move that code at the end of the TB */ ! 776: /* qemu_st_helper[s_bits](arg0, arg1, arg2) */ ! 777: tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits] ! 778: - (tcg_target_ulong)s->code_ptr) >> 2) ! 779: & 0x3fffffff)); ! 780: /* Store AREG0 in stack to avoid ugly glibc bugs that mangle ! 781: global registers */ ! 782: // delay slot ! 783: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 784: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP); ! 785: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 786: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP); ! 787: ! 788: /* will become: ! 789: ba label2 */ ! 790: label2_ptr = (uint32_t *)s->code_ptr; ! 791: tcg_out32(s, 0); ! 792: ! 793: /* nop (delay slot) */ ! 794: tcg_out_nop(s); ! 795: ! 796: /* label1: */ ! 797: *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) | ! 798: INSN_OFF22((unsigned long)s->code_ptr - ! 799: (unsigned long)label1_ptr)); ! 800: ! 801: /* ld [arg1 + x], arg1 */ ! 802: tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - ! 803: offsetof(CPUTLBEntry, addr_write), TARGET_ADDEND_LD_OP); ! 804: ! 805: #if TARGET_LONG_BITS == 32 ! 806: /* and addr_reg, x, arg0 */ ! 807: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff); ! 808: tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND); ! 809: /* add arg0, arg1, arg0 */ ! 810: tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD); ! 811: #else ! 812: /* add addr_reg, arg1, arg0 */ ! 813: tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); ! 814: #endif ! 815: ! 816: #else ! 817: arg0 = addr_reg; ! 818: #endif ! 819: ! 820: switch(opc) { ! 821: case 0: ! 822: /* stb data_reg, [arg0] */ ! 823: tcg_out_ldst(s, data_reg, arg0, 0, STB); ! 824: break; ! 825: case 1: ! 826: #ifdef TARGET_WORDS_BIGENDIAN ! 827: /* sth data_reg, [arg0] */ ! 828: tcg_out_ldst(s, data_reg, arg0, 0, STH); ! 829: #else ! 830: /* stha data_reg, [arg0] ASI_PRIMARY_LITTLE */ ! 831: tcg_out_ldst_asi(s, data_reg, arg0, 0, STHA, ASI_PRIMARY_LITTLE); ! 832: #endif ! 833: break; ! 834: case 2: ! 835: #ifdef TARGET_WORDS_BIGENDIAN ! 836: /* stw data_reg, [arg0] */ ! 837: tcg_out_ldst(s, data_reg, arg0, 0, STW); ! 838: #else ! 839: /* stwa data_reg, [arg0] ASI_PRIMARY_LITTLE */ ! 840: tcg_out_ldst_asi(s, data_reg, arg0, 0, STWA, ASI_PRIMARY_LITTLE); ! 841: #endif ! 842: break; ! 843: case 3: ! 844: #ifdef TARGET_WORDS_BIGENDIAN ! 845: /* stx data_reg, [arg0] */ ! 846: tcg_out_ldst(s, data_reg, arg0, 0, STX); ! 847: #else ! 848: /* stxa data_reg, [arg0] ASI_PRIMARY_LITTLE */ ! 849: tcg_out_ldst_asi(s, data_reg, arg0, 0, STXA, ASI_PRIMARY_LITTLE); ! 850: #endif ! 851: break; ! 852: default: ! 853: tcg_abort(); ! 854: } ! 855: ! 856: #if defined(CONFIG_SOFTMMU) ! 857: /* label2: */ ! 858: *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) | ! 859: INSN_OFF22((unsigned long)s->code_ptr - ! 860: (unsigned long)label2_ptr)); ! 861: #endif ! 862: } ! 863: ! 864: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, ! 865: const int *const_args) ! 866: { ! 867: int c; ! 868: ! 869: switch (opc) { ! 870: case INDEX_op_exit_tb: ! 871: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]); ! 872: tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) | ! 873: INSN_IMM13(8)); ! 874: tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) | ! 875: INSN_RS2(TCG_REG_G0)); ! 876: break; ! 877: case INDEX_op_goto_tb: ! 878: if (s->tb_jmp_offset) { ! 879: /* direct jump method */ ! 880: tcg_out_sethi(s, TCG_REG_I5, args[0] & 0xffffe000); ! 881: tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | ! 882: INSN_IMM13((args[0] & 0x1fff))); ! 883: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; ! 884: } else { ! 885: /* indirect jump method */ ! 886: tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0])); ! 887: tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | ! 888: INSN_RS2(TCG_REG_G0)); ! 889: } ! 890: tcg_out_nop(s); ! 891: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ! 892: break; ! 893: case INDEX_op_call: ! 894: if (const_args[0]) ! 895: tcg_out32(s, CALL | ((((tcg_target_ulong)args[0] ! 896: - (tcg_target_ulong)s->code_ptr) >> 2) ! 897: & 0x3fffffff)); ! 898: else { ! 899: tcg_out_ld_ptr(s, TCG_REG_I5, ! 900: (tcg_target_long)(s->tb_next + args[0])); ! 901: tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) | ! 902: INSN_RS2(TCG_REG_G0)); ! 903: } ! 904: /* Store AREG0 in stack to avoid ugly glibc bugs that mangle ! 905: global registers */ ! 906: // delay slot ! 907: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 908: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP); ! 909: tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, ! 910: TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP); ! 911: break; ! 912: case INDEX_op_jmp: ! 913: case INDEX_op_br: ! 914: tcg_out_branch(s, COND_A, args[0]); ! 915: tcg_out_nop(s); ! 916: break; ! 917: case INDEX_op_movi_i32: ! 918: tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]); ! 919: break; ! 920: ! 921: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 922: #define OP_32_64(x) \ ! 923: glue(glue(case INDEX_op_, x), _i32:) \ ! 924: glue(glue(case INDEX_op_, x), _i64:) ! 925: #else ! 926: #define OP_32_64(x) \ ! 927: glue(glue(case INDEX_op_, x), _i32:) ! 928: #endif ! 929: OP_32_64(ld8u); ! 930: tcg_out_ldst(s, args[0], args[1], args[2], LDUB); ! 931: break; ! 932: OP_32_64(ld8s); ! 933: tcg_out_ldst(s, args[0], args[1], args[2], LDSB); ! 934: break; ! 935: OP_32_64(ld16u); ! 936: tcg_out_ldst(s, args[0], args[1], args[2], LDUH); ! 937: break; ! 938: OP_32_64(ld16s); ! 939: tcg_out_ldst(s, args[0], args[1], args[2], LDSH); ! 940: break; ! 941: case INDEX_op_ld_i32: ! 942: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 943: case INDEX_op_ld32u_i64: ! 944: #endif ! 945: tcg_out_ldst(s, args[0], args[1], args[2], LDUW); ! 946: break; ! 947: OP_32_64(st8); ! 948: tcg_out_ldst(s, args[0], args[1], args[2], STB); ! 949: break; ! 950: OP_32_64(st16); ! 951: tcg_out_ldst(s, args[0], args[1], args[2], STH); ! 952: break; ! 953: case INDEX_op_st_i32: ! 954: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 955: case INDEX_op_st32_i64: ! 956: #endif ! 957: tcg_out_ldst(s, args[0], args[1], args[2], STW); ! 958: break; ! 959: OP_32_64(add); ! 960: c = ARITH_ADD; ! 961: goto gen_arith32; ! 962: OP_32_64(sub); ! 963: c = ARITH_SUB; ! 964: goto gen_arith32; ! 965: OP_32_64(and); ! 966: c = ARITH_AND; ! 967: goto gen_arith32; ! 968: OP_32_64(or); ! 969: c = ARITH_OR; ! 970: goto gen_arith32; ! 971: OP_32_64(xor); ! 972: c = ARITH_XOR; ! 973: goto gen_arith32; ! 974: case INDEX_op_shl_i32: ! 975: c = SHIFT_SLL; ! 976: goto gen_arith32; ! 977: case INDEX_op_shr_i32: ! 978: c = SHIFT_SRL; ! 979: goto gen_arith32; ! 980: case INDEX_op_sar_i32: ! 981: c = SHIFT_SRA; ! 982: goto gen_arith32; ! 983: case INDEX_op_mul_i32: ! 984: c = ARITH_UMUL; ! 985: goto gen_arith32; ! 986: case INDEX_op_div2_i32: ! 987: #if defined(__sparc_v9__) || defined(__sparc_v8plus__) ! 988: c = ARITH_SDIVX; ! 989: goto gen_arith32; ! 990: #else ! 991: tcg_out_sety(s, 0); ! 992: c = ARITH_SDIV; ! 993: goto gen_arith32; ! 994: #endif ! 995: case INDEX_op_divu2_i32: ! 996: #if defined(__sparc_v9__) || defined(__sparc_v8plus__) ! 997: c = ARITH_UDIVX; ! 998: goto gen_arith32; ! 999: #else ! 1000: tcg_out_sety(s, 0); ! 1001: c = ARITH_UDIV; ! 1002: goto gen_arith32; ! 1003: #endif ! 1004: ! 1005: case INDEX_op_brcond_i32: ! 1006: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], ! 1007: args[3]); ! 1008: break; ! 1009: ! 1010: case INDEX_op_qemu_ld8u: ! 1011: tcg_out_qemu_ld(s, args, 0); ! 1012: break; ! 1013: case INDEX_op_qemu_ld8s: ! 1014: tcg_out_qemu_ld(s, args, 0 | 4); ! 1015: break; ! 1016: case INDEX_op_qemu_ld16u: ! 1017: tcg_out_qemu_ld(s, args, 1); ! 1018: break; ! 1019: case INDEX_op_qemu_ld16s: ! 1020: tcg_out_qemu_ld(s, args, 1 | 4); ! 1021: break; ! 1022: case INDEX_op_qemu_ld32u: ! 1023: tcg_out_qemu_ld(s, args, 2); ! 1024: break; ! 1025: case INDEX_op_qemu_ld32s: ! 1026: tcg_out_qemu_ld(s, args, 2 | 4); ! 1027: break; ! 1028: case INDEX_op_qemu_st8: ! 1029: tcg_out_qemu_st(s, args, 0); ! 1030: break; ! 1031: case INDEX_op_qemu_st16: ! 1032: tcg_out_qemu_st(s, args, 1); ! 1033: break; ! 1034: case INDEX_op_qemu_st32: ! 1035: tcg_out_qemu_st(s, args, 2); ! 1036: break; ! 1037: ! 1038: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 1039: case INDEX_op_movi_i64: ! 1040: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]); ! 1041: break; ! 1042: case INDEX_op_ld32s_i64: ! 1043: tcg_out_ldst(s, args[0], args[1], args[2], LDSW); ! 1044: break; ! 1045: case INDEX_op_ld_i64: ! 1046: tcg_out_ldst(s, args[0], args[1], args[2], LDX); ! 1047: break; ! 1048: case INDEX_op_st_i64: ! 1049: tcg_out_ldst(s, args[0], args[1], args[2], STX); ! 1050: break; ! 1051: case INDEX_op_shl_i64: ! 1052: c = SHIFT_SLLX; ! 1053: goto gen_arith32; ! 1054: case INDEX_op_shr_i64: ! 1055: c = SHIFT_SRLX; ! 1056: goto gen_arith32; ! 1057: case INDEX_op_sar_i64: ! 1058: c = SHIFT_SRAX; ! 1059: goto gen_arith32; ! 1060: case INDEX_op_mul_i64: ! 1061: c = ARITH_MULX; ! 1062: goto gen_arith32; ! 1063: case INDEX_op_div2_i64: ! 1064: c = ARITH_SDIVX; ! 1065: goto gen_arith32; ! 1066: case INDEX_op_divu2_i64: ! 1067: c = ARITH_UDIVX; ! 1068: goto gen_arith32; ! 1069: ! 1070: case INDEX_op_brcond_i64: ! 1071: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], ! 1072: args[3]); ! 1073: break; ! 1074: case INDEX_op_qemu_ld64: ! 1075: tcg_out_qemu_ld(s, args, 3); ! 1076: break; ! 1077: case INDEX_op_qemu_st64: ! 1078: tcg_out_qemu_st(s, args, 3); ! 1079: break; ! 1080: ! 1081: #endif ! 1082: gen_arith32: ! 1083: if (const_args[2]) { ! 1084: tcg_out_arithi(s, args[0], args[1], args[2], c); ! 1085: } else { ! 1086: tcg_out_arith(s, args[0], args[1], args[2], c); ! 1087: } ! 1088: break; ! 1089: ! 1090: default: ! 1091: fprintf(stderr, "unknown opcode 0x%x\n", opc); ! 1092: tcg_abort(); ! 1093: } ! 1094: } ! 1095: ! 1096: static const TCGTargetOpDef sparc_op_defs[] = { ! 1097: { INDEX_op_exit_tb, { } }, ! 1098: { INDEX_op_goto_tb, { } }, ! 1099: { INDEX_op_call, { "ri" } }, ! 1100: { INDEX_op_jmp, { "ri" } }, ! 1101: { INDEX_op_br, { } }, ! 1102: ! 1103: { INDEX_op_mov_i32, { "r", "r" } }, ! 1104: { INDEX_op_movi_i32, { "r" } }, ! 1105: { INDEX_op_ld8u_i32, { "r", "r" } }, ! 1106: { INDEX_op_ld8s_i32, { "r", "r" } }, ! 1107: { INDEX_op_ld16u_i32, { "r", "r" } }, ! 1108: { INDEX_op_ld16s_i32, { "r", "r" } }, ! 1109: { INDEX_op_ld_i32, { "r", "r" } }, ! 1110: { INDEX_op_st8_i32, { "r", "r" } }, ! 1111: { INDEX_op_st16_i32, { "r", "r" } }, ! 1112: { INDEX_op_st_i32, { "r", "r" } }, ! 1113: ! 1114: { INDEX_op_add_i32, { "r", "r", "rJ" } }, ! 1115: { INDEX_op_mul_i32, { "r", "r", "rJ" } }, ! 1116: { INDEX_op_div2_i32, { "r", "r", "0", "1", "r" } }, ! 1117: { INDEX_op_divu2_i32, { "r", "r", "0", "1", "r" } }, ! 1118: { INDEX_op_sub_i32, { "r", "r", "rJ" } }, ! 1119: { INDEX_op_and_i32, { "r", "r", "rJ" } }, ! 1120: { INDEX_op_or_i32, { "r", "r", "rJ" } }, ! 1121: { INDEX_op_xor_i32, { "r", "r", "rJ" } }, ! 1122: ! 1123: { INDEX_op_shl_i32, { "r", "r", "rJ" } }, ! 1124: { INDEX_op_shr_i32, { "r", "r", "rJ" } }, ! 1125: { INDEX_op_sar_i32, { "r", "r", "rJ" } }, ! 1126: ! 1127: { INDEX_op_brcond_i32, { "r", "ri" } }, ! 1128: ! 1129: { INDEX_op_qemu_ld8u, { "r", "L" } }, ! 1130: { INDEX_op_qemu_ld8s, { "r", "L" } }, ! 1131: { INDEX_op_qemu_ld16u, { "r", "L" } }, ! 1132: { INDEX_op_qemu_ld16s, { "r", "L" } }, ! 1133: { INDEX_op_qemu_ld32u, { "r", "L" } }, ! 1134: { INDEX_op_qemu_ld32s, { "r", "L" } }, ! 1135: ! 1136: { INDEX_op_qemu_st8, { "L", "L" } }, ! 1137: { INDEX_op_qemu_st16, { "L", "L" } }, ! 1138: { INDEX_op_qemu_st32, { "L", "L" } }, ! 1139: ! 1140: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 1141: { INDEX_op_mov_i64, { "r", "r" } }, ! 1142: { INDEX_op_movi_i64, { "r" } }, ! 1143: { INDEX_op_ld8u_i64, { "r", "r" } }, ! 1144: { INDEX_op_ld8s_i64, { "r", "r" } }, ! 1145: { INDEX_op_ld16u_i64, { "r", "r" } }, ! 1146: { INDEX_op_ld16s_i64, { "r", "r" } }, ! 1147: { INDEX_op_ld32u_i64, { "r", "r" } }, ! 1148: { INDEX_op_ld32s_i64, { "r", "r" } }, ! 1149: { INDEX_op_ld_i64, { "r", "r" } }, ! 1150: { INDEX_op_st8_i64, { "r", "r" } }, ! 1151: { INDEX_op_st16_i64, { "r", "r" } }, ! 1152: { INDEX_op_st32_i64, { "r", "r" } }, ! 1153: { INDEX_op_st_i64, { "r", "r" } }, ! 1154: { INDEX_op_qemu_ld64, { "L", "L" } }, ! 1155: { INDEX_op_qemu_st64, { "L", "L" } }, ! 1156: ! 1157: { INDEX_op_add_i64, { "r", "r", "rJ" } }, ! 1158: { INDEX_op_mul_i64, { "r", "r", "rJ" } }, ! 1159: { INDEX_op_div2_i64, { "r", "r", "0", "1", "r" } }, ! 1160: { INDEX_op_divu2_i64, { "r", "r", "0", "1", "r" } }, ! 1161: { INDEX_op_sub_i64, { "r", "r", "rJ" } }, ! 1162: { INDEX_op_and_i64, { "r", "r", "rJ" } }, ! 1163: { INDEX_op_or_i64, { "r", "r", "rJ" } }, ! 1164: { INDEX_op_xor_i64, { "r", "r", "rJ" } }, ! 1165: ! 1166: { INDEX_op_shl_i64, { "r", "r", "rJ" } }, ! 1167: { INDEX_op_shr_i64, { "r", "r", "rJ" } }, ! 1168: { INDEX_op_sar_i64, { "r", "r", "rJ" } }, ! 1169: ! 1170: { INDEX_op_brcond_i64, { "r", "ri" } }, ! 1171: #endif ! 1172: { -1 }, ! 1173: }; ! 1174: ! 1175: void tcg_target_init(TCGContext *s) ! 1176: { ! 1177: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); ! 1178: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 1179: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); ! 1180: #endif ! 1181: tcg_regset_set32(tcg_target_call_clobber_regs, 0, ! 1182: (1 << TCG_REG_G1) | ! 1183: (1 << TCG_REG_G2) | ! 1184: (1 << TCG_REG_G3) | ! 1185: (1 << TCG_REG_G4) | ! 1186: (1 << TCG_REG_G5) | ! 1187: (1 << TCG_REG_G6) | ! 1188: (1 << TCG_REG_G7) | ! 1189: (1 << TCG_REG_O0) | ! 1190: (1 << TCG_REG_O1) | ! 1191: (1 << TCG_REG_O2) | ! 1192: (1 << TCG_REG_O3) | ! 1193: (1 << TCG_REG_O4) | ! 1194: (1 << TCG_REG_O5) | ! 1195: (1 << TCG_REG_O7)); ! 1196: ! 1197: tcg_regset_clear(s->reserved_regs); ! 1198: tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); ! 1199: #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) ! 1200: tcg_regset_set_reg(s->reserved_regs, TCG_REG_I4); // for internal use ! 1201: #endif ! 1202: tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use ! 1203: tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); ! 1204: tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); ! 1205: tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); ! 1206: tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7); ! 1207: tcg_add_target_add_op_defs(sparc_op_defs); ! 1208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.