tcg-target.c 66.3 KB
Newer Older
B
bellard 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Tiny Code Generator for QEMU
 *
 * Copyright (c) 2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24 25 26

#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
27 28 29 30 31 32
#if TCG_TARGET_REG_BITS == 64
    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
#else
    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
#endif
B
bellard 已提交
33
};
34
#endif
B
bellard 已提交
35

36
static const int tcg_target_reg_alloc_order[] = {
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#if TCG_TARGET_REG_BITS == 64
    TCG_REG_RBP,
    TCG_REG_RBX,
    TCG_REG_R12,
    TCG_REG_R13,
    TCG_REG_R14,
    TCG_REG_R15,
    TCG_REG_R10,
    TCG_REG_R11,
    TCG_REG_R9,
    TCG_REG_R8,
    TCG_REG_RCX,
    TCG_REG_RDX,
    TCG_REG_RSI,
    TCG_REG_RDI,
    TCG_REG_RAX,
#else
B
bellard 已提交
54 55 56 57
    TCG_REG_EBX,
    TCG_REG_ESI,
    TCG_REG_EDI,
    TCG_REG_EBP,
58 59 60
    TCG_REG_ECX,
    TCG_REG_EDX,
    TCG_REG_EAX,
61
#endif
B
bellard 已提交
62 63
};

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
static const int tcg_target_call_iarg_regs[] = {
#if TCG_TARGET_REG_BITS == 64
    TCG_REG_RDI,
    TCG_REG_RSI,
    TCG_REG_RDX,
    TCG_REG_RCX,
    TCG_REG_R8,
    TCG_REG_R9,
#else
    TCG_REG_EAX,
    TCG_REG_EDX,
    TCG_REG_ECX
#endif
};

79
static const int tcg_target_call_oarg_regs[] = {
80
    TCG_REG_EAX,
81
#if TCG_TARGET_REG_BITS == 32
82
    TCG_REG_EDX
83
#endif
84
};
B
bellard 已提交
85

86 87
static uint8_t *tb_ret_addr;

88
static void patch_reloc(uint8_t *code_ptr, int type,
A
aurel32 已提交
89
                        tcg_target_long value, tcg_target_long addend)
B
bellard 已提交
90
{
A
aurel32 已提交
91
    value += addend;
B
bellard 已提交
92 93
    switch(type) {
    case R_386_PC32:
94 95 96 97 98
        value -= (uintptr_t)code_ptr;
        if (value != (int32_t)value) {
            tcg_abort();
        }
        *(uint32_t *)code_ptr = value;
B
bellard 已提交
99
        break;
100
    case R_386_PC8:
101
        value -= (uintptr_t)code_ptr;
102 103 104 105 106
        if (value != (int8_t)value) {
            tcg_abort();
        }
        *(uint8_t *)code_ptr = value;
        break;
B
bellard 已提交
107 108 109 110 111 112 113 114
    default:
        tcg_abort();
    }
}

/* maximum number of register used for input function arguments */
static inline int tcg_target_get_call_iarg_regs_count(int flags)
{
115 116 117 118
    if (TCG_TARGET_REG_BITS == 64) {
        return 6;
    }

B
Blue Swirl 已提交
119
    return 0;
B
bellard 已提交
120 121 122
}

/* parse target specific constraints */
123
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
B
bellard 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
{
    const char *ct_str;

    ct_str = *pct_str;
    switch(ct_str[0]) {
    case 'a':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
        break;
    case 'b':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
        break;
    case 'c':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
        break;
    case 'd':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
        break;
    case 'S':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
        break;
    case 'D':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
        break;
    case 'q':
        ct->ct |= TCG_CT_REG;
155 156 157 158 159
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
        } else {
            tcg_regset_set32(ct->u.regs, 0, 0xf);
        }
B
bellard 已提交
160
        break;
161 162 163 164
    case 'Q':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set32(ct->u.regs, 0, 0xf);
        break;
B
bellard 已提交
165 166
    case 'r':
        ct->ct |= TCG_CT_REG;
167 168 169 170 171
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
        } else {
            tcg_regset_set32(ct->u.regs, 0, 0xff);
        }
B
bellard 已提交
172 173 174 175 176
        break;

        /* qemu_ld/st address constraint */
    case 'L':
        ct->ct |= TCG_CT_REG;
177 178 179 180
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
181 182 183
#ifdef CONFIG_TCG_PASS_AREG0
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX);
#endif
184 185 186 187 188 189 190 191 192 193 194 195
        } else {
            tcg_regset_set32(ct->u.regs, 0, 0xff);
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
        }
        break;

    case 'e':
        ct->ct |= TCG_CT_CONST_S32;
        break;
    case 'Z':
        ct->ct |= TCG_CT_CONST_U32;
B
bellard 已提交
196
        break;
197

B
bellard 已提交
198 199 200 201 202 203 204 205 206 207 208 209
    default:
        return -1;
    }
    ct_str++;
    *pct_str = ct_str;
    return 0;
}

/* test if a constant matches the constraint */
static inline int tcg_target_const_match(tcg_target_long val,
                                         const TCGArgConstraint *arg_ct)
{
210 211
    int ct = arg_ct->ct;
    if (ct & TCG_CT_CONST) {
B
bellard 已提交
212
        return 1;
213 214 215 216 217 218 219 220
    }
    if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
        return 1;
    }
    if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
        return 1;
    }
    return 0;
B
bellard 已提交
221 222
}

223 224 225 226 227 228
#if TCG_TARGET_REG_BITS == 64
# define LOWREGMASK(x)	((x) & 7)
#else
# define LOWREGMASK(x)	(x)
#endif

229 230
#define P_EXT		0x100		/* 0x0f opcode prefix */
#define P_DATA16	0x200		/* 0x66 opcode prefix */
231 232 233 234 235 236 237 238 239 240 241
#if TCG_TARGET_REG_BITS == 64
# define P_ADDR32	0x400		/* 0x67 opcode prefix */
# define P_REXW		0x800		/* Set REX.W = 1 */
# define P_REXB_R	0x1000		/* REG field as byte register */
# define P_REXB_RM	0x2000		/* R/M field as byte register */
#else
# define P_ADDR32	0
# define P_REXW		0
# define P_REXB_R	0
# define P_REXB_RM	0
#endif
242

243 244
#define OPC_ARITH_EvIz	(0x81)
#define OPC_ARITH_EvIb	(0x83)
245 246
#define OPC_ARITH_GvEv	(0x03)		/* ... plus (ARITH_FOO << 3) */
#define OPC_ADD_GvEv	(OPC_ARITH_GvEv | (ARITH_ADD << 3))
247
#define OPC_BSWAP	(0xc8 | P_EXT)
R
Richard Henderson 已提交
248
#define OPC_CALL_Jz	(0xe8)
249 250
#define OPC_CMP_GvEv	(OPC_ARITH_GvEv | (ARITH_CMP << 3))
#define OPC_DEC_r32	(0x48)
R
Richard Henderson 已提交
251 252 253
#define OPC_IMUL_GvEv	(0xaf | P_EXT)
#define OPC_IMUL_GvEvIb	(0x6b)
#define OPC_IMUL_GvEvIz	(0x69)
254
#define OPC_INC_r32	(0x40)
R
Richard Henderson 已提交
255 256 257 258
#define OPC_JCC_long	(0x80 | P_EXT)	/* ... plus condition code */
#define OPC_JCC_short	(0x70)		/* ... plus condition code */
#define OPC_JMP_long	(0xe9)
#define OPC_JMP_short	(0xeb)
R
Richard Henderson 已提交
259
#define OPC_LEA         (0x8d)
260 261 262
#define OPC_MOVB_EvGv	(0x88)		/* stores, more or less */
#define OPC_MOVL_EvGv	(0x89)		/* stores, more or less */
#define OPC_MOVL_GvEv	(0x8b)		/* loads, more or less */
263
#define OPC_MOVL_EvIz	(0xc7)
R
Richard Henderson 已提交
264
#define OPC_MOVL_Iv     (0xb8)
265 266
#define OPC_MOVSBL	(0xbe | P_EXT)
#define OPC_MOVSWL	(0xbf | P_EXT)
267
#define OPC_MOVSLQ	(0x63 | P_REXW)
268 269
#define OPC_MOVZBL	(0xb6 | P_EXT)
#define OPC_MOVZWL	(0xb7 | P_EXT)
R
Richard Henderson 已提交
270 271 272 273
#define OPC_POP_r32	(0x58)
#define OPC_PUSH_r32	(0x50)
#define OPC_PUSH_Iv	(0x68)
#define OPC_PUSH_Ib	(0x6a)
R
Richard Henderson 已提交
274
#define OPC_RET		(0xc3)
275
#define OPC_SETCC	(0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
276 277 278
#define OPC_SHIFT_1	(0xd1)
#define OPC_SHIFT_Ib	(0xc1)
#define OPC_SHIFT_cl	(0xd3)
279
#define OPC_TESTL	(0x85)
R
Richard Henderson 已提交
280
#define OPC_XCHG_ax_r32	(0x90)
281

