|
|
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: "%rax", ! 28: "%rcx", ! 29: "%rdx", ! 30: "%rbx", ! 31: "%rsp", ! 32: "%rbp", ! 33: "%rsi", ! 34: "%rdi", ! 35: "%r8", ! 36: "%r9", ! 37: "%r10", ! 38: "%r11", ! 39: "%r12", ! 40: "%r13", ! 41: "%r14", ! 42: "%r15", ! 43: }; ! 44: #endif ! 45: ! 46: static const int tcg_target_reg_alloc_order[] = { ! 47: TCG_REG_RDI, ! 48: TCG_REG_RSI, ! 49: TCG_REG_RDX, ! 50: TCG_REG_RCX, ! 51: TCG_REG_R8, ! 52: TCG_REG_R9, ! 53: TCG_REG_RAX, ! 54: TCG_REG_R10, ! 55: TCG_REG_R11, ! 56: ! 57: TCG_REG_RBP, ! 58: TCG_REG_RBX, ! 59: TCG_REG_R12, ! 60: TCG_REG_R13, ! 61: TCG_REG_R14, ! 62: TCG_REG_R15, ! 63: }; ! 64: ! 65: static const int tcg_target_call_iarg_regs[6] = { ! 66: TCG_REG_RDI, ! 67: TCG_REG_RSI, ! 68: TCG_REG_RDX, ! 69: TCG_REG_RCX, ! 70: TCG_REG_R8, ! 71: TCG_REG_R9, ! 72: }; ! 73: ! 74: static const int tcg_target_call_oarg_regs[2] = { ! 75: TCG_REG_RAX, ! 76: TCG_REG_RDX ! 77: }; ! 78: ! 79: static uint8_t *tb_ret_addr; ! 80: ! 81: static void patch_reloc(uint8_t *code_ptr, int type, ! 82: tcg_target_long value, tcg_target_long addend) ! 83: { ! 84: value += addend; ! 85: switch(type) { ! 86: case R_X86_64_32: ! 87: if (value != (uint32_t)value) ! 88: tcg_abort(); ! 89: *(uint32_t *)code_ptr = value; ! 90: break; ! 91: case R_X86_64_32S: ! 92: if (value != (int32_t)value) ! 93: tcg_abort(); ! 94: *(uint32_t *)code_ptr = value; ! 95: break; ! 96: case R_386_PC32: ! 97: value -= (long)code_ptr; ! 98: if (value != (int32_t)value) ! 99: tcg_abort(); ! 100: *(uint32_t *)code_ptr = value; ! 101: break; ! 102: default: ! 103: tcg_abort(); ! 104: } ! 105: } ! 106: ! 107: /* maximum number of register used for input function arguments */ ! 108: static inline int tcg_target_get_call_iarg_regs_count(int flags) ! 109: { ! 110: return 6; ! 111: } ! 112: ! 113: /* parse target specific constraints */ ! 114: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ! 115: { ! 116: const char *ct_str; ! 117: ! 118: ct_str = *pct_str; ! 119: switch(ct_str[0]) { ! 120: case 'a': ! 121: ct->ct |= TCG_CT_REG; ! 122: tcg_regset_set_reg(ct->u.regs, TCG_REG_RAX); ! 123: break; ! 124: case 'b': ! 125: ct->ct |= TCG_CT_REG; ! 126: tcg_regset_set_reg(ct->u.regs, TCG_REG_RBX); ! 127: break; ! 128: case 'c': ! 129: ct->ct |= TCG_CT_REG; ! 130: tcg_regset_set_reg(ct->u.regs, TCG_REG_RCX); ! 131: break; ! 132: case 'd': ! 133: ct->ct |= TCG_CT_REG; ! 134: tcg_regset_set_reg(ct->u.regs, TCG_REG_RDX); ! 135: break; ! 136: case 'S': ! 137: ct->ct |= TCG_CT_REG; ! 138: tcg_regset_set_reg(ct->u.regs, TCG_REG_RSI); ! 139: break; ! 140: case 'D': ! 141: ct->ct |= TCG_CT_REG; ! 142: tcg_regset_set_reg(ct->u.regs, TCG_REG_RDI); ! 143: break; ! 144: case 'q': ! 145: ct->ct |= TCG_CT_REG; ! 146: tcg_regset_set32(ct->u.regs, 0, 0xf); ! 147: break; ! 148: case 'r': ! 149: ct->ct |= TCG_CT_REG; ! 150: tcg_regset_set32(ct->u.regs, 0, 0xffff); ! 151: break; ! 152: case 'L': /* qemu_ld/st constraint */ ! 153: ct->ct |= TCG_CT_REG; ! 154: tcg_regset_set32(ct->u.regs, 0, 0xffff); ! 155: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI); ! 156: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI); ! 157: break; ! 158: case 'e': ! 159: ct->ct |= TCG_CT_CONST_S32; ! 160: break; ! 161: case 'Z': ! 162: ct->ct |= TCG_CT_CONST_U32; ! 163: break; ! 164: default: ! 165: return -1; ! 166: } ! 167: ct_str++; ! 168: *pct_str = ct_str; ! 169: return 0; ! 170: } ! 171: ! 172: /* test if a constant matches the constraint */ ! 173: static inline int tcg_target_const_match(tcg_target_long val, ! 174: const TCGArgConstraint *arg_ct) ! 175: { ! 176: int ct; ! 177: ct = arg_ct->ct; ! 178: if (ct & TCG_CT_CONST) ! 179: return 1; ! 180: else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) ! 181: return 1; ! 182: else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) ! 183: return 1; ! 184: else ! 185: return 0; ! 186: } ! 187: ! 188: #define ARITH_ADD 0 ! 189: #define ARITH_OR 1 ! 190: #define ARITH_ADC 2 ! 191: #define ARITH_SBB 3 ! 192: #define ARITH_AND 4 ! 193: #define ARITH_SUB 5 ! 194: #define ARITH_XOR 6 ! 195: #define ARITH_CMP 7 ! 196: ! 197: #define SHIFT_SHL 4 ! 198: #define SHIFT_SHR 5 ! 199: #define SHIFT_SAR 7 ! 200: ! 201: #define JCC_JMP (-1) ! 202: #define JCC_JO 0x0 ! 203: #define JCC_JNO 0x1 ! 204: #define JCC_JB 0x2 ! 205: #define JCC_JAE 0x3 ! 206: #define JCC_JE 0x4 ! 207: #define JCC_JNE 0x5 ! 208: #define JCC_JBE 0x6 ! 209: #define JCC_JA 0x7 ! 210: #define JCC_JS 0x8 ! 211: #define JCC_JNS 0x9 ! 212: #define JCC_JP 0xa ! 213: #define JCC_JNP 0xb ! 214: #define JCC_JL 0xc ! 215: #define JCC_JGE 0xd ! 216: #define JCC_JLE 0xe ! 217: #define JCC_JG 0xf ! 218: ! 219: #define P_EXT 0x100 /* 0x0f opcode prefix */ ! 220: #define P_REXW 0x200 /* set rex.w = 1 */ ! 221: #define P_REXB 0x400 /* force rex use for byte registers */ ! 222: ! 223: static const uint8_t tcg_cond_to_jcc[10] = { ! 224: [TCG_COND_EQ] = JCC_JE, ! 225: [TCG_COND_NE] = JCC_JNE, ! 226: [TCG_COND_LT] = JCC_JL, ! 227: [TCG_COND_GE] = JCC_JGE, ! 228: [TCG_COND_LE] = JCC_JLE, ! 229: [TCG_COND_GT] = JCC_JG, ! 230: [TCG_COND_LTU] = JCC_JB, ! 231: [TCG_COND_GEU] = JCC_JAE, ! 232: [TCG_COND_LEU] = JCC_JBE, ! 233: [TCG_COND_GTU] = JCC_JA, ! 234: }; ! 235: ! 236: static inline void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x) ! 237: { ! 238: int rex; ! 239: rex = ((opc >> 6) & 0x8) | ((r >> 1) & 0x4) | ! 240: ((x >> 2) & 2) | ((rm >> 3) & 1); ! 241: if (rex || (opc & P_REXB)) { ! 242: tcg_out8(s, rex | 0x40); ! 243: } ! 244: if (opc & P_EXT) ! 245: tcg_out8(s, 0x0f); ! 246: tcg_out8(s, opc); ! 247: } ! 248: ! 249: static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm) ! 250: { ! 251: tcg_out_opc(s, opc, r, rm, 0); ! 252: tcg_out8(s, 0xc0 | ((r & 7) << 3) | (rm & 7)); ! 253: } ! 254: ! 255: /* rm < 0 means no register index plus (-rm - 1 immediate bytes) */ ! 256: static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, ! 257: tcg_target_long offset) ! 258: { ! 259: if (rm < 0) { ! 260: tcg_target_long val; ! 261: tcg_out_opc(s, opc, r, 0, 0); ! 262: val = offset - ((tcg_target_long)s->code_ptr + 5 + (-rm - 1)); ! 263: if (val == (int32_t)val) { ! 264: /* eip relative */ ! 265: tcg_out8(s, 0x05 | ((r & 7) << 3)); ! 266: tcg_out32(s, val); ! 267: } else if (offset == (int32_t)offset) { ! 268: tcg_out8(s, 0x04 | ((r & 7) << 3)); ! 269: tcg_out8(s, 0x25); /* sib */ ! 270: tcg_out32(s, offset); ! 271: } else { ! 272: tcg_abort(); ! 273: } ! 274: } else if (offset == 0 && (rm & 7) != TCG_REG_RBP) { ! 275: tcg_out_opc(s, opc, r, rm, 0); ! 276: if ((rm & 7) == TCG_REG_RSP) { ! 277: tcg_out8(s, 0x04 | ((r & 7) << 3)); ! 278: tcg_out8(s, 0x24); ! 279: } else { ! 280: tcg_out8(s, 0x00 | ((r & 7) << 3) | (rm & 7)); ! 281: } ! 282: } else if ((int8_t)offset == offset) { ! 283: tcg_out_opc(s, opc, r, rm, 0); ! 284: if ((rm & 7) == TCG_REG_RSP) { ! 285: tcg_out8(s, 0x44 | ((r & 7) << 3)); ! 286: tcg_out8(s, 0x24); ! 287: } else { ! 288: tcg_out8(s, 0x40 | ((r & 7) << 3) | (rm & 7)); ! 289: } ! 290: tcg_out8(s, offset); ! 291: } else { ! 292: tcg_out_opc(s, opc, r, rm, 0); ! 293: if ((rm & 7) == TCG_REG_RSP) { ! 294: tcg_out8(s, 0x84 | ((r & 7) << 3)); ! 295: tcg_out8(s, 0x24); ! 296: } else { ! 297: tcg_out8(s, 0x80 | ((r & 7) << 3) | (rm & 7)); ! 298: } ! 299: tcg_out32(s, offset); ! 300: } ! 301: } ! 302: ! 303: #if defined(CONFIG_SOFTMMU) ! 304: /* XXX: incomplete. index must be different from ESP */ ! 305: static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm, ! 306: int index, int shift, ! 307: tcg_target_long offset) ! 308: { ! 309: int mod; ! 310: if (rm == -1) ! 311: tcg_abort(); ! 312: if (offset == 0 && (rm & 7) != TCG_REG_RBP) { ! 313: mod = 0; ! 314: } else if (offset == (int8_t)offset) { ! 315: mod = 0x40; ! 316: } else if (offset == (int32_t)offset) { ! 317: mod = 0x80; ! 318: } else { ! 319: tcg_abort(); ! 320: } ! 321: if (index == -1) { ! 322: tcg_out_opc(s, opc, r, rm, 0); ! 323: if ((rm & 7) == TCG_REG_RSP) { ! 324: tcg_out8(s, mod | ((r & 7) << 3) | 0x04); ! 325: tcg_out8(s, 0x04 | (rm & 7)); ! 326: } else { ! 327: tcg_out8(s, mod | ((r & 7) << 3) | (rm & 7)); ! 328: } ! 329: } else { ! 330: tcg_out_opc(s, opc, r, rm, index); ! 331: tcg_out8(s, mod | ((r & 7) << 3) | 0x04); ! 332: tcg_out8(s, (shift << 6) | ((index & 7) << 3) | (rm & 7)); ! 333: } ! 334: if (mod == 0x40) { ! 335: tcg_out8(s, offset); ! 336: } else if (mod == 0x80) { ! 337: tcg_out32(s, offset); ! 338: } ! 339: } ! 340: #endif ! 341: ! 342: static inline void tcg_out_mov(TCGContext *s, int ret, int arg) ! 343: { ! 344: tcg_out_modrm(s, 0x8b | P_REXW, ret, arg); ! 345: } ! 346: ! 347: static inline void tcg_out_movi(TCGContext *s, TCGType type, ! 348: int ret, tcg_target_long arg) ! 349: { ! 350: if (arg == 0) { ! 351: tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret); /* xor r0,r0 */ ! 352: } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) { ! 353: tcg_out_opc(s, 0xb8 + (ret & 7), 0, ret, 0); ! 354: tcg_out32(s, arg); ! 355: } else if (arg == (int32_t)arg) { ! 356: tcg_out_modrm(s, 0xc7 | P_REXW, 0, ret); ! 357: tcg_out32(s, arg); ! 358: } else { ! 359: tcg_out_opc(s, (0xb8 + (ret & 7)) | P_REXW, 0, ret, 0); ! 360: tcg_out32(s, arg); ! 361: tcg_out32(s, arg >> 32); ! 362: } ! 363: } ! 364: ! 365: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, ! 366: int arg1, tcg_target_long arg2) ! 367: { ! 368: if (type == TCG_TYPE_I32) ! 369: tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */ ! 370: else ! 371: tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */ ! 372: } ! 373: ! 374: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, ! 375: int arg1, tcg_target_long arg2) ! 376: { ! 377: if (type == TCG_TYPE_I32) ! 378: tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */ ! 379: else ! 380: tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */ ! 381: } ! 382: ! 383: static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val) ! 384: { ! 385: if (val == (int8_t)val) { ! 386: tcg_out_modrm(s, 0x83, c, r0); ! 387: tcg_out8(s, val); ! 388: } else if (c == ARITH_AND && val == 0xffu) { ! 389: /* movzbl */ ! 390: tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, r0, r0); ! 391: } else if (c == ARITH_AND && val == 0xffffu) { ! 392: /* movzwl */ ! 393: tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0); ! 394: } else { ! 395: tcg_out_modrm(s, 0x81, c, r0); ! 396: tcg_out32(s, val); ! 397: } ! 398: } ! 399: ! 400: static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val) ! 401: { ! 402: if (val == (int8_t)val) { ! 403: tcg_out_modrm(s, 0x83 | P_REXW, c, r0); ! 404: tcg_out8(s, val); ! 405: } else if (c == ARITH_AND && val == 0xffu) { ! 406: /* movzbl */ ! 407: tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, r0, r0); ! 408: } else if (c == ARITH_AND && val == 0xffffu) { ! 409: /* movzwl */ ! 410: tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, r0, r0); ! 411: } else if (c == ARITH_AND && val == 0xffffffffu) { ! 412: /* 32-bit mov zero extends */ ! 413: tcg_out_modrm(s, 0x8b, r0, r0); ! 414: } else if (val == (int32_t)val) { ! 415: tcg_out_modrm(s, 0x81 | P_REXW, c, r0); ! 416: tcg_out32(s, val); ! 417: } else if (c == ARITH_AND && val == (uint32_t)val) { ! 418: tcg_out_modrm(s, 0x81, c, r0); ! 419: tcg_out32(s, val); ! 420: } else { ! 421: tcg_abort(); ! 422: } ! 423: } ! 424: ! 425: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) ! 426: { ! 427: if (val != 0) ! 428: tgen_arithi64(s, ARITH_ADD, reg, val); ! 429: } ! 430: ! 431: static void tcg_out_jxx(TCGContext *s, int opc, int label_index) ! 432: { ! 433: int32_t val, val1; ! 434: TCGLabel *l = &s->labels[label_index]; ! 435: ! 436: if (l->has_value) { ! 437: val = l->u.value - (tcg_target_long)s->code_ptr; ! 438: val1 = val - 2; ! 439: if ((int8_t)val1 == val1) { ! 440: if (opc == -1) ! 441: tcg_out8(s, 0xeb); ! 442: else ! 443: tcg_out8(s, 0x70 + opc); ! 444: tcg_out8(s, val1); ! 445: } else { ! 446: if (opc == -1) { ! 447: tcg_out8(s, 0xe9); ! 448: tcg_out32(s, val - 5); ! 449: } else { ! 450: tcg_out8(s, 0x0f); ! 451: tcg_out8(s, 0x80 + opc); ! 452: tcg_out32(s, val - 6); ! 453: } ! 454: } ! 455: } else { ! 456: if (opc == -1) { ! 457: tcg_out8(s, 0xe9); ! 458: } else { ! 459: tcg_out8(s, 0x0f); ! 460: tcg_out8(s, 0x80 + opc); ! 461: } ! 462: tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4); ! 463: s->code_ptr += 4; ! 464: } ! 465: } ! 466: ! 467: static void tcg_out_brcond(TCGContext *s, int cond, ! 468: TCGArg arg1, TCGArg arg2, int const_arg2, ! 469: int label_index, int rexw) ! 470: { ! 471: if (const_arg2) { ! 472: if (arg2 == 0) { ! 473: /* test r, r */ ! 474: tcg_out_modrm(s, 0x85 | rexw, arg1, arg1); ! 475: } else { ! 476: if (rexw) ! 477: tgen_arithi64(s, ARITH_CMP, arg1, arg2); ! 478: else ! 479: tgen_arithi32(s, ARITH_CMP, arg1, arg2); ! 480: } ! 481: } else { ! 482: tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1); ! 483: } ! 484: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index); ! 485: } ! 486: ! 487: #if defined(CONFIG_SOFTMMU) ! 488: ! 489: #include "../../softmmu_defs.h" ! 490: ! 491: static void *qemu_ld_helpers[4] = { ! 492: __ldb_mmu, ! 493: __ldw_mmu, ! 494: __ldl_mmu, ! 495: __ldq_mmu, ! 496: }; ! 497: ! 498: static void *qemu_st_helpers[4] = { ! 499: __stb_mmu, ! 500: __stw_mmu, ! 501: __stl_mmu, ! 502: __stq_mmu, ! 503: }; ! 504: #endif ! 505: ! 506: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, ! 507: int opc) ! 508: { ! 509: int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; ! 510: #if defined(CONFIG_SOFTMMU) ! 511: uint8_t *label1_ptr, *label2_ptr; ! 512: #endif ! 513: ! 514: data_reg = *args++; ! 515: addr_reg = *args++; ! 516: mem_index = *args; ! 517: s_bits = opc & 3; ! 518: ! 519: r0 = TCG_REG_RDI; ! 520: r1 = TCG_REG_RSI; ! 521: ! 522: #if TARGET_LONG_BITS == 32 ! 523: rexw = 0; ! 524: #else ! 525: rexw = P_REXW; ! 526: #endif ! 527: #if defined(CONFIG_SOFTMMU) ! 528: /* mov */ ! 529: tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg); ! 530: ! 531: /* mov */ ! 532: tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg); ! 533: ! 534: tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */ ! 535: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ! 536: ! 537: tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */ ! 538: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ! 539: ! 540: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */ ! 541: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ! 542: ! 543: /* lea offset(r1, env), r1 */ ! 544: tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0, ! 545: offsetof(CPUState, tlb_table[mem_index][0].addr_read)); ! 546: ! 547: /* cmp 0(r1), r0 */ ! 548: tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0); ! 549: ! 550: /* mov */ ! 551: tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg); ! 552: ! 553: /* je label1 */ ! 554: tcg_out8(s, 0x70 + JCC_JE); ! 555: label1_ptr = s->code_ptr; ! 556: s->code_ptr++; ! 557: ! 558: /* XXX: move that code at the end of the TB */ ! 559: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index); ! 560: tcg_out8(s, 0xe8); ! 561: tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - ! 562: (tcg_target_long)s->code_ptr - 4); ! 563: ! 564: switch(opc) { ! 565: case 0 | 4: ! 566: /* movsbq */ ! 567: tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX); ! 568: break; ! 569: case 1 | 4: ! 570: /* movswq */ ! 571: tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX); ! 572: break; ! 573: case 2 | 4: ! 574: /* movslq */ ! 575: tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX); ! 576: break; ! 577: case 0: ! 578: /* movzbq */ ! 579: tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX); ! 580: break; ! 581: case 1: ! 582: /* movzwq */ ! 583: tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX); ! 584: break; ! 585: case 2: ! 586: default: ! 587: /* movl */ ! 588: tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX); ! 589: break; ! 590: case 3: ! 591: tcg_out_mov(s, data_reg, TCG_REG_RAX); ! 592: break; ! 593: } ! 594: ! 595: /* jmp label2 */ ! 596: tcg_out8(s, 0xeb); ! 597: label2_ptr = s->code_ptr; ! 598: s->code_ptr++; ! 599: ! 600: /* label1: */ ! 601: *label1_ptr = s->code_ptr - label1_ptr - 1; ! 602: ! 603: /* add x(r1), r0 */ ! 604: tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - ! 605: offsetof(CPUTLBEntry, addr_read)); ! 606: #else ! 607: r0 = addr_reg; ! 608: #endif ! 609: ! 610: #ifdef TARGET_WORDS_BIGENDIAN ! 611: bswap = 1; ! 612: #else ! 613: bswap = 0; ! 614: #endif ! 615: switch(opc) { ! 616: case 0: ! 617: /* movzbl */ ! 618: tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); ! 619: break; ! 620: case 0 | 4: ! 621: /* movsbX */ ! 622: tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0); ! 623: break; ! 624: case 1: ! 625: /* movzwl */ ! 626: tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); ! 627: if (bswap) { ! 628: /* rolw $8, data_reg */ ! 629: tcg_out8(s, 0x66); ! 630: tcg_out_modrm(s, 0xc1, 0, data_reg); ! 631: tcg_out8(s, 8); ! 632: } ! 633: break; ! 634: case 1 | 4: ! 635: if (bswap) { ! 636: /* movzwl */ ! 637: tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); ! 638: /* rolw $8, data_reg */ ! 639: tcg_out8(s, 0x66); ! 640: tcg_out_modrm(s, 0xc1, 0, data_reg); ! 641: tcg_out8(s, 8); ! 642: ! 643: /* movswX data_reg, data_reg */ ! 644: tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); ! 645: } else { ! 646: /* movswX */ ! 647: tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0); ! 648: } ! 649: break; ! 650: case 2: ! 651: /* movl (r0), data_reg */ ! 652: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); ! 653: if (bswap) { ! 654: /* bswap */ ! 655: tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); ! 656: } ! 657: break; ! 658: case 2 | 4: ! 659: if (bswap) { ! 660: /* movl (r0), data_reg */ ! 661: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); ! 662: /* bswap */ ! 663: tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); ! 664: /* movslq */ ! 665: tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); ! 666: } else { ! 667: /* movslq */ ! 668: tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0); ! 669: } ! 670: break; ! 671: case 3: ! 672: /* movq (r0), data_reg */ ! 673: tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0); ! 674: if (bswap) { ! 675: /* bswap */ ! 676: tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); ! 677: } ! 678: break; ! 679: default: ! 680: tcg_abort(); ! 681: } ! 682: ! 683: #if defined(CONFIG_SOFTMMU) ! 684: /* label2: */ ! 685: *label2_ptr = s->code_ptr - label2_ptr - 1; ! 686: #endif ! 687: } ! 688: ! 689: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, ! 690: int opc) ! 691: { ! 692: int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; ! 693: #if defined(CONFIG_SOFTMMU) ! 694: uint8_t *label1_ptr, *label2_ptr; ! 695: #endif ! 696: ! 697: data_reg = *args++; ! 698: addr_reg = *args++; ! 699: mem_index = *args; ! 700: ! 701: s_bits = opc; ! 702: ! 703: r0 = TCG_REG_RDI; ! 704: r1 = TCG_REG_RSI; ! 705: ! 706: #if TARGET_LONG_BITS == 32 ! 707: rexw = 0; ! 708: #else ! 709: rexw = P_REXW; ! 710: #endif ! 711: #if defined(CONFIG_SOFTMMU) ! 712: /* mov */ ! 713: tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg); ! 714: ! 715: /* mov */ ! 716: tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg); ! 717: ! 718: tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */ ! 719: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ! 720: ! 721: tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */ ! 722: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ! 723: ! 724: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */ ! 725: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ! 726: ! 727: /* lea offset(r1, env), r1 */ ! 728: tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0, ! 729: offsetof(CPUState, tlb_table[mem_index][0].addr_write)); ! 730: ! 731: /* cmp 0(r1), r0 */ ! 732: tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0); ! 733: ! 734: /* mov */ ! 735: tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg); ! 736: ! 737: /* je label1 */ ! 738: tcg_out8(s, 0x70 + JCC_JE); ! 739: label1_ptr = s->code_ptr; ! 740: s->code_ptr++; ! 741: ! 742: /* XXX: move that code at the end of the TB */ ! 743: switch(opc) { ! 744: case 0: ! 745: /* movzbl */ ! 746: tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, TCG_REG_RSI, data_reg); ! 747: break; ! 748: case 1: ! 749: /* movzwl */ ! 750: tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg); ! 751: break; ! 752: case 2: ! 753: /* movl */ ! 754: tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg); ! 755: break; ! 756: default: ! 757: case 3: ! 758: tcg_out_mov(s, TCG_REG_RSI, data_reg); ! 759: break; ! 760: } ! 761: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index); ! 762: tcg_out8(s, 0xe8); ! 763: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - ! 764: (tcg_target_long)s->code_ptr - 4); ! 765: ! 766: /* jmp label2 */ ! 767: tcg_out8(s, 0xeb); ! 768: label2_ptr = s->code_ptr; ! 769: s->code_ptr++; ! 770: ! 771: /* label1: */ ! 772: *label1_ptr = s->code_ptr - label1_ptr - 1; ! 773: ! 774: /* add x(r1), r0 */ ! 775: tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - ! 776: offsetof(CPUTLBEntry, addr_write)); ! 777: #else ! 778: r0 = addr_reg; ! 779: #endif ! 780: ! 781: #ifdef TARGET_WORDS_BIGENDIAN ! 782: bswap = 1; ! 783: #else ! 784: bswap = 0; ! 785: #endif ! 786: switch(opc) { ! 787: case 0: ! 788: /* movb */ ! 789: tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0); ! 790: break; ! 791: case 1: ! 792: if (bswap) { ! 793: tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */ ! 794: tcg_out8(s, 0x66); /* rolw $8, %ecx */ ! 795: tcg_out_modrm(s, 0xc1, 0, r1); ! 796: tcg_out8(s, 8); ! 797: data_reg = r1; ! 798: } ! 799: /* movw */ ! 800: tcg_out8(s, 0x66); ! 801: tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); ! 802: break; ! 803: case 2: ! 804: if (bswap) { ! 805: tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */ ! 806: /* bswap data_reg */ ! 807: tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0); ! 808: data_reg = r1; ! 809: } ! 810: /* movl */ ! 811: tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); ! 812: break; ! 813: case 3: ! 814: if (bswap) { ! 815: tcg_out_mov(s, r1, data_reg); ! 816: /* bswap data_reg */ ! 817: tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0); ! 818: data_reg = r1; ! 819: } ! 820: /* movq */ ! 821: tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0); ! 822: break; ! 823: default: ! 824: tcg_abort(); ! 825: } ! 826: ! 827: #if defined(CONFIG_SOFTMMU) ! 828: /* label2: */ ! 829: *label2_ptr = s->code_ptr - label2_ptr - 1; ! 830: #endif ! 831: } ! 832: ! 833: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, ! 834: const int *const_args) ! 835: { ! 836: int c; ! 837: ! 838: switch(opc) { ! 839: case INDEX_op_exit_tb: ! 840: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]); ! 841: tcg_out8(s, 0xe9); /* jmp tb_ret_addr */ ! 842: tcg_out32(s, tb_ret_addr - s->code_ptr - 4); ! 843: break; ! 844: case INDEX_op_goto_tb: ! 845: if (s->tb_jmp_offset) { ! 846: /* direct jump method */ ! 847: tcg_out8(s, 0xe9); /* jmp im */ ! 848: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; ! 849: tcg_out32(s, 0); ! 850: } else { ! 851: /* indirect jump method */ ! 852: /* jmp Ev */ ! 853: tcg_out_modrm_offset(s, 0xff, 4, -1, ! 854: (tcg_target_long)(s->tb_next + ! 855: args[0])); ! 856: } ! 857: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ! 858: break; ! 859: case INDEX_op_call: ! 860: if (const_args[0]) { ! 861: tcg_out8(s, 0xe8); ! 862: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4); ! 863: } else { ! 864: tcg_out_modrm(s, 0xff, 2, args[0]); ! 865: } ! 866: break; ! 867: case INDEX_op_jmp: ! 868: if (const_args[0]) { ! 869: tcg_out8(s, 0xe9); ! 870: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4); ! 871: } else { ! 872: tcg_out_modrm(s, 0xff, 4, args[0]); ! 873: } ! 874: break; ! 875: case INDEX_op_br: ! 876: tcg_out_jxx(s, JCC_JMP, args[0]); ! 877: break; ! 878: case INDEX_op_movi_i32: ! 879: tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]); ! 880: break; ! 881: case INDEX_op_movi_i64: ! 882: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]); ! 883: break; ! 884: case INDEX_op_ld8u_i32: ! 885: case INDEX_op_ld8u_i64: ! 886: /* movzbl */ ! 887: tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]); ! 888: break; ! 889: case INDEX_op_ld8s_i32: ! 890: /* movsbl */ ! 891: tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]); ! 892: break; ! 893: case INDEX_op_ld8s_i64: ! 894: /* movsbq */ ! 895: tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]); ! 896: break; ! 897: case INDEX_op_ld16u_i32: ! 898: case INDEX_op_ld16u_i64: ! 899: /* movzwl */ ! 900: tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]); ! 901: break; ! 902: case INDEX_op_ld16s_i32: ! 903: /* movswl */ ! 904: tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]); ! 905: break; ! 906: case INDEX_op_ld16s_i64: ! 907: /* movswq */ ! 908: tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]); ! 909: break; ! 910: case INDEX_op_ld_i32: ! 911: case INDEX_op_ld32u_i64: ! 912: /* movl */ ! 913: tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]); ! 914: break; ! 915: case INDEX_op_ld32s_i64: ! 916: /* movslq */ ! 917: tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]); ! 918: break; ! 919: case INDEX_op_ld_i64: ! 920: /* movq */ ! 921: tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]); ! 922: break; ! 923: ! 924: case INDEX_op_st8_i32: ! 925: case INDEX_op_st8_i64: ! 926: /* movb */ ! 927: tcg_out_modrm_offset(s, 0x88 | P_REXB, args[0], args[1], args[2]); ! 928: break; ! 929: case INDEX_op_st16_i32: ! 930: case INDEX_op_st16_i64: ! 931: /* movw */ ! 932: tcg_out8(s, 0x66); ! 933: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]); ! 934: break; ! 935: case INDEX_op_st_i32: ! 936: case INDEX_op_st32_i64: ! 937: /* movl */ ! 938: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]); ! 939: break; ! 940: case INDEX_op_st_i64: ! 941: /* movq */ ! 942: tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]); ! 943: break; ! 944: ! 945: case INDEX_op_sub_i32: ! 946: c = ARITH_SUB; ! 947: goto gen_arith32; ! 948: case INDEX_op_and_i32: ! 949: c = ARITH_AND; ! 950: goto gen_arith32; ! 951: case INDEX_op_or_i32: ! 952: c = ARITH_OR; ! 953: goto gen_arith32; ! 954: case INDEX_op_xor_i32: ! 955: c = ARITH_XOR; ! 956: goto gen_arith32; ! 957: case INDEX_op_add_i32: ! 958: c = ARITH_ADD; ! 959: gen_arith32: ! 960: if (const_args[2]) { ! 961: tgen_arithi32(s, c, args[0], args[2]); ! 962: } else { ! 963: tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]); ! 964: } ! 965: break; ! 966: ! 967: case INDEX_op_sub_i64: ! 968: c = ARITH_SUB; ! 969: goto gen_arith64; ! 970: case INDEX_op_and_i64: ! 971: c = ARITH_AND; ! 972: goto gen_arith64; ! 973: case INDEX_op_or_i64: ! 974: c = ARITH_OR; ! 975: goto gen_arith64; ! 976: case INDEX_op_xor_i64: ! 977: c = ARITH_XOR; ! 978: goto gen_arith64; ! 979: case INDEX_op_add_i64: ! 980: c = ARITH_ADD; ! 981: gen_arith64: ! 982: if (const_args[2]) { ! 983: tgen_arithi64(s, c, args[0], args[2]); ! 984: } else { ! 985: tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]); ! 986: } ! 987: break; ! 988: ! 989: case INDEX_op_mul_i32: ! 990: if (const_args[2]) { ! 991: int32_t val; ! 992: val = args[2]; ! 993: if (val == (int8_t)val) { ! 994: tcg_out_modrm(s, 0x6b, args[0], args[0]); ! 995: tcg_out8(s, val); ! 996: } else { ! 997: tcg_out_modrm(s, 0x69, args[0], args[0]); ! 998: tcg_out32(s, val); ! 999: } ! 1000: } else { ! 1001: tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]); ! 1002: } ! 1003: break; ! 1004: case INDEX_op_mul_i64: ! 1005: if (const_args[2]) { ! 1006: int32_t val; ! 1007: val = args[2]; ! 1008: if (val == (int8_t)val) { ! 1009: tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]); ! 1010: tcg_out8(s, val); ! 1011: } else { ! 1012: tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]); ! 1013: tcg_out32(s, val); ! 1014: } ! 1015: } else { ! 1016: tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]); ! 1017: } ! 1018: break; ! 1019: case INDEX_op_div2_i32: ! 1020: tcg_out_modrm(s, 0xf7, 7, args[4]); ! 1021: break; ! 1022: case INDEX_op_divu2_i32: ! 1023: tcg_out_modrm(s, 0xf7, 6, args[4]); ! 1024: break; ! 1025: case INDEX_op_div2_i64: ! 1026: tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]); ! 1027: break; ! 1028: case INDEX_op_divu2_i64: ! 1029: tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]); ! 1030: break; ! 1031: ! 1032: case INDEX_op_shl_i32: ! 1033: c = SHIFT_SHL; ! 1034: gen_shift32: ! 1035: if (const_args[2]) { ! 1036: if (args[2] == 1) { ! 1037: tcg_out_modrm(s, 0xd1, c, args[0]); ! 1038: } else { ! 1039: tcg_out_modrm(s, 0xc1, c, args[0]); ! 1040: tcg_out8(s, args[2]); ! 1041: } ! 1042: } else { ! 1043: tcg_out_modrm(s, 0xd3, c, args[0]); ! 1044: } ! 1045: break; ! 1046: case INDEX_op_shr_i32: ! 1047: c = SHIFT_SHR; ! 1048: goto gen_shift32; ! 1049: case INDEX_op_sar_i32: ! 1050: c = SHIFT_SAR; ! 1051: goto gen_shift32; ! 1052: ! 1053: case INDEX_op_shl_i64: ! 1054: c = SHIFT_SHL; ! 1055: gen_shift64: ! 1056: if (const_args[2]) { ! 1057: if (args[2] == 1) { ! 1058: tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]); ! 1059: } else { ! 1060: tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]); ! 1061: tcg_out8(s, args[2]); ! 1062: } ! 1063: } else { ! 1064: tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]); ! 1065: } ! 1066: break; ! 1067: case INDEX_op_shr_i64: ! 1068: c = SHIFT_SHR; ! 1069: goto gen_shift64; ! 1070: case INDEX_op_sar_i64: ! 1071: c = SHIFT_SAR; ! 1072: goto gen_shift64; ! 1073: ! 1074: case INDEX_op_brcond_i32: ! 1075: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], ! 1076: args[3], 0); ! 1077: break; ! 1078: case INDEX_op_brcond_i64: ! 1079: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], ! 1080: args[3], P_REXW); ! 1081: break; ! 1082: ! 1083: case INDEX_op_bswap_i32: ! 1084: tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0); ! 1085: break; ! 1086: case INDEX_op_bswap_i64: ! 1087: tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0); ! 1088: break; ! 1089: ! 1090: case INDEX_op_neg_i32: ! 1091: tcg_out_modrm(s, 0xf7, 3, args[0]); ! 1092: break; ! 1093: case INDEX_op_neg_i64: ! 1094: tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]); ! 1095: break; ! 1096: ! 1097: case INDEX_op_ext8s_i32: ! 1098: tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]); ! 1099: break; ! 1100: case INDEX_op_ext16s_i32: ! 1101: tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]); ! 1102: break; ! 1103: case INDEX_op_ext8s_i64: ! 1104: tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]); ! 1105: break; ! 1106: case INDEX_op_ext16s_i64: ! 1107: tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]); ! 1108: break; ! 1109: case INDEX_op_ext32s_i64: ! 1110: tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]); ! 1111: break; ! 1112: ! 1113: case INDEX_op_qemu_ld8u: ! 1114: tcg_out_qemu_ld(s, args, 0); ! 1115: break; ! 1116: case INDEX_op_qemu_ld8s: ! 1117: tcg_out_qemu_ld(s, args, 0 | 4); ! 1118: break; ! 1119: case INDEX_op_qemu_ld16u: ! 1120: tcg_out_qemu_ld(s, args, 1); ! 1121: break; ! 1122: case INDEX_op_qemu_ld16s: ! 1123: tcg_out_qemu_ld(s, args, 1 | 4); ! 1124: break; ! 1125: case INDEX_op_qemu_ld32u: ! 1126: tcg_out_qemu_ld(s, args, 2); ! 1127: break; ! 1128: case INDEX_op_qemu_ld32s: ! 1129: tcg_out_qemu_ld(s, args, 2 | 4); ! 1130: break; ! 1131: case INDEX_op_qemu_ld64: ! 1132: tcg_out_qemu_ld(s, args, 3); ! 1133: break; ! 1134: ! 1135: case INDEX_op_qemu_st8: ! 1136: tcg_out_qemu_st(s, args, 0); ! 1137: break; ! 1138: case INDEX_op_qemu_st16: ! 1139: tcg_out_qemu_st(s, args, 1); ! 1140: break; ! 1141: case INDEX_op_qemu_st32: ! 1142: tcg_out_qemu_st(s, args, 2); ! 1143: break; ! 1144: case INDEX_op_qemu_st64: ! 1145: tcg_out_qemu_st(s, args, 3); ! 1146: break; ! 1147: ! 1148: default: ! 1149: tcg_abort(); ! 1150: } ! 1151: } ! 1152: ! 1153: static int tcg_target_callee_save_regs[] = { ! 1154: TCG_REG_RBP, ! 1155: TCG_REG_RBX, ! 1156: TCG_REG_R12, ! 1157: TCG_REG_R13, ! 1158: /* TCG_REG_R14, */ /* currently used for the global env, so no ! 1159: need to save */ ! 1160: TCG_REG_R15, ! 1161: }; ! 1162: ! 1163: static inline void tcg_out_push(TCGContext *s, int reg) ! 1164: { ! 1165: tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0); ! 1166: } ! 1167: ! 1168: static inline void tcg_out_pop(TCGContext *s, int reg) ! 1169: { ! 1170: tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0); ! 1171: } ! 1172: ! 1173: /* Generate global QEMU prologue and epilogue code */ ! 1174: void tcg_target_qemu_prologue(TCGContext *s) ! 1175: { ! 1176: int i, frame_size, push_size, stack_addend; ! 1177: ! 1178: /* TB prologue */ ! 1179: /* save all callee saved registers */ ! 1180: for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { ! 1181: tcg_out_push(s, tcg_target_callee_save_regs[i]); ! 1182: ! 1183: } ! 1184: /* reserve some stack space */ ! 1185: push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8; ! 1186: frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE; ! 1187: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ! 1188: ~(TCG_TARGET_STACK_ALIGN - 1); ! 1189: stack_addend = frame_size - push_size; ! 1190: tcg_out_addi(s, TCG_REG_RSP, -stack_addend); ! 1191: ! 1192: tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */ ! 1193: ! 1194: /* TB epilogue */ ! 1195: tb_ret_addr = s->code_ptr; ! 1196: tcg_out_addi(s, TCG_REG_RSP, stack_addend); ! 1197: for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) { ! 1198: tcg_out_pop(s, tcg_target_callee_save_regs[i]); ! 1199: } ! 1200: tcg_out8(s, 0xc3); /* ret */ ! 1201: } ! 1202: ! 1203: static const TCGTargetOpDef x86_64_op_defs[] = { ! 1204: { INDEX_op_exit_tb, { } }, ! 1205: { INDEX_op_goto_tb, { } }, ! 1206: { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */ ! 1207: { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */ ! 1208: { INDEX_op_br, { } }, ! 1209: ! 1210: { INDEX_op_mov_i32, { "r", "r" } }, ! 1211: { INDEX_op_movi_i32, { "r" } }, ! 1212: { INDEX_op_ld8u_i32, { "r", "r" } }, ! 1213: { INDEX_op_ld8s_i32, { "r", "r" } }, ! 1214: { INDEX_op_ld16u_i32, { "r", "r" } }, ! 1215: { INDEX_op_ld16s_i32, { "r", "r" } }, ! 1216: { INDEX_op_ld_i32, { "r", "r" } }, ! 1217: { INDEX_op_st8_i32, { "r", "r" } }, ! 1218: { INDEX_op_st16_i32, { "r", "r" } }, ! 1219: { INDEX_op_st_i32, { "r", "r" } }, ! 1220: ! 1221: { INDEX_op_add_i32, { "r", "0", "ri" } }, ! 1222: { INDEX_op_mul_i32, { "r", "0", "ri" } }, ! 1223: { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } }, ! 1224: { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } }, ! 1225: { INDEX_op_sub_i32, { "r", "0", "ri" } }, ! 1226: { INDEX_op_and_i32, { "r", "0", "ri" } }, ! 1227: { INDEX_op_or_i32, { "r", "0", "ri" } }, ! 1228: { INDEX_op_xor_i32, { "r", "0", "ri" } }, ! 1229: ! 1230: { INDEX_op_shl_i32, { "r", "0", "ci" } }, ! 1231: { INDEX_op_shr_i32, { "r", "0", "ci" } }, ! 1232: { INDEX_op_sar_i32, { "r", "0", "ci" } }, ! 1233: ! 1234: { INDEX_op_brcond_i32, { "r", "ri" } }, ! 1235: ! 1236: { INDEX_op_mov_i64, { "r", "r" } }, ! 1237: { INDEX_op_movi_i64, { "r" } }, ! 1238: { INDEX_op_ld8u_i64, { "r", "r" } }, ! 1239: { INDEX_op_ld8s_i64, { "r", "r" } }, ! 1240: { INDEX_op_ld16u_i64, { "r", "r" } }, ! 1241: { INDEX_op_ld16s_i64, { "r", "r" } }, ! 1242: { INDEX_op_ld32u_i64, { "r", "r" } }, ! 1243: { INDEX_op_ld32s_i64, { "r", "r" } }, ! 1244: { INDEX_op_ld_i64, { "r", "r" } }, ! 1245: { INDEX_op_st8_i64, { "r", "r" } }, ! 1246: { INDEX_op_st16_i64, { "r", "r" } }, ! 1247: { INDEX_op_st32_i64, { "r", "r" } }, ! 1248: { INDEX_op_st_i64, { "r", "r" } }, ! 1249: ! 1250: { INDEX_op_add_i64, { "r", "0", "re" } }, ! 1251: { INDEX_op_mul_i64, { "r", "0", "re" } }, ! 1252: { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } }, ! 1253: { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } }, ! 1254: { INDEX_op_sub_i64, { "r", "0", "re" } }, ! 1255: { INDEX_op_and_i64, { "r", "0", "reZ" } }, ! 1256: { INDEX_op_or_i64, { "r", "0", "re" } }, ! 1257: { INDEX_op_xor_i64, { "r", "0", "re" } }, ! 1258: ! 1259: { INDEX_op_shl_i64, { "r", "0", "ci" } }, ! 1260: { INDEX_op_shr_i64, { "r", "0", "ci" } }, ! 1261: { INDEX_op_sar_i64, { "r", "0", "ci" } }, ! 1262: ! 1263: { INDEX_op_brcond_i64, { "r", "re" } }, ! 1264: ! 1265: { INDEX_op_bswap_i32, { "r", "0" } }, ! 1266: { INDEX_op_bswap_i64, { "r", "0" } }, ! 1267: ! 1268: { INDEX_op_neg_i32, { "r", "0" } }, ! 1269: { INDEX_op_neg_i64, { "r", "0" } }, ! 1270: ! 1271: { INDEX_op_ext8s_i32, { "r", "r"} }, ! 1272: { INDEX_op_ext16s_i32, { "r", "r"} }, ! 1273: { INDEX_op_ext8s_i64, { "r", "r"} }, ! 1274: { INDEX_op_ext16s_i64, { "r", "r"} }, ! 1275: { INDEX_op_ext32s_i64, { "r", "r"} }, ! 1276: ! 1277: { INDEX_op_qemu_ld8u, { "r", "L" } }, ! 1278: { INDEX_op_qemu_ld8s, { "r", "L" } }, ! 1279: { INDEX_op_qemu_ld16u, { "r", "L" } }, ! 1280: { INDEX_op_qemu_ld16s, { "r", "L" } }, ! 1281: { INDEX_op_qemu_ld32u, { "r", "L" } }, ! 1282: { INDEX_op_qemu_ld32s, { "r", "L" } }, ! 1283: { INDEX_op_qemu_ld64, { "r", "L" } }, ! 1284: ! 1285: { INDEX_op_qemu_st8, { "L", "L" } }, ! 1286: { INDEX_op_qemu_st16, { "L", "L" } }, ! 1287: { INDEX_op_qemu_st32, { "L", "L" } }, ! 1288: { INDEX_op_qemu_st64, { "L", "L", "L" } }, ! 1289: ! 1290: { -1 }, ! 1291: }; ! 1292: ! 1293: void tcg_target_init(TCGContext *s) ! 1294: { ! 1295: /* fail safe */ ! 1296: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) ! 1297: tcg_abort(); ! 1298: ! 1299: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); ! 1300: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff); ! 1301: tcg_regset_set32(tcg_target_call_clobber_regs, 0, ! 1302: (1 << TCG_REG_RDI) | ! 1303: (1 << TCG_REG_RSI) | ! 1304: (1 << TCG_REG_RDX) | ! 1305: (1 << TCG_REG_RCX) | ! 1306: (1 << TCG_REG_R8) | ! 1307: (1 << TCG_REG_R9) | ! 1308: (1 << TCG_REG_RAX) | ! 1309: (1 << TCG_REG_R10) | ! 1310: (1 << TCG_REG_R11)); ! 1311: ! 1312: tcg_regset_clear(s->reserved_regs); ! 1313: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP); ! 1314: ! 1315: tcg_add_target_add_op_defs(x86_64_op_defs); ! 1316: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.