|
|
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: "%r0", ! 28: "%r1", ! 29: "%rp", ! 30: "%r3", ! 31: "%r4", ! 32: "%r5", ! 33: "%r6", ! 34: "%r7", ! 35: "%r8", ! 36: "%r9", ! 37: "%r10", ! 38: "%r11", ! 39: "%r12", ! 40: "%r13", ! 41: "%r14", ! 42: "%r15", ! 43: "%r16", ! 44: "%r17", ! 45: "%r18", ! 46: "%r19", ! 47: "%r20", ! 48: "%r21", ! 49: "%r22", ! 50: "%r23", ! 51: "%r24", ! 52: "%r25", ! 53: "%r26", ! 54: "%dp", ! 55: "%ret0", ! 56: "%ret1", ! 57: "%sp", ! 58: "%r31", ! 59: }; ! 60: #endif ! 61: ! 62: static const int tcg_target_reg_alloc_order[] = { ! 63: TCG_REG_R4, ! 64: TCG_REG_R5, ! 65: TCG_REG_R6, ! 66: TCG_REG_R7, ! 67: TCG_REG_R8, ! 68: TCG_REG_R9, ! 69: TCG_REG_R10, ! 70: TCG_REG_R11, ! 71: TCG_REG_R12, ! 72: TCG_REG_R13, ! 73: ! 74: TCG_REG_R17, ! 75: TCG_REG_R14, ! 76: TCG_REG_R15, ! 77: TCG_REG_R16, ! 78: }; ! 79: ! 80: static const int tcg_target_call_iarg_regs[4] = { ! 81: TCG_REG_R26, ! 82: TCG_REG_R25, ! 83: TCG_REG_R24, ! 84: TCG_REG_R23, ! 85: }; ! 86: ! 87: static const int tcg_target_call_oarg_regs[2] = { ! 88: TCG_REG_RET0, ! 89: TCG_REG_RET1, ! 90: }; ! 91: ! 92: static void patch_reloc(uint8_t *code_ptr, int type, ! 93: tcg_target_long value, tcg_target_long addend) ! 94: { ! 95: switch (type) { ! 96: case R_PARISC_PCREL17F: ! 97: hppa_patch17f((uint32_t *)code_ptr, value, addend); ! 98: break; ! 99: default: ! 100: tcg_abort(); ! 101: } ! 102: } ! 103: ! 104: /* maximum number of register used for input function arguments */ ! 105: static inline int tcg_target_get_call_iarg_regs_count(int flags) ! 106: { ! 107: return 4; ! 108: } ! 109: ! 110: /* parse target specific constraints */ ! 111: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ! 112: { ! 113: const char *ct_str; ! 114: ! 115: ct_str = *pct_str; ! 116: switch (ct_str[0]) { ! 117: case 'r': ! 118: ct->ct |= TCG_CT_REG; ! 119: tcg_regset_set32(ct->u.regs, 0, 0xffffffff); ! 120: break; ! 121: case 'L': /* qemu_ld/st constraint */ ! 122: ct->ct |= TCG_CT_REG; ! 123: tcg_regset_set32(ct->u.regs, 0, 0xffffffff); ! 124: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R26); ! 125: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R25); ! 126: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R24); ! 127: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R23); ! 128: break; ! 129: default: ! 130: return -1; ! 131: } ! 132: ct_str++; ! 133: *pct_str = ct_str; ! 134: return 0; ! 135: } ! 136: ! 137: /* test if a constant matches the constraint */ ! 138: static inline int tcg_target_const_match(tcg_target_long val, ! 139: const TCGArgConstraint *arg_ct) ! 140: { ! 141: int ct; ! 142: ! 143: ct = arg_ct->ct; ! 144: ! 145: /* TODO */ ! 146: ! 147: return 0; ! 148: } ! 149: ! 150: #define INSN_OP(x) ((x) << 26) ! 151: #define INSN_EXT3BR(x) ((x) << 13) ! 152: #define INSN_EXT3SH(x) ((x) << 10) ! 153: #define INSN_EXT4(x) ((x) << 6) ! 154: #define INSN_EXT5(x) (x) ! 155: #define INSN_EXT6(x) ((x) << 6) ! 156: #define INSN_EXT7(x) ((x) << 6) ! 157: #define INSN_EXT8A(x) ((x) << 6) ! 158: #define INSN_EXT8B(x) ((x) << 5) ! 159: #define INSN_T(x) (x) ! 160: #define INSN_R1(x) ((x) << 16) ! 161: #define INSN_R2(x) ((x) << 21) ! 162: #define INSN_DEP_LEN(x) (32 - (x)) ! 163: #define INSN_SHDEP_CP(x) ((31 - (x)) << 5) ! 164: #define INSN_SHDEP_P(x) ((x) << 5) ! 165: #define INSN_COND(x) ((x) << 13) ! 166: ! 167: #define COND_NEVER 0 ! 168: #define COND_EQUAL 1 ! 169: #define COND_LT 2 ! 170: #define COND_LTEQ 3 ! 171: #define COND_LTU 4 ! 172: #define COND_LTUEQ 5 ! 173: #define COND_SV 6 ! 174: #define COND_OD 7 ! 175: ! 176: ! 177: /* Logical ADD */ ! 178: #define ARITH_ADD (INSN_OP(0x02) | INSN_EXT6(0x28)) ! 179: #define ARITH_AND (INSN_OP(0x02) | INSN_EXT6(0x08)) ! 180: #define ARITH_OR (INSN_OP(0x02) | INSN_EXT6(0x09)) ! 181: #define ARITH_XOR (INSN_OP(0x02) | INSN_EXT6(0x0a)) ! 182: #define ARITH_SUB (INSN_OP(0x02) | INSN_EXT6(0x10)) ! 183: ! 184: #define SHD (INSN_OP(0x34) | INSN_EXT3SH(2)) ! 185: #define VSHD (INSN_OP(0x34) | INSN_EXT3SH(0)) ! 186: #define DEP (INSN_OP(0x35) | INSN_EXT3SH(3)) ! 187: #define ZDEP (INSN_OP(0x35) | INSN_EXT3SH(2)) ! 188: #define ZVDEP (INSN_OP(0x35) | INSN_EXT3SH(0)) ! 189: #define EXTRU (INSN_OP(0x34) | INSN_EXT3SH(6)) ! 190: #define EXTRS (INSN_OP(0x34) | INSN_EXT3SH(7)) ! 191: #define VEXTRS (INSN_OP(0x34) | INSN_EXT3SH(5)) ! 192: ! 193: #define SUBI (INSN_OP(0x25)) ! 194: #define MTCTL (INSN_OP(0x00) | INSN_EXT8B(0xc2)) ! 195: ! 196: #define BL (INSN_OP(0x3a) | INSN_EXT3BR(0)) ! 197: #define BLE_SR4 (INSN_OP(0x39) | (1 << 13)) ! 198: #define BV (INSN_OP(0x3a) | INSN_EXT3BR(6)) ! 199: #define BV_N (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2) ! 200: #define LDIL (INSN_OP(0x08)) ! 201: #define LDO (INSN_OP(0x0d)) ! 202: ! 203: #define LDB (INSN_OP(0x10)) ! 204: #define LDH (INSN_OP(0x11)) ! 205: #define LDW (INSN_OP(0x12)) ! 206: #define LDWM (INSN_OP(0x13)) ! 207: ! 208: #define STB (INSN_OP(0x18)) ! 209: #define STH (INSN_OP(0x19)) ! 210: #define STW (INSN_OP(0x1a)) ! 211: #define STWM (INSN_OP(0x1b)) ! 212: ! 213: #define COMBT (INSN_OP(0x20)) ! 214: #define COMBF (INSN_OP(0x22)) ! 215: ! 216: static int lowsignext(uint32_t val, int start, int length) ! 217: { ! 218: return (((val << 1) & ~(~0 << length)) | ! 219: ((val >> (length - 1)) & 1)) << start; ! 220: } ! 221: ! 222: static inline void tcg_out_mov(TCGContext *s, int ret, int arg) ! 223: { ! 224: /* PA1.1 defines COPY as OR r,0,t */ ! 225: tcg_out32(s, ARITH_OR | INSN_T(ret) | INSN_R1(arg) | INSN_R2(TCG_REG_R0)); ! 226: ! 227: /* PA2.0 defines COPY as LDO 0(r),t ! 228: * but hppa-dis.c is unaware of this definition */ ! 229: /* tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(arg) | reassemble_14(0)); */ ! 230: } ! 231: ! 232: static inline void tcg_out_movi(TCGContext *s, TCGType type, ! 233: int ret, tcg_target_long arg) ! 234: { ! 235: if (arg == (arg & 0x1fff)) { ! 236: tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(TCG_REG_R0) | ! 237: reassemble_14(arg)); ! 238: } else { ! 239: tcg_out32(s, LDIL | INSN_R2(ret) | ! 240: reassemble_21(lrsel((uint32_t)arg, 0))); ! 241: if (arg & 0x7ff) ! 242: tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(ret) | ! 243: reassemble_14(rrsel((uint32_t)arg, 0))); ! 244: } ! 245: } ! 246: ! 247: static inline void tcg_out_ld_raw(TCGContext *s, int ret, ! 248: tcg_target_long arg) ! 249: { ! 250: tcg_out32(s, LDIL | INSN_R2(ret) | ! 251: reassemble_21(lrsel((uint32_t)arg, 0))); ! 252: tcg_out32(s, LDW | INSN_R1(ret) | INSN_R2(ret) | ! 253: reassemble_14(rrsel((uint32_t)arg, 0))); ! 254: } ! 255: ! 256: static inline void tcg_out_ld_ptr(TCGContext *s, int ret, ! 257: tcg_target_long arg) ! 258: { ! 259: tcg_out_ld_raw(s, ret, arg); ! 260: } ! 261: ! 262: static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, ! 263: int op) ! 264: { ! 265: if (offset == (offset & 0xfff)) ! 266: tcg_out32(s, op | INSN_R1(ret) | INSN_R2(addr) | ! 267: reassemble_14(offset)); ! 268: else { ! 269: fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset); ! 270: tcg_abort(); ! 271: } ! 272: } ! 273: ! 274: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, ! 275: int arg1, tcg_target_long arg2) ! 276: { ! 277: fprintf(stderr, "unimplemented %s\n", __func__); ! 278: tcg_abort(); ! 279: } ! 280: ! 281: static inline void tcg_out_st(TCGContext *s, TCGType type, int ret, ! 282: int arg1, tcg_target_long arg2) ! 283: { ! 284: fprintf(stderr, "unimplemented %s\n", __func__); ! 285: tcg_abort(); ! 286: } ! 287: ! 288: static inline void tcg_out_arith(TCGContext *s, int t, int r1, int r2, int op) ! 289: { ! 290: tcg_out32(s, op | INSN_T(t) | INSN_R1(r1) | INSN_R2(r2)); ! 291: } ! 292: ! 293: static inline void tcg_out_arithi(TCGContext *s, int t, int r1, ! 294: tcg_target_long val, int op) ! 295: { ! 296: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, val); ! 297: tcg_out_arith(s, t, r1, TCG_REG_R20, op); ! 298: } ! 299: ! 300: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) ! 301: { ! 302: tcg_out_arithi(s, reg, reg, val, ARITH_ADD); ! 303: } ! 304: ! 305: static inline void tcg_out_nop(TCGContext *s) ! 306: { ! 307: tcg_out32(s, ARITH_OR | INSN_T(TCG_REG_R0) | INSN_R1(TCG_REG_R0) | ! 308: INSN_R2(TCG_REG_R0)); ! 309: } ! 310: ! 311: static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) { ! 312: tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) | ! 313: INSN_SHDEP_P(31) | INSN_DEP_LEN(8)); ! 314: } ! 315: ! 316: static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) { ! 317: tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) | ! 318: INSN_SHDEP_P(31) | INSN_DEP_LEN(16)); ! 319: } ! 320: ! 321: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) { ! 322: if(ret != arg) ! 323: tcg_out_mov(s, ret, arg); ! 324: tcg_out32(s, DEP | INSN_R2(ret) | INSN_R1(ret) | ! 325: INSN_SHDEP_CP(15) | INSN_DEP_LEN(8)); ! 326: tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(TCG_REG_R0) | ! 327: INSN_R2(ret) | INSN_SHDEP_CP(8)); ! 328: } ! 329: ! 330: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp) { ! 331: tcg_out32(s, SHD | INSN_T(temp) | INSN_R1(arg) | ! 332: INSN_R2(arg) | INSN_SHDEP_CP(16)); ! 333: tcg_out32(s, DEP | INSN_R2(temp) | INSN_R1(temp) | ! 334: INSN_SHDEP_CP(15) | INSN_DEP_LEN(8)); ! 335: tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(arg) | ! 336: INSN_R2(temp) | INSN_SHDEP_CP(8)); ! 337: } ! 338: ! 339: static inline void tcg_out_call(TCGContext *s, void *func) ! 340: { ! 341: uint32_t val = (uint32_t)__canonicalize_funcptr_for_compare(func); ! 342: tcg_out32(s, LDIL | INSN_R2(TCG_REG_R20) | ! 343: reassemble_21(lrsel(val, 0))); ! 344: tcg_out32(s, BLE_SR4 | INSN_R2(TCG_REG_R20) | ! 345: reassemble_17(rrsel(val, 0) >> 2)); ! 346: tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31); ! 347: } ! 348: ! 349: #if defined(CONFIG_SOFTMMU) ! 350: ! 351: #include "../../softmmu_defs.h" ! 352: ! 353: static void *qemu_ld_helpers[4] = { ! 354: __ldb_mmu, ! 355: __ldw_mmu, ! 356: __ldl_mmu, ! 357: __ldq_mmu, ! 358: }; ! 359: ! 360: static void *qemu_st_helpers[4] = { ! 361: __stb_mmu, ! 362: __stw_mmu, ! 363: __stl_mmu, ! 364: __stq_mmu, ! 365: }; ! 366: #endif ! 367: ! 368: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) ! 369: { ! 370: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap; ! 371: #if defined(CONFIG_SOFTMMU) ! 372: uint32_t *label1_ptr, *label2_ptr; ! 373: #endif ! 374: #if TARGET_LONG_BITS == 64 ! 375: #if defined(CONFIG_SOFTMMU) ! 376: uint32_t *label3_ptr; ! 377: #endif ! 378: int addr_reg2; ! 379: #endif ! 380: ! 381: data_reg = *args++; ! 382: if (opc == 3) ! 383: data_reg2 = *args++; ! 384: else ! 385: data_reg2 = 0; /* surpress warning */ ! 386: addr_reg = *args++; ! 387: #if TARGET_LONG_BITS == 64 ! 388: addr_reg2 = *args++; ! 389: #endif ! 390: mem_index = *args; ! 391: s_bits = opc & 3; ! 392: ! 393: r0 = TCG_REG_R26; ! 394: r1 = TCG_REG_R25; ! 395: ! 396: #if defined(CONFIG_SOFTMMU) ! 397: tcg_out_mov(s, r1, addr_reg); ! 398: ! 399: tcg_out_mov(s, r0, addr_reg); ! 400: ! 401: tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) | ! 402: INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)); ! 403: ! 404: tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), ! 405: ARITH_AND); ! 406: ! 407: tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, ! 408: ARITH_AND); ! 409: ! 410: tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD); ! 411: tcg_out_arithi(s, r1, r1, ! 412: offsetof(CPUState, tlb_table[mem_index][0].addr_read), ! 413: ARITH_ADD); ! 414: ! 415: tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW); ! 416: ! 417: #if TARGET_LONG_BITS == 32 ! 418: /* if equal, jump to label1 */ ! 419: label1_ptr = (uint32_t *)s->code_ptr; ! 420: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) | ! 421: INSN_COND(COND_EQUAL)); ! 422: tcg_out_mov(s, r0, addr_reg); /* delay slot */ ! 423: #else ! 424: /* if not equal, jump to label3 */ ! 425: label3_ptr = (uint32_t *)s->code_ptr; ! 426: tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) | ! 427: INSN_COND(COND_EQUAL)); ! 428: tcg_out_mov(s, r0, addr_reg); /* delay slot */ ! 429: ! 430: tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW); ! 431: ! 432: /* if equal, jump to label1 */ ! 433: label1_ptr = (uint32_t *)s->code_ptr; ! 434: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) | ! 435: INSN_COND(COND_EQUAL)); ! 436: tcg_out_nop(s); /* delay slot */ ! 437: ! 438: /* label3: */ ! 439: *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2); ! 440: #endif ! 441: ! 442: #if TARGET_LONG_BITS == 32 ! 443: tcg_out_mov(s, TCG_REG_R26, addr_reg); ! 444: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R25, mem_index); ! 445: #else ! 446: tcg_out_mov(s, TCG_REG_R26, addr_reg); ! 447: tcg_out_mov(s, TCG_REG_R25, addr_reg2); ! 448: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index); ! 449: #endif ! 450: ! 451: tcg_out_call(s, qemu_ld_helpers[s_bits]); ! 452: ! 453: switch(opc) { ! 454: case 0 | 4: ! 455: tcg_out_ext8s(s, data_reg, TCG_REG_RET0); ! 456: break; ! 457: case 1 | 4: ! 458: tcg_out_ext16s(s, data_reg, TCG_REG_RET0); ! 459: break; ! 460: case 0: ! 461: case 1: ! 462: case 2: ! 463: default: ! 464: tcg_out_mov(s, data_reg, TCG_REG_RET0); ! 465: break; ! 466: case 3: ! 467: tcg_abort(); ! 468: tcg_out_mov(s, data_reg, TCG_REG_RET0); ! 469: tcg_out_mov(s, data_reg2, TCG_REG_RET1); ! 470: break; ! 471: } ! 472: ! 473: /* jump to label2 */ ! 474: label2_ptr = (uint32_t *)s->code_ptr; ! 475: tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2); ! 476: ! 477: /* label1: */ ! 478: *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2); ! 479: ! 480: tcg_out_arithi(s, TCG_REG_R20, r1, ! 481: offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read), ! 482: ARITH_ADD); ! 483: tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW); ! 484: tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD); ! 485: #else ! 486: r0 = addr_reg; ! 487: #endif ! 488: ! 489: #ifdef TARGET_WORDS_BIGENDIAN ! 490: bswap = 0; ! 491: #else ! 492: bswap = 1; ! 493: #endif ! 494: switch (opc) { ! 495: case 0: ! 496: tcg_out_ldst(s, data_reg, r0, 0, LDB); ! 497: break; ! 498: case 0 | 4: ! 499: tcg_out_ldst(s, data_reg, r0, 0, LDB); ! 500: tcg_out_ext8s(s, data_reg, data_reg); ! 501: break; ! 502: case 1: ! 503: tcg_out_ldst(s, data_reg, r0, 0, LDH); ! 504: if (bswap) ! 505: tcg_out_bswap16(s, data_reg, data_reg); ! 506: break; ! 507: case 1 | 4: ! 508: tcg_out_ldst(s, data_reg, r0, 0, LDH); ! 509: if (bswap) ! 510: tcg_out_bswap16(s, data_reg, data_reg); ! 511: tcg_out_ext16s(s, data_reg, data_reg); ! 512: break; ! 513: case 2: ! 514: tcg_out_ldst(s, data_reg, r0, 0, LDW); ! 515: if (bswap) ! 516: tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20); ! 517: break; ! 518: case 3: ! 519: tcg_abort(); ! 520: if (!bswap) { ! 521: tcg_out_ldst(s, data_reg, r0, 0, LDW); ! 522: tcg_out_ldst(s, data_reg2, r0, 4, LDW); ! 523: } else { ! 524: tcg_out_ldst(s, data_reg, r0, 4, LDW); ! 525: tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20); ! 526: tcg_out_ldst(s, data_reg2, r0, 0, LDW); ! 527: tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20); ! 528: } ! 529: break; ! 530: default: ! 531: tcg_abort(); ! 532: } ! 533: ! 534: #if defined(CONFIG_SOFTMMU) ! 535: /* label2: */ ! 536: *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2); ! 537: #endif ! 538: } ! 539: ! 540: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) ! 541: { ! 542: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap; ! 543: #if defined(CONFIG_SOFTMMU) ! 544: uint32_t *label1_ptr, *label2_ptr; ! 545: #endif ! 546: #if TARGET_LONG_BITS == 64 ! 547: #if defined(CONFIG_SOFTMMU) ! 548: uint32_t *label3_ptr; ! 549: #endif ! 550: int addr_reg2; ! 551: #endif ! 552: ! 553: data_reg = *args++; ! 554: if (opc == 3) ! 555: data_reg2 = *args++; ! 556: else ! 557: data_reg2 = 0; /* surpress warning */ ! 558: addr_reg = *args++; ! 559: #if TARGET_LONG_BITS == 64 ! 560: addr_reg2 = *args++; ! 561: #endif ! 562: mem_index = *args; ! 563: ! 564: s_bits = opc; ! 565: ! 566: r0 = TCG_REG_R26; ! 567: r1 = TCG_REG_R25; ! 568: ! 569: #if defined(CONFIG_SOFTMMU) ! 570: tcg_out_mov(s, r1, addr_reg); ! 571: ! 572: tcg_out_mov(s, r0, addr_reg); ! 573: ! 574: tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) | ! 575: INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)); ! 576: ! 577: tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), ! 578: ARITH_AND); ! 579: ! 580: tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, ! 581: ARITH_AND); ! 582: ! 583: tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD); ! 584: tcg_out_arithi(s, r1, r1, ! 585: offsetof(CPUState, tlb_table[mem_index][0].addr_write), ! 586: ARITH_ADD); ! 587: ! 588: tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW); ! 589: ! 590: #if TARGET_LONG_BITS == 32 ! 591: /* if equal, jump to label1 */ ! 592: label1_ptr = (uint32_t *)s->code_ptr; ! 593: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) | ! 594: INSN_COND(COND_EQUAL)); ! 595: tcg_out_mov(s, r0, addr_reg); /* delay slot */ ! 596: #else ! 597: /* if not equal, jump to label3 */ ! 598: label3_ptr = (uint32_t *)s->code_ptr; ! 599: tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) | ! 600: INSN_COND(COND_EQUAL)); ! 601: tcg_out_mov(s, r0, addr_reg); /* delay slot */ ! 602: ! 603: tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW); ! 604: ! 605: /* if equal, jump to label1 */ ! 606: label1_ptr = (uint32_t *)s->code_ptr; ! 607: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) | ! 608: INSN_COND(COND_EQUAL)); ! 609: tcg_out_nop(s); /* delay slot */ ! 610: ! 611: /* label3: */ ! 612: *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2); ! 613: #endif ! 614: ! 615: tcg_out_mov(s, TCG_REG_R26, addr_reg); ! 616: #if TARGET_LONG_BITS == 64 ! 617: tcg_out_mov(s, TCG_REG_R25, addr_reg2); ! 618: if (opc == 3) { ! 619: tcg_abort(); ! 620: tcg_out_mov(s, TCG_REG_R24, data_reg); ! 621: tcg_out_mov(s, TCG_REG_R23, data_reg2); ! 622: /* TODO: push mem_index */ ! 623: tcg_abort(); ! 624: } else { ! 625: switch(opc) { ! 626: case 0: ! 627: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) | ! 628: INSN_SHDEP_P(31) | INSN_DEP_LEN(8)); ! 629: break; ! 630: case 1: ! 631: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) | ! 632: INSN_SHDEP_P(31) | INSN_DEP_LEN(16)); ! 633: break; ! 634: case 2: ! 635: tcg_out_mov(s, TCG_REG_R24, data_reg); ! 636: break; ! 637: } ! 638: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index); ! 639: } ! 640: #else ! 641: if (opc == 3) { ! 642: tcg_abort(); ! 643: tcg_out_mov(s, TCG_REG_R25, data_reg); ! 644: tcg_out_mov(s, TCG_REG_R24, data_reg2); ! 645: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index); ! 646: } else { ! 647: switch(opc) { ! 648: case 0: ! 649: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) | ! 650: INSN_SHDEP_P(31) | INSN_DEP_LEN(8)); ! 651: break; ! 652: case 1: ! 653: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) | ! 654: INSN_SHDEP_P(31) | INSN_DEP_LEN(16)); ! 655: break; ! 656: case 2: ! 657: tcg_out_mov(s, TCG_REG_R25, data_reg); ! 658: break; ! 659: } ! 660: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index); ! 661: } ! 662: #endif ! 663: tcg_out_call(s, qemu_st_helpers[s_bits]); ! 664: ! 665: /* jump to label2 */ ! 666: label2_ptr = (uint32_t *)s->code_ptr; ! 667: tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2); ! 668: ! 669: /* label1: */ ! 670: *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2); ! 671: ! 672: tcg_out_arithi(s, TCG_REG_R20, r1, ! 673: offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write), ! 674: ARITH_ADD); ! 675: tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW); ! 676: tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD); ! 677: #else ! 678: r0 = addr_reg; ! 679: #endif ! 680: ! 681: #ifdef TARGET_WORDS_BIGENDIAN ! 682: bswap = 0; ! 683: #else ! 684: bswap = 1; ! 685: #endif ! 686: switch (opc) { ! 687: case 0: ! 688: tcg_out_ldst(s, data_reg, r0, 0, STB); ! 689: break; ! 690: case 1: ! 691: if (bswap) { ! 692: tcg_out_bswap16(s, TCG_REG_R20, data_reg); ! 693: data_reg = TCG_REG_R20; ! 694: } ! 695: tcg_out_ldst(s, data_reg, r0, 0, STH); ! 696: break; ! 697: case 2: ! 698: if (bswap) { ! 699: tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20); ! 700: data_reg = TCG_REG_R20; ! 701: } ! 702: tcg_out_ldst(s, data_reg, r0, 0, STW); ! 703: break; ! 704: case 3: ! 705: tcg_abort(); ! 706: if (!bswap) { ! 707: tcg_out_ldst(s, data_reg, r0, 0, STW); ! 708: tcg_out_ldst(s, data_reg2, r0, 4, STW); ! 709: } else { ! 710: tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20); ! 711: tcg_out_ldst(s, TCG_REG_R20, r0, 4, STW); ! 712: tcg_out_bswap32(s, TCG_REG_R20, data_reg2, TCG_REG_R20); ! 713: tcg_out_ldst(s, TCG_REG_R20, r0, 0, STW); ! 714: } ! 715: break; ! 716: default: ! 717: tcg_abort(); ! 718: } ! 719: ! 720: #if defined(CONFIG_SOFTMMU) ! 721: /* label2: */ ! 722: *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2); ! 723: #endif ! 724: } ! 725: ! 726: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, ! 727: const int *const_args) ! 728: { ! 729: int c; ! 730: ! 731: switch (opc) { ! 732: case INDEX_op_exit_tb: ! 733: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, args[0]); ! 734: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R18)); ! 735: break; ! 736: case INDEX_op_goto_tb: ! 737: if (s->tb_jmp_offset) { ! 738: /* direct jump method */ ! 739: fprintf(stderr, "goto_tb direct\n"); ! 740: tcg_abort(); ! 741: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, args[0]); ! 742: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20)); ! 743: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; ! 744: } else { ! 745: /* indirect jump method */ ! 746: tcg_out_ld_ptr(s, TCG_REG_R20, ! 747: (tcg_target_long)(s->tb_next + args[0])); ! 748: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20)); ! 749: } ! 750: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ! 751: break; ! 752: case INDEX_op_call: ! 753: tcg_out32(s, BLE_SR4 | INSN_R2(args[0])); ! 754: tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31); ! 755: break; ! 756: case INDEX_op_jmp: ! 757: fprintf(stderr, "unimplemented jmp\n"); ! 758: tcg_abort(); ! 759: break; ! 760: case INDEX_op_br: ! 761: fprintf(stderr, "unimplemented br\n"); ! 762: tcg_abort(); ! 763: break; ! 764: case INDEX_op_movi_i32: ! 765: tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]); ! 766: break; ! 767: ! 768: case INDEX_op_ld8u_i32: ! 769: tcg_out_ldst(s, args[0], args[1], args[2], LDB); ! 770: break; ! 771: case INDEX_op_ld8s_i32: ! 772: tcg_out_ldst(s, args[0], args[1], args[2], LDB); ! 773: tcg_out_ext8s(s, args[0], args[0]); ! 774: break; ! 775: case INDEX_op_ld16u_i32: ! 776: tcg_out_ldst(s, args[0], args[1], args[2], LDH); ! 777: break; ! 778: case INDEX_op_ld16s_i32: ! 779: tcg_out_ldst(s, args[0], args[1], args[2], LDH); ! 780: tcg_out_ext16s(s, args[0], args[0]); ! 781: break; ! 782: case INDEX_op_ld_i32: ! 783: tcg_out_ldst(s, args[0], args[1], args[2], LDW); ! 784: break; ! 785: ! 786: case INDEX_op_st8_i32: ! 787: tcg_out_ldst(s, args[0], args[1], args[2], STB); ! 788: break; ! 789: case INDEX_op_st16_i32: ! 790: tcg_out_ldst(s, args[0], args[1], args[2], STH); ! 791: break; ! 792: case INDEX_op_st_i32: ! 793: tcg_out_ldst(s, args[0], args[1], args[2], STW); ! 794: break; ! 795: ! 796: case INDEX_op_sub_i32: ! 797: c = ARITH_SUB; ! 798: goto gen_arith; ! 799: case INDEX_op_and_i32: ! 800: c = ARITH_AND; ! 801: goto gen_arith; ! 802: case INDEX_op_or_i32: ! 803: c = ARITH_OR; ! 804: goto gen_arith; ! 805: case INDEX_op_xor_i32: ! 806: c = ARITH_XOR; ! 807: goto gen_arith; ! 808: case INDEX_op_add_i32: ! 809: c = ARITH_ADD; ! 810: goto gen_arith; ! 811: ! 812: case INDEX_op_shl_i32: ! 813: tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) | ! 814: lowsignext(0x1f, 0, 11)); ! 815: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20)); ! 816: tcg_out32(s, ZVDEP | INSN_R2(args[0]) | INSN_R1(args[1]) | ! 817: INSN_DEP_LEN(32)); ! 818: break; ! 819: case INDEX_op_shr_i32: ! 820: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(args[2])); ! 821: tcg_out32(s, VSHD | INSN_T(args[0]) | INSN_R1(TCG_REG_R0) | ! 822: INSN_R2(args[1])); ! 823: break; ! 824: case INDEX_op_sar_i32: ! 825: tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) | ! 826: lowsignext(0x1f, 0, 11)); ! 827: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20)); ! 828: tcg_out32(s, VEXTRS | INSN_R1(args[0]) | INSN_R2(args[1]) | ! 829: INSN_DEP_LEN(32)); ! 830: break; ! 831: ! 832: case INDEX_op_mul_i32: ! 833: fprintf(stderr, "unimplemented mul\n"); ! 834: tcg_abort(); ! 835: break; ! 836: case INDEX_op_mulu2_i32: ! 837: fprintf(stderr, "unimplemented mulu2\n"); ! 838: tcg_abort(); ! 839: break; ! 840: case INDEX_op_div2_i32: ! 841: fprintf(stderr, "unimplemented div2\n"); ! 842: tcg_abort(); ! 843: break; ! 844: case INDEX_op_divu2_i32: ! 845: fprintf(stderr, "unimplemented divu2\n"); ! 846: tcg_abort(); ! 847: break; ! 848: ! 849: case INDEX_op_brcond_i32: ! 850: fprintf(stderr, "unimplemented brcond\n"); ! 851: tcg_abort(); ! 852: break; ! 853: ! 854: case INDEX_op_qemu_ld8u: ! 855: tcg_out_qemu_ld(s, args, 0); ! 856: break; ! 857: case INDEX_op_qemu_ld8s: ! 858: tcg_out_qemu_ld(s, args, 0 | 4); ! 859: break; ! 860: case INDEX_op_qemu_ld16u: ! 861: tcg_out_qemu_ld(s, args, 1); ! 862: break; ! 863: case INDEX_op_qemu_ld16s: ! 864: tcg_out_qemu_ld(s, args, 1 | 4); ! 865: break; ! 866: case INDEX_op_qemu_ld32u: ! 867: tcg_out_qemu_ld(s, args, 2); ! 868: break; ! 869: ! 870: case INDEX_op_qemu_st8: ! 871: tcg_out_qemu_st(s, args, 0); ! 872: break; ! 873: case INDEX_op_qemu_st16: ! 874: tcg_out_qemu_st(s, args, 1); ! 875: break; ! 876: case INDEX_op_qemu_st32: ! 877: tcg_out_qemu_st(s, args, 2); ! 878: break; ! 879: ! 880: default: ! 881: fprintf(stderr, "unknown opcode 0x%x\n", opc); ! 882: tcg_abort(); ! 883: } ! 884: return; ! 885: ! 886: gen_arith: ! 887: tcg_out_arith(s, args[0], args[1], args[2], c); ! 888: } ! 889: ! 890: static const TCGTargetOpDef hppa_op_defs[] = { ! 891: { INDEX_op_exit_tb, { } }, ! 892: { INDEX_op_goto_tb, { } }, ! 893: ! 894: { INDEX_op_call, { "r" } }, ! 895: { INDEX_op_jmp, { "r" } }, ! 896: { INDEX_op_br, { } }, ! 897: ! 898: { INDEX_op_mov_i32, { "r", "r" } }, ! 899: { INDEX_op_movi_i32, { "r" } }, ! 900: { INDEX_op_ld8u_i32, { "r", "r" } }, ! 901: { INDEX_op_ld8s_i32, { "r", "r" } }, ! 902: { INDEX_op_ld16u_i32, { "r", "r" } }, ! 903: { INDEX_op_ld16s_i32, { "r", "r" } }, ! 904: { INDEX_op_ld_i32, { "r", "r" } }, ! 905: { INDEX_op_st8_i32, { "r", "r" } }, ! 906: { INDEX_op_st16_i32, { "r", "r" } }, ! 907: { INDEX_op_st_i32, { "r", "r" } }, ! 908: ! 909: { INDEX_op_add_i32, { "r", "r", "r" } }, ! 910: { INDEX_op_sub_i32, { "r", "r", "r" } }, ! 911: { INDEX_op_and_i32, { "r", "r", "r" } }, ! 912: { INDEX_op_or_i32, { "r", "r", "r" } }, ! 913: { INDEX_op_xor_i32, { "r", "r", "r" } }, ! 914: ! 915: { INDEX_op_shl_i32, { "r", "r", "r" } }, ! 916: { INDEX_op_shr_i32, { "r", "r", "r" } }, ! 917: { INDEX_op_sar_i32, { "r", "r", "r" } }, ! 918: ! 919: { INDEX_op_brcond_i32, { "r", "r" } }, ! 920: ! 921: #if TARGET_LONG_BITS == 32 ! 922: { INDEX_op_qemu_ld8u, { "r", "L" } }, ! 923: { INDEX_op_qemu_ld8s, { "r", "L" } }, ! 924: { INDEX_op_qemu_ld16u, { "r", "L" } }, ! 925: { INDEX_op_qemu_ld16s, { "r", "L" } }, ! 926: { INDEX_op_qemu_ld32u, { "r", "L" } }, ! 927: { INDEX_op_qemu_ld64, { "r", "r", "L" } }, ! 928: ! 929: { INDEX_op_qemu_st8, { "L", "L" } }, ! 930: { INDEX_op_qemu_st16, { "L", "L" } }, ! 931: { INDEX_op_qemu_st32, { "L", "L" } }, ! 932: { INDEX_op_qemu_st64, { "L", "L", "L" } }, ! 933: #else ! 934: { INDEX_op_qemu_ld8u, { "r", "L", "L" } }, ! 935: { INDEX_op_qemu_ld8s, { "r", "L", "L" } }, ! 936: { INDEX_op_qemu_ld16u, { "r", "L", "L" } }, ! 937: { INDEX_op_qemu_ld16s, { "r", "L", "L" } }, ! 938: { INDEX_op_qemu_ld32u, { "r", "L", "L" } }, ! 939: { INDEX_op_qemu_ld32s, { "r", "L", "L" } }, ! 940: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } }, ! 941: ! 942: { INDEX_op_qemu_st8, { "L", "L", "L" } }, ! 943: { INDEX_op_qemu_st16, { "L", "L", "L" } }, ! 944: { INDEX_op_qemu_st32, { "L", "L", "L" } }, ! 945: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } }, ! 946: #endif ! 947: { -1 }, ! 948: }; ! 949: ! 950: void tcg_target_init(TCGContext *s) ! 951: { ! 952: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); ! 953: tcg_regset_set32(tcg_target_call_clobber_regs, 0, ! 954: (1 << TCG_REG_R20) | ! 955: (1 << TCG_REG_R21) | ! 956: (1 << TCG_REG_R22) | ! 957: (1 << TCG_REG_R23) | ! 958: (1 << TCG_REG_R24) | ! 959: (1 << TCG_REG_R25) | ! 960: (1 << TCG_REG_R26)); ! 961: ! 962: tcg_regset_clear(s->reserved_regs); ! 963: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* hardwired to zero */ ! 964: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* addil target */ ! 965: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RP); /* link register */ ! 966: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3); /* frame pointer */ ! 967: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R18); /* return pointer */ ! 968: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */ ! 969: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */ ! 970: tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP); /* data pointer */ ! 971: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */ ! 972: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */ ! 973: ! 974: tcg_add_target_add_op_defs(hppa_op_defs); ! 975: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.