282 283 284 285 286
#define OPC_GRP3_Ev	(0xf7)
#define OPC_GRP5	(0xff)

/* Group 1 opcode extensions for 0x80-0x83.
   These are also used as modifiers for OPC_ARITH.  */
B
bellard 已提交
287 288 289 290 291 292 293 294 295
#define ARITH_ADD 0
#define ARITH_OR  1
#define ARITH_ADC 2
#define ARITH_SBB 3
#define ARITH_AND 4
#define ARITH_SUB 5
#define ARITH_XOR 6
#define ARITH_CMP 7

R
Richard Henderson 已提交
296
/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3.  */
297 298
#define SHIFT_ROL 0
#define SHIFT_ROR 1
B
bellard 已提交
299 300 301 302
#define SHIFT_SHL 4
#define SHIFT_SHR 5
#define SHIFT_SAR 7

303 304 305 306 307 308 309 310 311
/* Group 3 opcode extensions for 0xf6, 0xf7.  To be used with OPC_GRP3.  */
#define EXT3_NOT   2
#define EXT3_NEG   3
#define EXT3_MUL   4
#define EXT3_IMUL  5
#define EXT3_DIV   6
#define EXT3_IDIV  7

/* Group 5 opcode extensions for 0xff.  To be used with OPC_GRP5.  */
312 313
#define EXT5_INC_Ev	0
#define EXT5_DEC_Ev	1
314 315
#define EXT5_CALLN_Ev	2
#define EXT5_JMPN_Ev	4
R
Richard Henderson 已提交
316 317

/* Condition codes to be added to OPC_JCC_{long,short}.  */
B
bellard 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
#define JCC_JMP (-1)
#define JCC_JO  0x0
#define JCC_JNO 0x1
#define JCC_JB  0x2
#define JCC_JAE 0x3
#define JCC_JE  0x4
#define JCC_JNE 0x5
#define JCC_JBE 0x6
#define JCC_JA  0x7
#define JCC_JS  0x8
#define JCC_JNS 0x9
#define JCC_JP  0xa
#define JCC_JNP 0xb
#define JCC_JL  0xc
#define JCC_JGE 0xd
#define JCC_JLE 0xe
#define JCC_JG  0xf

static const uint8_t tcg_cond_to_jcc[10] = {
    [TCG_COND_EQ] = JCC_JE,
    [TCG_COND_NE] = JCC_JNE,
    [TCG_COND_LT] = JCC_JL,
    [TCG_COND_GE] = JCC_JGE,
    [TCG_COND_LE] = JCC_JLE,
    [TCG_COND_GT] = JCC_JG,
    [TCG_COND_LTU] = JCC_JB,
    [TCG_COND_GEU] = JCC_JAE,
    [TCG_COND_LEU] = JCC_JBE,
    [TCG_COND_GTU] = JCC_JA,
};

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
{
    int rex;

    if (opc & P_DATA16) {
        /* We should never be asking for both 16 and 64-bit operation.  */
        assert((opc & P_REXW) == 0);
        tcg_out8(s, 0x66);
    }
    if (opc & P_ADDR32) {
        tcg_out8(s, 0x67);
    }

    rex = 0;
    rex |= (opc & P_REXW) >> 8;		/* REX.W */
    rex |= (r & 8) >> 1;		/* REX.R */
    rex |= (x & 8) >> 2;		/* REX.X */
    rex |= (rm & 8) >> 3;		/* REX.B */

    /* P_REXB_{R,RM} indicates that the given register is the low byte.
       For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
       as otherwise the encoding indicates %[abcd]h.  Note that the values
       that are ORed in merely indicate that the REX byte must be present;
       those bits get discarded in output.  */
    rex |= opc & (r >= 4 ? P_REXB_R : 0);
    rex |= opc & (rm >= 4 ? P_REXB_RM : 0);

    if (rex) {
        tcg_out8(s, (uint8_t)(rex | 0x40));
    }

    if (opc & P_EXT) {
        tcg_out8(s, 0x0f);
    }
    tcg_out8(s, opc);
}
#else
static void tcg_out_opc(TCGContext *s, int opc)
B
bellard 已提交
388
{
389 390 391 392
    if (opc & P_DATA16) {
        tcg_out8(s, 0x66);
    }
    if (opc & P_EXT) {
B
bellard 已提交
393
        tcg_out8(s, 0x0f);
394
    }
B
bellard 已提交
395 396
    tcg_out8(s, opc);
}
397 398 399 400 401
/* Discard the register arguments to tcg_out_opc early, so as not to penalize
   the 32-bit compilation paths.  This method works with all versions of gcc,
   whereas relying on optimization may not be able to exclude them.  */
#define tcg_out_opc(s, opc, r, rm, x)  (tcg_out_opc)(s, opc)
#endif
B
bellard 已提交
402

403
static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
B
bellard 已提交
404
{
405 406
    tcg_out_opc(s, opc, r, rm, 0);
    tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
B
bellard 已提交
407 408
}

R
Richard Henderson 已提交
409
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
410 411 412
   We handle either RM and INDEX missing with a negative value.  In 64-bit
   mode for absolute addresses, ~RM is the size of the immediate operand
   that will follow the instruction.  */
R
Richard Henderson 已提交
413 414

static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
415 416
                                     int index, int shift,
                                     tcg_target_long offset)
B
bellard 已提交
417
{
R
Richard Henderson 已提交
418 419
    int mod, len;

420 421 422 423 424 425 426 427 428 429 430 431
    if (index < 0 && rm < 0) {
        if (TCG_TARGET_REG_BITS == 64) {
            /* Try for a rip-relative addressing mode.  This has replaced
               the 32-bit-mode absolute addressing encoding.  */
            tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
            tcg_target_long disp = offset - pc;
            if (disp == (int32_t)disp) {
                tcg_out_opc(s, opc, r, 0, 0);
                tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
                tcg_out32(s, disp);
                return;
            }
R
Richard Henderson 已提交
432

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
            /* Try for an absolute address encoding.  This requires the
               use of the MODRM+SIB encoding and is therefore larger than
               rip-relative addressing.  */
            if (offset == (int32_t)offset) {
                tcg_out_opc(s, opc, r, 0, 0);
                tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
                tcg_out8(s, (4 << 3) | 5);
                tcg_out32(s, offset);
                return;
            }

            /* ??? The memory isn't directly addressable.  */
            tcg_abort();
        } else {
            /* Absolute address.  */
            tcg_out_opc(s, opc, r, 0, 0);
            tcg_out8(s, (r << 3) | 5);
            tcg_out32(s, offset);
            return;
        }
    }
R
Richard Henderson 已提交
454 455 456

    /* Find the length of the immediate addend.  Note that the encoding
       that would be used for (%ebp) indicates absolute addressing.  */
457
    if (rm < 0) {
R
Richard Henderson 已提交
458
        mod = 0, len = 4, rm = 5;
459
    } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
R
Richard Henderson 已提交
460 461 462
        mod = 0, len = 0;
    } else if (offset == (int8_t)offset) {
        mod = 0x40, len = 1;
B
bellard 已提交
463
    } else {
R
Richard Henderson 已提交
464 465 466 467 468
        mod = 0x80, len = 4;
    }

    /* Use a single byte MODRM format if possible.  Note that the encoding
       that would be used for %esp is the escape to the two byte form.  */
469
    if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
R
Richard Henderson 已提交
470
        /* Single byte MODRM format.  */
471 472
        tcg_out_opc(s, opc, r, rm, 0);
        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
R
Richard Henderson 已提交
473 474 475 476
    } else {
        /* Two byte MODRM+SIB format.  */

        /* Note that the encoding that would place %esp into the index
477 478 479
           field indicates no index register.  In 64-bit mode, the REX.X
           bit counts, so %r12 can be used as the index.  */
        if (index < 0) {
R
Richard Henderson 已提交
480
            index = 4;
B
bellard 已提交
481
        } else {
R
Richard Henderson 已提交
482
            assert(index != TCG_REG_ESP);
B
bellard 已提交
483
        }
R
Richard Henderson 已提交
484

485 486 487
        tcg_out_opc(s, opc, r, rm, index);
        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
        tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
R
Richard Henderson 已提交
488 489 490 491 492
    }

    if (len == 1) {
        tcg_out8(s, offset);
    } else if (len == 4) {
B
bellard 已提交
493 494 495 496
        tcg_out32(s, offset);
    }
}

497 498 499
/* A simplification of the above with no index or shift.  */
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
                                        int rm, tcg_target_long offset)
R
Richard Henderson 已提交
500 501 502 503
{
    tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
}

504 505 506
/* Generate dest op= src.  Uses the same ARITH_* codes as tgen_arithi.  */
static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
{
507 508 509 510 511
    /* Propagate an opcode prefix, such as P_REXW.  */
    int ext = subop & ~0x7;
    subop &= 0x7;

    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
512 513
}

514 515
static inline void tcg_out_mov(TCGContext *s, TCGType type,
                               TCGReg ret, TCGReg arg)
