Annotation of qemu/tcg/i386/tcg-target.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.