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