B
bellard 已提交
516
{
517
    if (arg != ret) {
518 519
        int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
        tcg_out_modrm(s, opc, ret, arg);
520
    }
B
bellard 已提交
521 522
}

523
static void tcg_out_movi(TCGContext *s, TCGType type,
524
                         TCGReg ret, tcg_target_long arg)
B
bellard 已提交
525 526
{
    if (arg == 0) {
527
        tgen_arithr(s, ARITH_XOR, ret, ret);
528 529 530 531 532 533 534
        return;
    } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
        tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
        tcg_out32(s, arg);
    } else if (arg == (int32_t)arg) {
        tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
        tcg_out32(s, arg);
B
bellard 已提交
535
    } else {
536
        tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
B
bellard 已提交
537
        tcg_out32(s, arg);
538
        tcg_out32(s, arg >> 31 >> 1);
B
bellard 已提交
539 540 541
    }
}

R
Richard Henderson 已提交
542 543 544
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
{
    if (val == (int8_t)val) {
545
        tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
R
Richard Henderson 已提交
546
        tcg_out8(s, val);
547 548
    } else if (val == (int32_t)val) {
        tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
R
Richard Henderson 已提交
549
        tcg_out32(s, val);
550 551
    } else {
        tcg_abort();
R
Richard Henderson 已提交
552 553 554 555 556
    }
}

static inline void tcg_out_push(TCGContext *s, int reg)
{
557
    tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
R
Richard Henderson 已提交
558 559 560 561
}

static inline void tcg_out_pop(TCGContext *s, int reg)
{
562
    tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
R
Richard Henderson 已提交
563 564
}

565 566
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
                              TCGReg arg1, tcg_target_long arg2)
B
bellard 已提交
567
{
568 569
    int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
    tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
B
bellard 已提交
570 571
}

572 573
static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
                              TCGReg arg1, tcg_target_long arg2)
B
bellard 已提交
574
{
575 576
    int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
    tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
B
bellard 已提交
577 578
}

579 580
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
{
581 582 583 584
    /* Propagate an opcode prefix, such as P_DATA16.  */
    int ext = subopc & ~0x7;
    subopc &= 0x7;

585
    if (count == 1) {
586
        tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
587
    } else {
588
        tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
589 590 591 592
        tcg_out8(s, count);
    }
}

593 594
static inline void tcg_out_bswap32(TCGContext *s, int reg)
{
595
    tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
596 597 598 599
}

static inline void tcg_out_rolw_8(TCGContext *s, int reg)
{
600
    tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
601 602
}

603 604 605
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
{
    /* movzbl */
606 607
    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
    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 614
    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
    tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
615 616
}

617 618 619 620 621 622
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
{
    /* movzwl */
    tcg_out_modrm(s, OPC_MOVZWL, dest, src);
}

623
static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
624
{
625 626
    /* movsw[lq] */
    tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
627 628
}

629
static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
B
bellard 已提交
630
{
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
    /* 32-bit mov zero extends.  */
    tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
}

static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
{
    tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
}

static inline void tcg_out_bswap64(TCGContext *s, int reg)
{
    tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
}

static void tgen_arithi(TCGContext *s, int c, int r0,
                        tcg_target_long val, int cf)
{
    int rexw = 0;

    if (TCG_TARGET_REG_BITS == 64) {
        rexw = c & -8;
        c &= 7;
    }

655 656 657 658
    /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
       partial flags update stalls on Pentium4 and are not recommended
       by current Intel optimization manuals.  */
    if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
659
        int is_inc = (c == ARITH_ADD) ^ (val < 0);
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
        if (TCG_TARGET_REG_BITS == 64) {
            /* The single-byte increment encodings are re-tasked as the
               REX prefixes.  Use the MODRM encoding.  */
            tcg_out_modrm(s, OPC_GRP5 + rexw,
                          (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
        } else {
            tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
        }
        return;
    }

    if (c == ARITH_AND) {
        if (TCG_TARGET_REG_BITS == 64) {
            if (val == 0xffffffffu) {
                tcg_out_ext32u(s, r0, r0);
                return;
            }
            if (val == (uint32_t)val) {
                /* AND with no high bits set can use a 32-bit operation.  */
                rexw = 0;
            }
        }
A
Aurelien Jarno 已提交
682
        if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
683 684 685 686 687 688 689 690 691 692 693
            tcg_out_ext8u(s, r0, r0);
            return;
        }
        if (val == 0xffffu) {
            tcg_out_ext16u(s, r0, r0);
            return;
        }
    }

    if (val == (int8_t)val) {
        tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
B
bellard 已提交
694
        tcg_out8(s, val);
695 696 697 698
        return;
    }
    if (rexw == 0 || val == (int32_t)val) {
        tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
B
bellard 已提交
699
        tcg_out32(s, val);
700
        return;
B
bellard 已提交
701
    }
702 703

    tcg_abort();
B
bellard 已提交
704 705
}

A
aurel32 已提交
706
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
B
bellard 已提交
707
{
708 709 710
    if (val != 0) {
        tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
    }
B
bellard 已提交
711 712
}

713 714
/* Use SMALL != 0 to force a short forward branch.  */
static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
B
bellard 已提交
715 716 717
{
    int32_t val, val1;
    TCGLabel *l = &s->labels[label_index];
718

B
bellard 已提交
719 720 721 722
    if (l->has_value) {
        val = l->u.value - (tcg_target_long)s->code_ptr;
        val1 = val - 2;
        if ((int8_t)val1 == val1) {
723
            if (opc == -1) {
R
Richard Henderson 已提交
724
                tcg_out8(s, OPC_JMP_short);
725
            } else {
R
Richard Henderson 已提交
726
                tcg_out8(s, OPC_JCC_short + opc);
727
            }
B
bellard 已提交
728 729
            tcg_out8(s, val1);
        } else {
730 731 732
            if (small) {
                tcg_abort();
            }
B
bellard 已提交
733
            if (opc == -1) {
R
Richard Henderson 已提交
734
                tcg_out8(s, OPC_JMP_long);
B
bellard 已提交
735 736
                tcg_out32(s, val - 5);
            } else {
737
                tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
B
bellard 已提交
738 739 740
                tcg_out32(s, val - 6);
            }
        }
741 742
    } else if (small) {
        if (opc == -1) {
R
Richard Henderson 已提交
743
            tcg_out8(s, OPC_JMP_short);
744
        } else {
R
Richard Henderson 已提交
745
            tcg_out8(s, OPC_JCC_short + opc);
746 747 748
        }
        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
        s->code_ptr += 1;
B
bellard 已提交
749 750
    } else {
        if (opc == -1) {
R
Richard Henderson 已提交
751
            tcg_out8(s, OPC_JMP_long);
B
bellard 已提交
752
        } else {
753
            tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
B
bellard 已提交
754 755
        }
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
P
pbrook 已提交
756
        s->code_ptr += 4;
B
bellard 已提交
757 758 759
    }
}

R
Richard Henderson 已提交
760
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
761
                        int const_arg2, int rexw)
B
bellard 已提交
762 763 764 765
{
    if (const_arg2) {
        if (arg2 == 0) {
            /* test r, r */
766
            tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
B
bellard 已提交
767
        } else {
768
            tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
B
bellard 已提交
769 770
        }
    } else {
771
        tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
B
bellard 已提交
772
    }
R
Richard Henderson 已提交
773 774
}

775 776 777
static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
                             TCGArg arg1, TCGArg arg2, int const_arg2,
                             int label_index, int small)
R
Richard Henderson 已提交
778
{
779
    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
780
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
B
bellard 已提交
781 782
}

783 784 785 786 787 788 789 790 791
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
                             TCGArg arg1, TCGArg arg2, int const_arg2,
                             int label_index, int small)
{
    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
}
#else
B
bellard 已提交
792 793
/* XXX: we implement it at the target level to avoid having to
   handle cross basic blocks temporaries */
794 795
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
                            const int *const_args, int small)
B
bellard 已提交
796 797 798 799 800
{
    int label_next;
    label_next = gen_new_label();
    switch(args[4]) {
    case TCG_COND_EQ:
801 802 803 804
        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
                         label_next, 1);
        tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
                         args[5], small);
B
bellard 已提交
805 806
        break;
    case TCG_COND_NE:
807 808 809 810
        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
                         args[5], small);
        tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
                         args[5], small);
B
bellard 已提交
811 812
        break;
    case TCG_COND_LT:
813 814
        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
                         args[5], small);
815
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
816 817
        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
818 819
        break;
    case TCG_COND_LE:
820 821
        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
                         args[5], small);
822
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
823 824
        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
825 826
        break;
    case TCG_COND_GT:
827 828
        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
                         args[5], small);
829
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
830 831
        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
832 833
        break;
    case TCG_COND_GE:
834 835
        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
                         args[5], small);
836
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
837 838
        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
839 840
        break;
    case TCG_COND_LTU:
841 842
        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
                         args[5], small);
843
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
844 845
        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
