|
|
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] = {
1.1.1.4 ! root 27: #if TCG_TARGET_REG_BITS == 64
! 28: "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
! 29: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
! 30: #else
! 31: "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
! 32: #endif
1.1 root 33: };
34: #endif
35:
36: static const int tcg_target_reg_alloc_order[] = {
1.1.1.4 ! root 37: #if TCG_TARGET_REG_BITS == 64
! 38: TCG_REG_RBP,
! 39: TCG_REG_RBX,
! 40: TCG_REG_R12,
! 41: TCG_REG_R13,
! 42: TCG_REG_R14,
! 43: TCG_REG_R15,
! 44: TCG_REG_R10,
! 45: TCG_REG_R11,
! 46: TCG_REG_R9,
! 47: TCG_REG_R8,
! 48: TCG_REG_RCX,
! 49: TCG_REG_RDX,
! 50: TCG_REG_RSI,
! 51: TCG_REG_RDI,
! 52: TCG_REG_RAX,
! 53: #else
1.1 root 54: TCG_REG_EBX,
55: TCG_REG_ESI,
56: TCG_REG_EDI,
57: TCG_REG_EBP,
1.1.1.4 ! root 58: TCG_REG_ECX,
! 59: TCG_REG_EDX,
! 60: TCG_REG_EAX,
! 61: #endif
1.1 root 62: };
63:
1.1.1.4 ! root 64: static const int tcg_target_call_iarg_regs[] = {
! 65: #if TCG_TARGET_REG_BITS == 64
! 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: #else
! 73: TCG_REG_EAX,
! 74: TCG_REG_EDX,
! 75: TCG_REG_ECX
! 76: #endif
! 77: };
! 78:
! 79: static const int tcg_target_call_oarg_regs[2] = {
! 80: TCG_REG_EAX,
! 81: TCG_REG_EDX
! 82: };
1.1 root 83:
84: static uint8_t *tb_ret_addr;
85:
1.1.1.4 ! root 86: static void patch_reloc(uint8_t *code_ptr, int type,
1.1 root 87: tcg_target_long value, tcg_target_long addend)
88: {
89: value += addend;
90: switch(type) {
1.1.1.4 ! root 91: case R_386_PC32:
! 92: value -= (uintptr_t)code_ptr;
! 93: if (value != (int32_t)value) {
! 94: tcg_abort();
! 95: }
1.1 root 96: *(uint32_t *)code_ptr = value;
97: break;
1.1.1.4 ! root 98: case R_386_PC8:
! 99: value -= (uintptr_t)code_ptr;
! 100: if (value != (int8_t)value) {
! 101: tcg_abort();
! 102: }
! 103: *(uint8_t *)code_ptr = value;
1.1 root 104: break;
105: default:
106: tcg_abort();
107: }
108: }
109:
110: /* maximum number of register used for input function arguments */
111: static inline int tcg_target_get_call_iarg_regs_count(int flags)
112: {
1.1.1.4 ! root 113: if (TCG_TARGET_REG_BITS == 64) {
! 114: return 6;
! 115: }
! 116:
1.1 root 117: flags &= TCG_CALL_TYPE_MASK;
118: switch(flags) {
119: case TCG_CALL_TYPE_STD:
120: return 0;
121: case TCG_CALL_TYPE_REGPARM_1:
122: case TCG_CALL_TYPE_REGPARM_2:
123: case TCG_CALL_TYPE_REGPARM:
124: return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
125: default:
126: tcg_abort();
127: }
128: }
129:
130: /* parse target specific constraints */
131: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
132: {
133: const char *ct_str;
134:
135: ct_str = *pct_str;
136: switch(ct_str[0]) {
137: case 'a':
138: ct->ct |= TCG_CT_REG;
139: tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
140: break;
141: case 'b':
142: ct->ct |= TCG_CT_REG;
143: tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
144: break;
145: case 'c':
146: ct->ct |= TCG_CT_REG;
147: tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
148: break;
149: case 'd':
150: ct->ct |= TCG_CT_REG;
151: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
152: break;
153: case 'S':
154: ct->ct |= TCG_CT_REG;
155: tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
156: break;
157: case 'D':
158: ct->ct |= TCG_CT_REG;
159: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
160: break;
161: case 'q':
162: ct->ct |= TCG_CT_REG;
1.1.1.4 ! root 163: if (TCG_TARGET_REG_BITS == 64) {
! 164: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 165: } else {
! 166: tcg_regset_set32(ct->u.regs, 0, 0xf);
! 167: }
1.1 root 168: break;
169: case 'r':
170: ct->ct |= TCG_CT_REG;
1.1.1.4 ! root 171: if (TCG_TARGET_REG_BITS == 64) {
! 172: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 173: } else {
! 174: tcg_regset_set32(ct->u.regs, 0, 0xff);
! 175: }
1.1 root 176: break;
177:
178: /* qemu_ld/st address constraint */
179: case 'L':
180: ct->ct |= TCG_CT_REG;
1.1.1.4 ! root 181: if (TCG_TARGET_REG_BITS == 64) {
! 182: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 183: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
! 184: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
! 185: } else {
! 186: tcg_regset_set32(ct->u.regs, 0, 0xff);
! 187: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
! 188: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
! 189: }
! 190: break;
! 191:
! 192: case 'e':
! 193: ct->ct |= TCG_CT_CONST_S32;
! 194: break;
! 195: case 'Z':
! 196: ct->ct |= TCG_CT_CONST_U32;
1.1 root 197: break;
1.1.1.4 ! root 198:
1.1 root 199: default:
200: return -1;
201: }
202: ct_str++;
203: *pct_str = ct_str;
204: return 0;
205: }
206:
207: /* test if a constant matches the constraint */
208: static inline int tcg_target_const_match(tcg_target_long val,
209: const TCGArgConstraint *arg_ct)
210: {
1.1.1.4 ! root 211: int ct = arg_ct->ct;
! 212: if (ct & TCG_CT_CONST) {
1.1 root 213: return 1;
1.1.1.4 ! root 214: }
! 215: if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
! 216: return 1;
! 217: }
! 218: if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
! 219: return 1;
! 220: }
! 221: return 0;
1.1 root 222: }
223:
1.1.1.4 ! root 224: #if TCG_TARGET_REG_BITS == 64
! 225: # define LOWREGMASK(x) ((x) & 7)
! 226: #else
! 227: # define LOWREGMASK(x) (x)
! 228: #endif
! 229:
! 230: #define P_EXT 0x100 /* 0x0f opcode prefix */
! 231: #define P_DATA16 0x200 /* 0x66 opcode prefix */
! 232: #if TCG_TARGET_REG_BITS == 64
! 233: # define P_ADDR32 0x400 /* 0x67 opcode prefix */
! 234: # define P_REXW 0x800 /* Set REX.W = 1 */
! 235: # define P_REXB_R 0x1000 /* REG field as byte register */
! 236: # define P_REXB_RM 0x2000 /* R/M field as byte register */
! 237: #else
! 238: # define P_ADDR32 0
! 239: # define P_REXW 0
! 240: # define P_REXB_R 0
! 241: # define P_REXB_RM 0
! 242: #endif
! 243:
! 244: #define OPC_ARITH_EvIz (0x81)
! 245: #define OPC_ARITH_EvIb (0x83)
! 246: #define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
! 247: #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
! 248: #define OPC_BSWAP (0xc8 | P_EXT)
! 249: #define OPC_CALL_Jz (0xe8)
! 250: #define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
! 251: #define OPC_DEC_r32 (0x48)
! 252: #define OPC_IMUL_GvEv (0xaf | P_EXT)
! 253: #define OPC_IMUL_GvEvIb (0x6b)
! 254: #define OPC_IMUL_GvEvIz (0x69)
! 255: #define OPC_INC_r32 (0x40)
! 256: #define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
! 257: #define OPC_JCC_short (0x70) /* ... plus condition code */
! 258: #define OPC_JMP_long (0xe9)
! 259: #define OPC_JMP_short (0xeb)
! 260: #define OPC_LEA (0x8d)
! 261: #define OPC_MOVB_EvGv (0x88) /* stores, more or less */
! 262: #define OPC_MOVL_EvGv (0x89) /* stores, more or less */
! 263: #define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
! 264: #define OPC_MOVL_EvIz (0xc7)
! 265: #define OPC_MOVL_Iv (0xb8)
! 266: #define OPC_MOVSBL (0xbe | P_EXT)
! 267: #define OPC_MOVSWL (0xbf | P_EXT)
! 268: #define OPC_MOVSLQ (0x63 | P_REXW)
! 269: #define OPC_MOVZBL (0xb6 | P_EXT)
! 270: #define OPC_MOVZWL (0xb7 | P_EXT)
! 271: #define OPC_POP_r32 (0x58)
! 272: #define OPC_PUSH_r32 (0x50)
! 273: #define OPC_PUSH_Iv (0x68)
! 274: #define OPC_PUSH_Ib (0x6a)
! 275: #define OPC_RET (0xc3)
! 276: #define OPC_SETCC (0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
! 277: #define OPC_SHIFT_1 (0xd1)
! 278: #define OPC_SHIFT_Ib (0xc1)
! 279: #define OPC_SHIFT_cl (0xd3)
! 280: #define OPC_TESTL (0x85)
! 281: #define OPC_XCHG_ax_r32 (0x90)
! 282:
! 283: #define OPC_GRP3_Ev (0xf7)
! 284: #define OPC_GRP5 (0xff)
! 285:
! 286: /* Group 1 opcode extensions for 0x80-0x83.
! 287: These are also used as modifiers for OPC_ARITH. */
1.1 root 288: #define ARITH_ADD 0
289: #define ARITH_OR 1
290: #define ARITH_ADC 2
291: #define ARITH_SBB 3
292: #define ARITH_AND 4
293: #define ARITH_SUB 5
294: #define ARITH_XOR 6
295: #define ARITH_CMP 7
296:
1.1.1.4 ! root 297: /* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3. */
1.1.1.2 root 298: #define SHIFT_ROL 0
299: #define SHIFT_ROR 1
1.1 root 300: #define SHIFT_SHL 4
301: #define SHIFT_SHR 5
302: #define SHIFT_SAR 7
303:
1.1.1.4 ! root 304: /* Group 3 opcode extensions for 0xf6, 0xf7. To be used with OPC_GRP3. */
! 305: #define EXT3_NOT 2
! 306: #define EXT3_NEG 3
! 307: #define EXT3_MUL 4
! 308: #define EXT3_IMUL 5
! 309: #define EXT3_DIV 6
! 310: #define EXT3_IDIV 7
! 311:
! 312: /* Group 5 opcode extensions for 0xff. To be used with OPC_GRP5. */
! 313: #define EXT5_INC_Ev 0
! 314: #define EXT5_DEC_Ev 1
! 315: #define EXT5_CALLN_Ev 2
! 316: #define EXT5_JMPN_Ev 4
! 317:
! 318: /* Condition codes to be added to OPC_JCC_{long,short}. */
1.1 root 319: #define JCC_JMP (-1)
320: #define JCC_JO 0x0
321: #define JCC_JNO 0x1
322: #define JCC_JB 0x2
323: #define JCC_JAE 0x3
324: #define JCC_JE 0x4
325: #define JCC_JNE 0x5
326: #define JCC_JBE 0x6
327: #define JCC_JA 0x7
328: #define JCC_JS 0x8
329: #define JCC_JNS 0x9
330: #define JCC_JP 0xa
331: #define JCC_JNP 0xb
332: #define JCC_JL 0xc
333: #define JCC_JGE 0xd
334: #define JCC_JLE 0xe
335: #define JCC_JG 0xf
336:
337: static const uint8_t tcg_cond_to_jcc[10] = {
338: [TCG_COND_EQ] = JCC_JE,
339: [TCG_COND_NE] = JCC_JNE,
340: [TCG_COND_LT] = JCC_JL,
341: [TCG_COND_GE] = JCC_JGE,
342: [TCG_COND_LE] = JCC_JLE,
343: [TCG_COND_GT] = JCC_JG,
344: [TCG_COND_LTU] = JCC_JB,
345: [TCG_COND_GEU] = JCC_JAE,
346: [TCG_COND_LEU] = JCC_JBE,
347: [TCG_COND_GTU] = JCC_JA,
348: };
349:
1.1.1.4 ! root 350: #if TCG_TARGET_REG_BITS == 64
! 351: static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
1.1 root 352: {
1.1.1.4 ! root 353: int rex;
! 354:
! 355: if (opc & P_DATA16) {
! 356: /* We should never be asking for both 16 and 64-bit operation. */
! 357: assert((opc & P_REXW) == 0);
! 358: tcg_out8(s, 0x66);
! 359: }
! 360: if (opc & P_ADDR32) {
! 361: tcg_out8(s, 0x67);
! 362: }
! 363:
! 364: rex = 0;
! 365: rex |= (opc & P_REXW) >> 8; /* REX.W */
! 366: rex |= (r & 8) >> 1; /* REX.R */
! 367: rex |= (x & 8) >> 2; /* REX.X */
! 368: rex |= (rm & 8) >> 3; /* REX.B */
! 369:
! 370: /* P_REXB_{R,RM} indicates that the given register is the low byte.
! 371: For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
! 372: as otherwise the encoding indicates %[abcd]h. Note that the values
! 373: that are ORed in merely indicate that the REX byte must be present;
! 374: those bits get discarded in output. */
! 375: rex |= opc & (r >= 4 ? P_REXB_R : 0);
! 376: rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
! 377:
! 378: if (rex) {
! 379: tcg_out8(s, (uint8_t)(rex | 0x40));
! 380: }
! 381:
! 382: if (opc & P_EXT) {
1.1 root 383: tcg_out8(s, 0x0f);
1.1.1.4 ! root 384: }
1.1 root 385: tcg_out8(s, opc);
386: }
1.1.1.4 ! root 387: #else
! 388: static void tcg_out_opc(TCGContext *s, int opc)
1.1 root 389: {
1.1.1.4 ! root 390: if (opc & P_DATA16) {
! 391: tcg_out8(s, 0x66);
! 392: }
! 393: if (opc & P_EXT) {
! 394: tcg_out8(s, 0x0f);
! 395: }
! 396: tcg_out8(s, opc);
1.1 root 397: }
1.1.1.4 ! root 398: /* Discard the register arguments to tcg_out_opc early, so as not to penalize
! 399: the 32-bit compilation paths. This method works with all versions of gcc,
! 400: whereas relying on optimization may not be able to exclude them. */
! 401: #define tcg_out_opc(s, opc, r, rm, x) (tcg_out_opc)(s, opc)
! 402: #endif
! 403:
! 404: static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
! 405: {
! 406: tcg_out_opc(s, opc, r, rm, 0);
! 407: tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
! 408: }
! 409:
! 410: /* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
! 411: We handle either RM and INDEX missing with a negative value. In 64-bit
! 412: mode for absolute addresses, ~RM is the size of the immediate operand
! 413: that will follow the instruction. */
! 414:
! 415: static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
! 416: int index, int shift,
! 417: tcg_target_long offset)
! 418: {
! 419: int mod, len;
! 420:
! 421: if (index < 0 && rm < 0) {
! 422: if (TCG_TARGET_REG_BITS == 64) {
! 423: /* Try for a rip-relative addressing mode. This has replaced
! 424: the 32-bit-mode absolute addressing encoding. */
! 425: tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
! 426: tcg_target_long disp = offset - pc;
! 427: if (disp == (int32_t)disp) {
! 428: tcg_out_opc(s, opc, r, 0, 0);
! 429: tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
! 430: tcg_out32(s, disp);
! 431: return;
! 432: }
1.1 root 433:
1.1.1.4 ! root 434: /* Try for an absolute address encoding. This requires the
! 435: use of the MODRM+SIB encoding and is therefore larger than
! 436: rip-relative addressing. */
! 437: if (offset == (int32_t)offset) {
! 438: tcg_out_opc(s, opc, r, 0, 0);
! 439: tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
! 440: tcg_out8(s, (4 << 3) | 5);
! 441: tcg_out32(s, offset);
! 442: return;
! 443: }
! 444:
! 445: /* ??? The memory isn't directly addressable. */
! 446: tcg_abort();
1.1 root 447: } else {
1.1.1.4 ! root 448: /* Absolute address. */
! 449: tcg_out_opc(s, opc, r, 0, 0);
! 450: tcg_out8(s, (r << 3) | 5);
! 451: tcg_out32(s, offset);
! 452: return;
1.1 root 453: }
1.1.1.4 ! root 454: }
! 455:
! 456: /* Find the length of the immediate addend. Note that the encoding
! 457: that would be used for (%ebp) indicates absolute addressing. */
! 458: if (rm < 0) {
! 459: mod = 0, len = 4, rm = 5;
! 460: } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
! 461: mod = 0, len = 0;
! 462: } else if (offset == (int8_t)offset) {
! 463: mod = 0x40, len = 1;
! 464: } else {
! 465: mod = 0x80, len = 4;
! 466: }
! 467:
! 468: /* Use a single byte MODRM format if possible. Note that the encoding
! 469: that would be used for %esp is the escape to the two byte form. */
! 470: if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
! 471: /* Single byte MODRM format. */
! 472: tcg_out_opc(s, opc, r, rm, 0);
! 473: tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
1.1 root 474: } else {
1.1.1.4 ! root 475: /* Two byte MODRM+SIB format. */
! 476:
! 477: /* Note that the encoding that would place %esp into the index
! 478: field indicates no index register. In 64-bit mode, the REX.X
! 479: bit counts, so %r12 can be used as the index. */
! 480: if (index < 0) {
! 481: index = 4;
1.1 root 482: } else {
1.1.1.4 ! root 483: assert(index != TCG_REG_ESP);
1.1 root 484: }
1.1.1.4 ! root 485:
! 486: tcg_out_opc(s, opc, r, rm, index);
! 487: tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
! 488: tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
! 489: }
! 490:
! 491: if (len == 1) {
! 492: tcg_out8(s, offset);
! 493: } else if (len == 4) {
1.1 root 494: tcg_out32(s, offset);
495: }
496: }
497:
1.1.1.4 ! root 498: /* A simplification of the above with no index or shift. */
! 499: static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
! 500: int rm, tcg_target_long offset)
! 501: {
! 502: tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
! 503: }
! 504:
! 505: /* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
! 506: static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
1.1 root 507: {
1.1.1.4 ! root 508: /* Propagate an opcode prefix, such as P_REXW. */
! 509: int ext = subop & ~0x7;
! 510: subop &= 0x7;
! 511:
! 512: tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
1.1 root 513: }
514:
1.1.1.4 ! root 515: static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
! 516: {
! 517: if (arg != ret) {
! 518: int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
! 519: tcg_out_modrm(s, opc, ret, arg);
! 520: }
! 521: }
! 522:
! 523: static void tcg_out_movi(TCGContext *s, TCGType type,
! 524: int ret, tcg_target_long arg)
1.1 root 525: {
526: if (arg == 0) {
1.1.1.4 ! root 527: tgen_arithr(s, ARITH_XOR, ret, ret);
! 528: return;
! 529: } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
! 530: tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
! 531: tcg_out32(s, arg);
! 532: } else if (arg == (int32_t)arg) {
! 533: tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
! 534: tcg_out32(s, arg);
1.1 root 535: } else {
1.1.1.4 ! root 536: tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
1.1 root 537: tcg_out32(s, arg);
1.1.1.4 ! root 538: tcg_out32(s, arg >> 31 >> 1);
! 539: }
! 540: }
! 541:
! 542: static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
! 543: {
! 544: if (val == (int8_t)val) {
! 545: tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
! 546: tcg_out8(s, val);
! 547: } else if (val == (int32_t)val) {
! 548: tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
! 549: tcg_out32(s, val);
! 550: } else {
! 551: tcg_abort();
1.1 root 552: }
553: }
554:
1.1.1.4 ! root 555: static inline void tcg_out_push(TCGContext *s, int reg)
! 556: {
! 557: tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
! 558: }
! 559:
! 560: static inline void tcg_out_pop(TCGContext *s, int reg)
! 561: {
! 562: tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
! 563: }
! 564:
1.1 root 565: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
566: int arg1, tcg_target_long arg2)
567: {
1.1.1.4 ! root 568: int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
! 569: tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
1.1 root 570: }
571:
572: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
573: int arg1, tcg_target_long arg2)
574: {
1.1.1.4 ! root 575: int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
! 576: tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
1.1 root 577: }
578:
1.1.1.4 ! root 579: static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
1.1 root 580: {
1.1.1.4 ! root 581: /* Propagate an opcode prefix, such as P_DATA16. */
! 582: int ext = subopc & ~0x7;
! 583: subopc &= 0x7;
! 584:
! 585: if (count == 1) {
! 586: tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
1.1 root 587: } else {
1.1.1.4 ! root 588: tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
! 589: tcg_out8(s, count);
! 590: }
! 591: }
! 592:
! 593: static inline void tcg_out_bswap32(TCGContext *s, int reg)
! 594: {
! 595: tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
! 596: }
! 597:
! 598: static inline void tcg_out_rolw_8(TCGContext *s, int reg)
! 599: {
! 600: tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
! 601: }
! 602:
! 603: static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
! 604: {
! 605: /* movzbl */
! 606: assert(src < 4 || TCG_TARGET_REG_BITS == 64);
! 607: tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
! 608: }
! 609:
! 610: static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
! 611: {
! 612: /* movsbl */
! 613: assert(src < 4 || TCG_TARGET_REG_BITS == 64);
! 614: tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
! 615: }
! 616:
! 617: static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
! 618: {
! 619: /* movzwl */
! 620: tcg_out_modrm(s, OPC_MOVZWL, dest, src);
! 621: }
! 622:
! 623: static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
! 624: {
! 625: /* movsw[lq] */
! 626: tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
! 627: }
! 628:
! 629: static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
! 630: {
! 631: /* 32-bit mov zero extends. */
! 632: tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
! 633: }
! 634:
! 635: static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
! 636: {
! 637: tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
! 638: }
! 639:
! 640: static inline void tcg_out_bswap64(TCGContext *s, int reg)
! 641: {
! 642: tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
! 643: }
! 644:
! 645: static void tgen_arithi(TCGContext *s, int c, int r0,
! 646: tcg_target_long val, int cf)
! 647: {
! 648: int rexw = 0;
! 649:
! 650: if (TCG_TARGET_REG_BITS == 64) {
! 651: rexw = c & -8;
! 652: c &= 7;
! 653: }
! 654:
! 655: /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
! 656: partial flags update stalls on Pentium4 and are not recommended
! 657: by current Intel optimization manuals. */
! 658: if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
! 659: int is_inc = (c == ARITH_ADD) ^ (val < 0);
! 660: if (TCG_TARGET_REG_BITS == 64) {
! 661: /* The single-byte increment encodings are re-tasked as the
! 662: REX prefixes. Use the MODRM encoding. */
! 663: tcg_out_modrm(s, OPC_GRP5 + rexw,
! 664: (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
! 665: } else {
! 666: tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
! 667: }
! 668: return;
! 669: }
! 670:
! 671: if (c == ARITH_AND) {
! 672: if (TCG_TARGET_REG_BITS == 64) {
! 673: if (val == 0xffffffffu) {
! 674: tcg_out_ext32u(s, r0, r0);
! 675: return;
! 676: }
! 677: if (val == (uint32_t)val) {
! 678: /* AND with no high bits set can use a 32-bit operation. */
! 679: rexw = 0;
! 680: }
! 681: }
! 682: if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
! 683: tcg_out_ext8u(s, r0, r0);
! 684: return;
! 685: }
! 686: if (val == 0xffffu) {
! 687: tcg_out_ext16u(s, r0, r0);
! 688: return;
! 689: }
! 690: }
! 691:
! 692: if (val == (int8_t)val) {
! 693: tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
! 694: tcg_out8(s, val);
! 695: return;
! 696: }
! 697: if (rexw == 0 || val == (int32_t)val) {
! 698: tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
1.1 root 699: tcg_out32(s, val);
1.1.1.4 ! root 700: return;
1.1 root 701: }
1.1.1.4 ! root 702:
! 703: tcg_abort();
1.1 root 704: }
705:
706: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
707: {
1.1.1.4 ! root 708: if (val != 0) {
! 709: tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
! 710: }
1.1 root 711: }
712:
1.1.1.4 ! root 713: /* Use SMALL != 0 to force a short forward branch. */
! 714: static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
1.1 root 715: {
716: int32_t val, val1;
717: TCGLabel *l = &s->labels[label_index];
1.1.1.4 ! root 718:
1.1 root 719: if (l->has_value) {
720: val = l->u.value - (tcg_target_long)s->code_ptr;
721: val1 = val - 2;
722: if ((int8_t)val1 == val1) {
1.1.1.4 ! root 723: if (opc == -1) {
! 724: tcg_out8(s, OPC_JMP_short);
! 725: } else {
! 726: tcg_out8(s, OPC_JCC_short + opc);
! 727: }
1.1 root 728: tcg_out8(s, val1);
729: } else {
1.1.1.4 ! root 730: if (small) {
! 731: tcg_abort();
! 732: }
1.1 root 733: if (opc == -1) {
1.1.1.4 ! root 734: tcg_out8(s, OPC_JMP_long);
1.1 root 735: tcg_out32(s, val - 5);
736: } else {
1.1.1.4 ! root 737: tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
1.1 root 738: tcg_out32(s, val - 6);
739: }
740: }
1.1.1.4 ! root 741: } else if (small) {
! 742: if (opc == -1) {
! 743: tcg_out8(s, OPC_JMP_short);
! 744: } else {
! 745: tcg_out8(s, OPC_JCC_short + opc);
! 746: }
! 747: tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
! 748: s->code_ptr += 1;
1.1 root 749: } else {
750: if (opc == -1) {
1.1.1.4 ! root 751: tcg_out8(s, OPC_JMP_long);
1.1 root 752: } else {
1.1.1.4 ! root 753: tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
1.1 root 754: }
755: tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
756: s->code_ptr += 4;
757: }
758: }
759:
1.1.1.4 ! root 760: static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
! 761: int const_arg2, int rexw)
1.1 root 762: {
763: if (const_arg2) {
764: if (arg2 == 0) {
765: /* test r, r */
1.1.1.4 ! root 766: tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
1.1 root 767: } else {
1.1.1.4 ! root 768: tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
1.1 root 769: }
770: } else {
1.1.1.4 ! root 771: tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
1.1 root 772: }
773: }
774:
1.1.1.4 ! root 775: static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
! 776: TCGArg arg1, TCGArg arg2, int const_arg2,
! 777: int label_index, int small)
! 778: {
! 779: tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
! 780: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
! 781: }
! 782:
! 783: #if TCG_TARGET_REG_BITS == 64
! 784: static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
! 785: TCGArg arg1, TCGArg arg2, int const_arg2,
! 786: int label_index, int small)
! 787: {
! 788: tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
! 789: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
! 790: }
! 791: #else
1.1 root 792: /* XXX: we implement it at the target level to avoid having to
793: handle cross basic blocks temporaries */
1.1.1.4 ! root 794: static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
! 795: const int *const_args, int small)
1.1 root 796: {
797: int label_next;
798: label_next = gen_new_label();
799: switch(args[4]) {
800: case TCG_COND_EQ:
1.1.1.4 ! root 801: tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
! 802: label_next, 1);
! 803: tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
! 804: args[5], small);
1.1 root 805: break;
806: case TCG_COND_NE:
1.1.1.4 ! root 807: tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
! 808: args[5], small);
! 809: tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
! 810: args[5], small);
1.1 root 811: break;
812: case TCG_COND_LT:
1.1.1.4 ! root 813: tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
! 814: args[5], small);
! 815: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 816: tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
! 817: args[5], small);
1.1 root 818: break;
819: case TCG_COND_LE:
1.1.1.4 ! root 820: tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
! 821: args[5], small);
! 822: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 823: tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
! 824: args[5], small);
1.1 root 825: break;
826: case TCG_COND_GT:
1.1.1.4 ! root 827: tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
! 828: args[5], small);
! 829: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 830: tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
! 831: args[5], small);
1.1 root 832: break;
833: case TCG_COND_GE:
1.1.1.4 ! root 834: tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
! 835: args[5], small);
! 836: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 837: tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
! 838: args[5], small);
1.1 root 839: break;
840: case TCG_COND_LTU:
1.1.1.4 ! root 841: tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
! 842: args[5], small);
! 843: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 844: tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
! 845: args[5], small);
1.1 root 846: break;
847: case TCG_COND_LEU:
1.1.1.4 ! root 848: tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
! 849: args[5], small);
! 850: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 851: tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
! 852: args[5], small);
1.1 root 853: break;
854: case TCG_COND_GTU:
1.1.1.4 ! root 855: tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
! 856: args[5], small);
! 857: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 858: tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
! 859: args[5], small);
1.1 root 860: break;
861: case TCG_COND_GEU:
1.1.1.4 ! root 862: tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
! 863: args[5], small);
! 864: tcg_out_jxx(s, JCC_JNE, label_next, 1);
! 865: tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
! 866: args[5], small);
1.1 root 867: break;
868: default:
869: tcg_abort();
870: }
871: tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
872: }
1.1.1.4 ! root 873: #endif
! 874:
! 875: static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
! 876: TCGArg arg1, TCGArg arg2, int const_arg2)
! 877: {
! 878: tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
! 879: tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
! 880: tcg_out_ext8u(s, dest, dest);
! 881: }
! 882:
! 883: #if TCG_TARGET_REG_BITS == 64
! 884: static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
! 885: TCGArg arg1, TCGArg arg2, int const_arg2)
! 886: {
! 887: tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
! 888: tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
! 889: tcg_out_ext8u(s, dest, dest);
! 890: }
! 891: #else
! 892: static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
! 893: const int *const_args)
! 894: {
! 895: TCGArg new_args[6];
! 896: int label_true, label_over;
! 897:
! 898: memcpy(new_args, args+1, 5*sizeof(TCGArg));
! 899:
! 900: if (args[0] == args[1] || args[0] == args[2]
! 901: || (!const_args[3] && args[0] == args[3])
! 902: || (!const_args[4] && args[0] == args[4])) {
! 903: /* When the destination overlaps with one of the argument
! 904: registers, don't do anything tricky. */
! 905: label_true = gen_new_label();
! 906: label_over = gen_new_label();
! 907:
! 908: new_args[5] = label_true;
! 909: tcg_out_brcond2(s, new_args, const_args+1, 1);
! 910:
! 911: tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
! 912: tcg_out_jxx(s, JCC_JMP, label_over, 1);
! 913: tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
! 914:
! 915: tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
! 916: tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
! 917: } else {
! 918: /* When the destination does not overlap one of the arguments,
! 919: clear the destination first, jump if cond false, and emit an
! 920: increment in the true case. This results in smaller code. */
! 921:
! 922: tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
! 923:
! 924: label_over = gen_new_label();
! 925: new_args[4] = tcg_invert_cond(new_args[4]);
! 926: new_args[5] = label_over;
! 927: tcg_out_brcond2(s, new_args, const_args+1, 1);
! 928:
! 929: tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
! 930: tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
! 931: }
! 932: }
! 933: #endif
! 934:
! 935: static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
! 936: {
! 937: tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
! 938:
! 939: if (disp == (int32_t)disp) {
! 940: tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
! 941: tcg_out32(s, disp);
! 942: } else {
! 943: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
! 944: tcg_out_modrm(s, OPC_GRP5,
! 945: call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
! 946: }
! 947: }
! 948:
! 949: static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
! 950: {
! 951: tcg_out_branch(s, 1, dest);
! 952: }
! 953:
! 954: static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
! 955: {
! 956: tcg_out_branch(s, 0, dest);
! 957: }
1.1 root 958:
959: #if defined(CONFIG_SOFTMMU)
960:
961: #include "../../softmmu_defs.h"
962:
963: static void *qemu_ld_helpers[4] = {
964: __ldb_mmu,
965: __ldw_mmu,
966: __ldl_mmu,
967: __ldq_mmu,
968: };
969:
970: static void *qemu_st_helpers[4] = {
971: __stb_mmu,
972: __stw_mmu,
973: __stl_mmu,
974: __stq_mmu,
975: };
1.1.1.4 ! root 976:
! 977: /* Perform the TLB load and compare.
! 978:
! 979: Inputs:
! 980: ADDRLO_IDX contains the index into ARGS of the low part of the
! 981: address; the high part of the address is at ADDR_LOW_IDX+1.
! 982:
! 983: MEM_INDEX and S_BITS are the memory context and log2 size of the load.
! 984:
! 985: WHICH is the offset into the CPUTLBEntry structure of the slot to read.
! 986: This should be offsetof addr_read or addr_write.
! 987:
! 988: Outputs:
! 989: LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
! 990: positions of the displacements of forward jumps to the TLB miss case.
! 991:
! 992: First argument register is loaded with the low part of the address.
! 993: In the TLB hit case, it has been adjusted as indicated by the TLB
! 994: and so is a host address. In the TLB miss case, it continues to
! 995: hold a guest address.
! 996:
! 997: Second argument register is clobbered. */
! 998:
! 999: static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
! 1000: int mem_index, int s_bits,
! 1001: const TCGArg *args,
! 1002: uint8_t **label_ptr, int which)
! 1003: {
! 1004: const int addrlo = args[addrlo_idx];
! 1005: const int r0 = tcg_target_call_iarg_regs[0];
! 1006: const int r1 = tcg_target_call_iarg_regs[1];
! 1007: TCGType type = TCG_TYPE_I32;
! 1008: int rexw = 0;
! 1009:
! 1010: if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
! 1011: type = TCG_TYPE_I64;
! 1012: rexw = P_REXW;
! 1013: }
! 1014:
! 1015: tcg_out_mov(s, type, r1, addrlo);
! 1016: tcg_out_mov(s, type, r0, addrlo);
! 1017:
! 1018: tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
! 1019: TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
! 1020:
! 1021: tgen_arithi(s, ARITH_AND + rexw, r0,
! 1022: TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
! 1023: tgen_arithi(s, ARITH_AND + rexw, r1,
! 1024: (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
! 1025:
! 1026: tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
! 1027: offsetof(CPUState, tlb_table[mem_index][0])
! 1028: + which);
! 1029:
! 1030: /* cmp 0(r1), r0 */
! 1031: tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
! 1032:
! 1033: tcg_out_mov(s, type, r0, addrlo);
! 1034:
! 1035: /* jne label1 */
! 1036: tcg_out8(s, OPC_JCC_short + JCC_JNE);
! 1037: label_ptr[0] = s->code_ptr;
! 1038: s->code_ptr++;
! 1039:
! 1040: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
! 1041: /* cmp 4(r1), addrhi */
! 1042: tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
! 1043:
! 1044: /* jne label1 */
! 1045: tcg_out8(s, OPC_JCC_short + JCC_JNE);
! 1046: label_ptr[1] = s->code_ptr;
! 1047: s->code_ptr++;
! 1048: }
! 1049:
! 1050: /* TLB Hit. */
! 1051:
! 1052: /* add addend(r1), r0 */
! 1053: tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
! 1054: offsetof(CPUTLBEntry, addend) - which);
! 1055: }
1.1 root 1056: #endif
1057:
1.1.1.4 ! root 1058: static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
! 1059: int base, tcg_target_long ofs, int sizeop)
! 1060: {
! 1061: #ifdef TARGET_WORDS_BIGENDIAN
! 1062: const int bswap = 1;
! 1063: #else
! 1064: const int bswap = 0;
1.1.1.3 root 1065: #endif
1.1.1.4 ! root 1066: switch (sizeop) {
! 1067: case 0:
! 1068: tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
! 1069: break;
! 1070: case 0 | 4:
! 1071: tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
! 1072: break;
! 1073: case 1:
! 1074: tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
! 1075: if (bswap) {
! 1076: tcg_out_rolw_8(s, datalo);
! 1077: }
! 1078: break;
! 1079: case 1 | 4:
! 1080: if (bswap) {
! 1081: tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
! 1082: tcg_out_rolw_8(s, datalo);
! 1083: tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
! 1084: } else {
! 1085: tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
! 1086: }
! 1087: break;
! 1088: case 2:
! 1089: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
! 1090: if (bswap) {
! 1091: tcg_out_bswap32(s, datalo);
! 1092: }
! 1093: break;
! 1094: #if TCG_TARGET_REG_BITS == 64
! 1095: case 2 | 4:
! 1096: if (bswap) {
! 1097: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
! 1098: tcg_out_bswap32(s, datalo);
! 1099: tcg_out_ext32s(s, datalo, datalo);
! 1100: } else {
! 1101: tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
! 1102: }
! 1103: break;
! 1104: #endif
! 1105: case 3:
! 1106: if (TCG_TARGET_REG_BITS == 64) {
! 1107: tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
! 1108: if (bswap) {
! 1109: tcg_out_bswap64(s, datalo);
! 1110: }
! 1111: } else {
! 1112: if (bswap) {
! 1113: int t = datalo;
! 1114: datalo = datahi;
! 1115: datahi = t;
! 1116: }
! 1117: if (base != datalo) {
! 1118: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
! 1119: tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
! 1120: } else {
! 1121: tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
! 1122: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
! 1123: }
! 1124: if (bswap) {
! 1125: tcg_out_bswap32(s, datalo);
! 1126: tcg_out_bswap32(s, datahi);
! 1127: }
! 1128: }
! 1129: break;
! 1130: default:
! 1131: tcg_abort();
! 1132: }
! 1133: }
1.1.1.3 root 1134:
1.1 root 1135: /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
1136: EAX. It will be useful once fixed registers globals are less
1137: common. */
1138: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
1139: int opc)
1140: {
1.1.1.4 ! root 1141: int data_reg, data_reg2 = 0;
! 1142: int addrlo_idx;
1.1 root 1143: #if defined(CONFIG_SOFTMMU)
1.1.1.4 ! root 1144: int mem_index, s_bits, arg_idx;
! 1145: uint8_t *label_ptr[3];
1.1 root 1146: #endif
1147:
1.1.1.4 ! root 1148: data_reg = args[0];
! 1149: addrlo_idx = 1;
! 1150: if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
! 1151: data_reg2 = args[1];
! 1152: addrlo_idx = 2;
! 1153: }
1.1 root 1154:
1155: #if defined(CONFIG_SOFTMMU)
1.1.1.4 ! root 1156: mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
! 1157: s_bits = opc & 3;
1.1 root 1158:
1.1.1.4 ! root 1159: tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
! 1160: label_ptr, offsetof(CPUTLBEntry, addr_read));
1.1 root 1161:
1.1.1.4 ! root 1162: /* TLB Hit. */
! 1163: tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
! 1164: tcg_target_call_iarg_regs[0], 0, opc);
! 1165:
! 1166: /* jmp label2 */
! 1167: tcg_out8(s, OPC_JMP_short);
! 1168: label_ptr[2] = s->code_ptr;
1.1 root 1169: s->code_ptr++;
1.1.1.4 ! root 1170:
! 1171: /* TLB Miss. */
! 1172:
! 1173: /* label1: */
! 1174: *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
! 1175: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
! 1176: *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
! 1177: }
1.1 root 1178:
1179: /* XXX: move that code at the end of the TB */
1.1.1.4 ! root 1180: /* The first argument is already loaded with addrlo. */
! 1181: arg_idx = 1;
! 1182: if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
! 1183: tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
! 1184: args[addrlo_idx + 1]);
! 1185: }
! 1186: tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
! 1187: mem_index);
! 1188: tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
1.1 root 1189:
1190: switch(opc) {
1191: case 0 | 4:
1.1.1.4 ! root 1192: tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
1.1 root 1193: break;
1194: case 1 | 4:
1.1.1.4 ! root 1195: tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
1.1 root 1196: break;
1197: case 0:
1.1.1.4 ! root 1198: tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
1.1 root 1199: break;
1200: case 1:
1.1.1.4 ! root 1201: tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
1.1 root 1202: break;
1203: case 2:
1.1.1.4 ! root 1204: tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
! 1205: break;
! 1206: #if TCG_TARGET_REG_BITS == 64
! 1207: case 2 | 4:
! 1208: tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
1.1 root 1209: break;
1.1.1.4 ! root 1210: #endif
1.1 root 1211: case 3:
1.1.1.4 ! root 1212: if (TCG_TARGET_REG_BITS == 64) {
! 1213: tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
! 1214: } else if (data_reg == TCG_REG_EDX) {
! 1215: /* xchg %edx, %eax */
! 1216: tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
! 1217: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
1.1 root 1218: } else {
1.1.1.4 ! root 1219: tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
! 1220: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
1.1 root 1221: }
1222: break;
1.1.1.4 ! root 1223: default:
! 1224: tcg_abort();
1.1 root 1225: }
1226:
1.1.1.4 ! root 1227: /* label2: */
! 1228: *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1.1 root 1229: #else
1.1.1.4 ! root 1230: {
! 1231: int32_t offset = GUEST_BASE;
! 1232: int base = args[addrlo_idx];
! 1233:
! 1234: if (TCG_TARGET_REG_BITS == 64) {
! 1235: /* ??? We assume all operations have left us with register
! 1236: contents that are zero extended. So far this appears to
! 1237: be true. If we want to enforce this, we can either do
! 1238: an explicit zero-extension here, or (if GUEST_BASE == 0)
! 1239: use the ADDR32 prefix. For now, do nothing. */
! 1240:
! 1241: if (offset != GUEST_BASE) {
! 1242: tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
! 1243: tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
! 1244: base = TCG_REG_RDI, offset = 0;
! 1245: }
! 1246: }
! 1247:
! 1248: tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
! 1249: }
1.1 root 1250: #endif
1.1.1.4 ! root 1251: }
1.1 root 1252:
1.1.1.4 ! root 1253: static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
! 1254: int base, tcg_target_long ofs, int sizeop)
! 1255: {
1.1 root 1256: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.4 ! root 1257: const int bswap = 1;
1.1 root 1258: #else
1.1.1.4 ! root 1259: const int bswap = 0;
1.1 root 1260: #endif
1.1.1.4 ! root 1261: /* ??? Ideally we wouldn't need a scratch register. For user-only,
! 1262: we could perform the bswap twice to restore the original value
! 1263: instead of moving to the scratch. But as it is, the L constraint
! 1264: means that the second argument reg is definitely free here. */
! 1265: int scratch = tcg_target_call_iarg_regs[1];
! 1266:
! 1267: switch (sizeop) {
1.1 root 1268: case 0:
1.1.1.4 ! root 1269: tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
1.1 root 1270: break;
1271: case 1:
1272: if (bswap) {
1.1.1.4 ! root 1273: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
! 1274: tcg_out_rolw_8(s, scratch);
! 1275: datalo = scratch;
1.1 root 1276: }
1.1.1.4 ! root 1277: tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
1.1 root 1278: break;
1279: case 2:
1280: if (bswap) {
1.1.1.4 ! root 1281: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
! 1282: tcg_out_bswap32(s, scratch);
! 1283: datalo = scratch;
1.1 root 1284: }
1.1.1.4 ! root 1285: tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
1.1 root 1286: break;
1287: case 3:
1.1.1.4 ! root 1288: if (TCG_TARGET_REG_BITS == 64) {
! 1289: if (bswap) {
! 1290: tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
! 1291: tcg_out_bswap64(s, scratch);
! 1292: datalo = scratch;
! 1293: }
! 1294: tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
! 1295: } else if (bswap) {
! 1296: tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
! 1297: tcg_out_bswap32(s, scratch);
! 1298: tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
! 1299: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
! 1300: tcg_out_bswap32(s, scratch);
! 1301: tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
! 1302: } else {
! 1303: tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
! 1304: tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1.1 root 1305: }
1306: break;
1307: default:
1308: tcg_abort();
1309: }
1310: }
1311:
1312: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1313: int opc)
1314: {
1.1.1.4 ! root 1315: int data_reg, data_reg2 = 0;
! 1316: int addrlo_idx;
1.1 root 1317: #if defined(CONFIG_SOFTMMU)
1.1.1.4 ! root 1318: int mem_index, s_bits;
! 1319: int stack_adjust;
! 1320: uint8_t *label_ptr[3];
1.1 root 1321: #endif
1322:
1.1.1.4 ! root 1323: data_reg = args[0];
! 1324: addrlo_idx = 1;
! 1325: if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
! 1326: data_reg2 = args[1];
! 1327: addrlo_idx = 2;
! 1328: }
1.1 root 1329:
1.1.1.4 ! root 1330: #if defined(CONFIG_SOFTMMU)
! 1331: mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1.1 root 1332: s_bits = opc;
1333:
1.1.1.4 ! root 1334: tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
! 1335: label_ptr, offsetof(CPUTLBEntry, addr_write));
1.1 root 1336:
1.1.1.4 ! root 1337: /* TLB Hit. */
! 1338: tcg_out_qemu_st_direct(s, data_reg, data_reg2,
! 1339: tcg_target_call_iarg_regs[0], 0, opc);
1.1 root 1340:
1.1.1.4 ! root 1341: /* jmp label2 */
! 1342: tcg_out8(s, OPC_JMP_short);
! 1343: label_ptr[2] = s->code_ptr;
1.1 root 1344: s->code_ptr++;
1.1.1.4 ! root 1345:
! 1346: /* TLB Miss. */
! 1347:
! 1348: /* label1: */
! 1349: *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
! 1350: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
! 1351: *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
! 1352: }
1.1 root 1353:
1354: /* XXX: move that code at the end of the TB */
1.1.1.4 ! root 1355: if (TCG_TARGET_REG_BITS == 64) {
! 1356: tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
! 1357: TCG_REG_RSI, data_reg);
! 1358: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
! 1359: stack_adjust = 0;
! 1360: } else if (TARGET_LONG_BITS == 32) {
! 1361: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
! 1362: if (opc == 3) {
! 1363: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
! 1364: tcg_out_pushi(s, mem_index);
! 1365: stack_adjust = 4;
! 1366: } else {
! 1367: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
! 1368: stack_adjust = 0;
1.1 root 1369: }
1370: } else {
1.1.1.4 ! root 1371: if (opc == 3) {
! 1372: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
! 1373: tcg_out_pushi(s, mem_index);
! 1374: tcg_out_push(s, data_reg2);
! 1375: tcg_out_push(s, data_reg);
! 1376: stack_adjust = 12;
! 1377: } else {
! 1378: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
! 1379: switch(opc) {
! 1380: case 0:
! 1381: tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
! 1382: break;
! 1383: case 1:
! 1384: tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
! 1385: break;
! 1386: case 2:
! 1387: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
! 1388: break;
! 1389: }
! 1390: tcg_out_pushi(s, mem_index);
! 1391: stack_adjust = 4;
1.1 root 1392: }
1393: }
1394:
1.1.1.4 ! root 1395: tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
1.1 root 1396:
1.1.1.4 ! root 1397: if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
! 1398: /* Pop and discard. This is 2 bytes smaller than the add. */
! 1399: tcg_out_pop(s, TCG_REG_ECX);
! 1400: } else if (stack_adjust != 0) {
! 1401: tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
1.1 root 1402: }
1403:
1404: /* label2: */
1.1.1.4 ! root 1405: *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
! 1406: #else
! 1407: {
! 1408: int32_t offset = GUEST_BASE;
! 1409: int base = args[addrlo_idx];
! 1410:
! 1411: if (TCG_TARGET_REG_BITS == 64) {
! 1412: /* ??? We assume all operations have left us with register
! 1413: contents that are zero extended. So far this appears to
! 1414: be true. If we want to enforce this, we can either do
! 1415: an explicit zero-extension here, or (if GUEST_BASE == 0)
! 1416: use the ADDR32 prefix. For now, do nothing. */
! 1417:
! 1418: if (offset != GUEST_BASE) {
! 1419: tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
! 1420: tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
! 1421: base = TCG_REG_RDI, offset = 0;
! 1422: }
! 1423: }
! 1424:
! 1425: tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
! 1426: }
1.1 root 1427: #endif
1428: }
1429:
1.1.1.4 ! root 1430: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1431: const TCGArg *args, const int *const_args)
1432: {
1.1.1.4 ! root 1433: int c, rexw = 0;
! 1434:
! 1435: #if TCG_TARGET_REG_BITS == 64
! 1436: # define OP_32_64(x) \
! 1437: case glue(glue(INDEX_op_, x), _i64): \
! 1438: rexw = P_REXW; /* FALLTHRU */ \
! 1439: case glue(glue(INDEX_op_, x), _i32)
! 1440: #else
! 1441: # define OP_32_64(x) \
! 1442: case glue(glue(INDEX_op_, x), _i32)
! 1443: #endif
! 1444:
1.1 root 1445: switch(opc) {
1446: case INDEX_op_exit_tb:
1.1.1.4 ! root 1447: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
! 1448: tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
1.1 root 1449: break;
1450: case INDEX_op_goto_tb:
1451: if (s->tb_jmp_offset) {
1452: /* direct jump method */
1.1.1.4 ! root 1453: tcg_out8(s, OPC_JMP_long); /* jmp im */
1.1 root 1454: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1455: tcg_out32(s, 0);
1456: } else {
1457: /* indirect jump method */
1.1.1.4 ! root 1458: tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
1.1 root 1459: (tcg_target_long)(s->tb_next + args[0]));
1460: }
1461: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1462: break;
1463: case INDEX_op_call:
1464: if (const_args[0]) {
1.1.1.4 ! root 1465: tcg_out_calli(s, args[0]);
1.1 root 1466: } else {
1.1.1.4 ! root 1467: /* call *reg */
! 1468: tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
1.1 root 1469: }
1470: break;
1471: case INDEX_op_jmp:
1472: if (const_args[0]) {
1.1.1.4 ! root 1473: tcg_out_jmp(s, args[0]);
1.1 root 1474: } else {
1.1.1.4 ! root 1475: /* jmp *reg */
! 1476: tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
1.1 root 1477: }
1478: break;
1479: case INDEX_op_br:
1.1.1.4 ! root 1480: tcg_out_jxx(s, JCC_JMP, args[0], 0);
1.1 root 1481: break;
1482: case INDEX_op_movi_i32:
1483: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1484: break;
1.1.1.4 ! root 1485: OP_32_64(ld8u):
! 1486: /* Note that we can ignore REXW for the zero-extend to 64-bit. */
! 1487: tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
! 1488: break;
! 1489: OP_32_64(ld8s):
! 1490: tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
! 1491: break;
! 1492: OP_32_64(ld16u):
! 1493: /* Note that we can ignore REXW for the zero-extend to 64-bit. */
! 1494: tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
1.1 root 1495: break;
1.1.1.4 ! root 1496: OP_32_64(ld16s):
! 1497: tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
! 1498: break;
! 1499: #if TCG_TARGET_REG_BITS == 64
! 1500: case INDEX_op_ld32u_i64:
! 1501: #endif
1.1 root 1502: case INDEX_op_ld_i32:
1.1.1.4 ! root 1503: tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1.1 root 1504: break;
1.1.1.4 ! root 1505:
! 1506: OP_32_64(st8):
! 1507: tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
! 1508: args[0], args[1], args[2]);
1.1 root 1509: break;
1.1.1.4 ! root 1510: OP_32_64(st16):
! 1511: tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
! 1512: args[0], args[1], args[2]);
1.1 root 1513: break;
1.1.1.4 ! root 1514: #if TCG_TARGET_REG_BITS == 64
! 1515: case INDEX_op_st32_i64:
! 1516: #endif
1.1 root 1517: case INDEX_op_st_i32:
1.1.1.4 ! root 1518: tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1.1 root 1519: break;
1.1.1.4 ! root 1520:
! 1521: OP_32_64(add):
! 1522: /* For 3-operand addition, use LEA. */
! 1523: if (args[0] != args[1]) {
! 1524: TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
! 1525:
! 1526: if (const_args[2]) {
! 1527: c3 = a2, a2 = -1;
! 1528: } else if (a0 == a2) {
! 1529: /* Watch out for dest = src + dest, since we've removed
! 1530: the matching constraint on the add. */
! 1531: tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
! 1532: break;
! 1533: }
! 1534:
! 1535: tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
! 1536: break;
! 1537: }
! 1538: c = ARITH_ADD;
! 1539: goto gen_arith;
! 1540: OP_32_64(sub):
1.1 root 1541: c = ARITH_SUB;
1542: goto gen_arith;
1.1.1.4 ! root 1543: OP_32_64(and):
1.1 root 1544: c = ARITH_AND;
1545: goto gen_arith;
1.1.1.4 ! root 1546: OP_32_64(or):
1.1 root 1547: c = ARITH_OR;
1548: goto gen_arith;
1.1.1.4 ! root 1549: OP_32_64(xor):
1.1 root 1550: c = ARITH_XOR;
1551: goto gen_arith;
1552: gen_arith:
1553: if (const_args[2]) {
1.1.1.4 ! root 1554: tgen_arithi(s, c + rexw, args[0], args[2], 0);
1.1 root 1555: } else {
1.1.1.4 ! root 1556: tgen_arithr(s, c + rexw, args[0], args[2]);
1.1 root 1557: }
1558: break;
1.1.1.4 ! root 1559:
! 1560: OP_32_64(mul):
1.1 root 1561: if (const_args[2]) {
1562: int32_t val;
1563: val = args[2];
1564: if (val == (int8_t)val) {
1.1.1.4 ! root 1565: tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
1.1 root 1566: tcg_out8(s, val);
1567: } else {
1.1.1.4 ! root 1568: tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
1.1 root 1569: tcg_out32(s, val);
1570: }
1571: } else {
1.1.1.4 ! root 1572: tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
1.1 root 1573: }
1574: break;
1.1.1.4 ! root 1575:
! 1576: OP_32_64(div2):
! 1577: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
1.1 root 1578: break;
1.1.1.4 ! root 1579: OP_32_64(divu2):
! 1580: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
1.1 root 1581: break;
1.1.1.4 ! root 1582:
! 1583: OP_32_64(shl):
1.1 root 1584: c = SHIFT_SHL;
1.1.1.4 ! root 1585: goto gen_shift;
! 1586: OP_32_64(shr):
1.1 root 1587: c = SHIFT_SHR;
1.1.1.4 ! root 1588: goto gen_shift;
! 1589: OP_32_64(sar):
1.1 root 1590: c = SHIFT_SAR;
1.1.1.4 ! root 1591: goto gen_shift;
! 1592: OP_32_64(rotl):
1.1.1.2 root 1593: c = SHIFT_ROL;
1.1.1.4 ! root 1594: goto gen_shift;
! 1595: OP_32_64(rotr):
1.1.1.2 root 1596: c = SHIFT_ROR;
1.1.1.4 ! root 1597: goto gen_shift;
! 1598: gen_shift:
! 1599: if (const_args[2]) {
! 1600: tcg_out_shifti(s, c + rexw, args[0], args[2]);
! 1601: } else {
! 1602: tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
! 1603: }
1.1 root 1604: break;
1.1.1.4 ! root 1605:
1.1 root 1606: case INDEX_op_brcond_i32:
1.1.1.4 ! root 1607: tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
! 1608: args[3], 0);
1.1 root 1609: break;
1.1.1.4 ! root 1610: case INDEX_op_setcond_i32:
! 1611: tcg_out_setcond32(s, args[3], args[0], args[1],
! 1612: args[2], const_args[2]);
1.1 root 1613: break;
1614:
1.1.1.4 ! root 1615: OP_32_64(bswap16):
! 1616: tcg_out_rolw_8(s, args[0]);
1.1.1.2 root 1617: break;
1.1.1.4 ! root 1618: OP_32_64(bswap32):
! 1619: tcg_out_bswap32(s, args[0]);
1.1.1.2 root 1620: break;
1621:
1.1.1.4 ! root 1622: OP_32_64(neg):
! 1623: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
1.1.1.2 root 1624: break;
1.1.1.4 ! root 1625: OP_32_64(not):
! 1626: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
1.1.1.2 root 1627: break;
1628:
1.1.1.4 ! root 1629: OP_32_64(ext8s):
! 1630: tcg_out_ext8s(s, args[0], args[1], rexw);
1.1.1.2 root 1631: break;
1.1.1.4 ! root 1632: OP_32_64(ext16s):
! 1633: tcg_out_ext16s(s, args[0], args[1], rexw);
1.1.1.2 root 1634: break;
1.1.1.4 ! root 1635: OP_32_64(ext8u):
! 1636: tcg_out_ext8u(s, args[0], args[1]);
1.1.1.3 root 1637: break;
1.1.1.4 ! root 1638: OP_32_64(ext16u):
! 1639: tcg_out_ext16u(s, args[0], args[1]);
1.1.1.3 root 1640: break;
1.1.1.2 root 1641:
1.1 root 1642: case INDEX_op_qemu_ld8u:
1643: tcg_out_qemu_ld(s, args, 0);
1644: break;
1645: case INDEX_op_qemu_ld8s:
1646: tcg_out_qemu_ld(s, args, 0 | 4);
1647: break;
1648: case INDEX_op_qemu_ld16u:
1649: tcg_out_qemu_ld(s, args, 1);
1650: break;
1651: case INDEX_op_qemu_ld16s:
1652: tcg_out_qemu_ld(s, args, 1 | 4);
1653: break;
1.1.1.4 ! root 1654: #if TCG_TARGET_REG_BITS == 64
1.1 root 1655: case INDEX_op_qemu_ld32u:
1.1.1.4 ! root 1656: #endif
! 1657: case INDEX_op_qemu_ld32:
1.1 root 1658: tcg_out_qemu_ld(s, args, 2);
1659: break;
1660: case INDEX_op_qemu_ld64:
1661: tcg_out_qemu_ld(s, args, 3);
1662: break;
1.1.1.4 ! root 1663:
1.1 root 1664: case INDEX_op_qemu_st8:
1665: tcg_out_qemu_st(s, args, 0);
1666: break;
1667: case INDEX_op_qemu_st16:
1668: tcg_out_qemu_st(s, args, 1);
1669: break;
1670: case INDEX_op_qemu_st32:
1671: tcg_out_qemu_st(s, args, 2);
1672: break;
1673: case INDEX_op_qemu_st64:
1674: tcg_out_qemu_st(s, args, 3);
1675: break;
1676:
1.1.1.4 ! root 1677: #if TCG_TARGET_REG_BITS == 32
! 1678: case INDEX_op_brcond2_i32:
! 1679: tcg_out_brcond2(s, args, const_args, 0);
! 1680: break;
! 1681: case INDEX_op_setcond2_i32:
! 1682: tcg_out_setcond2(s, args, const_args);
! 1683: break;
! 1684: case INDEX_op_mulu2_i32:
! 1685: tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
! 1686: break;
! 1687: case INDEX_op_add2_i32:
! 1688: if (const_args[4]) {
! 1689: tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
! 1690: } else {
! 1691: tgen_arithr(s, ARITH_ADD, args[0], args[4]);
! 1692: }
! 1693: if (const_args[5]) {
! 1694: tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
! 1695: } else {
! 1696: tgen_arithr(s, ARITH_ADC, args[1], args[5]);
! 1697: }
! 1698: break;
! 1699: case INDEX_op_sub2_i32:
! 1700: if (const_args[4]) {
! 1701: tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
! 1702: } else {
! 1703: tgen_arithr(s, ARITH_SUB, args[0], args[4]);
! 1704: }
! 1705: if (const_args[5]) {
! 1706: tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
! 1707: } else {
! 1708: tgen_arithr(s, ARITH_SBB, args[1], args[5]);
! 1709: }
! 1710: break;
! 1711: #else /* TCG_TARGET_REG_BITS == 64 */
! 1712: case INDEX_op_movi_i64:
! 1713: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
! 1714: break;
! 1715: case INDEX_op_ld32s_i64:
! 1716: tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
! 1717: break;
! 1718: case INDEX_op_ld_i64:
! 1719: tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
! 1720: break;
! 1721: case INDEX_op_st_i64:
! 1722: tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
! 1723: break;
! 1724: case INDEX_op_qemu_ld32s:
! 1725: tcg_out_qemu_ld(s, args, 2 | 4);
! 1726: break;
! 1727:
! 1728: case INDEX_op_brcond_i64:
! 1729: tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
! 1730: args[3], 0);
! 1731: break;
! 1732: case INDEX_op_setcond_i64:
! 1733: tcg_out_setcond64(s, args[3], args[0], args[1],
! 1734: args[2], const_args[2]);
! 1735: break;
! 1736:
! 1737: case INDEX_op_bswap64_i64:
! 1738: tcg_out_bswap64(s, args[0]);
! 1739: break;
! 1740: case INDEX_op_ext32u_i64:
! 1741: tcg_out_ext32u(s, args[0], args[1]);
! 1742: break;
! 1743: case INDEX_op_ext32s_i64:
! 1744: tcg_out_ext32s(s, args[0], args[1]);
! 1745: break;
! 1746: #endif
! 1747:
1.1 root 1748: default:
1749: tcg_abort();
1750: }
1.1.1.4 ! root 1751:
! 1752: #undef OP_32_64
1.1 root 1753: }
1754:
1755: static const TCGTargetOpDef x86_op_defs[] = {
1756: { INDEX_op_exit_tb, { } },
1757: { INDEX_op_goto_tb, { } },
1758: { INDEX_op_call, { "ri" } },
1759: { INDEX_op_jmp, { "ri" } },
1760: { INDEX_op_br, { } },
1761: { INDEX_op_mov_i32, { "r", "r" } },
1762: { INDEX_op_movi_i32, { "r" } },
1763: { INDEX_op_ld8u_i32, { "r", "r" } },
1764: { INDEX_op_ld8s_i32, { "r", "r" } },
1765: { INDEX_op_ld16u_i32, { "r", "r" } },
1766: { INDEX_op_ld16s_i32, { "r", "r" } },
1767: { INDEX_op_ld_i32, { "r", "r" } },
1768: { INDEX_op_st8_i32, { "q", "r" } },
1769: { INDEX_op_st16_i32, { "r", "r" } },
1770: { INDEX_op_st_i32, { "r", "r" } },
1771:
1.1.1.4 ! root 1772: { INDEX_op_add_i32, { "r", "r", "ri" } },
1.1 root 1773: { INDEX_op_sub_i32, { "r", "0", "ri" } },
1774: { INDEX_op_mul_i32, { "r", "0", "ri" } },
1775: { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1776: { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1777: { INDEX_op_and_i32, { "r", "0", "ri" } },
1778: { INDEX_op_or_i32, { "r", "0", "ri" } },
1779: { INDEX_op_xor_i32, { "r", "0", "ri" } },
1780:
1781: { INDEX_op_shl_i32, { "r", "0", "ci" } },
1782: { INDEX_op_shr_i32, { "r", "0", "ci" } },
1783: { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2 root 1784: { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1785: { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1 root 1786:
1787: { INDEX_op_brcond_i32, { "r", "ri" } },
1788:
1.1.1.2 root 1789: { INDEX_op_bswap16_i32, { "r", "0" } },
1790: { INDEX_op_bswap32_i32, { "r", "0" } },
1791:
1792: { INDEX_op_neg_i32, { "r", "0" } },
1793:
1794: { INDEX_op_not_i32, { "r", "0" } },
1795:
1796: { INDEX_op_ext8s_i32, { "r", "q" } },
1797: { INDEX_op_ext16s_i32, { "r", "r" } },
1.1.1.4 ! root 1798: { INDEX_op_ext8u_i32, { "r", "q" } },
! 1799: { INDEX_op_ext16u_i32, { "r", "r" } },
! 1800:
! 1801: { INDEX_op_setcond_i32, { "q", "r", "ri" } },
! 1802:
! 1803: #if TCG_TARGET_REG_BITS == 32
! 1804: { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
! 1805: { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
! 1806: { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
! 1807: { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
! 1808: { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
! 1809: #else
! 1810: { INDEX_op_mov_i64, { "r", "r" } },
! 1811: { INDEX_op_movi_i64, { "r" } },
! 1812: { INDEX_op_ld8u_i64, { "r", "r" } },
! 1813: { INDEX_op_ld8s_i64, { "r", "r" } },
! 1814: { INDEX_op_ld16u_i64, { "r", "r" } },
! 1815: { INDEX_op_ld16s_i64, { "r", "r" } },
! 1816: { INDEX_op_ld32u_i64, { "r", "r" } },
! 1817: { INDEX_op_ld32s_i64, { "r", "r" } },
! 1818: { INDEX_op_ld_i64, { "r", "r" } },
! 1819: { INDEX_op_st8_i64, { "r", "r" } },
! 1820: { INDEX_op_st16_i64, { "r", "r" } },
! 1821: { INDEX_op_st32_i64, { "r", "r" } },
! 1822: { INDEX_op_st_i64, { "r", "r" } },
! 1823:
! 1824: { INDEX_op_add_i64, { "r", "0", "re" } },
! 1825: { INDEX_op_mul_i64, { "r", "0", "re" } },
! 1826: { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
! 1827: { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
! 1828: { INDEX_op_sub_i64, { "r", "0", "re" } },
! 1829: { INDEX_op_and_i64, { "r", "0", "reZ" } },
! 1830: { INDEX_op_or_i64, { "r", "0", "re" } },
! 1831: { INDEX_op_xor_i64, { "r", "0", "re" } },
! 1832:
! 1833: { INDEX_op_shl_i64, { "r", "0", "ci" } },
! 1834: { INDEX_op_shr_i64, { "r", "0", "ci" } },
! 1835: { INDEX_op_sar_i64, { "r", "0", "ci" } },
! 1836: { INDEX_op_rotl_i64, { "r", "0", "ci" } },
! 1837: { INDEX_op_rotr_i64, { "r", "0", "ci" } },
! 1838:
! 1839: { INDEX_op_brcond_i64, { "r", "re" } },
! 1840: { INDEX_op_setcond_i64, { "r", "r", "re" } },
! 1841:
! 1842: { INDEX_op_bswap16_i64, { "r", "0" } },
! 1843: { INDEX_op_bswap32_i64, { "r", "0" } },
! 1844: { INDEX_op_bswap64_i64, { "r", "0" } },
! 1845: { INDEX_op_neg_i64, { "r", "0" } },
! 1846: { INDEX_op_not_i64, { "r", "0" } },
! 1847:
! 1848: { INDEX_op_ext8s_i64, { "r", "r" } },
! 1849: { INDEX_op_ext16s_i64, { "r", "r" } },
! 1850: { INDEX_op_ext32s_i64, { "r", "r" } },
! 1851: { INDEX_op_ext8u_i64, { "r", "r" } },
! 1852: { INDEX_op_ext16u_i64, { "r", "r" } },
! 1853: { INDEX_op_ext32u_i64, { "r", "r" } },
! 1854: #endif
1.1.1.2 root 1855:
1.1.1.4 ! root 1856: #if TCG_TARGET_REG_BITS == 64
1.1 root 1857: { INDEX_op_qemu_ld8u, { "r", "L" } },
1858: { INDEX_op_qemu_ld8s, { "r", "L" } },
1859: { INDEX_op_qemu_ld16u, { "r", "L" } },
1860: { INDEX_op_qemu_ld16s, { "r", "L" } },
1.1.1.4 ! root 1861: { INDEX_op_qemu_ld32, { "r", "L" } },
1.1 root 1862: { INDEX_op_qemu_ld32u, { "r", "L" } },
1.1.1.4 ! root 1863: { INDEX_op_qemu_ld32s, { "r", "L" } },
! 1864: { INDEX_op_qemu_ld64, { "r", "L" } },
! 1865:
! 1866: { INDEX_op_qemu_st8, { "L", "L" } },
! 1867: { INDEX_op_qemu_st16, { "L", "L" } },
! 1868: { INDEX_op_qemu_st32, { "L", "L" } },
! 1869: { INDEX_op_qemu_st64, { "L", "L" } },
! 1870: #elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
! 1871: { INDEX_op_qemu_ld8u, { "r", "L" } },
! 1872: { INDEX_op_qemu_ld8s, { "r", "L" } },
! 1873: { INDEX_op_qemu_ld16u, { "r", "L" } },
! 1874: { INDEX_op_qemu_ld16s, { "r", "L" } },
! 1875: { INDEX_op_qemu_ld32, { "r", "L" } },
1.1 root 1876: { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1877:
1878: { INDEX_op_qemu_st8, { "cb", "L" } },
1879: { INDEX_op_qemu_st16, { "L", "L" } },
1880: { INDEX_op_qemu_st32, { "L", "L" } },
1881: { INDEX_op_qemu_st64, { "L", "L", "L" } },
1882: #else
1883: { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1884: { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1885: { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1886: { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1.1.1.4 ! root 1887: { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1.1 root 1888: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1889:
1890: { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1891: { INDEX_op_qemu_st16, { "L", "L", "L" } },
1892: { INDEX_op_qemu_st32, { "L", "L", "L" } },
1893: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1894: #endif
1895: { -1 },
1896: };
1897:
1898: static int tcg_target_callee_save_regs[] = {
1.1.1.4 ! root 1899: #if TCG_TARGET_REG_BITS == 64
! 1900: TCG_REG_RBP,
! 1901: TCG_REG_RBX,
! 1902: TCG_REG_R12,
! 1903: TCG_REG_R13,
! 1904: /* TCG_REG_R14, */ /* Currently used for the global env. */
! 1905: TCG_REG_R15,
! 1906: #else
! 1907: /* TCG_REG_EBP, */ /* Currently used for the global env. */
1.1 root 1908: TCG_REG_EBX,
1909: TCG_REG_ESI,
1910: TCG_REG_EDI,
1.1.1.4 ! root 1911: #endif
1.1 root 1912: };
1913:
1914: /* Generate global QEMU prologue and epilogue code */
1.1.1.4 ! root 1915: static void tcg_target_qemu_prologue(TCGContext *s)
1.1 root 1916: {
1917: int i, frame_size, push_size, stack_addend;
1.1.1.4 ! root 1918:
1.1 root 1919: /* TB prologue */
1.1.1.4 ! root 1920:
! 1921: /* Save all callee saved registers. */
! 1922: for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1.1 root 1923: tcg_out_push(s, tcg_target_callee_save_regs[i]);
1924: }
1.1.1.4 ! root 1925:
! 1926: /* Reserve some stack space. */
! 1927: push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
! 1928: push_size *= TCG_TARGET_REG_BITS / 8;
! 1929:
1.1 root 1930: frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1.1.1.4 ! root 1931: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1.1 root 1932: ~(TCG_TARGET_STACK_ALIGN - 1);
1933: stack_addend = frame_size - push_size;
1934: tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1935:
1.1.1.4 ! root 1936: /* jmp *tb. */
! 1937: tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
! 1938:
1.1 root 1939: /* TB epilogue */
1940: tb_ret_addr = s->code_ptr;
1.1.1.4 ! root 1941:
1.1 root 1942: tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1.1.1.4 ! root 1943:
! 1944: for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1.1 root 1945: tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1946: }
1.1.1.4 ! root 1947: tcg_out_opc(s, OPC_RET, 0, 0, 0);
1.1 root 1948: }
1949:
1.1.1.4 ! root 1950: static void tcg_target_init(TCGContext *s)
1.1 root 1951: {
1.1.1.4 ! root 1952: #if !defined(CONFIG_USER_ONLY)
1.1 root 1953: /* fail safe */
1954: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1955: tcg_abort();
1.1.1.4 ! root 1956: #endif
! 1957:
! 1958: if (TCG_TARGET_REG_BITS == 64) {
! 1959: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
! 1960: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
! 1961: } else {
! 1962: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
! 1963: }
! 1964:
! 1965: tcg_regset_clear(tcg_target_call_clobber_regs);
! 1966: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
! 1967: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
! 1968: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
! 1969: if (TCG_TARGET_REG_BITS == 64) {
! 1970: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
! 1971: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
! 1972: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
! 1973: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
! 1974: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
! 1975: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
! 1976: }
1.1 root 1977:
1978: tcg_regset_clear(s->reserved_regs);
1979: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1980:
1981: tcg_add_target_add_op_defs(x86_op_defs);
1982: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.