|
|
1.1 ! root 1: /* ! 2: * Tiny Code Generator for QEMU ! 3: * ! 4: * Copyright (c) 2009, 2011 Stefan Weil ! 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: /* TODO list: ! 26: * - See TODO comments in code. ! 27: */ ! 28: ! 29: /* Marker for missing code. */ ! 30: #define TODO() \ ! 31: do { \ ! 32: fprintf(stderr, "TODO %s:%u: %s()\n", \ ! 33: __FILE__, __LINE__, __func__); \ ! 34: tcg_abort(); \ ! 35: } while (0) ! 36: ! 37: /* Single bit n. */ ! 38: #define BIT(n) (1 << (n)) ! 39: ! 40: /* Bitfield n...m (in 32 bit value). */ ! 41: #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) ! 42: ! 43: /* Used for function call generation. */ ! 44: #define TCG_REG_CALL_STACK TCG_REG_R4 ! 45: #define TCG_TARGET_STACK_ALIGN 16 ! 46: #define TCG_TARGET_CALL_STACK_OFFSET 0 ! 47: ! 48: /* TODO: documentation. */ ! 49: static uint8_t *tb_ret_addr; ! 50: ! 51: /* Macros used in tcg_target_op_defs. */ ! 52: #define R "r" ! 53: #define RI "ri" ! 54: #if TCG_TARGET_REG_BITS == 32 ! 55: # define R64 "r", "r" ! 56: #else ! 57: # define R64 "r" ! 58: #endif ! 59: #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS ! 60: # define L "L", "L" ! 61: # define S "S", "S" ! 62: #else ! 63: # define L "L" ! 64: # define S "S" ! 65: #endif ! 66: ! 67: /* TODO: documentation. */ ! 68: static const TCGTargetOpDef tcg_target_op_defs[] = { ! 69: { INDEX_op_exit_tb, { NULL } }, ! 70: { INDEX_op_goto_tb, { NULL } }, ! 71: { INDEX_op_call, { RI } }, ! 72: { INDEX_op_jmp, { RI } }, ! 73: { INDEX_op_br, { NULL } }, ! 74: ! 75: { INDEX_op_mov_i32, { R, R } }, ! 76: { INDEX_op_movi_i32, { R } }, ! 77: ! 78: { INDEX_op_ld8u_i32, { R, R } }, ! 79: { INDEX_op_ld8s_i32, { R, R } }, ! 80: { INDEX_op_ld16u_i32, { R, R } }, ! 81: { INDEX_op_ld16s_i32, { R, R } }, ! 82: { INDEX_op_ld_i32, { R, R } }, ! 83: { INDEX_op_st8_i32, { R, R } }, ! 84: { INDEX_op_st16_i32, { R, R } }, ! 85: { INDEX_op_st_i32, { R, R } }, ! 86: ! 87: { INDEX_op_add_i32, { R, RI, RI } }, ! 88: { INDEX_op_sub_i32, { R, RI, RI } }, ! 89: { INDEX_op_mul_i32, { R, RI, RI } }, ! 90: #if TCG_TARGET_HAS_div_i32 ! 91: { INDEX_op_div_i32, { R, R, R } }, ! 92: { INDEX_op_divu_i32, { R, R, R } }, ! 93: { INDEX_op_rem_i32, { R, R, R } }, ! 94: { INDEX_op_remu_i32, { R, R, R } }, ! 95: #elif TCG_TARGET_HAS_div2_i32 ! 96: { INDEX_op_div2_i32, { R, R, "0", "1", R } }, ! 97: { INDEX_op_divu2_i32, { R, R, "0", "1", R } }, ! 98: #endif ! 99: /* TODO: Does R, RI, RI result in faster code than R, R, RI? ! 100: If both operands are constants, we can optimize. */ ! 101: { INDEX_op_and_i32, { R, RI, RI } }, ! 102: #if TCG_TARGET_HAS_andc_i32 ! 103: { INDEX_op_andc_i32, { R, RI, RI } }, ! 104: #endif ! 105: #if TCG_TARGET_HAS_eqv_i32 ! 106: { INDEX_op_eqv_i32, { R, RI, RI } }, ! 107: #endif ! 108: #if TCG_TARGET_HAS_nand_i32 ! 109: { INDEX_op_nand_i32, { R, RI, RI } }, ! 110: #endif ! 111: #if TCG_TARGET_HAS_nor_i32 ! 112: { INDEX_op_nor_i32, { R, RI, RI } }, ! 113: #endif ! 114: { INDEX_op_or_i32, { R, RI, RI } }, ! 115: #if TCG_TARGET_HAS_orc_i32 ! 116: { INDEX_op_orc_i32, { R, RI, RI } }, ! 117: #endif ! 118: { INDEX_op_xor_i32, { R, RI, RI } }, ! 119: { INDEX_op_shl_i32, { R, RI, RI } }, ! 120: { INDEX_op_shr_i32, { R, RI, RI } }, ! 121: { INDEX_op_sar_i32, { R, RI, RI } }, ! 122: #if TCG_TARGET_HAS_rot_i32 ! 123: { INDEX_op_rotl_i32, { R, RI, RI } }, ! 124: { INDEX_op_rotr_i32, { R, RI, RI } }, ! 125: #endif ! 126: ! 127: { INDEX_op_brcond_i32, { R, RI } }, ! 128: ! 129: { INDEX_op_setcond_i32, { R, R, RI } }, ! 130: #if TCG_TARGET_REG_BITS == 64 ! 131: { INDEX_op_setcond_i64, { R, R, RI } }, ! 132: #endif /* TCG_TARGET_REG_BITS == 64 */ ! 133: ! 134: #if TCG_TARGET_REG_BITS == 32 ! 135: /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */ ! 136: { INDEX_op_add2_i32, { R, R, R, R, R, R } }, ! 137: { INDEX_op_sub2_i32, { R, R, R, R, R, R } }, ! 138: { INDEX_op_brcond2_i32, { R, R, RI, RI } }, ! 139: { INDEX_op_mulu2_i32, { R, R, R, R } }, ! 140: { INDEX_op_setcond2_i32, { R, R, R, RI, RI } }, ! 141: #endif ! 142: ! 143: #if TCG_TARGET_HAS_not_i32 ! 144: { INDEX_op_not_i32, { R, R } }, ! 145: #endif ! 146: #if TCG_TARGET_HAS_neg_i32 ! 147: { INDEX_op_neg_i32, { R, R } }, ! 148: #endif ! 149: ! 150: #if TCG_TARGET_REG_BITS == 64 ! 151: { INDEX_op_mov_i64, { R, R } }, ! 152: { INDEX_op_movi_i64, { R } }, ! 153: ! 154: { INDEX_op_ld8u_i64, { R, R } }, ! 155: { INDEX_op_ld8s_i64, { R, R } }, ! 156: { INDEX_op_ld16u_i64, { R, R } }, ! 157: { INDEX_op_ld16s_i64, { R, R } }, ! 158: { INDEX_op_ld32u_i64, { R, R } }, ! 159: { INDEX_op_ld32s_i64, { R, R } }, ! 160: { INDEX_op_ld_i64, { R, R } }, ! 161: ! 162: { INDEX_op_st8_i64, { R, R } }, ! 163: { INDEX_op_st16_i64, { R, R } }, ! 164: { INDEX_op_st32_i64, { R, R } }, ! 165: { INDEX_op_st_i64, { R, R } }, ! 166: ! 167: { INDEX_op_add_i64, { R, RI, RI } }, ! 168: { INDEX_op_sub_i64, { R, RI, RI } }, ! 169: { INDEX_op_mul_i64, { R, RI, RI } }, ! 170: #if TCG_TARGET_HAS_div_i64 ! 171: { INDEX_op_div_i64, { R, R, R } }, ! 172: { INDEX_op_divu_i64, { R, R, R } }, ! 173: { INDEX_op_rem_i64, { R, R, R } }, ! 174: { INDEX_op_remu_i64, { R, R, R } }, ! 175: #elif TCG_TARGET_HAS_div2_i64 ! 176: { INDEX_op_div2_i64, { R, R, "0", "1", R } }, ! 177: { INDEX_op_divu2_i64, { R, R, "0", "1", R } }, ! 178: #endif ! 179: { INDEX_op_and_i64, { R, RI, RI } }, ! 180: #if TCG_TARGET_HAS_andc_i64 ! 181: { INDEX_op_andc_i64, { R, RI, RI } }, ! 182: #endif ! 183: #if TCG_TARGET_HAS_eqv_i64 ! 184: { INDEX_op_eqv_i64, { R, RI, RI } }, ! 185: #endif ! 186: #if TCG_TARGET_HAS_nand_i64 ! 187: { INDEX_op_nand_i64, { R, RI, RI } }, ! 188: #endif ! 189: #if TCG_TARGET_HAS_nor_i64 ! 190: { INDEX_op_nor_i64, { R, RI, RI } }, ! 191: #endif ! 192: { INDEX_op_or_i64, { R, RI, RI } }, ! 193: #if TCG_TARGET_HAS_orc_i64 ! 194: { INDEX_op_orc_i64, { R, RI, RI } }, ! 195: #endif ! 196: { INDEX_op_xor_i64, { R, RI, RI } }, ! 197: { INDEX_op_shl_i64, { R, RI, RI } }, ! 198: { INDEX_op_shr_i64, { R, RI, RI } }, ! 199: { INDEX_op_sar_i64, { R, RI, RI } }, ! 200: #if TCG_TARGET_HAS_rot_i64 ! 201: { INDEX_op_rotl_i64, { R, RI, RI } }, ! 202: { INDEX_op_rotr_i64, { R, RI, RI } }, ! 203: #endif ! 204: { INDEX_op_brcond_i64, { R, RI } }, ! 205: ! 206: #if TCG_TARGET_HAS_ext8s_i64 ! 207: { INDEX_op_ext8s_i64, { R, R } }, ! 208: #endif ! 209: #if TCG_TARGET_HAS_ext16s_i64 ! 210: { INDEX_op_ext16s_i64, { R, R } }, ! 211: #endif ! 212: #if TCG_TARGET_HAS_ext32s_i64 ! 213: { INDEX_op_ext32s_i64, { R, R } }, ! 214: #endif ! 215: #if TCG_TARGET_HAS_ext8u_i64 ! 216: { INDEX_op_ext8u_i64, { R, R } }, ! 217: #endif ! 218: #if TCG_TARGET_HAS_ext16u_i64 ! 219: { INDEX_op_ext16u_i64, { R, R } }, ! 220: #endif ! 221: #if TCG_TARGET_HAS_ext32u_i64 ! 222: { INDEX_op_ext32u_i64, { R, R } }, ! 223: #endif ! 224: #if TCG_TARGET_HAS_bswap16_i64 ! 225: { INDEX_op_bswap16_i64, { R, R } }, ! 226: #endif ! 227: #if TCG_TARGET_HAS_bswap32_i64 ! 228: { INDEX_op_bswap32_i64, { R, R } }, ! 229: #endif ! 230: #if TCG_TARGET_HAS_bswap64_i64 ! 231: { INDEX_op_bswap64_i64, { R, R } }, ! 232: #endif ! 233: #if TCG_TARGET_HAS_not_i64 ! 234: { INDEX_op_not_i64, { R, R } }, ! 235: #endif ! 236: #if TCG_TARGET_HAS_neg_i64 ! 237: { INDEX_op_neg_i64, { R, R } }, ! 238: #endif ! 239: #endif /* TCG_TARGET_REG_BITS == 64 */ ! 240: ! 241: { INDEX_op_qemu_ld8u, { R, L } }, ! 242: { INDEX_op_qemu_ld8s, { R, L } }, ! 243: { INDEX_op_qemu_ld16u, { R, L } }, ! 244: { INDEX_op_qemu_ld16s, { R, L } }, ! 245: { INDEX_op_qemu_ld32, { R, L } }, ! 246: #if TCG_TARGET_REG_BITS == 64 ! 247: { INDEX_op_qemu_ld32u, { R, L } }, ! 248: { INDEX_op_qemu_ld32s, { R, L } }, ! 249: #endif ! 250: { INDEX_op_qemu_ld64, { R64, L } }, ! 251: ! 252: { INDEX_op_qemu_st8, { R, S } }, ! 253: { INDEX_op_qemu_st16, { R, S } }, ! 254: { INDEX_op_qemu_st32, { R, S } }, ! 255: { INDEX_op_qemu_st64, { R64, S } }, ! 256: ! 257: #if TCG_TARGET_HAS_ext8s_i32 ! 258: { INDEX_op_ext8s_i32, { R, R } }, ! 259: #endif ! 260: #if TCG_TARGET_HAS_ext16s_i32 ! 261: { INDEX_op_ext16s_i32, { R, R } }, ! 262: #endif ! 263: #if TCG_TARGET_HAS_ext8u_i32 ! 264: { INDEX_op_ext8u_i32, { R, R } }, ! 265: #endif ! 266: #if TCG_TARGET_HAS_ext16u_i32 ! 267: { INDEX_op_ext16u_i32, { R, R } }, ! 268: #endif ! 269: ! 270: #if TCG_TARGET_HAS_bswap16_i32 ! 271: { INDEX_op_bswap16_i32, { R, R } }, ! 272: #endif ! 273: #if TCG_TARGET_HAS_bswap32_i32 ! 274: { INDEX_op_bswap32_i32, { R, R } }, ! 275: #endif ! 276: ! 277: { -1 }, ! 278: }; ! 279: ! 280: static const int tcg_target_reg_alloc_order[] = { ! 281: TCG_REG_R0, ! 282: TCG_REG_R1, ! 283: TCG_REG_R2, ! 284: TCG_REG_R3, ! 285: #if 0 /* used for TCG_REG_CALL_STACK */ ! 286: TCG_REG_R4, ! 287: #endif ! 288: TCG_REG_R5, ! 289: TCG_REG_R6, ! 290: TCG_REG_R7, ! 291: #if TCG_TARGET_NB_REGS >= 16 ! 292: TCG_REG_R8, ! 293: TCG_REG_R9, ! 294: TCG_REG_R10, ! 295: TCG_REG_R11, ! 296: TCG_REG_R12, ! 297: TCG_REG_R13, ! 298: TCG_REG_R14, ! 299: TCG_REG_R15, ! 300: #endif ! 301: }; ! 302: ! 303: #if MAX_OPC_PARAM_IARGS != 4 ! 304: # error Fix needed, number of supported input arguments changed! ! 305: #endif ! 306: ! 307: static const int tcg_target_call_iarg_regs[] = { ! 308: TCG_REG_R0, ! 309: TCG_REG_R1, ! 310: TCG_REG_R2, ! 311: TCG_REG_R3, ! 312: #if TCG_TARGET_REG_BITS == 32 ! 313: /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */ ! 314: #if 0 /* used for TCG_REG_CALL_STACK */ ! 315: TCG_REG_R4, ! 316: #endif ! 317: TCG_REG_R5, ! 318: TCG_REG_R6, ! 319: TCG_REG_R7, ! 320: #if TCG_TARGET_NB_REGS >= 16 ! 321: TCG_REG_R8, ! 322: #else ! 323: # error Too few input registers available ! 324: #endif ! 325: #endif ! 326: }; ! 327: ! 328: static const int tcg_target_call_oarg_regs[] = { ! 329: TCG_REG_R0, ! 330: #if TCG_TARGET_REG_BITS == 32 ! 331: TCG_REG_R1 ! 332: #endif ! 333: }; ! 334: ! 335: #ifndef NDEBUG ! 336: static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ! 337: "r00", ! 338: "r01", ! 339: "r02", ! 340: "r03", ! 341: "r04", ! 342: "r05", ! 343: "r06", ! 344: "r07", ! 345: #if TCG_TARGET_NB_REGS >= 16 ! 346: "r08", ! 347: "r09", ! 348: "r10", ! 349: "r11", ! 350: "r12", ! 351: "r13", ! 352: "r14", ! 353: "r15", ! 354: #if TCG_TARGET_NB_REGS >= 32 ! 355: "r16", ! 356: "r17", ! 357: "r18", ! 358: "r19", ! 359: "r20", ! 360: "r21", ! 361: "r22", ! 362: "r23", ! 363: "r24", ! 364: "r25", ! 365: "r26", ! 366: "r27", ! 367: "r28", ! 368: "r29", ! 369: "r30", ! 370: "r31" ! 371: #endif ! 372: #endif ! 373: }; ! 374: #endif ! 375: ! 376: static void patch_reloc(uint8_t *code_ptr, int type, ! 377: tcg_target_long value, tcg_target_long addend) ! 378: { ! 379: /* tcg_out_reloc always uses the same type, addend. */ ! 380: assert(type == sizeof(tcg_target_long)); ! 381: assert(addend == 0); ! 382: assert(value != 0); ! 383: *(tcg_target_long *)code_ptr = value; ! 384: } ! 385: ! 386: /* Parse target specific constraints. */ ! 387: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ! 388: { ! 389: const char *ct_str = *pct_str; ! 390: switch (ct_str[0]) { ! 391: case 'r': ! 392: case 'L': /* qemu_ld constraint */ ! 393: case 'S': /* qemu_st constraint */ ! 394: ct->ct |= TCG_CT_REG; ! 395: tcg_regset_set32(ct->u.regs, 0, BIT(TCG_TARGET_NB_REGS) - 1); ! 396: break; ! 397: default: ! 398: return -1; ! 399: } ! 400: ct_str++; ! 401: *pct_str = ct_str; ! 402: return 0; ! 403: } ! 404: ! 405: #if defined(CONFIG_DEBUG_TCG_INTERPRETER) ! 406: /* Show current bytecode. Used by tcg interpreter. */ ! 407: void tci_disas(uint8_t opc) ! 408: { ! 409: const TCGOpDef *def = &tcg_op_defs[opc]; ! 410: fprintf(stderr, "TCG %s %u, %u, %u\n", ! 411: def->name, def->nb_oargs, def->nb_iargs, def->nb_cargs); ! 412: } ! 413: #endif ! 414: ! 415: /* Write value (native size). */ ! 416: static void tcg_out_i(TCGContext *s, tcg_target_ulong v) ! 417: { ! 418: *(tcg_target_ulong *)s->code_ptr = v; ! 419: s->code_ptr += sizeof(tcg_target_ulong); ! 420: } ! 421: ! 422: /* Write 64 bit value. */ ! 423: static void tcg_out64(TCGContext *s, uint64_t v) ! 424: { ! 425: *(uint64_t *)s->code_ptr = v; ! 426: s->code_ptr += sizeof(v); ! 427: } ! 428: ! 429: /* Write opcode. */ ! 430: static void tcg_out_op_t(TCGContext *s, TCGOpcode op) ! 431: { ! 432: tcg_out8(s, op); ! 433: tcg_out8(s, 0); ! 434: } ! 435: ! 436: /* Write register. */ ! 437: static void tcg_out_r(TCGContext *s, TCGArg t0) ! 438: { ! 439: assert(t0 < TCG_TARGET_NB_REGS); ! 440: tcg_out8(s, t0); ! 441: } ! 442: ! 443: /* Write register or constant (native size). */ ! 444: static void tcg_out_ri(TCGContext *s, int const_arg, TCGArg arg) ! 445: { ! 446: if (const_arg) { ! 447: assert(const_arg == 1); ! 448: tcg_out8(s, TCG_CONST); ! 449: tcg_out_i(s, arg); ! 450: } else { ! 451: tcg_out_r(s, arg); ! 452: } ! 453: } ! 454: ! 455: /* Write register or constant (32 bit). */ ! 456: static void tcg_out_ri32(TCGContext *s, int const_arg, TCGArg arg) ! 457: { ! 458: if (const_arg) { ! 459: assert(const_arg == 1); ! 460: tcg_out8(s, TCG_CONST); ! 461: tcg_out32(s, arg); ! 462: } else { ! 463: tcg_out_r(s, arg); ! 464: } ! 465: } ! 466: ! 467: #if TCG_TARGET_REG_BITS == 64 ! 468: /* Write register or constant (64 bit). */ ! 469: static void tcg_out_ri64(TCGContext *s, int const_arg, TCGArg arg) ! 470: { ! 471: if (const_arg) { ! 472: assert(const_arg == 1); ! 473: tcg_out8(s, TCG_CONST); ! 474: tcg_out64(s, arg); ! 475: } else { ! 476: tcg_out_r(s, arg); ! 477: } ! 478: } ! 479: #endif ! 480: ! 481: /* Write label. */ ! 482: static void tci_out_label(TCGContext *s, TCGArg arg) ! 483: { ! 484: TCGLabel *label = &s->labels[arg]; ! 485: if (label->has_value) { ! 486: tcg_out_i(s, label->u.value); ! 487: assert(label->u.value); ! 488: } else { ! 489: tcg_out_reloc(s, s->code_ptr, sizeof(tcg_target_ulong), arg, 0); ! 490: tcg_out_i(s, 0); ! 491: } ! 492: } ! 493: ! 494: static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, ! 495: tcg_target_long arg2) ! 496: { ! 497: uint8_t *old_code_ptr = s->code_ptr; ! 498: if (type == TCG_TYPE_I32) { ! 499: tcg_out_op_t(s, INDEX_op_ld_i32); ! 500: tcg_out_r(s, ret); ! 501: tcg_out_r(s, arg1); ! 502: tcg_out32(s, arg2); ! 503: } else { ! 504: assert(type == TCG_TYPE_I64); ! 505: #if TCG_TARGET_REG_BITS == 64 ! 506: tcg_out_op_t(s, INDEX_op_ld_i64); ! 507: tcg_out_r(s, ret); ! 508: tcg_out_r(s, arg1); ! 509: assert(arg2 == (uint32_t)arg2); ! 510: tcg_out32(s, arg2); ! 511: #else ! 512: TODO(); ! 513: #endif ! 514: } ! 515: old_code_ptr[1] = s->code_ptr - old_code_ptr; ! 516: } ! 517: ! 518: static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) ! 519: { ! 520: uint8_t *old_code_ptr = s->code_ptr; ! 521: assert(ret != arg); ! 522: #if TCG_TARGET_REG_BITS == 32 ! 523: tcg_out_op_t(s, INDEX_op_mov_i32); ! 524: #else ! 525: tcg_out_op_t(s, INDEX_op_mov_i64); ! 526: #endif ! 527: tcg_out_r(s, ret); ! 528: tcg_out_r(s, arg); ! 529: old_code_ptr[1] = s->code_ptr - old_code_ptr; ! 530: } ! 531: ! 532: static void tcg_out_movi(TCGContext *s, TCGType type, ! 533: TCGReg t0, tcg_target_long arg) ! 534: { ! 535: uint8_t *old_code_ptr = s->code_ptr; ! 536: uint32_t arg32 = arg; ! 537: if (type == TCG_TYPE_I32 || arg == arg32) { ! 538: tcg_out_op_t(s, INDEX_op_movi_i32); ! 539: tcg_out_r(s, t0); ! 540: tcg_out32(s, arg32); ! 541: } else { ! 542: assert(type == TCG_TYPE_I64); ! 543: #if TCG_TARGET_REG_BITS == 64 ! 544: tcg_out_op_t(s, INDEX_op_movi_i64); ! 545: tcg_out_r(s, t0); ! 546: tcg_out64(s, arg); ! 547: #else ! 548: TODO(); ! 549: #endif ! 550: } ! 551: old_code_ptr[1] = s->code_ptr - old_code_ptr; ! 552: } ! 553: ! 554: static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, ! 555: const int *const_args) ! 556: { ! 557: uint8_t *old_code_ptr = s->code_ptr; ! 558: ! 559: tcg_out_op_t(s, opc); ! 560: ! 561: switch (opc) { ! 562: case INDEX_op_exit_tb: ! 563: tcg_out64(s, args[0]); ! 564: break; ! 565: case INDEX_op_goto_tb: ! 566: if (s->tb_jmp_offset) { ! 567: /* Direct jump method. */ ! 568: assert(args[0] < ARRAY_SIZE(s->tb_jmp_offset)); ! 569: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; ! 570: tcg_out32(s, 0); ! 571: } else { ! 572: /* Indirect jump method. */ ! 573: TODO(); ! 574: } ! 575: assert(args[0] < ARRAY_SIZE(s->tb_next_offset)); ! 576: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ! 577: break; ! 578: case INDEX_op_br: ! 579: tci_out_label(s, args[0]); ! 580: break; ! 581: case INDEX_op_call: ! 582: tcg_out_ri(s, const_args[0], args[0]); ! 583: break; ! 584: case INDEX_op_jmp: ! 585: TODO(); ! 586: break; ! 587: case INDEX_op_setcond_i32: ! 588: tcg_out_r(s, args[0]); ! 589: tcg_out_r(s, args[1]); ! 590: tcg_out_ri32(s, const_args[2], args[2]); ! 591: tcg_out8(s, args[3]); /* condition */ ! 592: break; ! 593: #if TCG_TARGET_REG_BITS == 32 ! 594: case INDEX_op_setcond2_i32: ! 595: /* setcond2_i32 cond, t0, t1_low, t1_high, t2_low, t2_high */ ! 596: tcg_out_r(s, args[0]); ! 597: tcg_out_r(s, args[1]); ! 598: tcg_out_r(s, args[2]); ! 599: tcg_out_ri32(s, const_args[3], args[3]); ! 600: tcg_out_ri32(s, const_args[4], args[4]); ! 601: tcg_out8(s, args[5]); /* condition */ ! 602: break; ! 603: #elif TCG_TARGET_REG_BITS == 64 ! 604: case INDEX_op_setcond_i64: ! 605: tcg_out_r(s, args[0]); ! 606: tcg_out_r(s, args[1]); ! 607: tcg_out_ri64(s, const_args[2], args[2]); ! 608: tcg_out8(s, args[3]); /* condition */ ! 609: break; ! 610: #endif ! 611: case INDEX_op_movi_i32: ! 612: TODO(); /* Handled by tcg_out_movi? */ ! 613: break; ! 614: case INDEX_op_ld8u_i32: ! 615: case INDEX_op_ld8s_i32: ! 616: case INDEX_op_ld16u_i32: ! 617: case INDEX_op_ld16s_i32: ! 618: case INDEX_op_ld_i32: ! 619: case INDEX_op_st8_i32: ! 620: case INDEX_op_st16_i32: ! 621: case INDEX_op_st_i32: ! 622: case INDEX_op_ld8u_i64: ! 623: case INDEX_op_ld8s_i64: ! 624: case INDEX_op_ld16u_i64: ! 625: case INDEX_op_ld16s_i64: ! 626: case INDEX_op_ld32u_i64: ! 627: case INDEX_op_ld32s_i64: ! 628: case INDEX_op_ld_i64: ! 629: case INDEX_op_st8_i64: ! 630: case INDEX_op_st16_i64: ! 631: case INDEX_op_st32_i64: ! 632: case INDEX_op_st_i64: ! 633: tcg_out_r(s, args[0]); ! 634: tcg_out_r(s, args[1]); ! 635: assert(args[2] == (uint32_t)args[2]); ! 636: tcg_out32(s, args[2]); ! 637: break; ! 638: case INDEX_op_add_i32: ! 639: case INDEX_op_sub_i32: ! 640: case INDEX_op_mul_i32: ! 641: case INDEX_op_and_i32: ! 642: case INDEX_op_andc_i32: /* Optional (TCG_TARGET_HAS_andc_i32). */ ! 643: case INDEX_op_eqv_i32: /* Optional (TCG_TARGET_HAS_eqv_i32). */ ! 644: case INDEX_op_nand_i32: /* Optional (TCG_TARGET_HAS_nand_i32). */ ! 645: case INDEX_op_nor_i32: /* Optional (TCG_TARGET_HAS_nor_i32). */ ! 646: case INDEX_op_or_i32: ! 647: case INDEX_op_orc_i32: /* Optional (TCG_TARGET_HAS_orc_i32). */ ! 648: case INDEX_op_xor_i32: ! 649: case INDEX_op_shl_i32: ! 650: case INDEX_op_shr_i32: ! 651: case INDEX_op_sar_i32: ! 652: case INDEX_op_rotl_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */ ! 653: case INDEX_op_rotr_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */ ! 654: tcg_out_r(s, args[0]); ! 655: tcg_out_ri32(s, const_args[1], args[1]); ! 656: tcg_out_ri32(s, const_args[2], args[2]); ! 657: break; ! 658: ! 659: #if TCG_TARGET_REG_BITS == 64 ! 660: case INDEX_op_mov_i64: ! 661: case INDEX_op_movi_i64: ! 662: TODO(); ! 663: break; ! 664: case INDEX_op_add_i64: ! 665: case INDEX_op_sub_i64: ! 666: case INDEX_op_mul_i64: ! 667: case INDEX_op_and_i64: ! 668: case INDEX_op_andc_i64: /* Optional (TCG_TARGET_HAS_andc_i64). */ ! 669: case INDEX_op_eqv_i64: /* Optional (TCG_TARGET_HAS_eqv_i64). */ ! 670: case INDEX_op_nand_i64: /* Optional (TCG_TARGET_HAS_nand_i64). */ ! 671: case INDEX_op_nor_i64: /* Optional (TCG_TARGET_HAS_nor_i64). */ ! 672: case INDEX_op_or_i64: ! 673: case INDEX_op_orc_i64: /* Optional (TCG_TARGET_HAS_orc_i64). */ ! 674: case INDEX_op_xor_i64: ! 675: case INDEX_op_shl_i64: ! 676: case INDEX_op_shr_i64: ! 677: case INDEX_op_sar_i64: ! 678: /* TODO: Implementation of rotl_i64, rotr_i64 missing in tci.c. */ ! 679: case INDEX_op_rotl_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ ! 680: case INDEX_op_rotr_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ ! 681: tcg_out_r(s, args[0]); ! 682: tcg_out_ri64(s, const_args[1], args[1]); ! 683: tcg_out_ri64(s, const_args[2], args[2]); ! 684: break; ! 685: case INDEX_op_div_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ ! 686: case INDEX_op_divu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ ! 687: case INDEX_op_rem_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ ! 688: case INDEX_op_remu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ ! 689: TODO(); ! 690: break; ! 691: case INDEX_op_div2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */ ! 692: case INDEX_op_divu2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */ ! 693: TODO(); ! 694: break; ! 695: case INDEX_op_brcond_i64: ! 696: tcg_out_r(s, args[0]); ! 697: tcg_out_ri64(s, const_args[1], args[1]); ! 698: tcg_out8(s, args[2]); /* condition */ ! 699: tci_out_label(s, args[3]); ! 700: break; ! 701: case INDEX_op_bswap16_i64: /* Optional (TCG_TARGET_HAS_bswap16_i64). */ ! 702: case INDEX_op_bswap32_i64: /* Optional (TCG_TARGET_HAS_bswap32_i64). */ ! 703: case INDEX_op_bswap64_i64: /* Optional (TCG_TARGET_HAS_bswap64_i64). */ ! 704: case INDEX_op_not_i64: /* Optional (TCG_TARGET_HAS_not_i64). */ ! 705: case INDEX_op_neg_i64: /* Optional (TCG_TARGET_HAS_neg_i64). */ ! 706: case INDEX_op_ext8s_i64: /* Optional (TCG_TARGET_HAS_ext8s_i64). */ ! 707: case INDEX_op_ext8u_i64: /* Optional (TCG_TARGET_HAS_ext8u_i64). */ ! 708: case INDEX_op_ext16s_i64: /* Optional (TCG_TARGET_HAS_ext16s_i64). */ ! 709: case INDEX_op_ext16u_i64: /* Optional (TCG_TARGET_HAS_ext16u_i64). */ ! 710: case INDEX_op_ext32s_i64: /* Optional (TCG_TARGET_HAS_ext32s_i64). */ ! 711: case INDEX_op_ext32u_i64: /* Optional (TCG_TARGET_HAS_ext32u_i64). */ ! 712: #endif /* TCG_TARGET_REG_BITS == 64 */ ! 713: case INDEX_op_neg_i32: /* Optional (TCG_TARGET_HAS_neg_i32). */ ! 714: case INDEX_op_not_i32: /* Optional (TCG_TARGET_HAS_not_i32). */ ! 715: case INDEX_op_ext8s_i32: /* Optional (TCG_TARGET_HAS_ext8s_i32). */ ! 716: case INDEX_op_ext16s_i32: /* Optional (TCG_TARGET_HAS_ext16s_i32). */ ! 717: case INDEX_op_ext8u_i32: /* Optional (TCG_TARGET_HAS_ext8u_i32). */ ! 718: case INDEX_op_ext16u_i32: /* Optional (TCG_TARGET_HAS_ext16u_i32). */ ! 719: case INDEX_op_bswap16_i32: /* Optional (TCG_TARGET_HAS_bswap16_i32). */ ! 720: case INDEX_op_bswap32_i32: /* Optional (TCG_TARGET_HAS_bswap32_i32). */ ! 721: tcg_out_r(s, args[0]); ! 722: tcg_out_r(s, args[1]); ! 723: break; ! 724: case INDEX_op_div_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ ! 725: case INDEX_op_divu_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ ! 726: case INDEX_op_rem_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ ! 727: case INDEX_op_remu_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ ! 728: tcg_out_r(s, args[0]); ! 729: tcg_out_ri32(s, const_args[1], args[1]); ! 730: tcg_out_ri32(s, const_args[2], args[2]); ! 731: break; ! 732: case INDEX_op_div2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */ ! 733: case INDEX_op_divu2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */ ! 734: TODO(); ! 735: break; ! 736: #if TCG_TARGET_REG_BITS == 32 ! 737: case INDEX_op_add2_i32: ! 738: case INDEX_op_sub2_i32: ! 739: tcg_out_r(s, args[0]); ! 740: tcg_out_r(s, args[1]); ! 741: tcg_out_r(s, args[2]); ! 742: tcg_out_r(s, args[3]); ! 743: tcg_out_r(s, args[4]); ! 744: tcg_out_r(s, args[5]); ! 745: break; ! 746: case INDEX_op_brcond2_i32: ! 747: tcg_out_r(s, args[0]); ! 748: tcg_out_r(s, args[1]); ! 749: tcg_out_ri32(s, const_args[2], args[2]); ! 750: tcg_out_ri32(s, const_args[3], args[3]); ! 751: tcg_out8(s, args[4]); /* condition */ ! 752: tci_out_label(s, args[5]); ! 753: break; ! 754: case INDEX_op_mulu2_i32: ! 755: tcg_out_r(s, args[0]); ! 756: tcg_out_r(s, args[1]); ! 757: tcg_out_r(s, args[2]); ! 758: tcg_out_r(s, args[3]); ! 759: break; ! 760: #endif ! 761: case INDEX_op_brcond_i32: ! 762: tcg_out_r(s, args[0]); ! 763: tcg_out_ri32(s, const_args[1], args[1]); ! 764: tcg_out8(s, args[2]); /* condition */ ! 765: tci_out_label(s, args[3]); ! 766: break; ! 767: case INDEX_op_qemu_ld8u: ! 768: case INDEX_op_qemu_ld8s: ! 769: case INDEX_op_qemu_ld16u: ! 770: case INDEX_op_qemu_ld16s: ! 771: case INDEX_op_qemu_ld32: ! 772: #if TCG_TARGET_REG_BITS == 64 ! 773: case INDEX_op_qemu_ld32s: ! 774: case INDEX_op_qemu_ld32u: ! 775: #endif ! 776: tcg_out_r(s, *args++); ! 777: tcg_out_r(s, *args++); ! 778: #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS ! 779: tcg_out_r(s, *args++); ! 780: #endif ! 781: #ifdef CONFIG_SOFTMMU ! 782: tcg_out_i(s, *args); ! 783: #endif ! 784: break; ! 785: case INDEX_op_qemu_ld64: ! 786: tcg_out_r(s, *args++); ! 787: #if TCG_TARGET_REG_BITS == 32 ! 788: tcg_out_r(s, *args++); ! 789: #endif ! 790: tcg_out_r(s, *args++); ! 791: #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS ! 792: tcg_out_r(s, *args++); ! 793: #endif ! 794: #ifdef CONFIG_SOFTMMU ! 795: tcg_out_i(s, *args); ! 796: #endif ! 797: break; ! 798: case INDEX_op_qemu_st8: ! 799: case INDEX_op_qemu_st16: ! 800: case INDEX_op_qemu_st32: ! 801: tcg_out_r(s, *args++); ! 802: tcg_out_r(s, *args++); ! 803: #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS ! 804: tcg_out_r(s, *args++); ! 805: #endif ! 806: #ifdef CONFIG_SOFTMMU ! 807: tcg_out_i(s, *args); ! 808: #endif ! 809: break; ! 810: case INDEX_op_qemu_st64: ! 811: tcg_out_r(s, *args++); ! 812: #if TCG_TARGET_REG_BITS == 32 ! 813: tcg_out_r(s, *args++); ! 814: #endif ! 815: tcg_out_r(s, *args++); ! 816: #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS ! 817: tcg_out_r(s, *args++); ! 818: #endif ! 819: #ifdef CONFIG_SOFTMMU ! 820: tcg_out_i(s, *args); ! 821: #endif ! 822: break; ! 823: case INDEX_op_end: ! 824: TODO(); ! 825: break; ! 826: default: ! 827: fprintf(stderr, "Missing: %s\n", tcg_op_defs[opc].name); ! 828: tcg_abort(); ! 829: } ! 830: old_code_ptr[1] = s->code_ptr - old_code_ptr; ! 831: } ! 832: ! 833: static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, ! 834: tcg_target_long arg2) ! 835: { ! 836: uint8_t *old_code_ptr = s->code_ptr; ! 837: if (type == TCG_TYPE_I32) { ! 838: tcg_out_op_t(s, INDEX_op_st_i32); ! 839: tcg_out_r(s, arg); ! 840: tcg_out_r(s, arg1); ! 841: tcg_out32(s, arg2); ! 842: } else { ! 843: assert(type == TCG_TYPE_I64); ! 844: #if TCG_TARGET_REG_BITS == 64 ! 845: tcg_out_op_t(s, INDEX_op_st_i64); ! 846: tcg_out_r(s, arg); ! 847: tcg_out_r(s, arg1); ! 848: tcg_out32(s, arg2); ! 849: #else ! 850: TODO(); ! 851: #endif ! 852: } ! 853: old_code_ptr[1] = s->code_ptr - old_code_ptr; ! 854: } ! 855: ! 856: /* Test if a constant matches the constraint. */ ! 857: static int tcg_target_const_match(tcg_target_long val, ! 858: const TCGArgConstraint *arg_ct) ! 859: { ! 860: /* No need to return 0 or 1, 0 or != 0 is good enough. */ ! 861: return arg_ct->ct & TCG_CT_CONST; ! 862: } ! 863: ! 864: /* Maximum number of register used for input function arguments. */ ! 865: static int tcg_target_get_call_iarg_regs_count(int flags) ! 866: { ! 867: return ARRAY_SIZE(tcg_target_call_iarg_regs); ! 868: } ! 869: ! 870: static void tcg_target_init(TCGContext *s) ! 871: { ! 872: #if defined(CONFIG_DEBUG_TCG_INTERPRETER) ! 873: const char *envval = getenv("DEBUG_TCG"); ! 874: if (envval) { ! 875: loglevel = strtol(envval, NULL, 0); ! 876: } ! 877: #endif ! 878: ! 879: /* The current code uses uint8_t for tcg operations. */ ! 880: assert(ARRAY_SIZE(tcg_op_defs) <= UINT8_MAX); ! 881: ! 882: /* Registers available for 32 bit operations. */ ! 883: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, ! 884: BIT(TCG_TARGET_NB_REGS) - 1); ! 885: /* Registers available for 64 bit operations. */ ! 886: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, ! 887: BIT(TCG_TARGET_NB_REGS) - 1); ! 888: /* TODO: Which registers should be set here? */ ! 889: tcg_regset_set32(tcg_target_call_clobber_regs, 0, ! 890: BIT(TCG_TARGET_NB_REGS) - 1); ! 891: tcg_regset_clear(s->reserved_regs); ! 892: tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); ! 893: tcg_add_target_add_op_defs(tcg_target_op_defs); ! 894: tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf), ! 895: CPU_TEMP_BUF_NLONGS * sizeof(long)); ! 896: } ! 897: ! 898: /* Generate global QEMU prologue and epilogue code. */ ! 899: static void tcg_target_qemu_prologue(TCGContext *s) ! 900: { ! 901: tb_ret_addr = s->code_ptr; ! 902: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.