846 847
        break;
    case TCG_COND_LEU:
848 849
        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
                         args[5], small);
850
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
851 852
        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
853 854
        break;
    case TCG_COND_GTU:
855 856
        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
                         args[5], small);
857
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
858 859
        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
860 861
        break;
    case TCG_COND_GEU:
862 863
        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
                         args[5], small);
864
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
865 866
        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
                         args[5], small);
B
bellard 已提交
867 868 869 870
        break;
    default:
        tcg_abort();
    }
871
    tcg_out_label(s, label_next, s->code_ptr);
B
bellard 已提交
872
}
873
#endif
B
bellard 已提交
874

875 876
static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
                              TCGArg arg1, TCGArg arg2, int const_arg2)
R
Richard Henderson 已提交
877
{
878
    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
R
Richard Henderson 已提交
879
    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
880
    tcg_out_ext8u(s, dest, dest);
R
Richard Henderson 已提交
881 882
}

883 884 885 886 887 888 889 890 891
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
                              TCGArg arg1, TCGArg arg2, int const_arg2)
{
    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
    tcg_out_ext8u(s, dest, dest);
}
#else
R
Richard Henderson 已提交
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
                             const int *const_args)
{
    TCGArg new_args[6];
    int label_true, label_over;

    memcpy(new_args, args+1, 5*sizeof(TCGArg));

    if (args[0] == args[1] || args[0] == args[2]
        || (!const_args[3] && args[0] == args[3])
        || (!const_args[4] && args[0] == args[4])) {
        /* When the destination overlaps with one of the argument
           registers, don't do anything tricky.  */
        label_true = gen_new_label();
        label_over = gen_new_label();

        new_args[5] = label_true;
        tcg_out_brcond2(s, new_args, const_args+1, 1);

        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
        tcg_out_jxx(s, JCC_JMP, label_over, 1);
913
        tcg_out_label(s, label_true, s->code_ptr);
R
Richard Henderson 已提交
914 915

        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
916
        tcg_out_label(s, label_over, s->code_ptr);
R
Richard Henderson 已提交
917 918 919 920 921 922 923 924 925 926 927 928 929
    } else {
        /* When the destination does not overlap one of the arguments,
           clear the destination first, jump if cond false, and emit an
           increment in the true case.  This results in smaller code.  */

        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);

        label_over = gen_new_label();
        new_args[4] = tcg_invert_cond(new_args[4]);
        new_args[5] = label_over;
        tcg_out_brcond2(s, new_args, const_args+1, 1);

        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
930
        tcg_out_label(s, label_over, s->code_ptr);
R
Richard Henderson 已提交
931 932
    }
}
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
#endif

static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
{
    tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;

    if (disp == (int32_t)disp) {
        tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
        tcg_out32(s, disp);
    } else {
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
        tcg_out_modrm(s, OPC_GRP5,
                      call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
    }
}

static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
{
    tcg_out_branch(s, 1, dest);
}
R
Richard Henderson 已提交
953

954
static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
R
Richard Henderson 已提交
955
{
956
    tcg_out_branch(s, 0, dest);
R
Richard Henderson 已提交
957 958
}

B
bellard 已提交
959
#if defined(CONFIG_SOFTMMU)
960 961

#include "../../softmmu_defs.h"
B
bellard 已提交
962

963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
#ifdef CONFIG_TCG_PASS_AREG0
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
   int mmu_idx) */
static const void *qemu_ld_helpers[4] = {
    helper_ldb_mmu,
    helper_ldw_mmu,
    helper_ldl_mmu,
    helper_ldq_mmu,
};

/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
   uintxx_t val, int mmu_idx) */
static const void *qemu_st_helpers[4] = {
    helper_stb_mmu,
    helper_stw_mmu,
    helper_stl_mmu,
    helper_stq_mmu,
};
#else
/* legacy helper signature: __ld_mmu(target_ulong addr, int
   mmu_idx) */
B
bellard 已提交
984 985 986 987 988 989 990
static void *qemu_ld_helpers[4] = {
    __ldb_mmu,
    __ldw_mmu,
    __ldl_mmu,
    __ldq_mmu,
};

991 992
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
   int mmu_idx) */
B
bellard 已提交
993 994 995 996 997 998
static void *qemu_st_helpers[4] = {
    __stb_mmu,
    __stw_mmu,
    __stl_mmu,
    __stq_mmu,
};
999
#endif
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015

/* Perform the TLB load and compare.

   Inputs:
   ADDRLO_IDX contains the index into ARGS of the low part of the
   address; the high part of the address is at ADDR_LOW_IDX+1.

   MEM_INDEX and S_BITS are the memory context and log2 size of the load.

   WHICH is the offset into the CPUTLBEntry structure of the slot to read.
   This should be offsetof addr_read or addr_write.

   Outputs:
   LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
   positions of the displacements of forward jumps to the TLB miss case.

1016 1017 1018 1019
   First argument register is loaded with the low part of the address.
   In the TLB hit case, it has been adjusted as indicated by the TLB
   and so is a host address.  In the TLB miss case, it continues to
   hold a guest address.
1020

1021
   Second argument register is clobbered.  */
1022

1023 1024
static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
                                    int mem_index, int s_bits,
A
Aurelien Jarno 已提交
1025
                                    const TCGArg *args,
1026
                                    uint8_t **label_ptr, int which)
1027 1028
{
    const int addrlo = args[addrlo_idx];
1029 1030 1031 1032 1033 1034 1035 1036 1037
    const int r0 = tcg_target_call_iarg_regs[0];
    const int r1 = tcg_target_call_iarg_regs[1];
    TCGType type = TCG_TYPE_I32;
    int rexw = 0;

    if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
        type = TCG_TYPE_I64;
        rexw = P_REXW;
    }
1038

1039 1040
    tcg_out_mov(s, type, r1, addrlo);
    tcg_out_mov(s, type, r0, addrlo);
1041

1042 1043
    tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1044

1045 1046 1047 1048
    tgen_arithi(s, ARITH_AND + rexw, r0,
                TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
    tgen_arithi(s, ARITH_AND + rexw, r1,
                (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
1049

1050
    tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
1051
                             offsetof(CPUArchState, tlb_table[mem_index][0])
1052 1053 1054
                             + which);

    /* cmp 0(r1), r0 */
1055
    tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
1056

1057
    tcg_out_mov(s, type, r0, addrlo);
1058 1059 1060 1061 1062 1063

    /* jne label1 */
    tcg_out8(s, OPC_JCC_short + JCC_JNE);
    label_ptr[0] = s->code_ptr;
    s->code_ptr++;

1064
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
        /* cmp 4(r1), addrhi */
        tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);

        /* jne label1 */
        tcg_out8(s, OPC_JCC_short + JCC_JNE);
        label_ptr[1] = s->code_ptr;
        s->code_ptr++;
    }

    /* TLB Hit.  */

    /* add addend(r1), r0 */
1077
    tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
1078 1079
                         offsetof(CPUTLBEntry, addend) - which);
}
B
bellard 已提交
1080 1081
#endif

1082 1083 1084 1085 1086 1087 1088
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
                                   int base, tcg_target_long ofs, int sizeop)
{
#ifdef TARGET_WORDS_BIGENDIAN
    const int bswap = 1;
#else
    const int bswap = 0;
P
Paul Brook 已提交
1089
#endif
1090 1091 1092 1093 1094
    switch (sizeop) {
    case 0:
        tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
        break;
    case 0 | 4:
1095
        tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
1096 1097 1098 1099 1100 1101 1102 1103 1104
        break;
    case 1:
        tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
        if (bswap) {
            tcg_out_rolw_8(s, datalo);
        }
        break;
    case 1 | 4:
        if (bswap) {
1105
            tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
1106
            tcg_out_rolw_8(s, datalo);
1107 1108 1109
            tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
        } else {
            tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
1110 1111 1112 1113 1114 1115 1116 1117
        }
        break;
    case 2:
        tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
        if (bswap) {
            tcg_out_bswap32(s, datalo);
        }
        break;
1118 1119
#if TCG_TARGET_REG_BITS == 64
    case 2 | 4:
1120 1121
        if (bswap) {
            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1122 1123
            tcg_out_bswap32(s, datalo);
            tcg_out_ext32s(s, datalo, datalo);
1124
        } else {
1125
            tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
1126
        }
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
        break;
#endif
    case 3:
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
            if (bswap) {
                tcg_out_bswap64(s, datalo);
            }
        } else {
            if (bswap) {
                int t = datalo;
                datalo = datahi;
                datahi = t;
            }
            if (base != datalo) {
                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
            } else {
                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
            }
            if (bswap) {
                tcg_out_bswap32(s, datalo);
                tcg_out_bswap32(s, datahi);
            }
1152 1153 1154 1155 1156 1157
        }
        break;
    default:
        tcg_abort();
    }
}
P
Paul Brook 已提交
1158

