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