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

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: 
        !           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: }

unix.superglobalmegacorp.com

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