B
bellard 已提交
1159 1160 1161 1162 1163 1164
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
   EAX. It will be useful once fixed registers globals are less
   common. */
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                            int opc)
{
1165
    int data_reg, data_reg2 = 0;
1166
    int addrlo_idx;
B
bellard 已提交
1167
#if defined(CONFIG_SOFTMMU)
B
Blue Swirl 已提交
1168 1169 1170 1171 1172 1173
    int mem_index, s_bits;
#if TCG_TARGET_REG_BITS == 64
    int arg_idx;
#else
    int stack_adjust;
#endif
1174
    uint8_t *label_ptr[3];
B
bellard 已提交
1175 1176
#endif

1177 1178
    data_reg = args[0];
    addrlo_idx = 1;
1179
    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1180 1181
        data_reg2 = args[1];
        addrlo_idx = 2;
1182
    }
B
bellard 已提交
1183 1184

#if defined(CONFIG_SOFTMMU)
1185
    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1186
    s_bits = opc & 3;
1187

1188 1189
    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                     label_ptr, offsetof(CPUTLBEntry, addr_read));
1190 1191

    /* TLB Hit.  */
1192 1193
    tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
                           tcg_target_call_iarg_regs[0], 0, opc);
B
bellard 已提交
1194

1195 1196 1197
    /* jmp label2 */
    tcg_out8(s, OPC_JMP_short);
    label_ptr[2] = s->code_ptr;
B
bellard 已提交
1198
    s->code_ptr++;
1199

1200 1201 1202 1203
    /* TLB Miss.  */

    /* label1: */
    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1204
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1205 1206
        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
    }
B
bellard 已提交
1207 1208

    /* XXX: move that code at the end of the TB */
B
Blue Swirl 已提交
1209 1210 1211 1212 1213 1214 1215 1216 1217
#if TCG_TARGET_REG_BITS == 32
    tcg_out_pushi(s, mem_index);
    stack_adjust = 4;
    if (TARGET_LONG_BITS == 64) {
        tcg_out_push(s, args[addrlo_idx + 1]);
        stack_adjust += 4;
    }
    tcg_out_push(s, args[addrlo_idx]);
    stack_adjust += 4;
1218 1219 1220 1221
#ifdef CONFIG_TCG_PASS_AREG0
    tcg_out_push(s, TCG_AREG0);
    stack_adjust += 4;
#endif
B
Blue Swirl 已提交
1222
#else
1223
    /* The first argument is already loaded with addrlo.  */
1224 1225 1226
    arg_idx = 1;
    tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
                 mem_index);
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
#ifdef CONFIG_TCG_PASS_AREG0
    /* XXX/FIXME: suboptimal */
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
                tcg_target_call_iarg_regs[2]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
                tcg_target_call_iarg_regs[1]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
                tcg_target_call_iarg_regs[0]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
                TCG_AREG0);
#endif
B
Blue Swirl 已提交
1238 1239
#endif

R
Richard Henderson 已提交
1240
    tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
B
bellard 已提交
1241

B
Blue Swirl 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250
#if TCG_TARGET_REG_BITS == 32
    if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
        /* Pop and discard.  This is 2 bytes smaller than the add.  */
        tcg_out_pop(s, TCG_REG_ECX);
    } else if (stack_adjust != 0) {
        tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
    }
#endif

B
bellard 已提交
1251 1252
    switch(opc) {
    case 0 | 4:
1253
        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
B
bellard 已提交
1254 1255
        break;
    case 1 | 4:
1256
        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
B
bellard 已提交
1257 1258
        break;
    case 0:
1259
        tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
1260
        break;
B
bellard 已提交
1261
    case 1:
1262
        tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
1263
        break;
B
bellard 已提交
1264
    case 2:
1265
        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
B
bellard 已提交
1266
        break;
1267 1268 1269 1270 1271
#if TCG_TARGET_REG_BITS == 64
    case 2 | 4:
        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
        break;
#endif
B
bellard 已提交
1272
    case 3:
1273 1274 1275
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
        } else if (data_reg == TCG_REG_EDX) {
R
Richard Henderson 已提交
1276
            /* xchg %edx, %eax */
1277
            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
1278
            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
B
bellard 已提交
1279
        } else {
1280 1281
            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
B
bellard 已提交
1282 1283
        }
        break;
1284 1285
    default:
        tcg_abort();
B
bellard 已提交
1286 1287
    }

1288
    /* label2: */
1289
    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
B
bellard 已提交
1290
#else
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
    {
        int32_t offset = GUEST_BASE;
        int base = args[addrlo_idx];

        if (TCG_TARGET_REG_BITS == 64) {
            /* ??? We assume all operations have left us with register
               contents that are zero extended.  So far this appears to
               be true.  If we want to enforce this, we can either do
               an explicit zero-extension here, or (if GUEST_BASE == 0)
               use the ADDR32 prefix.  For now, do nothing.  */

            if (offset != GUEST_BASE) {
                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
                base = TCG_REG_RDI, offset = 0;
            }
        }

        tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
    }
B
bellard 已提交
1311
#endif
1312
}
B
bellard 已提交
1313

1314 1315 1316
static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
                                   int base, tcg_target_long ofs, int sizeop)
{
B
bellard 已提交
1317
#ifdef TARGET_WORDS_BIGENDIAN
1318
    const int bswap = 1;
B
bellard 已提交
1319
#else
1320
    const int bswap = 0;
B
bellard 已提交
1321
#endif
1322 1323 1324
    /* ??? Ideally we wouldn't need a scratch register.  For user-only,
       we could perform the bswap twice to restore the original value
       instead of moving to the scratch.  But as it is, the L constraint
1325 1326
       means that the second argument reg is definitely free here.  */
    int scratch = tcg_target_call_iarg_regs[1];
1327 1328

    switch (sizeop) {
B
bellard 已提交
1329
    case 0:
1330
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
B
bellard 已提交
1331 1332 1333
        break;
    case 1:
        if (bswap) {
1334
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1335 1336
            tcg_out_rolw_8(s, scratch);
            datalo = scratch;
B
bellard 已提交
1337
        }
1338
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
B
bellard 已提交
1339 1340 1341
        break;
    case 2:
        if (bswap) {
1342
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1343 1344
            tcg_out_bswap32(s, scratch);
            datalo = scratch;
B
bellard 已提交
1345
        }
1346
        tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
B
bellard 已提交
1347 1348
        break;
    case 3:
1349 1350 1351 1352 1353 1354 1355 1356
        if (TCG_TARGET_REG_BITS == 64) {
            if (bswap) {
                tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
                tcg_out_bswap64(s, scratch);
                datalo = scratch;
            }
            tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
        } else if (bswap) {
1357
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
1358 1359
            tcg_out_bswap32(s, scratch);
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
1360
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1361 1362
            tcg_out_bswap32(s, scratch);
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
B
bellard 已提交
1363
        } else {
1364 1365
            tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
            tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
B
bellard 已提交
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
        }
        break;
    default:
        tcg_abort();
    }
}

static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                            int opc)
{
1376
    int data_reg, data_reg2 = 0;
1377
    int addrlo_idx;
B
bellard 已提交
1378
#if defined(CONFIG_SOFTMMU)
1379
    int mem_index, s_bits;
R
Richard Henderson 已提交
1380
    int stack_adjust;
1381
    uint8_t *label_ptr[3];
B
bellard 已提交
1382 1383
#endif

1384 1385
    data_reg = args[0];
    addrlo_idx = 1;
1386
    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1387 1388
        data_reg2 = args[1];
        addrlo_idx = 2;
1389
    }
B
bellard 已提交
1390 1391

#if defined(CONFIG_SOFTMMU)
1392
    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1393
    s_bits = opc;
1394

1395 1396
    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                     label_ptr, offsetof(CPUTLBEntry, addr_write));
1397 1398

    /* TLB Hit.  */
1399 1400
    tcg_out_qemu_st_direct(s, data_reg, data_reg2,
                           tcg_target_call_iarg_regs[0], 0, opc);
B
bellard 已提交
1401

1402 1403 1404
    /* jmp label2 */
    tcg_out8(s, OPC_JMP_short);
    label_ptr[2] = s->code_ptr;
B
bellard 已提交
1405
    s->code_ptr++;
1406

1407 1408 1409 1410
    /* TLB Miss.  */

    /* label1: */
    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1411
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1412 1413
        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
    }
B
bellard 已提交
1414 1415

    /* XXX: move that code at the end of the TB */
B
Blue Swirl 已提交
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
#if TCG_TARGET_REG_BITS == 32
    tcg_out_pushi(s, mem_index);
    stack_adjust = 4;
    if (opc == 3) {
        tcg_out_push(s, data_reg2);
        stack_adjust += 4;
    }
    tcg_out_push(s, data_reg);
    stack_adjust += 4;
    if (TARGET_LONG_BITS == 64) {
        tcg_out_push(s, args[addrlo_idx + 1]);
        stack_adjust += 4;
B
bellard 已提交
1428
    }
B
Blue Swirl 已提交
1429 1430
    tcg_out_push(s, args[addrlo_idx]);
    stack_adjust += 4;
1431 1432 1433 1434
#ifdef CONFIG_TCG_PASS_AREG0
    tcg_out_push(s, TCG_AREG0);
    stack_adjust += 4;
#endif
B
Blue Swirl 已提交
1435 1436 1437 1438 1439
#else
    tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
                TCG_REG_RSI, data_reg);
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
    stack_adjust = 0;
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
#ifdef CONFIG_TCG_PASS_AREG0
    /* XXX/FIXME: suboptimal */
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
                tcg_target_call_iarg_regs[2]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
                tcg_target_call_iarg_regs[1]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
                tcg_target_call_iarg_regs[0]);
    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
                TCG_AREG0);
#endif
B
Blue Swirl 已提交
1451
#endif
R
Richard Henderson 已提交
1452 1453 1454

    tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);

1455
    if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
R
Richard Henderson 已提交
1456 1457 1458
        /* Pop and discard.  This is 2 bytes smaller than the add.  */
        tcg_out_pop(s, TCG_REG_ECX);
    } else if (stack_adjust != 0) {
1459
        tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
R
Richard Henderson 已提交
1460 1461
    }

B
bellard 已提交
1462
    /* label2: */
1463
    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1464
#else
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484
    {
        int32_t offset = GUEST_BASE;
        int base = args[addrlo_idx];

        if (TCG_TARGET_REG_BITS == 64) {
            /* ??? We assume all operations have left us with register
               contents that are zero extended.  So far this appears to
               be true.  If we want to enforce this, we can either do
               an explicit zero-extension here, or (if GUEST_BASE == 0)
               use the ADDR32 prefix.  For now, do nothing.  */

            if (offset != GUEST_BASE) {
                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
                base = TCG_REG_RDI, offset = 0;
            }
        }

        tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
    }
B
bellard 已提交
1485 1486 1487
#endif
}

1488
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
B
bellard 已提交
1489 1490
                              const TCGArg *args, const int *const_args)
{
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
    int c, rexw = 0;

#if TCG_TARGET_REG_BITS == 64
# define OP_32_64(x) \
        case glue(glue(INDEX_op_, x), _i64): \
            rexw = P_REXW; /* FALLTHRU */    \
        case glue(glue(INDEX_op_, x), _i32)
#else
# define OP_32_64(x) \
        case glue(glue(INDEX_op_, x), _i32)
#endif
1502

B
bellard 已提交
1503 1504
    switch(opc) {
    case INDEX_op_exit_tb:
1505 1506
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
        tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
B
bellard 已提交
1507 1508 1509 1510
        break;
    case INDEX_op_goto_tb:
        if (s->tb_jmp_offset) {
            /* direct jump method */
R
Richard Henderson 已提交
1511
            tcg_out8(s, OPC_JMP_long); /* jmp im */
B
bellard 已提交
1512 1513 1514 1515
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
            tcg_out32(s, 0);
        } else {
            /* indirect jump method */
1516
            tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
B
bellard 已提交
1517 1518 1519 1520 1521 1522
                                 (tcg_target_long)(s->tb_next + args[0]));
        }
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
        break;
    case INDEX_op_call:
        if (const_args[0]) {
R
Richard Henderson 已提交
1523
            tcg_out_calli(s, args[0]);
B
bellard 已提交
1524
        } else {
R
Richard Henderson 已提交
1525
            /* call *reg */
1526
            tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
B
bellard 已提交
1527 1528 1529 1530
        }
        break;
    case INDEX_op_jmp:
        if (const_args[0]) {
1531
            tcg_out_jmp(s, args[0]);
B
bellard 已提交
1532
        } else {
R
Richard Henderson 已提交
1533
            /* jmp *reg */
1534
            tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
B
bellard 已提交
1535 1536 1537
        }
        break;
    case INDEX_op_br:
1538
        tcg_out_jxx(s, JCC_JMP, args[0], 0);
B
bellard 已提交
1539 1540 1541 1542
        break;
    case INDEX_op_movi_i32:
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
        break;
1543 1544
    OP_32_64(ld8u):
        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1545
        tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
B
bellard 已提交
1546
        break;
1547 1548
    OP_32_64(ld8s):
        tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
B
bellard 已提交
1549
        break;
1550 1551
    OP_32_64(ld16u):
        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1552
        tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
B
bellard 已提交
1553
        break;
1554 1555
    OP_32_64(ld16s):
        tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
B
bellard 已提交
1556
        break;
1557 1558 1559
#if TCG_TARGET_REG_BITS == 64
    case INDEX_op_ld32u_i64:
#endif
B
bellard 已提交
1560
    case INDEX_op_ld_i32:
1561
        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
B
bellard 已提交
1562
        break;
1563 1564 1565 1566

    OP_32_64(st8):
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
                             args[0], args[1], args[2]);
B
bellard 已提交
1567
        break;
1568
    OP_32_64(st16):
1569 1570
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
                             args[0], args[1], args[2]);
B
bellard 已提交
1571
        break;
1572 1573 1574
#if TCG_TARGET_REG_BITS == 64
    case INDEX_op_st32_i64:
#endif
B
bellard 已提交
1575
    case INDEX_op_st_i32:
1576
        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
B
bellard 已提交
1577
        break;
1578 1579

    OP_32_64(add):
1580 1581 1582 1583 1584 1585 1586 1587 1588
        /* For 3-operand addition, use LEA.  */
        if (args[0] != args[1]) {
            TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;

            if (const_args[2]) {
                c3 = a2, a2 = -1;
            } else if (a0 == a2) {
                /* Watch out for dest = src + dest, since we've removed
                   the matching constraint on the add.  */
1589
                tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
1590 1591 1592
                break;
            }

1593
            tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
1594 1595 1596 1597
            break;
        }
        c = ARITH_ADD;
        goto gen_arith;
1598
    OP_32_64(sub):
B
bellard 已提交
1599 1600
        c = ARITH_SUB;
        goto gen_arith;
1601
    OP_32_64(and):
B
bellard 已提交
1602 1603
        c = ARITH_AND;
        goto gen_arith;
1604
    OP_32_64(or):
B
bellard 已提交
1605 1606
        c = ARITH_OR;
        goto gen_arith;
1607
    OP_32_64(xor):
B
bellard 已提交
1608 1609 1610 1611
        c = ARITH_XOR;
        goto gen_arith;
    gen_arith:
        if (const_args[2]) {
1612
            tgen_arithi(s, c + rexw, args[0], args[2], 0);
B
bellard 已提交
1613
        } else {
1614
            tgen_arithr(s, c + rexw, args[0], args[2]);
B
bellard 已提交
1615 1616
        }
        break;
1617 1618

    OP_32_64(mul):
B
bellard 已提交
1619 1620 1621 1622
        if (const_args[2]) {
            int32_t val;
            val = args[2];
            if (val == (int8_t)val) {
1623
                tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
B
bellard 已提交
1624 1625
                tcg_out8(s, val);
            } else {
1626
                tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
B
bellard 已提交
1627 1628 1629
                tcg_out32(s, val);
            }
        } else {
1630
            tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
B
bellard 已提交
1631 1632
        }
        break;
1633 1634 1635

    OP_32_64(div2):
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
B
bellard 已提交
1636
        break;
1637 1638
    OP_32_64(divu2):
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
B
bellard 已提交
1639
        break;
1640 1641

    OP_32_64(shl):
B
bellard 已提交
1642
        c = SHIFT_SHL;
1643 1644
        goto gen_shift;
    OP_32_64(shr):
B
bellard 已提交
1645
        c = SHIFT_SHR;
1646 1647
        goto gen_shift;
    OP_32_64(sar):
B
bellard 已提交
1648
        c = SHIFT_SAR;
1649 1650
        goto gen_shift;
    OP_32_64(rotl):
1651
        c = SHIFT_ROL;
1652 1653
        goto gen_shift;
    OP_32_64(rotr):
1654
        c = SHIFT_ROR;
1655 1656 1657 1658
        goto gen_shift;
    gen_shift:
        if (const_args[2]) {
            tcg_out_shifti(s, c + rexw, args[0], args[2]);
1659
        } else {
1660
            tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
1661
        }
B
bellard 已提交
1662
        break;
1663

B
bellard 已提交
1664
    case INDEX_op_brcond_i32:
1665 1666
        tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
                         args[3], 0);
B
bellard 已提交
1667
        break;
1668 1669 1670
    case INDEX_op_setcond_i32:
        tcg_out_setcond32(s, args[3], args[0], args[1],
                          args[2], const_args[2]);
B
bellard 已提交
1671 1672
        break;

1673
    OP_32_64(bswap16):
1674
        tcg_out_rolw_8(s, args[0]);
A
aurel32 已提交
1675
        break;
1676
    OP_32_64(bswap32):
1677
        tcg_out_bswap32(s, args[0]);
1678 1679
        break;

1680 1681
    OP_32_64(neg):
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
1682
        break;
1683 1684
    OP_32_64(not):
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
1685 1686
        break;

1687 1688
    OP_32_64(ext8s):
        tcg_out_ext8s(s, args[0], args[1], rexw);
1689
        break;
1690 1691
    OP_32_64(ext16s):
        tcg_out_ext16s(s, args[0], args[1], rexw);
1692
        break;
1693
    OP_32_64(ext8u):
1694
        tcg_out_ext8u(s, args[0], args[1]);
1695
        break;
1696
    OP_32_64(ext16u):
1697
        tcg_out_ext16u(s, args[0], args[1]);
1698
        break;
1699

B
bellard 已提交
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
    case INDEX_op_qemu_ld8u:
        tcg_out_qemu_ld(s, args, 0);
        break;
    case INDEX_op_qemu_ld8s:
        tcg_out_qemu_ld(s, args, 0 | 4);
        break;
    case INDEX_op_qemu_ld16u:
        tcg_out_qemu_ld(s, args, 1);
        break;
    case INDEX_op_qemu_ld16s:
        tcg_out_qemu_ld(s, args, 1 | 4);
        break;
1712 1713 1714
#if TCG_TARGET_REG_BITS == 64
    case INDEX_op_qemu_ld32u:
#endif
1715
    case INDEX_op_qemu_ld32:
B
bellard 已提交
1716 1717 1718 1719 1720
        tcg_out_qemu_ld(s, args, 2);
        break;
    case INDEX_op_qemu_ld64:
        tcg_out_qemu_ld(s, args, 3);
        break;
1721

B
bellard 已提交
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
    case INDEX_op_qemu_st8:
        tcg_out_qemu_st(s, args, 0);
        break;
    case INDEX_op_qemu_st16:
        tcg_out_qemu_st(s, args, 1);
        break;
    case INDEX_op_qemu_st32:
        tcg_out_qemu_st(s, args, 2);
        break;
    case INDEX_op_qemu_st64:
        tcg_out_qemu_st(s, args, 3);
        break;

1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
#if TCG_TARGET_REG_BITS == 32
    case INDEX_op_brcond2_i32:
        tcg_out_brcond2(s, args, const_args, 0);
        break;
    case INDEX_op_setcond2_i32:
        tcg_out_setcond2(s, args, const_args);
        break;
    case INDEX_op_mulu2_i32:
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
        break;
    case INDEX_op_add2_i32:
        if (const_args[4]) {
            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
        } else {
            tgen_arithr(s, ARITH_ADD, args[0], args[4]);
        }
        if (const_args[5]) {
            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
        } else {
            tgen_arithr(s, ARITH_ADC, args[1], args[5]);
        }
        break;
    case INDEX_op_sub2_i32:
        if (const_args[4]) {
            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
        } else {
            tgen_arithr(s, ARITH_SUB, args[0], args[4]);
        }
        if (const_args[5]) {
            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
        } else {
            tgen_arithr(s, ARITH_SBB, args[1], args[5]);
        }
        break;
#else /* TCG_TARGET_REG_BITS == 64 */
    case INDEX_op_movi_i64:
        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
        break;
    case INDEX_op_ld32s_i64:
        tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
        break;
    case INDEX_op_ld_i64:
        tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
        break;
    case INDEX_op_st_i64:
        tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
        break;
    case INDEX_op_qemu_ld32s:
        tcg_out_qemu_ld(s, args, 2 | 4);
        break;

    case INDEX_op_brcond_i64:
        tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
                         args[3], 0);
        break;
    case INDEX_op_setcond_i64:
        tcg_out_setcond64(s, args[3], args[0], args[1],
                          args[2], const_args[2]);
        break;

    case INDEX_op_bswap64_i64:
        tcg_out_bswap64(s, args[0]);
        break;
    case INDEX_op_ext32u_i64:
        tcg_out_ext32u(s, args[0], args[1]);
        break;
    case INDEX_op_ext32s_i64:
        tcg_out_ext32s(s, args[0], args[1]);
        break;
#endif

1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
    OP_32_64(deposit):
        if (args[3] == 0 && args[4] == 8) {
            /* load bits 0..7 */
            tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM,
                          args[2], args[0]);
        } else if (args[3] == 8 && args[4] == 8) {
            /* load bits 8..15 */
            tcg_out_modrm(s, OPC_MOVB_EvGv, args[2], args[0] + 4);
        } else if (args[3] == 0 && args[4] == 16) {
            /* load bits 0..15 */
            tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, args[2], args[0]);
        } else {
            tcg_abort();
        }
        break;

B
bellard 已提交
1822 1823 1824
    default:
        tcg_abort();
    }
1825 1826

#undef OP_32_64
B
bellard 已提交
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
}

static const TCGTargetOpDef x86_op_defs[] = {
    { INDEX_op_exit_tb, { } },
    { INDEX_op_goto_tb, { } },
    { INDEX_op_call, { "ri" } },
    { INDEX_op_jmp, { "ri" } },
    { INDEX_op_br, { } },
    { INDEX_op_mov_i32, { "r", "r" } },
    { INDEX_op_movi_i32, { "r" } },
    { INDEX_op_ld8u_i32, { "r", "r" } },
    { INDEX_op_ld8s_i32, { "r", "r" } },
    { INDEX_op_ld16u_i32, { "r", "r" } },
    { INDEX_op_ld16s_i32, { "r", "r" } },
    { INDEX_op_ld_i32, { "r", "r" } },
    { INDEX_op_st8_i32, { "q", "r" } },
    { INDEX_op_st16_i32, { "r", "r" } },
    { INDEX_op_st_i32, { "r", "r" } },

1846
    { INDEX_op_add_i32, { "r", "r", "ri" } },
B
bellard 已提交
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
    { INDEX_op_and_i32, { "r", "0", "ri" } },
    { INDEX_op_or_i32, { "r", "0", "ri" } },
    { INDEX_op_xor_i32, { "r", "0", "ri" } },

    { INDEX_op_shl_i32, { "r", "0", "ci" } },
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1858 1859
    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
B
bellard 已提交
1860 1861 1862

    { INDEX_op_brcond_i32, { "r", "ri" } },

A
aurel32 已提交
1863
    { INDEX_op_bswap16_i32, { "r", "0" } },
A
aurel32 已提交
1864
    { INDEX_op_bswap32_i32, { "r", "0" } },
1865 1866 1867 1868 1869 1870 1871

    { INDEX_op_neg_i32, { "r", "0" } },

    { INDEX_op_not_i32, { "r", "0" } },

    { INDEX_op_ext8s_i32, { "r", "q" } },
    { INDEX_op_ext16s_i32, { "r", "r" } },
1872 1873
    { INDEX_op_ext8u_i32, { "r", "q" } },
    { INDEX_op_ext16u_i32, { "r", "r" } },
1874

R
Richard Henderson 已提交
1875
    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1876

1877 1878
    { INDEX_op_deposit_i32, { "Q", "0", "Q" } },

1879 1880 1881 1882 1883
#if TCG_TARGET_REG_BITS == 32
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
R
Richard Henderson 已提交
1884
    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929
#else
    { INDEX_op_mov_i64, { "r", "r" } },
    { INDEX_op_movi_i64, { "r" } },
    { INDEX_op_ld8u_i64, { "r", "r" } },
    { INDEX_op_ld8s_i64, { "r", "r" } },
    { INDEX_op_ld16u_i64, { "r", "r" } },
    { INDEX_op_ld16s_i64, { "r", "r" } },
    { INDEX_op_ld32u_i64, { "r", "r" } },
    { INDEX_op_ld32s_i64, { "r", "r" } },
    { INDEX_op_ld_i64, { "r", "r" } },
    { INDEX_op_st8_i64, { "r", "r" } },
    { INDEX_op_st16_i64, { "r", "r" } },
    { INDEX_op_st32_i64, { "r", "r" } },
    { INDEX_op_st_i64, { "r", "r" } },

    { INDEX_op_add_i64, { "r", "0", "re" } },
    { INDEX_op_mul_i64, { "r", "0", "re" } },
    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
    { INDEX_op_sub_i64, { "r", "0", "re" } },
    { INDEX_op_and_i64, { "r", "0", "reZ" } },
    { INDEX_op_or_i64, { "r", "0", "re" } },
    { INDEX_op_xor_i64, { "r", "0", "re" } },

    { INDEX_op_shl_i64, { "r", "0", "ci" } },
    { INDEX_op_shr_i64, { "r", "0", "ci" } },
    { INDEX_op_sar_i64, { "r", "0", "ci" } },
    { INDEX_op_rotl_i64, { "r", "0", "ci" } },
    { INDEX_op_rotr_i64, { "r", "0", "ci" } },

    { INDEX_op_brcond_i64, { "r", "re" } },
    { INDEX_op_setcond_i64, { "r", "r", "re" } },

    { INDEX_op_bswap16_i64, { "r", "0" } },
    { INDEX_op_bswap32_i64, { "r", "0" } },
    { INDEX_op_bswap64_i64, { "r", "0" } },
    { INDEX_op_neg_i64, { "r", "0" } },
    { INDEX_op_not_i64, { "r", "0" } },

    { INDEX_op_ext8s_i64, { "r", "r" } },
    { INDEX_op_ext16s_i64, { "r", "r" } },
    { INDEX_op_ext32s_i64, { "r", "r" } },
    { INDEX_op_ext8u_i64, { "r", "r" } },
    { INDEX_op_ext16u_i64, { "r", "r" } },
    { INDEX_op_ext32u_i64, { "r", "r" } },
1930 1931

    { INDEX_op_deposit_i64, { "Q", "0", "Q" } },
1932
#endif
R
Richard Henderson 已提交
1933

1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
#if TCG_TARGET_REG_BITS == 64
    { INDEX_op_qemu_ld8u, { "r", "L" } },
    { INDEX_op_qemu_ld8s, { "r", "L" } },
    { INDEX_op_qemu_ld16u, { "r", "L" } },
    { INDEX_op_qemu_ld16s, { "r", "L" } },
    { INDEX_op_qemu_ld32, { "r", "L" } },
    { INDEX_op_qemu_ld32u, { "r", "L" } },
    { INDEX_op_qemu_ld32s, { "r", "L" } },
    { INDEX_op_qemu_ld64, { "r", "L" } },

    { INDEX_op_qemu_st8, { "L", "L" } },
    { INDEX_op_qemu_st16, { "L", "L" } },
    { INDEX_op_qemu_st32, { "L", "L" } },
    { INDEX_op_qemu_st64, { "L", "L" } },
#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
B
bellard 已提交
1949 1950 1951 1952
    { INDEX_op_qemu_ld8u, { "r", "L" } },
    { INDEX_op_qemu_ld8s, { "r", "L" } },
    { INDEX_op_qemu_ld16u, { "r", "L" } },
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1953
    { INDEX_op_qemu_ld32, { "r", "L" } },
B
bellard 已提交
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },

    { INDEX_op_qemu_st8, { "cb", "L" } },
    { INDEX_op_qemu_st16, { "L", "L" } },
    { INDEX_op_qemu_st32, { "L", "L" } },
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
#else
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1965
    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
B
bellard 已提交
1966 1967 1968 1969 1970 1971 1972 1973 1974 1975
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },

    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
#endif
    { -1 },
};

1976
static int tcg_target_callee_save_regs[] = {
1977 1978 1979 1980 1981
#if TCG_TARGET_REG_BITS == 64
    TCG_REG_RBP,
    TCG_REG_RBX,
    TCG_REG_R12,
    TCG_REG_R13,
B
Blue Swirl 已提交
1982
    TCG_REG_R14, /* Currently used for the global env. */
1983 1984
    TCG_REG_R15,
#else
B
Blue Swirl 已提交
1985
    TCG_REG_EBP, /* Currently used for the global env. */
1986 1987 1988
    TCG_REG_EBX,
    TCG_REG_ESI,
    TCG_REG_EDI,
1989
#endif
1990 1991
};

1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
/* Compute frame size via macros, to share between tcg_target_qemu_prologue
   and tcg_register_jit.  */

#define PUSH_SIZE \
    ((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \
     * (TCG_TARGET_REG_BITS / 8))

#define FRAME_SIZE \
    ((PUSH_SIZE \
      + TCG_STATIC_CALL_ARGS_SIZE \
      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
      + TCG_TARGET_STACK_ALIGN - 1) \
     & ~(TCG_TARGET_STACK_ALIGN - 1))

2006
/* Generate global QEMU prologue and epilogue code */
2007
static void tcg_target_qemu_prologue(TCGContext *s)
2008
{
2009
    int i, stack_addend;
2010

2011
    /* TB prologue */
2012

B
Blue Swirl 已提交
2013
    /* Reserve some stack space, also for TCG temps.  */
2014
    stack_addend = FRAME_SIZE - PUSH_SIZE;
B
Blue Swirl 已提交
2015 2016 2017 2018 2019 2020 2021 2022
    tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
                  CPU_TEMP_BUF_NLONGS * sizeof(long));

    /* Save all callee saved registers.  */
    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
    }

B
Blue Swirl 已提交
2023 2024 2025 2026 2027 2028
#if TCG_TARGET_REG_BITS == 32
    tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
               (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
    tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[1], TCG_REG_ESP,
               (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4);
#else
B
Blue Swirl 已提交
2029
    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
B
Blue Swirl 已提交
2030 2031
#endif
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
B
Blue Swirl 已提交
2032

2033
    /* jmp *tb.  */
B
Blue Swirl 已提交
2034
    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
2035

2036 2037
    /* TB epilogue */
    tb_ret_addr = s->code_ptr;
2038

2039
    tcg_out_addi(s, TCG_REG_CALL_STACK, stack_addend);
2040 2041

    for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
2042 2043
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
    }
2044
    tcg_out_opc(s, OPC_RET, 0, 0, 0);
2045 2046
}

2047
static void tcg_target_init(TCGContext *s)
B
bellard 已提交
2048
{
P
Paul Brook 已提交
2049
#if !defined(CONFIG_USER_ONLY)
B
bellard 已提交
2050 2051 2052
    /* fail safe */
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
        tcg_abort();
P
Paul Brook 已提交
2053
#endif
B
bellard 已提交
2054

2055 2056 2057 2058 2059 2060
    if (TCG_TARGET_REG_BITS == 64) {
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
    } else {
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
    }
2061 2062 2063 2064 2065

    tcg_regset_clear(tcg_target_call_clobber_regs);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
2066 2067 2068 2069 2070 2071 2072 2073
    if (TCG_TARGET_REG_BITS == 64) {
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
    }
2074

B
bellard 已提交
2075
    tcg_regset_clear(s->reserved_regs);
2076
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
B
bellard 已提交
2077 2078 2079

    tcg_add_target_add_op_defs(x86_op_defs);
}
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104

typedef struct {
    uint32_t len __attribute__((aligned((sizeof(void *)))));
    uint32_t id;
    uint8_t version;
    char augmentation[1];
    uint8_t code_align;
    uint8_t data_align;
    uint8_t return_column;
} DebugFrameCIE;

typedef struct {
    uint32_t len __attribute__((aligned((sizeof(void *)))));
    uint32_t cie_offset;
    tcg_target_long func_start __attribute__((packed));
    tcg_target_long func_len __attribute__((packed));
    uint8_t def_cfa[4];
    uint8_t reg_ofs[14];
} DebugFrameFDE;

typedef struct {
    DebugFrameCIE cie;
    DebugFrameFDE fde;
} DebugFrame;

2105 2106 2107
#if !defined(__ELF__)
    /* Host machine without ELF. */
#elif TCG_TARGET_REG_BITS == 64
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160
#define ELF_HOST_MACHINE EM_X86_64
static DebugFrame debug_frame = {
    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
    .cie.id = -1,
    .cie.version = 1,
    .cie.code_align = 1,
    .cie.data_align = 0x78,             /* sleb128 -8 */
    .cie.return_column = 16,

    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
    .fde.def_cfa = {
        12, 7,                          /* DW_CFA_def_cfa %rsp, ... */
        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
        (FRAME_SIZE >> 7)
    },
    .fde.reg_ofs = {
        0x90, 1,                        /* DW_CFA_offset, %rip, -8 */
        /* The following ordering must match tcg_target_callee_save_regs.  */
        0x86, 2,                        /* DW_CFA_offset, %rbp, -16 */
        0x83, 3,                        /* DW_CFA_offset, %rbx, -24 */
        0x8c, 4,                        /* DW_CFA_offset, %r12, -32 */
        0x8d, 5,                        /* DW_CFA_offset, %r13, -40 */
        0x8e, 6,                        /* DW_CFA_offset, %r14, -48 */
        0x8f, 7,                        /* DW_CFA_offset, %r15, -56 */
    }
};
#else
#define ELF_HOST_MACHINE EM_386
static DebugFrame debug_frame = {
    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
    .cie.id = -1,
    .cie.version = 1,
    .cie.code_align = 1,
    .cie.data_align = 0x7c,             /* sleb128 -4 */
    .cie.return_column = 8,

    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
    .fde.def_cfa = {
        12, 4,                          /* DW_CFA_def_cfa %esp, ... */
        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
        (FRAME_SIZE >> 7)
    },
    .fde.reg_ofs = {
        0x88, 1,                        /* DW_CFA_offset, %eip, -4 */
        /* The following ordering must match tcg_target_callee_save_regs.  */
        0x85, 2,                        /* DW_CFA_offset, %ebp, -8 */
        0x83, 3,                        /* DW_CFA_offset, %ebx, -12 */
        0x86, 4,                        /* DW_CFA_offset, %esi, -16 */
        0x87, 5,                        /* DW_CFA_offset, %edi, -20 */
    }
};
#endif

2161
#if defined(ELF_HOST_MACHINE)
2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
void tcg_register_jit(void *buf, size_t buf_size)
{
    /* We're expecting a 2 byte uleb128 encoded value.  */
    assert(FRAME_SIZE >> 14 == 0);

    debug_frame.fde.func_start = (tcg_target_long) buf;
    debug_frame.fde.func_len = buf_size;

    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
2172
#endif