Annotation of qemu/target-i386/translate.c, revision 1.1.1.7

1.1       root        1: /*
                      2:  *  i386 translation
1.1.1.6   root        3:  *
1.1       root        4:  *  Copyright (c) 2003 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
1.1.1.7 ! root       18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
1.1       root       19:  */
                     20: #include <stdarg.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <inttypes.h>
                     25: #include <signal.h>
                     26: #include <assert.h>
                     27: 
                     28: #include "cpu.h"
                     29: #include "exec-all.h"
                     30: #include "disas.h"
1.1.1.7 ! root       31: #include "tcg-op.h"
1.1       root       32: 
1.1.1.7 ! root       33: #include "helper.h"
        !            34: #define GEN_HELPER 1
        !            35: #include "helper.h"
1.1       root       36: 
                     37: #define PREFIX_REPZ   0x01
                     38: #define PREFIX_REPNZ  0x02
                     39: #define PREFIX_LOCK   0x04
                     40: #define PREFIX_DATA   0x08
                     41: #define PREFIX_ADR    0x10
                     42: 
                     43: #ifdef TARGET_X86_64
                     44: #define X86_64_ONLY(x) x
                     45: #define X86_64_DEF(x...) x
                     46: #define CODE64(s) ((s)->code64)
                     47: #define REX_X(s) ((s)->rex_x)
                     48: #define REX_B(s) ((s)->rex_b)
                     49: /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
                     50: #if 1
                     51: #define BUGGY_64(x) NULL
                     52: #endif
                     53: #else
                     54: #define X86_64_ONLY(x) NULL
                     55: #define X86_64_DEF(x...)
                     56: #define CODE64(s) 0
                     57: #define REX_X(s) 0
                     58: #define REX_B(s) 0
                     59: #endif
                     60: 
1.1.1.7 ! root       61: //#define MACRO_TEST   1
        !            62: 
        !            63: /* global register indexes */
        !            64: static TCGv_ptr cpu_env;
        !            65: static TCGv cpu_A0, cpu_cc_src, cpu_cc_dst, cpu_cc_tmp;
        !            66: static TCGv_i32 cpu_cc_op;
        !            67: /* local temps */
        !            68: static TCGv cpu_T[2], cpu_T3;
        !            69: /* local register indexes (only used inside old micro ops) */
        !            70: static TCGv cpu_tmp0, cpu_tmp4;
        !            71: static TCGv_ptr cpu_ptr0, cpu_ptr1;
        !            72: static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
        !            73: static TCGv_i64 cpu_tmp1_i64;
        !            74: static TCGv cpu_tmp5, cpu_tmp6;
        !            75: 
        !            76: #include "gen-icount.h"
        !            77: 
1.1       root       78: #ifdef TARGET_X86_64
                     79: static int x86_64_hregs;
                     80: #endif
                     81: 
                     82: typedef struct DisasContext {
                     83:     /* current insn context */
                     84:     int override; /* -1 if no override */
                     85:     int prefix;
                     86:     int aflag, dflag;
                     87:     target_ulong pc; /* pc = eip + cs_base */
                     88:     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
                     89:                    static state change (stop translation) */
                     90:     /* current block context */
                     91:     target_ulong cs_base; /* base of CS segment */
                     92:     int pe;     /* protected mode */
                     93:     int code32; /* 32 bit code segment */
                     94: #ifdef TARGET_X86_64
                     95:     int lma;    /* long mode active */
                     96:     int code64; /* 64 bit code segment */
                     97:     int rex_x, rex_b;
                     98: #endif
                     99:     int ss32;   /* 32 bit stack segment */
                    100:     int cc_op;  /* current CC operation */
                    101:     int addseg; /* non zero if either DS/ES/SS have a non zero base */
                    102:     int f_st;   /* currently unused */
                    103:     int vm86;   /* vm86 mode */
                    104:     int cpl;
                    105:     int iopl;
                    106:     int tf;     /* TF cpu flag */
                    107:     int singlestep_enabled; /* "hardware" single step enabled */
                    108:     int jmp_opt; /* use direct block chaining for direct jumps */
                    109:     int mem_index; /* select memory access functions */
1.1.1.6   root      110:     uint64_t flags; /* all execution flags */
1.1       root      111:     struct TranslationBlock *tb;
                    112:     int popl_esp_hack; /* for correct popl with esp base handling */
                    113:     int rip_offset; /* only used in x86_64, but left for simplicity */
                    114:     int cpuid_features;
1.1.1.4   root      115:     int cpuid_ext_features;
1.1.1.7 ! root      116:     int cpuid_ext2_features;
        !           117:     int cpuid_ext3_features;
1.1       root      118: } DisasContext;
                    119: 
                    120: static void gen_eob(DisasContext *s);
                    121: static void gen_jmp(DisasContext *s, target_ulong eip);
                    122: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
                    123: 
                    124: /* i386 arith/logic operations */
                    125: enum {
1.1.1.6   root      126:     OP_ADDL,
                    127:     OP_ORL,
                    128:     OP_ADCL,
1.1       root      129:     OP_SBBL,
1.1.1.6   root      130:     OP_ANDL,
                    131:     OP_SUBL,
                    132:     OP_XORL,
1.1       root      133:     OP_CMPL,
                    134: };
                    135: 
                    136: /* i386 shift ops */
                    137: enum {
1.1.1.6   root      138:     OP_ROL,
                    139:     OP_ROR,
                    140:     OP_RCL,
                    141:     OP_RCR,
                    142:     OP_SHL,
                    143:     OP_SHR,
1.1       root      144:     OP_SHL1, /* undocumented */
                    145:     OP_SAR = 7,
                    146: };
                    147: 
                    148: enum {
1.1.1.7 ! root      149:     JCC_O,
        !           150:     JCC_B,
        !           151:     JCC_Z,
        !           152:     JCC_BE,
        !           153:     JCC_S,
        !           154:     JCC_P,
        !           155:     JCC_L,
        !           156:     JCC_LE,
1.1       root      157: };
                    158: 
                    159: /* operand size */
                    160: enum {
                    161:     OT_BYTE = 0,
                    162:     OT_WORD,
1.1.1.6   root      163:     OT_LONG,
1.1       root      164:     OT_QUAD,
                    165: };
                    166: 
                    167: enum {
                    168:     /* I386 int registers */
                    169:     OR_EAX,   /* MUST be even numbered */
                    170:     OR_ECX,
                    171:     OR_EDX,
                    172:     OR_EBX,
                    173:     OR_ESP,
                    174:     OR_EBP,
                    175:     OR_ESI,
                    176:     OR_EDI,
                    177: 
                    178:     OR_TMP0 = 16,    /* temporary operand register */
                    179:     OR_TMP1,
                    180:     OR_A0, /* temporary register used when doing address evaluation */
                    181: };
                    182: 
1.1.1.7 ! root      183: static inline void gen_op_movl_T0_0(void)
        !           184: {
        !           185:     tcg_gen_movi_tl(cpu_T[0], 0);
        !           186: }
        !           187: 
        !           188: static inline void gen_op_movl_T0_im(int32_t val)
        !           189: {
        !           190:     tcg_gen_movi_tl(cpu_T[0], val);
        !           191: }
        !           192: 
        !           193: static inline void gen_op_movl_T0_imu(uint32_t val)
        !           194: {
        !           195:     tcg_gen_movi_tl(cpu_T[0], val);
        !           196: }
        !           197: 
        !           198: static inline void gen_op_movl_T1_im(int32_t val)
        !           199: {
        !           200:     tcg_gen_movi_tl(cpu_T[1], val);
        !           201: }
        !           202: 
        !           203: static inline void gen_op_movl_T1_imu(uint32_t val)
        !           204: {
        !           205:     tcg_gen_movi_tl(cpu_T[1], val);
        !           206: }
        !           207: 
        !           208: static inline void gen_op_movl_A0_im(uint32_t val)
        !           209: {
        !           210:     tcg_gen_movi_tl(cpu_A0, val);
        !           211: }
        !           212: 
1.1       root      213: #ifdef TARGET_X86_64
1.1.1.7 ! root      214: static inline void gen_op_movq_A0_im(int64_t val)
        !           215: {
        !           216:     tcg_gen_movi_tl(cpu_A0, val);
        !           217: }
        !           218: #endif
1.1       root      219: 
1.1.1.7 ! root      220: static inline void gen_movtl_T0_im(target_ulong val)
        !           221: {
        !           222:     tcg_gen_movi_tl(cpu_T[0], val);
        !           223: }
        !           224: 
        !           225: static inline void gen_movtl_T1_im(target_ulong val)
        !           226: {
        !           227:     tcg_gen_movi_tl(cpu_T[1], val);
        !           228: }
        !           229: 
        !           230: static inline void gen_op_andl_T0_ffff(void)
        !           231: {
        !           232:     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
        !           233: }
        !           234: 
        !           235: static inline void gen_op_andl_T0_im(uint32_t val)
        !           236: {
        !           237:     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
        !           238: }
1.1       root      239: 
1.1.1.7 ! root      240: static inline void gen_op_movl_T0_T1(void)
        !           241: {
        !           242:     tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
        !           243: }
        !           244: 
        !           245: static inline void gen_op_andl_A0_ffff(void)
        !           246: {
        !           247:     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
        !           248: }
        !           249: 
        !           250: #ifdef TARGET_X86_64
        !           251: 
        !           252: #define NB_OP_SIZES 4
1.1       root      253: 
                    254: #else /* !TARGET_X86_64 */
                    255: 
                    256: #define NB_OP_SIZES 3
                    257: 
                    258: #endif /* !TARGET_X86_64 */
                    259: 
1.1.1.7 ! root      260: #if defined(WORDS_BIGENDIAN)
        !           261: #define REG_B_OFFSET (sizeof(target_ulong) - 1)
        !           262: #define REG_H_OFFSET (sizeof(target_ulong) - 2)
        !           263: #define REG_W_OFFSET (sizeof(target_ulong) - 2)
        !           264: #define REG_L_OFFSET (sizeof(target_ulong) - 4)
        !           265: #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
1.1       root      266: #else
1.1.1.7 ! root      267: #define REG_B_OFFSET 0
        !           268: #define REG_H_OFFSET 1
        !           269: #define REG_W_OFFSET 0
        !           270: #define REG_L_OFFSET 0
        !           271: #define REG_LH_OFFSET 4
1.1       root      272: #endif
                    273: 
1.1.1.7 ! root      274: static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
        !           275: {
        !           276:     switch(ot) {
        !           277:     case OT_BYTE:
        !           278:         if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
        !           279:             tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET);
        !           280:         } else {
        !           281:             tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);
        !           282:         }
        !           283:         break;
        !           284:     case OT_WORD:
        !           285:         tcg_gen_st16_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
        !           286:         break;
        !           287: #ifdef TARGET_X86_64
        !           288:     case OT_LONG:
        !           289:         tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !           290:         /* high part of register set to zero */
        !           291:         tcg_gen_movi_tl(cpu_tmp0, 0);
        !           292:         tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
        !           293:         break;
        !           294:     default:
        !           295:     case OT_QUAD:
        !           296:         tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, regs[reg]));
        !           297:         break;
1.1       root      298: #else
1.1.1.7 ! root      299:     default:
        !           300:     case OT_LONG:
        !           301:         tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !           302:         break;
1.1       root      303: #endif
1.1.1.7 ! root      304:     }
        !           305: }
1.1       root      306: 
1.1.1.7 ! root      307: static inline void gen_op_mov_reg_T0(int ot, int reg)
        !           308: {
        !           309:     gen_op_mov_reg_v(ot, reg, cpu_T[0]);
        !           310: }
1.1       root      311: 
1.1.1.7 ! root      312: static inline void gen_op_mov_reg_T1(int ot, int reg)
1.1       root      313: {
1.1.1.7 ! root      314:     gen_op_mov_reg_v(ot, reg, cpu_T[1]);
        !           315: }
        !           316: 
        !           317: static inline void gen_op_mov_reg_A0(int size, int reg)
        !           318: {
        !           319:     switch(size) {
        !           320:     case 0:
        !           321:         tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
        !           322:         break;
1.1       root      323: #ifdef TARGET_X86_64
1.1.1.7 ! root      324:     case 1:
        !           325:         tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !           326:         /* high part of register set to zero */
        !           327:         tcg_gen_movi_tl(cpu_tmp0, 0);
        !           328:         tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
        !           329:         break;
        !           330:     default:
        !           331:     case 2:
        !           332:         tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));
        !           333:         break;
        !           334: #else
        !           335:     default:
        !           336:     case 1:
        !           337:         tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !           338:         break;
1.1       root      339: #endif
1.1.1.7 ! root      340:     }
        !           341: }
1.1       root      342: 
1.1.1.7 ! root      343: static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
        !           344: {
        !           345:     switch(ot) {
        !           346:     case OT_BYTE:
        !           347:         if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
        !           348:             goto std_case;
        !           349:         } else {
        !           350:             tcg_gen_ld8u_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);
        !           351:         }
        !           352:         break;
        !           353:     default:
        !           354:     std_case:
        !           355:         tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, regs[reg]));
        !           356:         break;
        !           357:     }
        !           358: }
1.1       root      359: 
1.1.1.7 ! root      360: static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
        !           361: {
        !           362:     gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
        !           363: }
1.1       root      364: 
1.1.1.7 ! root      365: static inline void gen_op_movl_A0_reg(int reg)
        !           366: {
        !           367:     tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !           368: }
1.1       root      369: 
1.1.1.7 ! root      370: static inline void gen_op_addl_A0_im(int32_t val)
        !           371: {
        !           372:     tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
        !           373: #ifdef TARGET_X86_64
        !           374:     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
1.1       root      375: #endif
1.1.1.7 ! root      376: }
1.1       root      377: 
1.1.1.7 ! root      378: #ifdef TARGET_X86_64
        !           379: static inline void gen_op_addq_A0_im(int64_t val)
        !           380: {
        !           381:     tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
        !           382: }
1.1       root      383: #endif
1.1.1.7 ! root      384:     
        !           385: static void gen_add_A0_im(DisasContext *s, int val)
        !           386: {
        !           387: #ifdef TARGET_X86_64
        !           388:     if (CODE64(s))
        !           389:         gen_op_addq_A0_im(val);
        !           390:     else
1.1       root      391: #endif
1.1.1.7 ! root      392:         gen_op_addl_A0_im(val);
        !           393: }
1.1       root      394: 
1.1.1.7 ! root      395: static inline void gen_op_addl_T0_T1(void)
        !           396: {
        !           397:     tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !           398: }
1.1       root      399: 
1.1.1.7 ! root      400: static inline void gen_op_jmp_T0(void)
        !           401: {
        !           402:     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));
        !           403: }
1.1       root      404: 
1.1.1.7 ! root      405: static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
        !           406: {
        !           407:     switch(size) {
        !           408:     case 0:
        !           409:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           410:         tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
        !           411:         tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
        !           412:         break;
        !           413:     case 1:
        !           414:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           415:         tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
        !           416: #ifdef TARGET_X86_64
        !           417:         tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
1.1       root      418: #endif
1.1.1.7 ! root      419:         tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           420:         break;
        !           421: #ifdef TARGET_X86_64
        !           422:     case 2:
        !           423:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           424:         tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
        !           425:         tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           426:         break;
        !           427: #endif
        !           428:     }
        !           429: }
1.1       root      430: 
1.1.1.7 ! root      431: static inline void gen_op_add_reg_T0(int size, int reg)
        !           432: {
        !           433:     switch(size) {
        !           434:     case 0:
        !           435:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           436:         tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
        !           437:         tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
        !           438:         break;
        !           439:     case 1:
        !           440:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           441:         tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
        !           442: #ifdef TARGET_X86_64
        !           443:         tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
        !           444: #endif
        !           445:         tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           446:         break;
        !           447: #ifdef TARGET_X86_64
        !           448:     case 2:
        !           449:         tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           450:         tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
        !           451:         tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           452:         break;
        !           453: #endif
        !           454:     }
        !           455: }
1.1       root      456: 
1.1.1.7 ! root      457: static inline void gen_op_set_cc_op(int32_t val)
        !           458: {
        !           459:     tcg_gen_movi_i32(cpu_cc_op, val);
        !           460: }
1.1       root      461: 
1.1.1.7 ! root      462: static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
        !           463: {
        !           464:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           465:     if (shift != 0) 
        !           466:         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
        !           467:     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
        !           468: #ifdef TARGET_X86_64
        !           469:     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
1.1       root      470: #endif
1.1.1.7 ! root      471: }
1.1       root      472: 
1.1.1.7 ! root      473: static inline void gen_op_movl_A0_seg(int reg)
        !           474: {
        !           475:     tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET);
        !           476: }
1.1       root      477: 
1.1.1.7 ! root      478: static inline void gen_op_addl_A0_seg(int reg)
        !           479: {
        !           480:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
        !           481:     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
        !           482: #ifdef TARGET_X86_64
        !           483:     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
        !           484: #endif
        !           485: }
1.1       root      486: 
1.1.1.7 ! root      487: #ifdef TARGET_X86_64
        !           488: static inline void gen_op_movq_A0_seg(int reg)
        !           489: {
        !           490:     tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base));
        !           491: }
1.1       root      492: 
1.1.1.7 ! root      493: static inline void gen_op_addq_A0_seg(int reg)
        !           494: {
        !           495:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
        !           496:     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
        !           497: }
1.1       root      498: 
1.1.1.7 ! root      499: static inline void gen_op_movq_A0_reg(int reg)
        !           500: {
        !           501:     tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));
        !           502: }
1.1       root      503: 
1.1.1.7 ! root      504: static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
        !           505: {
        !           506:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
        !           507:     if (shift != 0) 
        !           508:         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
        !           509:     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
        !           510: }
1.1       root      511: #endif
                    512: 
1.1.1.7 ! root      513: static inline void gen_op_lds_T0_A0(int idx)
        !           514: {
        !           515:     int mem_index = (idx >> 2) - 1;
        !           516:     switch(idx & 3) {
        !           517:     case 0:
        !           518:         tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
        !           519:         break;
        !           520:     case 1:
        !           521:         tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
        !           522:         break;
        !           523:     default:
        !           524:     case 2:
        !           525:         tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
        !           526:         break;
        !           527:     }
        !           528: }
1.1       root      529: 
1.1.1.7 ! root      530: static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0)
        !           531: {
        !           532:     int mem_index = (idx >> 2) - 1;
        !           533:     switch(idx & 3) {
        !           534:     case 0:
        !           535:         tcg_gen_qemu_ld8u(t0, a0, mem_index);
        !           536:         break;
        !           537:     case 1:
        !           538:         tcg_gen_qemu_ld16u(t0, a0, mem_index);
        !           539:         break;
        !           540:     case 2:
        !           541:         tcg_gen_qemu_ld32u(t0, a0, mem_index);
        !           542:         break;
        !           543:     default:
        !           544:     case 3:
        !           545:         /* Should never happen on 32-bit targets.  */
        !           546: #ifdef TARGET_X86_64
        !           547:         tcg_gen_qemu_ld64(t0, a0, mem_index);
1.1       root      548: #endif
1.1.1.7 ! root      549:         break;
        !           550:     }
        !           551: }
1.1       root      552: 
1.1.1.7 ! root      553: /* XXX: always use ldu or lds */
        !           554: static inline void gen_op_ld_T0_A0(int idx)
        !           555: {
        !           556:     gen_op_ld_v(idx, cpu_T[0], cpu_A0);
        !           557: }
1.1       root      558: 
1.1.1.7 ! root      559: static inline void gen_op_ldu_T0_A0(int idx)
        !           560: {
        !           561:     gen_op_ld_v(idx, cpu_T[0], cpu_A0);
        !           562: }
1.1       root      563: 
1.1.1.7 ! root      564: static inline void gen_op_ld_T1_A0(int idx)
        !           565: {
        !           566:     gen_op_ld_v(idx, cpu_T[1], cpu_A0);
        !           567: }
1.1       root      568: 
1.1.1.7 ! root      569: static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0)
        !           570: {
        !           571:     int mem_index = (idx >> 2) - 1;
        !           572:     switch(idx & 3) {
        !           573:     case 0:
        !           574:         tcg_gen_qemu_st8(t0, a0, mem_index);
        !           575:         break;
        !           576:     case 1:
        !           577:         tcg_gen_qemu_st16(t0, a0, mem_index);
        !           578:         break;
        !           579:     case 2:
        !           580:         tcg_gen_qemu_st32(t0, a0, mem_index);
        !           581:         break;
        !           582:     default:
        !           583:     case 3:
        !           584:         /* Should never happen on 32-bit targets.  */
        !           585: #ifdef TARGET_X86_64
        !           586:         tcg_gen_qemu_st64(t0, a0, mem_index);
1.1       root      587: #endif
1.1.1.7 ! root      588:         break;
        !           589:     }
        !           590: }
1.1       root      591: 
1.1.1.7 ! root      592: static inline void gen_op_st_T0_A0(int idx)
        !           593: {
        !           594:     gen_op_st_v(idx, cpu_T[0], cpu_A0);
        !           595: }
1.1       root      596: 
1.1.1.7 ! root      597: static inline void gen_op_st_T1_A0(int idx)
        !           598: {
        !           599:     gen_op_st_v(idx, cpu_T[1], cpu_A0);
        !           600: }
1.1       root      601: 
                    602: static inline void gen_jmp_im(target_ulong pc)
                    603: {
1.1.1.7 ! root      604:     tcg_gen_movi_tl(cpu_tmp0, pc);
        !           605:     tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip));
1.1       root      606: }
                    607: 
                    608: static inline void gen_string_movl_A0_ESI(DisasContext *s)
                    609: {
                    610:     int override;
                    611: 
                    612:     override = s->override;
                    613: #ifdef TARGET_X86_64
                    614:     if (s->aflag == 2) {
                    615:         if (override >= 0) {
1.1.1.7 ! root      616:             gen_op_movq_A0_seg(override);
        !           617:             gen_op_addq_A0_reg_sN(0, R_ESI);
1.1       root      618:         } else {
1.1.1.7 ! root      619:             gen_op_movq_A0_reg(R_ESI);
1.1       root      620:         }
                    621:     } else
                    622: #endif
                    623:     if (s->aflag) {
                    624:         /* 32 bit address */
                    625:         if (s->addseg && override < 0)
                    626:             override = R_DS;
                    627:         if (override >= 0) {
1.1.1.7 ! root      628:             gen_op_movl_A0_seg(override);
        !           629:             gen_op_addl_A0_reg_sN(0, R_ESI);
1.1       root      630:         } else {
1.1.1.7 ! root      631:             gen_op_movl_A0_reg(R_ESI);
1.1       root      632:         }
                    633:     } else {
                    634:         /* 16 address, always override */
                    635:         if (override < 0)
                    636:             override = R_DS;
1.1.1.7 ! root      637:         gen_op_movl_A0_reg(R_ESI);
1.1       root      638:         gen_op_andl_A0_ffff();
1.1.1.7 ! root      639:         gen_op_addl_A0_seg(override);
1.1       root      640:     }
                    641: }
                    642: 
                    643: static inline void gen_string_movl_A0_EDI(DisasContext *s)
                    644: {
                    645: #ifdef TARGET_X86_64
                    646:     if (s->aflag == 2) {
1.1.1.7 ! root      647:         gen_op_movq_A0_reg(R_EDI);
1.1       root      648:     } else
                    649: #endif
                    650:     if (s->aflag) {
                    651:         if (s->addseg) {
1.1.1.7 ! root      652:             gen_op_movl_A0_seg(R_ES);
        !           653:             gen_op_addl_A0_reg_sN(0, R_EDI);
1.1       root      654:         } else {
1.1.1.7 ! root      655:             gen_op_movl_A0_reg(R_EDI);
1.1       root      656:         }
                    657:     } else {
1.1.1.7 ! root      658:         gen_op_movl_A0_reg(R_EDI);
1.1       root      659:         gen_op_andl_A0_ffff();
1.1.1.7 ! root      660:         gen_op_addl_A0_seg(R_ES);
1.1       root      661:     }
                    662: }
                    663: 
1.1.1.7 ! root      664: static inline void gen_op_movl_T0_Dshift(int ot) 
        !           665: {
        !           666:     tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df));
        !           667:     tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
1.1       root      668: };
                    669: 
1.1.1.7 ! root      670: static void gen_extu(int ot, TCGv reg)
        !           671: {
        !           672:     switch(ot) {
        !           673:     case OT_BYTE:
        !           674:         tcg_gen_ext8u_tl(reg, reg);
        !           675:         break;
        !           676:     case OT_WORD:
        !           677:         tcg_gen_ext16u_tl(reg, reg);
        !           678:         break;
        !           679:     case OT_LONG:
        !           680:         tcg_gen_ext32u_tl(reg, reg);
        !           681:         break;
        !           682:     default:
        !           683:         break;
        !           684:     }
        !           685: }
1.1       root      686: 
1.1.1.7 ! root      687: static void gen_exts(int ot, TCGv reg)
        !           688: {
        !           689:     switch(ot) {
        !           690:     case OT_BYTE:
        !           691:         tcg_gen_ext8s_tl(reg, reg);
        !           692:         break;
        !           693:     case OT_WORD:
        !           694:         tcg_gen_ext16s_tl(reg, reg);
        !           695:         break;
        !           696:     case OT_LONG:
        !           697:         tcg_gen_ext32s_tl(reg, reg);
        !           698:         break;
        !           699:     default:
        !           700:         break;
        !           701:     }
        !           702: }
1.1       root      703: 
1.1.1.7 ! root      704: static inline void gen_op_jnz_ecx(int size, int label1)
        !           705: {
        !           706:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX]));
        !           707:     gen_extu(size + 1, cpu_tmp0);
        !           708:     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
        !           709: }
1.1       root      710: 
1.1.1.7 ! root      711: static inline void gen_op_jz_ecx(int size, int label1)
        !           712: {
        !           713:     tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX]));
        !           714:     gen_extu(size + 1, cpu_tmp0);
        !           715:     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
        !           716: }
1.1       root      717: 
1.1.1.7 ! root      718: static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
        !           719: {
        !           720:     switch (ot) {
        !           721:     case 0: gen_helper_inb(v, n); break;
        !           722:     case 1: gen_helper_inw(v, n); break;
        !           723:     case 2: gen_helper_inl(v, n); break;
        !           724:     }
1.1       root      725: 
1.1.1.7 ! root      726: }
1.1       root      727: 
1.1.1.7 ! root      728: static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
        !           729: {
        !           730:     switch (ot) {
        !           731:     case 0: gen_helper_outb(v, n); break;
        !           732:     case 1: gen_helper_outw(v, n); break;
        !           733:     case 2: gen_helper_outl(v, n); break;
        !           734:     }
1.1       root      735: 
1.1.1.7 ! root      736: }
1.1       root      737: 
1.1.1.7 ! root      738: static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
        !           739:                          uint32_t svm_flags)
1.1       root      740: {
1.1.1.7 ! root      741:     int state_saved;
        !           742:     target_ulong next_eip;
        !           743: 
        !           744:     state_saved = 0;
1.1       root      745:     if (s->pe && (s->cpl > s->iopl || s->vm86)) {
                    746:         if (s->cc_op != CC_OP_DYNAMIC)
                    747:             gen_op_set_cc_op(s->cc_op);
                    748:         gen_jmp_im(cur_eip);
1.1.1.7 ! root      749:         state_saved = 1;
        !           750:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !           751:         switch (ot) {
        !           752:         case 0: gen_helper_check_iob(cpu_tmp2_i32); break;
        !           753:         case 1: gen_helper_check_iow(cpu_tmp2_i32); break;
        !           754:         case 2: gen_helper_check_iol(cpu_tmp2_i32); break;
        !           755:         }
        !           756:     }
        !           757:     if(s->flags & HF_SVMI_MASK) {
        !           758:         if (!state_saved) {
        !           759:             if (s->cc_op != CC_OP_DYNAMIC)
        !           760:                 gen_op_set_cc_op(s->cc_op);
        !           761:             gen_jmp_im(cur_eip);
        !           762:             state_saved = 1;
        !           763:         }
        !           764:         svm_flags |= (1 << (4 + ot));
        !           765:         next_eip = s->pc - s->cs_base;
        !           766:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !           767:         gen_helper_svm_check_io(cpu_tmp2_i32, tcg_const_i32(svm_flags),
        !           768:                                 tcg_const_i32(next_eip - cur_eip));
1.1       root      769:     }
                    770: }
                    771: 
                    772: static inline void gen_movs(DisasContext *s, int ot)
                    773: {
                    774:     gen_string_movl_A0_ESI(s);
1.1.1.7 ! root      775:     gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root      776:     gen_string_movl_A0_EDI(s);
1.1.1.7 ! root      777:     gen_op_st_T0_A0(ot + s->mem_index);
        !           778:     gen_op_movl_T0_Dshift(ot);
        !           779:     gen_op_add_reg_T0(s->aflag, R_ESI);
        !           780:     gen_op_add_reg_T0(s->aflag, R_EDI);
1.1       root      781: }
                    782: 
                    783: static inline void gen_update_cc_op(DisasContext *s)
                    784: {
                    785:     if (s->cc_op != CC_OP_DYNAMIC) {
                    786:         gen_op_set_cc_op(s->cc_op);
                    787:         s->cc_op = CC_OP_DYNAMIC;
                    788:     }
                    789: }
                    790: 
1.1.1.7 ! root      791: static void gen_op_update1_cc(void)
        !           792: {
        !           793:     tcg_gen_discard_tl(cpu_cc_src);
        !           794:     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !           795: }
        !           796: 
        !           797: static void gen_op_update2_cc(void)
        !           798: {
        !           799:     tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
        !           800:     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !           801: }
        !           802: 
        !           803: static inline void gen_op_cmpl_T0_T1_cc(void)
        !           804: {
        !           805:     tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
        !           806:     tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
        !           807: }
        !           808: 
        !           809: static inline void gen_op_testl_T0_T1_cc(void)
        !           810: {
        !           811:     tcg_gen_discard_tl(cpu_cc_src);
        !           812:     tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
        !           813: }
        !           814: 
        !           815: static void gen_op_update_neg_cc(void)
        !           816: {
        !           817:     tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
        !           818:     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !           819: }
        !           820: 
        !           821: /* compute eflags.C to reg */
        !           822: static void gen_compute_eflags_c(TCGv reg)
        !           823: {
        !           824:     gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_cc_op);
        !           825:     tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32);
        !           826: }
        !           827: 
        !           828: /* compute all eflags to cc_src */
        !           829: static void gen_compute_eflags(TCGv reg)
        !           830: {
        !           831:     gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_cc_op);
        !           832:     tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32);
        !           833: }
        !           834: 
        !           835: static inline void gen_setcc_slow_T0(DisasContext *s, int jcc_op)
        !           836: {
        !           837:     if (s->cc_op != CC_OP_DYNAMIC)
        !           838:         gen_op_set_cc_op(s->cc_op);
        !           839:     switch(jcc_op) {
        !           840:     case JCC_O:
        !           841:         gen_compute_eflags(cpu_T[0]);
        !           842:         tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 11);
        !           843:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           844:         break;
        !           845:     case JCC_B:
        !           846:         gen_compute_eflags_c(cpu_T[0]);
        !           847:         break;
        !           848:     case JCC_Z:
        !           849:         gen_compute_eflags(cpu_T[0]);
        !           850:         tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 6);
        !           851:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           852:         break;
        !           853:     case JCC_BE:
        !           854:         gen_compute_eflags(cpu_tmp0);
        !           855:         tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 6);
        !           856:         tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !           857:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           858:         break;
        !           859:     case JCC_S:
        !           860:         gen_compute_eflags(cpu_T[0]);
        !           861:         tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 7);
        !           862:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           863:         break;
        !           864:     case JCC_P:
        !           865:         gen_compute_eflags(cpu_T[0]);
        !           866:         tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 2);
        !           867:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           868:         break;
        !           869:     case JCC_L:
        !           870:         gen_compute_eflags(cpu_tmp0);
        !           871:         tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */
        !           872:         tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 7); /* CC_S */
        !           873:         tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !           874:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           875:         break;
        !           876:     default:
        !           877:     case JCC_LE:
        !           878:         gen_compute_eflags(cpu_tmp0);
        !           879:         tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */
        !           880:         tcg_gen_shri_tl(cpu_tmp4, cpu_tmp0, 7); /* CC_S */
        !           881:         tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 6); /* CC_Z */
        !           882:         tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
        !           883:         tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !           884:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
        !           885:         break;
        !           886:     }
        !           887: }
        !           888: 
        !           889: /* return true if setcc_slow is not needed (WARNING: must be kept in
        !           890:    sync with gen_jcc1) */
        !           891: static int is_fast_jcc_case(DisasContext *s, int b)
        !           892: {
        !           893:     int jcc_op;
        !           894:     jcc_op = (b >> 1) & 7;
        !           895:     switch(s->cc_op) {
        !           896:         /* we optimize the cmp/jcc case */
        !           897:     case CC_OP_SUBB:
        !           898:     case CC_OP_SUBW:
        !           899:     case CC_OP_SUBL:
        !           900:     case CC_OP_SUBQ:
        !           901:         if (jcc_op == JCC_O || jcc_op == JCC_P)
        !           902:             goto slow_jcc;
        !           903:         break;
        !           904: 
        !           905:         /* some jumps are easy to compute */
        !           906:     case CC_OP_ADDB:
        !           907:     case CC_OP_ADDW:
        !           908:     case CC_OP_ADDL:
        !           909:     case CC_OP_ADDQ:
        !           910: 
        !           911:     case CC_OP_LOGICB:
        !           912:     case CC_OP_LOGICW:
        !           913:     case CC_OP_LOGICL:
        !           914:     case CC_OP_LOGICQ:
        !           915: 
        !           916:     case CC_OP_INCB:
        !           917:     case CC_OP_INCW:
        !           918:     case CC_OP_INCL:
        !           919:     case CC_OP_INCQ:
        !           920: 
        !           921:     case CC_OP_DECB:
        !           922:     case CC_OP_DECW:
        !           923:     case CC_OP_DECL:
        !           924:     case CC_OP_DECQ:
        !           925: 
        !           926:     case CC_OP_SHLB:
        !           927:     case CC_OP_SHLW:
        !           928:     case CC_OP_SHLL:
        !           929:     case CC_OP_SHLQ:
        !           930:         if (jcc_op != JCC_Z && jcc_op != JCC_S)
        !           931:             goto slow_jcc;
        !           932:         break;
        !           933:     default:
        !           934:     slow_jcc:
        !           935:         return 0;
        !           936:     }
        !           937:     return 1;
        !           938: }
        !           939: 
        !           940: /* generate a conditional jump to label 'l1' according to jump opcode
        !           941:    value 'b'. In the fast case, T0 is guaranted not to be used. */
        !           942: static inline void gen_jcc1(DisasContext *s, int cc_op, int b, int l1)
        !           943: {
        !           944:     int inv, jcc_op, size, cond;
        !           945:     TCGv t0;
        !           946: 
        !           947:     inv = b & 1;
        !           948:     jcc_op = (b >> 1) & 7;
        !           949: 
        !           950:     switch(cc_op) {
        !           951:         /* we optimize the cmp/jcc case */
        !           952:     case CC_OP_SUBB:
        !           953:     case CC_OP_SUBW:
        !           954:     case CC_OP_SUBL:
        !           955:     case CC_OP_SUBQ:
        !           956:         
        !           957:         size = cc_op - CC_OP_SUBB;
        !           958:         switch(jcc_op) {
        !           959:         case JCC_Z:
        !           960:         fast_jcc_z:
        !           961:             switch(size) {
        !           962:             case 0:
        !           963:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xff);
        !           964:                 t0 = cpu_tmp0;
        !           965:                 break;
        !           966:             case 1:
        !           967:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffff);
        !           968:                 t0 = cpu_tmp0;
        !           969:                 break;
        !           970: #ifdef TARGET_X86_64
        !           971:             case 2:
        !           972:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffffffff);
        !           973:                 t0 = cpu_tmp0;
        !           974:                 break;
        !           975: #endif
        !           976:             default:
        !           977:                 t0 = cpu_cc_dst;
        !           978:                 break;
        !           979:             }
        !           980:             tcg_gen_brcondi_tl(inv ? TCG_COND_NE : TCG_COND_EQ, t0, 0, l1);
        !           981:             break;
        !           982:         case JCC_S:
        !           983:         fast_jcc_s:
        !           984:             switch(size) {
        !           985:             case 0:
        !           986:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80);
        !           987:                 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 
        !           988:                                    0, l1);
        !           989:                 break;
        !           990:             case 1:
        !           991:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x8000);
        !           992:                 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 
        !           993:                                    0, l1);
        !           994:                 break;
        !           995: #ifdef TARGET_X86_64
        !           996:             case 2:
        !           997:                 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80000000);
        !           998:                 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 
        !           999:                                    0, l1);
        !          1000:                 break;
        !          1001: #endif
        !          1002:             default:
        !          1003:                 tcg_gen_brcondi_tl(inv ? TCG_COND_GE : TCG_COND_LT, cpu_cc_dst, 
        !          1004:                                    0, l1);
        !          1005:                 break;
        !          1006:             }
        !          1007:             break;
        !          1008:             
        !          1009:         case JCC_B:
        !          1010:             cond = inv ? TCG_COND_GEU : TCG_COND_LTU;
        !          1011:             goto fast_jcc_b;
        !          1012:         case JCC_BE:
        !          1013:             cond = inv ? TCG_COND_GTU : TCG_COND_LEU;
        !          1014:         fast_jcc_b:
        !          1015:             tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src);
        !          1016:             switch(size) {
        !          1017:             case 0:
        !          1018:                 t0 = cpu_tmp0;
        !          1019:                 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xff);
        !          1020:                 tcg_gen_andi_tl(t0, cpu_cc_src, 0xff);
        !          1021:                 break;
        !          1022:             case 1:
        !          1023:                 t0 = cpu_tmp0;
        !          1024:                 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffff);
        !          1025:                 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffff);
        !          1026:                 break;
        !          1027: #ifdef TARGET_X86_64
        !          1028:             case 2:
        !          1029:                 t0 = cpu_tmp0;
        !          1030:                 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffffffff);
        !          1031:                 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffffffff);
        !          1032:                 break;
        !          1033: #endif
        !          1034:             default:
        !          1035:                 t0 = cpu_cc_src;
        !          1036:                 break;
        !          1037:             }
        !          1038:             tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1);
        !          1039:             break;
        !          1040:             
        !          1041:         case JCC_L:
        !          1042:             cond = inv ? TCG_COND_GE : TCG_COND_LT;
        !          1043:             goto fast_jcc_l;
        !          1044:         case JCC_LE:
        !          1045:             cond = inv ? TCG_COND_GT : TCG_COND_LE;
        !          1046:         fast_jcc_l:
        !          1047:             tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src);
        !          1048:             switch(size) {
        !          1049:             case 0:
        !          1050:                 t0 = cpu_tmp0;
        !          1051:                 tcg_gen_ext8s_tl(cpu_tmp4, cpu_tmp4);
        !          1052:                 tcg_gen_ext8s_tl(t0, cpu_cc_src);
        !          1053:                 break;
        !          1054:             case 1:
        !          1055:                 t0 = cpu_tmp0;
        !          1056:                 tcg_gen_ext16s_tl(cpu_tmp4, cpu_tmp4);
        !          1057:                 tcg_gen_ext16s_tl(t0, cpu_cc_src);
        !          1058:                 break;
        !          1059: #ifdef TARGET_X86_64
        !          1060:             case 2:
        !          1061:                 t0 = cpu_tmp0;
        !          1062:                 tcg_gen_ext32s_tl(cpu_tmp4, cpu_tmp4);
        !          1063:                 tcg_gen_ext32s_tl(t0, cpu_cc_src);
        !          1064:                 break;
        !          1065: #endif
        !          1066:             default:
        !          1067:                 t0 = cpu_cc_src;
        !          1068:                 break;
        !          1069:             }
        !          1070:             tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1);
        !          1071:             break;
        !          1072:             
        !          1073:         default:
        !          1074:             goto slow_jcc;
        !          1075:         }
        !          1076:         break;
        !          1077:         
        !          1078:         /* some jumps are easy to compute */
        !          1079:     case CC_OP_ADDB:
        !          1080:     case CC_OP_ADDW:
        !          1081:     case CC_OP_ADDL:
        !          1082:     case CC_OP_ADDQ:
        !          1083:         
        !          1084:     case CC_OP_ADCB:
        !          1085:     case CC_OP_ADCW:
        !          1086:     case CC_OP_ADCL:
        !          1087:     case CC_OP_ADCQ:
        !          1088:         
        !          1089:     case CC_OP_SBBB:
        !          1090:     case CC_OP_SBBW:
        !          1091:     case CC_OP_SBBL:
        !          1092:     case CC_OP_SBBQ:
        !          1093:         
        !          1094:     case CC_OP_LOGICB:
        !          1095:     case CC_OP_LOGICW:
        !          1096:     case CC_OP_LOGICL:
        !          1097:     case CC_OP_LOGICQ:
        !          1098:         
        !          1099:     case CC_OP_INCB:
        !          1100:     case CC_OP_INCW:
        !          1101:     case CC_OP_INCL:
        !          1102:     case CC_OP_INCQ:
        !          1103:         
        !          1104:     case CC_OP_DECB:
        !          1105:     case CC_OP_DECW:
        !          1106:     case CC_OP_DECL:
        !          1107:     case CC_OP_DECQ:
        !          1108:         
        !          1109:     case CC_OP_SHLB:
        !          1110:     case CC_OP_SHLW:
        !          1111:     case CC_OP_SHLL:
        !          1112:     case CC_OP_SHLQ:
        !          1113:         
        !          1114:     case CC_OP_SARB:
        !          1115:     case CC_OP_SARW:
        !          1116:     case CC_OP_SARL:
        !          1117:     case CC_OP_SARQ:
        !          1118:         switch(jcc_op) {
        !          1119:         case JCC_Z:
        !          1120:             size = (cc_op - CC_OP_ADDB) & 3;
        !          1121:             goto fast_jcc_z;
        !          1122:         case JCC_S:
        !          1123:             size = (cc_op - CC_OP_ADDB) & 3;
        !          1124:             goto fast_jcc_s;
        !          1125:         default:
        !          1126:             goto slow_jcc;
        !          1127:         }
        !          1128:         break;
        !          1129:     default:
        !          1130:     slow_jcc:
        !          1131:         gen_setcc_slow_T0(s, jcc_op);
        !          1132:         tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, 
        !          1133:                            cpu_T[0], 0, l1);
        !          1134:         break;
        !          1135:     }
        !          1136: }
        !          1137: 
1.1       root     1138: /* XXX: does not work with gdbstub "ice" single step - not a
                   1139:    serious problem */
                   1140: static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
                   1141: {
                   1142:     int l1, l2;
                   1143: 
                   1144:     l1 = gen_new_label();
                   1145:     l2 = gen_new_label();
1.1.1.7 ! root     1146:     gen_op_jnz_ecx(s->aflag, l1);
1.1       root     1147:     gen_set_label(l2);
                   1148:     gen_jmp_tb(s, next_eip, 1);
                   1149:     gen_set_label(l1);
                   1150:     return l2;
                   1151: }
                   1152: 
                   1153: static inline void gen_stos(DisasContext *s, int ot)
                   1154: {
1.1.1.7 ! root     1155:     gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1.1       root     1156:     gen_string_movl_A0_EDI(s);
1.1.1.7 ! root     1157:     gen_op_st_T0_A0(ot + s->mem_index);
        !          1158:     gen_op_movl_T0_Dshift(ot);
        !          1159:     gen_op_add_reg_T0(s->aflag, R_EDI);
1.1       root     1160: }
                   1161: 
                   1162: static inline void gen_lods(DisasContext *s, int ot)
                   1163: {
                   1164:     gen_string_movl_A0_ESI(s);
1.1.1.7 ! root     1165:     gen_op_ld_T0_A0(ot + s->mem_index);
        !          1166:     gen_op_mov_reg_T0(ot, R_EAX);
        !          1167:     gen_op_movl_T0_Dshift(ot);
        !          1168:     gen_op_add_reg_T0(s->aflag, R_ESI);
1.1       root     1169: }
                   1170: 
                   1171: static inline void gen_scas(DisasContext *s, int ot)
                   1172: {
1.1.1.7 ! root     1173:     gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1.1       root     1174:     gen_string_movl_A0_EDI(s);
1.1.1.7 ! root     1175:     gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     1176:     gen_op_cmpl_T0_T1_cc();
1.1.1.7 ! root     1177:     gen_op_movl_T0_Dshift(ot);
        !          1178:     gen_op_add_reg_T0(s->aflag, R_EDI);
1.1       root     1179: }
                   1180: 
                   1181: static inline void gen_cmps(DisasContext *s, int ot)
                   1182: {
                   1183:     gen_string_movl_A0_ESI(s);
1.1.1.7 ! root     1184:     gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     1185:     gen_string_movl_A0_EDI(s);
1.1.1.7 ! root     1186:     gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     1187:     gen_op_cmpl_T0_T1_cc();
1.1.1.7 ! root     1188:     gen_op_movl_T0_Dshift(ot);
        !          1189:     gen_op_add_reg_T0(s->aflag, R_ESI);
        !          1190:     gen_op_add_reg_T0(s->aflag, R_EDI);
1.1       root     1191: }
                   1192: 
                   1193: static inline void gen_ins(DisasContext *s, int ot)
                   1194: {
1.1.1.7 ! root     1195:     if (use_icount)
        !          1196:         gen_io_start();
1.1       root     1197:     gen_string_movl_A0_EDI(s);
1.1.1.7 ! root     1198:     /* Note: we must do this dummy write first to be restartable in
        !          1199:        case of page fault. */
1.1       root     1200:     gen_op_movl_T0_0();
1.1.1.7 ! root     1201:     gen_op_st_T0_A0(ot + s->mem_index);
        !          1202:     gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
        !          1203:     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
        !          1204:     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
        !          1205:     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
        !          1206:     gen_op_st_T0_A0(ot + s->mem_index);
        !          1207:     gen_op_movl_T0_Dshift(ot);
        !          1208:     gen_op_add_reg_T0(s->aflag, R_EDI);
        !          1209:     if (use_icount)
        !          1210:         gen_io_end();
1.1       root     1211: }
                   1212: 
                   1213: static inline void gen_outs(DisasContext *s, int ot)
                   1214: {
1.1.1.7 ! root     1215:     if (use_icount)
        !          1216:         gen_io_start();
1.1       root     1217:     gen_string_movl_A0_ESI(s);
1.1.1.7 ! root     1218:     gen_op_ld_T0_A0(ot + s->mem_index);
        !          1219: 
        !          1220:     gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
        !          1221:     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
        !          1222:     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
        !          1223:     tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
        !          1224:     gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
        !          1225: 
        !          1226:     gen_op_movl_T0_Dshift(ot);
        !          1227:     gen_op_add_reg_T0(s->aflag, R_ESI);
        !          1228:     if (use_icount)
        !          1229:         gen_io_end();
1.1       root     1230: }
                   1231: 
                   1232: /* same method as Valgrind : we generate jumps to current or next
                   1233:    instruction */
                   1234: #define GEN_REPZ(op)                                                          \
                   1235: static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
                   1236:                                  target_ulong cur_eip, target_ulong next_eip) \
                   1237: {                                                                             \
                   1238:     int l2;\
                   1239:     gen_update_cc_op(s);                                                      \
                   1240:     l2 = gen_jz_ecx_string(s, next_eip);                                      \
                   1241:     gen_ ## op(s, ot);                                                        \
1.1.1.7 ! root     1242:     gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
1.1       root     1243:     /* a loop would cause two single step exceptions if ECX = 1               \
                   1244:        before rep string_insn */                                              \
                   1245:     if (!s->jmp_opt)                                                          \
1.1.1.7 ! root     1246:         gen_op_jz_ecx(s->aflag, l2);                                          \
1.1       root     1247:     gen_jmp(s, cur_eip);                                                      \
                   1248: }
                   1249: 
                   1250: #define GEN_REPZ2(op)                                                         \
                   1251: static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
                   1252:                                    target_ulong cur_eip,                      \
                   1253:                                    target_ulong next_eip,                     \
                   1254:                                    int nz)                                    \
                   1255: {                                                                             \
                   1256:     int l2;\
                   1257:     gen_update_cc_op(s);                                                      \
                   1258:     l2 = gen_jz_ecx_string(s, next_eip);                                      \
                   1259:     gen_ ## op(s, ot);                                                        \
1.1.1.7 ! root     1260:     gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
1.1       root     1261:     gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
1.1.1.7 ! root     1262:     gen_jcc1(s, CC_OP_SUBB + ot, (JCC_Z << 1) | (nz ^ 1), l2);                \
1.1       root     1263:     if (!s->jmp_opt)                                                          \
1.1.1.7 ! root     1264:         gen_op_jz_ecx(s->aflag, l2);                                          \
1.1       root     1265:     gen_jmp(s, cur_eip);                                                      \
                   1266: }
                   1267: 
                   1268: GEN_REPZ(movs)
                   1269: GEN_REPZ(stos)
                   1270: GEN_REPZ(lods)
                   1271: GEN_REPZ(ins)
                   1272: GEN_REPZ(outs)
                   1273: GEN_REPZ2(scas)
                   1274: GEN_REPZ2(cmps)
                   1275: 
1.1.1.7 ! root     1276: static void gen_helper_fp_arith_ST0_FT0(int op)
        !          1277: {
        !          1278:     switch (op) {
        !          1279:     case 0: gen_helper_fadd_ST0_FT0(); break;
        !          1280:     case 1: gen_helper_fmul_ST0_FT0(); break;
        !          1281:     case 2: gen_helper_fcom_ST0_FT0(); break;
        !          1282:     case 3: gen_helper_fcom_ST0_FT0(); break;
        !          1283:     case 4: gen_helper_fsub_ST0_FT0(); break;
        !          1284:     case 5: gen_helper_fsubr_ST0_FT0(); break;
        !          1285:     case 6: gen_helper_fdiv_ST0_FT0(); break;
        !          1286:     case 7: gen_helper_fdivr_ST0_FT0(); break;
        !          1287:     }
        !          1288: }
1.1       root     1289: 
                   1290: /* NOTE the exception in "r" op ordering */
1.1.1.7 ! root     1291: static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
        !          1292: {
        !          1293:     TCGv_i32 tmp = tcg_const_i32(opreg);
        !          1294:     switch (op) {
        !          1295:     case 0: gen_helper_fadd_STN_ST0(tmp); break;
        !          1296:     case 1: gen_helper_fmul_STN_ST0(tmp); break;
        !          1297:     case 4: gen_helper_fsubr_STN_ST0(tmp); break;
        !          1298:     case 5: gen_helper_fsub_STN_ST0(tmp); break;
        !          1299:     case 6: gen_helper_fdivr_STN_ST0(tmp); break;
        !          1300:     case 7: gen_helper_fdiv_STN_ST0(tmp); break;
        !          1301:     }
        !          1302: }
1.1       root     1303: 
                   1304: /* if d == OR_TMP0, it means memory operand (address in A0) */
                   1305: static void gen_op(DisasContext *s1, int op, int ot, int d)
                   1306: {
                   1307:     if (d != OR_TMP0) {
1.1.1.7 ! root     1308:         gen_op_mov_TN_reg(ot, 0, d);
1.1       root     1309:     } else {
1.1.1.7 ! root     1310:         gen_op_ld_T0_A0(ot + s1->mem_index);
1.1       root     1311:     }
                   1312:     switch(op) {
                   1313:     case OP_ADCL:
1.1.1.7 ! root     1314:         if (s1->cc_op != CC_OP_DYNAMIC)
        !          1315:             gen_op_set_cc_op(s1->cc_op);
        !          1316:         gen_compute_eflags_c(cpu_tmp4);
        !          1317:         tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1318:         tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
        !          1319:         if (d != OR_TMP0)
        !          1320:             gen_op_mov_reg_T0(ot, d);
        !          1321:         else
        !          1322:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1323:         tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
        !          1324:         tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          1325:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4);
        !          1326:         tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2);
        !          1327:         tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot);
        !          1328:         s1->cc_op = CC_OP_DYNAMIC;
        !          1329:         break;
1.1       root     1330:     case OP_SBBL:
                   1331:         if (s1->cc_op != CC_OP_DYNAMIC)
                   1332:             gen_op_set_cc_op(s1->cc_op);
1.1.1.7 ! root     1333:         gen_compute_eflags_c(cpu_tmp4);
        !          1334:         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1335:         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
        !          1336:         if (d != OR_TMP0)
        !          1337:             gen_op_mov_reg_T0(ot, d);
        !          1338:         else
        !          1339:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1340:         tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
        !          1341:         tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          1342:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4);
        !          1343:         tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2);
        !          1344:         tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot);
1.1       root     1345:         s1->cc_op = CC_OP_DYNAMIC;
1.1.1.7 ! root     1346:         break;
1.1       root     1347:     case OP_ADDL:
                   1348:         gen_op_addl_T0_T1();
1.1.1.7 ! root     1349:         if (d != OR_TMP0)
        !          1350:             gen_op_mov_reg_T0(ot, d);
        !          1351:         else
        !          1352:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1353:         gen_op_update2_cc();
1.1       root     1354:         s1->cc_op = CC_OP_ADDB + ot;
                   1355:         break;
                   1356:     case OP_SUBL:
1.1.1.7 ! root     1357:         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1358:         if (d != OR_TMP0)
        !          1359:             gen_op_mov_reg_T0(ot, d);
        !          1360:         else
        !          1361:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1362:         gen_op_update2_cc();
1.1       root     1363:         s1->cc_op = CC_OP_SUBB + ot;
                   1364:         break;
                   1365:     default:
                   1366:     case OP_ANDL:
1.1.1.7 ! root     1367:         tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1368:         if (d != OR_TMP0)
        !          1369:             gen_op_mov_reg_T0(ot, d);
        !          1370:         else
        !          1371:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1372:         gen_op_update1_cc();
        !          1373:         s1->cc_op = CC_OP_LOGICB + ot;
        !          1374:         break;
1.1       root     1375:     case OP_ORL:
1.1.1.7 ! root     1376:         tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1377:         if (d != OR_TMP0)
        !          1378:             gen_op_mov_reg_T0(ot, d);
        !          1379:         else
        !          1380:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1381:         gen_op_update1_cc();
        !          1382:         s1->cc_op = CC_OP_LOGICB + ot;
        !          1383:         break;
1.1       root     1384:     case OP_XORL:
1.1.1.7 ! root     1385:         tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1386:         if (d != OR_TMP0)
        !          1387:             gen_op_mov_reg_T0(ot, d);
        !          1388:         else
        !          1389:             gen_op_st_T0_A0(ot + s1->mem_index);
        !          1390:         gen_op_update1_cc();
1.1       root     1391:         s1->cc_op = CC_OP_LOGICB + ot;
                   1392:         break;
                   1393:     case OP_CMPL:
                   1394:         gen_op_cmpl_T0_T1_cc();
                   1395:         s1->cc_op = CC_OP_SUBB + ot;
                   1396:         break;
                   1397:     }
1.1.1.7 ! root     1398: }
        !          1399: 
        !          1400: /* if d == OR_TMP0, it means memory operand (address in A0) */
        !          1401: static void gen_inc(DisasContext *s1, int ot, int d, int c)
        !          1402: {
        !          1403:     if (d != OR_TMP0)
        !          1404:         gen_op_mov_TN_reg(ot, 0, d);
        !          1405:     else
        !          1406:         gen_op_ld_T0_A0(ot + s1->mem_index);
        !          1407:     if (s1->cc_op != CC_OP_DYNAMIC)
        !          1408:         gen_op_set_cc_op(s1->cc_op);
        !          1409:     if (c > 0) {
        !          1410:         tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
        !          1411:         s1->cc_op = CC_OP_INCB + ot;
        !          1412:     } else {
        !          1413:         tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
        !          1414:         s1->cc_op = CC_OP_DECB + ot;
        !          1415:     }
        !          1416:     if (d != OR_TMP0)
        !          1417:         gen_op_mov_reg_T0(ot, d);
        !          1418:     else
        !          1419:         gen_op_st_T0_A0(ot + s1->mem_index);
        !          1420:     gen_compute_eflags_c(cpu_cc_src);
        !          1421:     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          1422: }
        !          1423: 
        !          1424: static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, 
        !          1425:                             int is_right, int is_arith)
        !          1426: {
        !          1427:     target_ulong mask;
        !          1428:     int shift_label;
        !          1429:     TCGv t0, t1;
        !          1430: 
        !          1431:     if (ot == OT_QUAD)
        !          1432:         mask = 0x3f;
        !          1433:     else
        !          1434:         mask = 0x1f;
        !          1435: 
        !          1436:     /* load */
        !          1437:     if (op1 == OR_TMP0)
        !          1438:         gen_op_ld_T0_A0(ot + s->mem_index);
        !          1439:     else
        !          1440:         gen_op_mov_TN_reg(ot, 0, op1);
        !          1441: 
        !          1442:     tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
        !          1443: 
        !          1444:     tcg_gen_addi_tl(cpu_tmp5, cpu_T[1], -1);
        !          1445: 
        !          1446:     if (is_right) {
        !          1447:         if (is_arith) {
        !          1448:             gen_exts(ot, cpu_T[0]);
        !          1449:             tcg_gen_sar_tl(cpu_T3, cpu_T[0], cpu_tmp5);
        !          1450:             tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1451:         } else {
        !          1452:             gen_extu(ot, cpu_T[0]);
        !          1453:             tcg_gen_shr_tl(cpu_T3, cpu_T[0], cpu_tmp5);
        !          1454:             tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1455:         }
        !          1456:     } else {
        !          1457:         tcg_gen_shl_tl(cpu_T3, cpu_T[0], cpu_tmp5);
        !          1458:         tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          1459:     }
        !          1460: 
        !          1461:     /* store */
        !          1462:     if (op1 == OR_TMP0)
        !          1463:         gen_op_st_T0_A0(ot + s->mem_index);
        !          1464:     else
        !          1465:         gen_op_mov_reg_T0(ot, op1);
        !          1466:         
        !          1467:     /* update eflags if non zero shift */
        !          1468:     if (s->cc_op != CC_OP_DYNAMIC)
        !          1469:         gen_op_set_cc_op(s->cc_op);
        !          1470: 
        !          1471:     /* XXX: inefficient */
        !          1472:     t0 = tcg_temp_local_new();
        !          1473:     t1 = tcg_temp_local_new();
        !          1474: 
        !          1475:     tcg_gen_mov_tl(t0, cpu_T[0]);
        !          1476:     tcg_gen_mov_tl(t1, cpu_T3);
        !          1477: 
        !          1478:     shift_label = gen_new_label();
        !          1479:     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, shift_label);
        !          1480: 
        !          1481:     tcg_gen_mov_tl(cpu_cc_src, t1);
        !          1482:     tcg_gen_mov_tl(cpu_cc_dst, t0);
        !          1483:     if (is_right)
        !          1484:         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
        !          1485:     else
        !          1486:         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
        !          1487:         
        !          1488:     gen_set_label(shift_label);
        !          1489:     s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
        !          1490: 
        !          1491:     tcg_temp_free(t0);
        !          1492:     tcg_temp_free(t1);
        !          1493: }
        !          1494: 
        !          1495: static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
        !          1496:                             int is_right, int is_arith)
        !          1497: {
        !          1498:     int mask;
        !          1499:     
        !          1500:     if (ot == OT_QUAD)
        !          1501:         mask = 0x3f;
        !          1502:     else
        !          1503:         mask = 0x1f;
        !          1504: 
        !          1505:     /* load */
        !          1506:     if (op1 == OR_TMP0)
        !          1507:         gen_op_ld_T0_A0(ot + s->mem_index);
        !          1508:     else
        !          1509:         gen_op_mov_TN_reg(ot, 0, op1);
        !          1510: 
        !          1511:     op2 &= mask;
        !          1512:     if (op2 != 0) {
        !          1513:         if (is_right) {
        !          1514:             if (is_arith) {
        !          1515:                 gen_exts(ot, cpu_T[0]);
        !          1516:                 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
        !          1517:                 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
        !          1518:             } else {
        !          1519:                 gen_extu(ot, cpu_T[0]);
        !          1520:                 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
        !          1521:                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
        !          1522:             }
        !          1523:         } else {
        !          1524:             tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
        !          1525:             tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
        !          1526:         }
        !          1527:     }
        !          1528: 
        !          1529:     /* store */
        !          1530:     if (op1 == OR_TMP0)
        !          1531:         gen_op_st_T0_A0(ot + s->mem_index);
        !          1532:     else
        !          1533:         gen_op_mov_reg_T0(ot, op1);
        !          1534:         
        !          1535:     /* update eflags if non zero shift */
        !          1536:     if (op2 != 0) {
        !          1537:         tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
        !          1538:         tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          1539:         if (is_right)
        !          1540:             s->cc_op = CC_OP_SARB + ot;
        !          1541:         else
        !          1542:             s->cc_op = CC_OP_SHLB + ot;
        !          1543:     }
        !          1544: }
        !          1545: 
        !          1546: static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
        !          1547: {
        !          1548:     if (arg2 >= 0)
        !          1549:         tcg_gen_shli_tl(ret, arg1, arg2);
        !          1550:     else
        !          1551:         tcg_gen_shri_tl(ret, arg1, -arg2);
        !          1552: }
        !          1553: 
        !          1554: /* XXX: add faster immediate case */
        !          1555: static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, 
        !          1556:                           int is_right)
        !          1557: {
        !          1558:     target_ulong mask;
        !          1559:     int label1, label2, data_bits;
        !          1560:     TCGv t0, t1, t2, a0;
        !          1561: 
        !          1562:     /* XXX: inefficient, but we must use local temps */
        !          1563:     t0 = tcg_temp_local_new();
        !          1564:     t1 = tcg_temp_local_new();
        !          1565:     t2 = tcg_temp_local_new();
        !          1566:     a0 = tcg_temp_local_new();
        !          1567: 
        !          1568:     if (ot == OT_QUAD)
        !          1569:         mask = 0x3f;
        !          1570:     else
        !          1571:         mask = 0x1f;
        !          1572: 
        !          1573:     /* load */
        !          1574:     if (op1 == OR_TMP0) {
        !          1575:         tcg_gen_mov_tl(a0, cpu_A0);
        !          1576:         gen_op_ld_v(ot + s->mem_index, t0, a0);
        !          1577:     } else {
        !          1578:         gen_op_mov_v_reg(ot, t0, op1);
        !          1579:     }
        !          1580: 
        !          1581:     tcg_gen_mov_tl(t1, cpu_T[1]);
        !          1582: 
        !          1583:     tcg_gen_andi_tl(t1, t1, mask);
        !          1584: 
        !          1585:     /* Must test zero case to avoid using undefined behaviour in TCG
        !          1586:        shifts. */
        !          1587:     label1 = gen_new_label();
        !          1588:     tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label1);
        !          1589:     
        !          1590:     if (ot <= OT_WORD)
        !          1591:         tcg_gen_andi_tl(cpu_tmp0, t1, (1 << (3 + ot)) - 1);
        !          1592:     else
        !          1593:         tcg_gen_mov_tl(cpu_tmp0, t1);
        !          1594:     
        !          1595:     gen_extu(ot, t0);
        !          1596:     tcg_gen_mov_tl(t2, t0);
        !          1597: 
        !          1598:     data_bits = 8 << ot;
        !          1599:     /* XXX: rely on behaviour of shifts when operand 2 overflows (XXX:
        !          1600:        fix TCG definition) */
        !          1601:     if (is_right) {
        !          1602:         tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp0);
        !          1603:         tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0);
        !          1604:         tcg_gen_shl_tl(t0, t0, cpu_tmp0);
        !          1605:     } else {
        !          1606:         tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp0);
        !          1607:         tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0);
        !          1608:         tcg_gen_shr_tl(t0, t0, cpu_tmp0);
        !          1609:     }
        !          1610:     tcg_gen_or_tl(t0, t0, cpu_tmp4);
        !          1611: 
        !          1612:     gen_set_label(label1);
        !          1613:     /* store */
        !          1614:     if (op1 == OR_TMP0) {
        !          1615:         gen_op_st_v(ot + s->mem_index, t0, a0);
        !          1616:     } else {
        !          1617:         gen_op_mov_reg_v(ot, op1, t0);
1.1       root     1618:     }
1.1.1.7 ! root     1619:     
        !          1620:     /* update eflags */
        !          1621:     if (s->cc_op != CC_OP_DYNAMIC)
        !          1622:         gen_op_set_cc_op(s->cc_op);
1.1       root     1623: 
1.1.1.7 ! root     1624:     label2 = gen_new_label();
        !          1625:     tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label2);
        !          1626: 
        !          1627:     gen_compute_eflags(cpu_cc_src);
        !          1628:     tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
        !          1629:     tcg_gen_xor_tl(cpu_tmp0, t2, t0);
        !          1630:     tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
        !          1631:     tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
        !          1632:     tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
        !          1633:     if (is_right) {
        !          1634:         tcg_gen_shri_tl(t0, t0, data_bits - 1);
        !          1635:     }
        !          1636:     tcg_gen_andi_tl(t0, t0, CC_C);
        !          1637:     tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
        !          1638:     
        !          1639:     tcg_gen_discard_tl(cpu_cc_dst);
        !          1640:     tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
        !          1641:         
        !          1642:     gen_set_label(label2);
        !          1643:     s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
        !          1644: 
        !          1645:     tcg_temp_free(t0);
        !          1646:     tcg_temp_free(t1);
        !          1647:     tcg_temp_free(t2);
        !          1648:     tcg_temp_free(a0);
        !          1649: }
        !          1650: 
        !          1651: /* XXX: add faster immediate = 1 case */
        !          1652: static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1, 
        !          1653:                            int is_right)
1.1       root     1654: {
1.1.1.7 ! root     1655:     int label1;
        !          1656: 
        !          1657:     if (s->cc_op != CC_OP_DYNAMIC)
        !          1658:         gen_op_set_cc_op(s->cc_op);
        !          1659: 
        !          1660:     /* load */
        !          1661:     if (op1 == OR_TMP0)
        !          1662:         gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     1663:     else
1.1.1.7 ! root     1664:         gen_op_mov_TN_reg(ot, 0, op1);
        !          1665:     
        !          1666:     if (is_right) {
        !          1667:         switch (ot) {
        !          1668:         case 0: gen_helper_rcrb(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1669:         case 1: gen_helper_rcrw(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1670:         case 2: gen_helper_rcrl(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1671: #ifdef TARGET_X86_64
        !          1672:         case 3: gen_helper_rcrq(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1673: #endif
        !          1674:         }
1.1       root     1675:     } else {
1.1.1.7 ! root     1676:         switch (ot) {
        !          1677:         case 0: gen_helper_rclb(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1678:         case 1: gen_helper_rclw(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1679:         case 2: gen_helper_rcll(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1680: #ifdef TARGET_X86_64
        !          1681:         case 3: gen_helper_rclq(cpu_T[0], cpu_T[0], cpu_T[1]); break;
        !          1682: #endif
        !          1683:         }
1.1       root     1684:     }
1.1.1.7 ! root     1685:     /* store */
        !          1686:     if (op1 == OR_TMP0)
        !          1687:         gen_op_st_T0_A0(ot + s->mem_index);
        !          1688:     else
        !          1689:         gen_op_mov_reg_T0(ot, op1);
        !          1690: 
        !          1691:     /* update eflags */
        !          1692:     label1 = gen_new_label();
        !          1693:     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cc_tmp, -1, label1);
        !          1694: 
        !          1695:     tcg_gen_mov_tl(cpu_cc_src, cpu_cc_tmp);
        !          1696:     tcg_gen_discard_tl(cpu_cc_dst);
        !          1697:     tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
        !          1698:         
        !          1699:     gen_set_label(label1);
        !          1700:     s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
        !          1701: }
        !          1702: 
        !          1703: /* XXX: add faster immediate case */
        !          1704: static void gen_shiftd_rm_T1_T3(DisasContext *s, int ot, int op1, 
        !          1705:                                 int is_right)
        !          1706: {
        !          1707:     int label1, label2, data_bits;
        !          1708:     target_ulong mask;
        !          1709:     TCGv t0, t1, t2, a0;
        !          1710: 
        !          1711:     t0 = tcg_temp_local_new();
        !          1712:     t1 = tcg_temp_local_new();
        !          1713:     t2 = tcg_temp_local_new();
        !          1714:     a0 = tcg_temp_local_new();
        !          1715: 
        !          1716:     if (ot == OT_QUAD)
        !          1717:         mask = 0x3f;
1.1       root     1718:     else
1.1.1.7 ! root     1719:         mask = 0x1f;
        !          1720: 
        !          1721:     /* load */
        !          1722:     if (op1 == OR_TMP0) {
        !          1723:         tcg_gen_mov_tl(a0, cpu_A0);
        !          1724:         gen_op_ld_v(ot + s->mem_index, t0, a0);
        !          1725:     } else {
        !          1726:         gen_op_mov_v_reg(ot, t0, op1);
        !          1727:     }
        !          1728: 
        !          1729:     tcg_gen_andi_tl(cpu_T3, cpu_T3, mask);
        !          1730: 
        !          1731:     tcg_gen_mov_tl(t1, cpu_T[1]);
        !          1732:     tcg_gen_mov_tl(t2, cpu_T3);
        !          1733: 
        !          1734:     /* Must test zero case to avoid using undefined behaviour in TCG
        !          1735:        shifts. */
        !          1736:     label1 = gen_new_label();
        !          1737:     tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
        !          1738:     
        !          1739:     tcg_gen_addi_tl(cpu_tmp5, t2, -1);
        !          1740:     if (ot == OT_WORD) {
        !          1741:         /* Note: we implement the Intel behaviour for shift count > 16 */
        !          1742:         if (is_right) {
        !          1743:             tcg_gen_andi_tl(t0, t0, 0xffff);
        !          1744:             tcg_gen_shli_tl(cpu_tmp0, t1, 16);
        !          1745:             tcg_gen_or_tl(t0, t0, cpu_tmp0);
        !          1746:             tcg_gen_ext32u_tl(t0, t0);
        !          1747: 
        !          1748:             tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
        !          1749:             
        !          1750:             /* only needed if count > 16, but a test would complicate */
        !          1751:             tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2);
        !          1752:             tcg_gen_shl_tl(cpu_tmp0, t0, cpu_tmp5);
        !          1753: 
        !          1754:             tcg_gen_shr_tl(t0, t0, t2);
        !          1755: 
        !          1756:             tcg_gen_or_tl(t0, t0, cpu_tmp0);
        !          1757:         } else {
        !          1758:             /* XXX: not optimal */
        !          1759:             tcg_gen_andi_tl(t0, t0, 0xffff);
        !          1760:             tcg_gen_shli_tl(t1, t1, 16);
        !          1761:             tcg_gen_or_tl(t1, t1, t0);
        !          1762:             tcg_gen_ext32u_tl(t1, t1);
        !          1763:             
        !          1764:             tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
        !          1765:             tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(32), cpu_tmp5);
        !          1766:             tcg_gen_shr_tl(cpu_tmp6, t1, cpu_tmp0);
        !          1767:             tcg_gen_or_tl(cpu_tmp4, cpu_tmp4, cpu_tmp6);
        !          1768: 
        !          1769:             tcg_gen_shl_tl(t0, t0, t2);
        !          1770:             tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2);
        !          1771:             tcg_gen_shr_tl(t1, t1, cpu_tmp5);
        !          1772:             tcg_gen_or_tl(t0, t0, t1);
        !          1773:         }
        !          1774:     } else {
        !          1775:         data_bits = 8 << ot;
        !          1776:         if (is_right) {
        !          1777:             if (ot == OT_LONG)
        !          1778:                 tcg_gen_ext32u_tl(t0, t0);
        !          1779: 
        !          1780:             tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
        !          1781: 
        !          1782:             tcg_gen_shr_tl(t0, t0, t2);
        !          1783:             tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2);
        !          1784:             tcg_gen_shl_tl(t1, t1, cpu_tmp5);
        !          1785:             tcg_gen_or_tl(t0, t0, t1);
        !          1786:             
        !          1787:         } else {
        !          1788:             if (ot == OT_LONG)
        !          1789:                 tcg_gen_ext32u_tl(t1, t1);
        !          1790: 
        !          1791:             tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
        !          1792:             
        !          1793:             tcg_gen_shl_tl(t0, t0, t2);
        !          1794:             tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2);
        !          1795:             tcg_gen_shr_tl(t1, t1, cpu_tmp5);
        !          1796:             tcg_gen_or_tl(t0, t0, t1);
        !          1797:         }
        !          1798:     }
        !          1799:     tcg_gen_mov_tl(t1, cpu_tmp4);
        !          1800: 
        !          1801:     gen_set_label(label1);
        !          1802:     /* store */
        !          1803:     if (op1 == OR_TMP0) {
        !          1804:         gen_op_st_v(ot + s->mem_index, t0, a0);
        !          1805:     } else {
        !          1806:         gen_op_mov_reg_v(ot, op1, t0);
        !          1807:     }
        !          1808:     
        !          1809:     /* update eflags */
        !          1810:     if (s->cc_op != CC_OP_DYNAMIC)
        !          1811:         gen_op_set_cc_op(s->cc_op);
        !          1812: 
        !          1813:     label2 = gen_new_label();
        !          1814:     tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label2);
        !          1815: 
        !          1816:     tcg_gen_mov_tl(cpu_cc_src, t1);
        !          1817:     tcg_gen_mov_tl(cpu_cc_dst, t0);
        !          1818:     if (is_right) {
        !          1819:         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
        !          1820:     } else {
        !          1821:         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
        !          1822:     }
        !          1823:     gen_set_label(label2);
        !          1824:     s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
        !          1825: 
        !          1826:     tcg_temp_free(t0);
        !          1827:     tcg_temp_free(t1);
        !          1828:     tcg_temp_free(t2);
        !          1829:     tcg_temp_free(a0);
1.1       root     1830: }
                   1831: 
                   1832: static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
                   1833: {
                   1834:     if (s != OR_TMP1)
1.1.1.7 ! root     1835:         gen_op_mov_TN_reg(ot, 1, s);
        !          1836:     switch(op) {
        !          1837:     case OP_ROL:
        !          1838:         gen_rot_rm_T1(s1, ot, d, 0);
        !          1839:         break;
        !          1840:     case OP_ROR:
        !          1841:         gen_rot_rm_T1(s1, ot, d, 1);
        !          1842:         break;
        !          1843:     case OP_SHL:
        !          1844:     case OP_SHL1:
        !          1845:         gen_shift_rm_T1(s1, ot, d, 0, 0);
        !          1846:         break;
        !          1847:     case OP_SHR:
        !          1848:         gen_shift_rm_T1(s1, ot, d, 1, 0);
        !          1849:         break;
        !          1850:     case OP_SAR:
        !          1851:         gen_shift_rm_T1(s1, ot, d, 1, 1);
        !          1852:         break;
        !          1853:     case OP_RCL:
        !          1854:         gen_rotc_rm_T1(s1, ot, d, 0);
        !          1855:         break;
        !          1856:     case OP_RCR:
        !          1857:         gen_rotc_rm_T1(s1, ot, d, 1);
        !          1858:         break;
        !          1859:     }
1.1       root     1860: }
                   1861: 
                   1862: static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
                   1863: {
1.1.1.7 ! root     1864:     switch(op) {
        !          1865:     case OP_SHL:
        !          1866:     case OP_SHL1:
        !          1867:         gen_shift_rm_im(s1, ot, d, c, 0, 0);
        !          1868:         break;
        !          1869:     case OP_SHR:
        !          1870:         gen_shift_rm_im(s1, ot, d, c, 1, 0);
        !          1871:         break;
        !          1872:     case OP_SAR:
        !          1873:         gen_shift_rm_im(s1, ot, d, c, 1, 1);
        !          1874:         break;
        !          1875:     default:
        !          1876:         /* currently not optimized */
        !          1877:         gen_op_movl_T1_im(c);
        !          1878:         gen_shift(s1, op, ot, d, OR_TMP1);
        !          1879:         break;
        !          1880:     }
1.1       root     1881: }
                   1882: 
                   1883: static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
                   1884: {
                   1885:     target_long disp;
                   1886:     int havesib;
                   1887:     int base;
                   1888:     int index;
                   1889:     int scale;
                   1890:     int opreg;
                   1891:     int mod, rm, code, override, must_add_seg;
                   1892: 
                   1893:     override = s->override;
                   1894:     must_add_seg = s->addseg;
                   1895:     if (override >= 0)
                   1896:         must_add_seg = 1;
                   1897:     mod = (modrm >> 6) & 3;
                   1898:     rm = modrm & 7;
                   1899: 
                   1900:     if (s->aflag) {
                   1901: 
                   1902:         havesib = 0;
                   1903:         base = rm;
                   1904:         index = 0;
                   1905:         scale = 0;
1.1.1.6   root     1906: 
1.1       root     1907:         if (base == 4) {
                   1908:             havesib = 1;
                   1909:             code = ldub_code(s->pc++);
                   1910:             scale = (code >> 6) & 3;
                   1911:             index = ((code >> 3) & 7) | REX_X(s);
                   1912:             base = (code & 7);
                   1913:         }
                   1914:         base |= REX_B(s);
                   1915: 
                   1916:         switch (mod) {
                   1917:         case 0:
                   1918:             if ((base & 7) == 5) {
                   1919:                 base = -1;
                   1920:                 disp = (int32_t)ldl_code(s->pc);
                   1921:                 s->pc += 4;
                   1922:                 if (CODE64(s) && !havesib) {
                   1923:                     disp += s->pc + s->rip_offset;
                   1924:                 }
                   1925:             } else {
                   1926:                 disp = 0;
                   1927:             }
                   1928:             break;
                   1929:         case 1:
                   1930:             disp = (int8_t)ldub_code(s->pc++);
                   1931:             break;
                   1932:         default:
                   1933:         case 2:
                   1934:             disp = ldl_code(s->pc);
                   1935:             s->pc += 4;
                   1936:             break;
                   1937:         }
1.1.1.6   root     1938: 
1.1       root     1939:         if (base >= 0) {
                   1940:             /* for correct popl handling with esp */
                   1941:             if (base == 4 && s->popl_esp_hack)
                   1942:                 disp += s->popl_esp_hack;
                   1943: #ifdef TARGET_X86_64
                   1944:             if (s->aflag == 2) {
1.1.1.7 ! root     1945:                 gen_op_movq_A0_reg(base);
1.1       root     1946:                 if (disp != 0) {
1.1.1.7 ! root     1947:                     gen_op_addq_A0_im(disp);
1.1       root     1948:                 }
1.1.1.6   root     1949:             } else
1.1       root     1950: #endif
                   1951:             {
1.1.1.7 ! root     1952:                 gen_op_movl_A0_reg(base);
1.1       root     1953:                 if (disp != 0)
                   1954:                     gen_op_addl_A0_im(disp);
                   1955:             }
                   1956:         } else {
                   1957: #ifdef TARGET_X86_64
                   1958:             if (s->aflag == 2) {
1.1.1.7 ! root     1959:                 gen_op_movq_A0_im(disp);
1.1.1.6   root     1960:             } else
1.1       root     1961: #endif
                   1962:             {
                   1963:                 gen_op_movl_A0_im(disp);
                   1964:             }
                   1965:         }
                   1966:         /* XXX: index == 4 is always invalid */
                   1967:         if (havesib && (index != 4 || scale != 0)) {
                   1968: #ifdef TARGET_X86_64
                   1969:             if (s->aflag == 2) {
1.1.1.7 ! root     1970:                 gen_op_addq_A0_reg_sN(scale, index);
1.1.1.6   root     1971:             } else
1.1       root     1972: #endif
                   1973:             {
1.1.1.7 ! root     1974:                 gen_op_addl_A0_reg_sN(scale, index);
1.1       root     1975:             }
                   1976:         }
                   1977:         if (must_add_seg) {
                   1978:             if (override < 0) {
                   1979:                 if (base == R_EBP || base == R_ESP)
                   1980:                     override = R_SS;
                   1981:                 else
                   1982:                     override = R_DS;
                   1983:             }
                   1984: #ifdef TARGET_X86_64
                   1985:             if (s->aflag == 2) {
1.1.1.7 ! root     1986:                 gen_op_addq_A0_seg(override);
1.1.1.6   root     1987:             } else
1.1       root     1988: #endif
                   1989:             {
1.1.1.7 ! root     1990:                 gen_op_addl_A0_seg(override);
1.1       root     1991:             }
                   1992:         }
                   1993:     } else {
                   1994:         switch (mod) {
                   1995:         case 0:
                   1996:             if (rm == 6) {
                   1997:                 disp = lduw_code(s->pc);
                   1998:                 s->pc += 2;
                   1999:                 gen_op_movl_A0_im(disp);
                   2000:                 rm = 0; /* avoid SS override */
                   2001:                 goto no_rm;
                   2002:             } else {
                   2003:                 disp = 0;
                   2004:             }
                   2005:             break;
                   2006:         case 1:
                   2007:             disp = (int8_t)ldub_code(s->pc++);
                   2008:             break;
                   2009:         default:
                   2010:         case 2:
                   2011:             disp = lduw_code(s->pc);
                   2012:             s->pc += 2;
                   2013:             break;
                   2014:         }
                   2015:         switch(rm) {
                   2016:         case 0:
1.1.1.7 ! root     2017:             gen_op_movl_A0_reg(R_EBX);
        !          2018:             gen_op_addl_A0_reg_sN(0, R_ESI);
1.1       root     2019:             break;
                   2020:         case 1:
1.1.1.7 ! root     2021:             gen_op_movl_A0_reg(R_EBX);
        !          2022:             gen_op_addl_A0_reg_sN(0, R_EDI);
1.1       root     2023:             break;
                   2024:         case 2:
1.1.1.7 ! root     2025:             gen_op_movl_A0_reg(R_EBP);
        !          2026:             gen_op_addl_A0_reg_sN(0, R_ESI);
1.1       root     2027:             break;
                   2028:         case 3:
1.1.1.7 ! root     2029:             gen_op_movl_A0_reg(R_EBP);
        !          2030:             gen_op_addl_A0_reg_sN(0, R_EDI);
1.1       root     2031:             break;
                   2032:         case 4:
1.1.1.7 ! root     2033:             gen_op_movl_A0_reg(R_ESI);
1.1       root     2034:             break;
                   2035:         case 5:
1.1.1.7 ! root     2036:             gen_op_movl_A0_reg(R_EDI);
1.1       root     2037:             break;
                   2038:         case 6:
1.1.1.7 ! root     2039:             gen_op_movl_A0_reg(R_EBP);
1.1       root     2040:             break;
                   2041:         default:
                   2042:         case 7:
1.1.1.7 ! root     2043:             gen_op_movl_A0_reg(R_EBX);
1.1       root     2044:             break;
                   2045:         }
                   2046:         if (disp != 0)
                   2047:             gen_op_addl_A0_im(disp);
                   2048:         gen_op_andl_A0_ffff();
                   2049:     no_rm:
                   2050:         if (must_add_seg) {
                   2051:             if (override < 0) {
                   2052:                 if (rm == 2 || rm == 3 || rm == 6)
                   2053:                     override = R_SS;
                   2054:                 else
                   2055:                     override = R_DS;
                   2056:             }
1.1.1.7 ! root     2057:             gen_op_addl_A0_seg(override);
1.1       root     2058:         }
                   2059:     }
                   2060: 
                   2061:     opreg = OR_A0;
                   2062:     disp = 0;
                   2063:     *reg_ptr = opreg;
                   2064:     *offset_ptr = disp;
                   2065: }
                   2066: 
1.1.1.5   root     2067: static void gen_nop_modrm(DisasContext *s, int modrm)
                   2068: {
                   2069:     int mod, rm, base, code;
                   2070: 
                   2071:     mod = (modrm >> 6) & 3;
                   2072:     if (mod == 3)
                   2073:         return;
                   2074:     rm = modrm & 7;
                   2075: 
                   2076:     if (s->aflag) {
                   2077: 
                   2078:         base = rm;
1.1.1.6   root     2079: 
1.1.1.5   root     2080:         if (base == 4) {
                   2081:             code = ldub_code(s->pc++);
                   2082:             base = (code & 7);
                   2083:         }
1.1.1.6   root     2084: 
1.1.1.5   root     2085:         switch (mod) {
                   2086:         case 0:
                   2087:             if (base == 5) {
                   2088:                 s->pc += 4;
                   2089:             }
                   2090:             break;
                   2091:         case 1:
                   2092:             s->pc++;
                   2093:             break;
                   2094:         default:
                   2095:         case 2:
                   2096:             s->pc += 4;
                   2097:             break;
                   2098:         }
                   2099:     } else {
                   2100:         switch (mod) {
                   2101:         case 0:
                   2102:             if (rm == 6) {
                   2103:                 s->pc += 2;
                   2104:             }
                   2105:             break;
                   2106:         case 1:
                   2107:             s->pc++;
                   2108:             break;
                   2109:         default:
                   2110:         case 2:
                   2111:             s->pc += 2;
                   2112:             break;
                   2113:         }
                   2114:     }
                   2115: }
                   2116: 
1.1       root     2117: /* used for LEA and MOV AX, mem */
                   2118: static void gen_add_A0_ds_seg(DisasContext *s)
                   2119: {
                   2120:     int override, must_add_seg;
                   2121:     must_add_seg = s->addseg;
                   2122:     override = R_DS;
                   2123:     if (s->override >= 0) {
                   2124:         override = s->override;
                   2125:         must_add_seg = 1;
                   2126:     } else {
                   2127:         override = R_DS;
                   2128:     }
                   2129:     if (must_add_seg) {
                   2130: #ifdef TARGET_X86_64
                   2131:         if (CODE64(s)) {
1.1.1.7 ! root     2132:             gen_op_addq_A0_seg(override);
1.1.1.6   root     2133:         } else
1.1       root     2134: #endif
                   2135:         {
1.1.1.7 ! root     2136:             gen_op_addl_A0_seg(override);
1.1       root     2137:         }
                   2138:     }
                   2139: }
                   2140: 
1.1.1.7 ! root     2141: /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
1.1       root     2142:    OR_TMP0 */
                   2143: static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
                   2144: {
                   2145:     int mod, rm, opreg, disp;
                   2146: 
                   2147:     mod = (modrm >> 6) & 3;
                   2148:     rm = (modrm & 7) | REX_B(s);
                   2149:     if (mod == 3) {
                   2150:         if (is_store) {
                   2151:             if (reg != OR_TMP0)
1.1.1.7 ! root     2152:                 gen_op_mov_TN_reg(ot, 0, reg);
        !          2153:             gen_op_mov_reg_T0(ot, rm);
1.1       root     2154:         } else {
1.1.1.7 ! root     2155:             gen_op_mov_TN_reg(ot, 0, rm);
1.1       root     2156:             if (reg != OR_TMP0)
1.1.1.7 ! root     2157:                 gen_op_mov_reg_T0(ot, reg);
1.1       root     2158:         }
                   2159:     } else {
                   2160:         gen_lea_modrm(s, modrm, &opreg, &disp);
                   2161:         if (is_store) {
                   2162:             if (reg != OR_TMP0)
1.1.1.7 ! root     2163:                 gen_op_mov_TN_reg(ot, 0, reg);
        !          2164:             gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     2165:         } else {
1.1.1.7 ! root     2166:             gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     2167:             if (reg != OR_TMP0)
1.1.1.7 ! root     2168:                 gen_op_mov_reg_T0(ot, reg);
1.1       root     2169:         }
                   2170:     }
                   2171: }
                   2172: 
                   2173: static inline uint32_t insn_get(DisasContext *s, int ot)
                   2174: {
                   2175:     uint32_t ret;
                   2176: 
                   2177:     switch(ot) {
                   2178:     case OT_BYTE:
                   2179:         ret = ldub_code(s->pc);
                   2180:         s->pc++;
                   2181:         break;
                   2182:     case OT_WORD:
                   2183:         ret = lduw_code(s->pc);
                   2184:         s->pc += 2;
                   2185:         break;
                   2186:     default:
                   2187:     case OT_LONG:
                   2188:         ret = ldl_code(s->pc);
                   2189:         s->pc += 4;
                   2190:         break;
                   2191:     }
                   2192:     return ret;
                   2193: }
                   2194: 
                   2195: static inline int insn_const_size(unsigned int ot)
                   2196: {
                   2197:     if (ot <= OT_LONG)
                   2198:         return 1 << ot;
                   2199:     else
                   2200:         return 4;
                   2201: }
                   2202: 
1.1.1.2   root     2203: static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
                   2204: {
                   2205:     TranslationBlock *tb;
                   2206:     target_ulong pc;
                   2207: 
                   2208:     pc = s->cs_base + eip;
                   2209:     tb = s->tb;
                   2210:     /* NOTE: we handle the case where the TB spans two pages here */
                   2211:     if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
                   2212:         (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))  {
                   2213:         /* jump to same page: we can use a direct jump */
1.1.1.7 ! root     2214:         tcg_gen_goto_tb(tb_num);
1.1.1.2   root     2215:         gen_jmp_im(eip);
1.1.1.7 ! root     2216:         tcg_gen_exit_tb((long)tb + tb_num);
1.1.1.2   root     2217:     } else {
                   2218:         /* jump to another page: currently not optimized */
                   2219:         gen_jmp_im(eip);
                   2220:         gen_eob(s);
                   2221:     }
                   2222: }
                   2223: 
1.1.1.6   root     2224: static inline void gen_jcc(DisasContext *s, int b,
1.1       root     2225:                            target_ulong val, target_ulong next_eip)
                   2226: {
1.1.1.7 ! root     2227:     int l1, l2, cc_op;
1.1.1.6   root     2228: 
1.1.1.7 ! root     2229:     cc_op = s->cc_op;
        !          2230:     if (s->cc_op != CC_OP_DYNAMIC) {
        !          2231:         gen_op_set_cc_op(s->cc_op);
        !          2232:         s->cc_op = CC_OP_DYNAMIC;
        !          2233:     }
1.1       root     2234:     if (s->jmp_opt) {
                   2235:         l1 = gen_new_label();
1.1.1.7 ! root     2236:         gen_jcc1(s, cc_op, b, l1);
        !          2237:         
1.1.1.2   root     2238:         gen_goto_tb(s, 0, next_eip);
1.1       root     2239: 
                   2240:         gen_set_label(l1);
1.1.1.2   root     2241:         gen_goto_tb(s, 1, val);
1.1       root     2242:         s->is_jmp = 3;
                   2243:     } else {
                   2244: 
                   2245:         l1 = gen_new_label();
                   2246:         l2 = gen_new_label();
1.1.1.7 ! root     2247:         gen_jcc1(s, cc_op, b, l1);
        !          2248: 
1.1       root     2249:         gen_jmp_im(next_eip);
1.1.1.7 ! root     2250:         tcg_gen_br(l2);
        !          2251: 
1.1       root     2252:         gen_set_label(l1);
                   2253:         gen_jmp_im(val);
                   2254:         gen_set_label(l2);
                   2255:         gen_eob(s);
                   2256:     }
                   2257: }
                   2258: 
                   2259: static void gen_setcc(DisasContext *s, int b)
                   2260: {
1.1.1.7 ! root     2261:     int inv, jcc_op, l1;
        !          2262:     TCGv t0;
1.1.1.6   root     2263: 
1.1.1.7 ! root     2264:     if (is_fast_jcc_case(s, b)) {
        !          2265:         /* nominal case: we use a jump */
        !          2266:         /* XXX: make it faster by adding new instructions in TCG */
        !          2267:         t0 = tcg_temp_local_new();
        !          2268:         tcg_gen_movi_tl(t0, 0);
        !          2269:         l1 = gen_new_label();
        !          2270:         gen_jcc1(s, s->cc_op, b ^ 1, l1);
        !          2271:         tcg_gen_movi_tl(t0, 1);
        !          2272:         gen_set_label(l1);
        !          2273:         tcg_gen_mov_tl(cpu_T[0], t0);
        !          2274:         tcg_temp_free(t0);
        !          2275:     } else {
        !          2276:         /* slow case: it is more efficient not to generate a jump,
        !          2277:            although it is questionnable whether this optimization is
        !          2278:            worth to */
        !          2279:         inv = b & 1;
        !          2280:         jcc_op = (b >> 1) & 7;
        !          2281:         gen_setcc_slow_T0(s, jcc_op);
        !          2282:         if (inv) {
        !          2283:             tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1);
1.1       root     2284:         }
                   2285:     }
                   2286: }
                   2287: 
1.1.1.7 ! root     2288: static inline void gen_op_movl_T0_seg(int seg_reg)
        !          2289: {
        !          2290:     tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
        !          2291:                      offsetof(CPUX86State,segs[seg_reg].selector));
        !          2292: }
        !          2293: 
        !          2294: static inline void gen_op_movl_seg_T0_vm(int seg_reg)
        !          2295: {
        !          2296:     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
        !          2297:     tcg_gen_st32_tl(cpu_T[0], cpu_env, 
        !          2298:                     offsetof(CPUX86State,segs[seg_reg].selector));
        !          2299:     tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
        !          2300:     tcg_gen_st_tl(cpu_T[0], cpu_env, 
        !          2301:                   offsetof(CPUX86State,segs[seg_reg].base));
        !          2302: }
        !          2303: 
1.1       root     2304: /* move T0 to seg_reg and compute if the CPU state may change. Never
                   2305:    call this function with seg_reg == R_CS */
                   2306: static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
                   2307: {
                   2308:     if (s->pe && !s->vm86) {
                   2309:         /* XXX: optimize by finding processor state dynamically */
                   2310:         if (s->cc_op != CC_OP_DYNAMIC)
                   2311:             gen_op_set_cc_op(s->cc_op);
                   2312:         gen_jmp_im(cur_eip);
1.1.1.7 ! root     2313:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          2314:         gen_helper_load_seg(tcg_const_i32(seg_reg), cpu_tmp2_i32);
1.1       root     2315:         /* abort translation because the addseg value may change or
                   2316:            because ss32 may change. For R_SS, translation must always
                   2317:            stop as a special handling must be done to disable hardware
                   2318:            interrupts for the next instruction */
                   2319:         if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
                   2320:             s->is_jmp = 3;
                   2321:     } else {
1.1.1.7 ! root     2322:         gen_op_movl_seg_T0_vm(seg_reg);
1.1       root     2323:         if (seg_reg == R_SS)
                   2324:             s->is_jmp = 3;
                   2325:     }
                   2326: }
                   2327: 
1.1.1.6   root     2328: static inline int svm_is_rep(int prefixes)
                   2329: {
                   2330:     return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
                   2331: }
                   2332: 
1.1.1.7 ! root     2333: static inline void
1.1.1.6   root     2334: gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
1.1.1.7 ! root     2335:                               uint32_t type, uint64_t param)
1.1.1.6   root     2336: {
1.1.1.7 ! root     2337:     /* no SVM activated; fast case */
        !          2338:     if (likely(!(s->flags & HF_SVMI_MASK)))
        !          2339:         return;
        !          2340:     if (s->cc_op != CC_OP_DYNAMIC)
        !          2341:         gen_op_set_cc_op(s->cc_op);
        !          2342:     gen_jmp_im(pc_start - s->cs_base);
        !          2343:     gen_helper_svm_check_intercept_param(tcg_const_i32(type),
        !          2344:                                          tcg_const_i64(param));
1.1.1.6   root     2345: }
                   2346: 
1.1.1.7 ! root     2347: static inline void
1.1.1.6   root     2348: gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
                   2349: {
1.1.1.7 ! root     2350:     gen_svm_check_intercept_param(s, pc_start, type, 0);
1.1.1.6   root     2351: }
                   2352: 
1.1       root     2353: static inline void gen_stack_update(DisasContext *s, int addend)
                   2354: {
                   2355: #ifdef TARGET_X86_64
                   2356:     if (CODE64(s)) {
1.1.1.7 ! root     2357:         gen_op_add_reg_im(2, R_ESP, addend);
1.1       root     2358:     } else
                   2359: #endif
                   2360:     if (s->ss32) {
1.1.1.7 ! root     2361:         gen_op_add_reg_im(1, R_ESP, addend);
1.1       root     2362:     } else {
1.1.1.7 ! root     2363:         gen_op_add_reg_im(0, R_ESP, addend);
1.1       root     2364:     }
                   2365: }
                   2366: 
                   2367: /* generate a push. It depends on ss32, addseg and dflag */
                   2368: static void gen_push_T0(DisasContext *s)
                   2369: {
                   2370: #ifdef TARGET_X86_64
                   2371:     if (CODE64(s)) {
1.1.1.7 ! root     2372:         gen_op_movq_A0_reg(R_ESP);
1.1       root     2373:         if (s->dflag) {
1.1.1.7 ! root     2374:             gen_op_addq_A0_im(-8);
        !          2375:             gen_op_st_T0_A0(OT_QUAD + s->mem_index);
1.1       root     2376:         } else {
1.1.1.7 ! root     2377:             gen_op_addq_A0_im(-2);
        !          2378:             gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     2379:         }
1.1.1.7 ! root     2380:         gen_op_mov_reg_A0(2, R_ESP);
1.1.1.6   root     2381:     } else
1.1       root     2382: #endif
                   2383:     {
1.1.1.7 ! root     2384:         gen_op_movl_A0_reg(R_ESP);
1.1       root     2385:         if (!s->dflag)
1.1.1.7 ! root     2386:             gen_op_addl_A0_im(-2);
1.1       root     2387:         else
1.1.1.7 ! root     2388:             gen_op_addl_A0_im(-4);
1.1       root     2389:         if (s->ss32) {
                   2390:             if (s->addseg) {
1.1.1.7 ! root     2391:                 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
        !          2392:                 gen_op_addl_A0_seg(R_SS);
1.1       root     2393:             }
                   2394:         } else {
                   2395:             gen_op_andl_A0_ffff();
1.1.1.7 ! root     2396:             tcg_gen_mov_tl(cpu_T[1], cpu_A0);
        !          2397:             gen_op_addl_A0_seg(R_SS);
1.1       root     2398:         }
1.1.1.7 ! root     2399:         gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
1.1       root     2400:         if (s->ss32 && !s->addseg)
1.1.1.7 ! root     2401:             gen_op_mov_reg_A0(1, R_ESP);
1.1       root     2402:         else
1.1.1.7 ! root     2403:             gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
1.1       root     2404:     }
                   2405: }
                   2406: 
                   2407: /* generate a push. It depends on ss32, addseg and dflag */
                   2408: /* slower version for T1, only used for call Ev */
                   2409: static void gen_push_T1(DisasContext *s)
                   2410: {
                   2411: #ifdef TARGET_X86_64
                   2412:     if (CODE64(s)) {
1.1.1.7 ! root     2413:         gen_op_movq_A0_reg(R_ESP);
1.1       root     2414:         if (s->dflag) {
1.1.1.7 ! root     2415:             gen_op_addq_A0_im(-8);
        !          2416:             gen_op_st_T1_A0(OT_QUAD + s->mem_index);
1.1       root     2417:         } else {
1.1.1.7 ! root     2418:             gen_op_addq_A0_im(-2);
        !          2419:             gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     2420:         }
1.1.1.7 ! root     2421:         gen_op_mov_reg_A0(2, R_ESP);
1.1.1.6   root     2422:     } else
1.1       root     2423: #endif
                   2424:     {
1.1.1.7 ! root     2425:         gen_op_movl_A0_reg(R_ESP);
1.1       root     2426:         if (!s->dflag)
1.1.1.7 ! root     2427:             gen_op_addl_A0_im(-2);
1.1       root     2428:         else
1.1.1.7 ! root     2429:             gen_op_addl_A0_im(-4);
1.1       root     2430:         if (s->ss32) {
                   2431:             if (s->addseg) {
1.1.1.7 ! root     2432:                 gen_op_addl_A0_seg(R_SS);
1.1       root     2433:             }
                   2434:         } else {
                   2435:             gen_op_andl_A0_ffff();
1.1.1.7 ! root     2436:             gen_op_addl_A0_seg(R_SS);
1.1       root     2437:         }
1.1.1.7 ! root     2438:         gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
1.1.1.6   root     2439: 
1.1       root     2440:         if (s->ss32 && !s->addseg)
1.1.1.7 ! root     2441:             gen_op_mov_reg_A0(1, R_ESP);
1.1       root     2442:         else
                   2443:             gen_stack_update(s, (-2) << s->dflag);
                   2444:     }
                   2445: }
                   2446: 
                   2447: /* two step pop is necessary for precise exceptions */
                   2448: static void gen_pop_T0(DisasContext *s)
                   2449: {
                   2450: #ifdef TARGET_X86_64
                   2451:     if (CODE64(s)) {
1.1.1.7 ! root     2452:         gen_op_movq_A0_reg(R_ESP);
        !          2453:         gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
1.1.1.6   root     2454:     } else
1.1       root     2455: #endif
                   2456:     {
1.1.1.7 ! root     2457:         gen_op_movl_A0_reg(R_ESP);
1.1       root     2458:         if (s->ss32) {
                   2459:             if (s->addseg)
1.1.1.7 ! root     2460:                 gen_op_addl_A0_seg(R_SS);
1.1       root     2461:         } else {
                   2462:             gen_op_andl_A0_ffff();
1.1.1.7 ! root     2463:             gen_op_addl_A0_seg(R_SS);
1.1       root     2464:         }
1.1.1.7 ! root     2465:         gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
1.1       root     2466:     }
                   2467: }
                   2468: 
                   2469: static void gen_pop_update(DisasContext *s)
                   2470: {
                   2471: #ifdef TARGET_X86_64
                   2472:     if (CODE64(s) && s->dflag) {
                   2473:         gen_stack_update(s, 8);
                   2474:     } else
                   2475: #endif
                   2476:     {
                   2477:         gen_stack_update(s, 2 << s->dflag);
                   2478:     }
                   2479: }
                   2480: 
                   2481: static void gen_stack_A0(DisasContext *s)
                   2482: {
1.1.1.7 ! root     2483:     gen_op_movl_A0_reg(R_ESP);
1.1       root     2484:     if (!s->ss32)
                   2485:         gen_op_andl_A0_ffff();
1.1.1.7 ! root     2486:     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1       root     2487:     if (s->addseg)
1.1.1.7 ! root     2488:         gen_op_addl_A0_seg(R_SS);
1.1       root     2489: }
                   2490: 
                   2491: /* NOTE: wrap around in 16 bit not fully handled */
                   2492: static void gen_pusha(DisasContext *s)
                   2493: {
                   2494:     int i;
1.1.1.7 ! root     2495:     gen_op_movl_A0_reg(R_ESP);
1.1       root     2496:     gen_op_addl_A0_im(-16 <<  s->dflag);
                   2497:     if (!s->ss32)
                   2498:         gen_op_andl_A0_ffff();
1.1.1.7 ! root     2499:     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1       root     2500:     if (s->addseg)
1.1.1.7 ! root     2501:         gen_op_addl_A0_seg(R_SS);
1.1       root     2502:     for(i = 0;i < 8; i++) {
1.1.1.7 ! root     2503:         gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
        !          2504:         gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
1.1       root     2505:         gen_op_addl_A0_im(2 <<  s->dflag);
                   2506:     }
1.1.1.7 ! root     2507:     gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1       root     2508: }
                   2509: 
                   2510: /* NOTE: wrap around in 16 bit not fully handled */
                   2511: static void gen_popa(DisasContext *s)
                   2512: {
                   2513:     int i;
1.1.1.7 ! root     2514:     gen_op_movl_A0_reg(R_ESP);
1.1       root     2515:     if (!s->ss32)
                   2516:         gen_op_andl_A0_ffff();
1.1.1.7 ! root     2517:     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
        !          2518:     tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 <<  s->dflag);
1.1       root     2519:     if (s->addseg)
1.1.1.7 ! root     2520:         gen_op_addl_A0_seg(R_SS);
1.1       root     2521:     for(i = 0;i < 8; i++) {
                   2522:         /* ESP is not reloaded */
                   2523:         if (i != 3) {
1.1.1.7 ! root     2524:             gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
        !          2525:             gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
1.1       root     2526:         }
                   2527:         gen_op_addl_A0_im(2 <<  s->dflag);
                   2528:     }
1.1.1.7 ! root     2529:     gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1       root     2530: }
                   2531: 
                   2532: static void gen_enter(DisasContext *s, int esp_addend, int level)
                   2533: {
                   2534:     int ot, opsize;
                   2535: 
                   2536:     level &= 0x1f;
                   2537: #ifdef TARGET_X86_64
                   2538:     if (CODE64(s)) {
                   2539:         ot = s->dflag ? OT_QUAD : OT_WORD;
                   2540:         opsize = 1 << ot;
1.1.1.6   root     2541: 
1.1.1.7 ! root     2542:         gen_op_movl_A0_reg(R_ESP);
1.1       root     2543:         gen_op_addq_A0_im(-opsize);
1.1.1.7 ! root     2544:         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1       root     2545: 
                   2546:         /* push bp */
1.1.1.7 ! root     2547:         gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
        !          2548:         gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     2549:         if (level) {
1.1.1.7 ! root     2550:             /* XXX: must save state */
        !          2551:             gen_helper_enter64_level(tcg_const_i32(level),
        !          2552:                                      tcg_const_i32((ot == OT_QUAD)),
        !          2553:                                      cpu_T[1]);
        !          2554:         }
        !          2555:         gen_op_mov_reg_T1(ot, R_EBP);
        !          2556:         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
        !          2557:         gen_op_mov_reg_T1(OT_QUAD, R_ESP);
1.1.1.6   root     2558:     } else
1.1       root     2559: #endif
                   2560:     {
                   2561:         ot = s->dflag + OT_WORD;
                   2562:         opsize = 2 << s->dflag;
1.1.1.6   root     2563: 
1.1.1.7 ! root     2564:         gen_op_movl_A0_reg(R_ESP);
1.1       root     2565:         gen_op_addl_A0_im(-opsize);
                   2566:         if (!s->ss32)
                   2567:             gen_op_andl_A0_ffff();
1.1.1.7 ! root     2568:         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1       root     2569:         if (s->addseg)
1.1.1.7 ! root     2570:             gen_op_addl_A0_seg(R_SS);
1.1       root     2571:         /* push bp */
1.1.1.7 ! root     2572:         gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
        !          2573:         gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     2574:         if (level) {
1.1.1.7 ! root     2575:             /* XXX: must save state */
        !          2576:             gen_helper_enter_level(tcg_const_i32(level),
        !          2577:                                    tcg_const_i32(s->dflag),
        !          2578:                                    cpu_T[1]);
        !          2579:         }
        !          2580:         gen_op_mov_reg_T1(ot, R_EBP);
        !          2581:         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
        !          2582:         gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1       root     2583:     }
                   2584: }
                   2585: 
                   2586: static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
                   2587: {
                   2588:     if (s->cc_op != CC_OP_DYNAMIC)
                   2589:         gen_op_set_cc_op(s->cc_op);
                   2590:     gen_jmp_im(cur_eip);
1.1.1.7 ! root     2591:     gen_helper_raise_exception(tcg_const_i32(trapno));
1.1       root     2592:     s->is_jmp = 3;
                   2593: }
                   2594: 
                   2595: /* an interrupt is different from an exception because of the
1.1.1.6   root     2596:    privilege checks */
                   2597: static void gen_interrupt(DisasContext *s, int intno,
1.1       root     2598:                           target_ulong cur_eip, target_ulong next_eip)
                   2599: {
                   2600:     if (s->cc_op != CC_OP_DYNAMIC)
                   2601:         gen_op_set_cc_op(s->cc_op);
                   2602:     gen_jmp_im(cur_eip);
1.1.1.7 ! root     2603:     gen_helper_raise_interrupt(tcg_const_i32(intno), 
        !          2604:                                tcg_const_i32(next_eip - cur_eip));
1.1       root     2605:     s->is_jmp = 3;
                   2606: }
                   2607: 
                   2608: static void gen_debug(DisasContext *s, target_ulong cur_eip)
                   2609: {
                   2610:     if (s->cc_op != CC_OP_DYNAMIC)
                   2611:         gen_op_set_cc_op(s->cc_op);
                   2612:     gen_jmp_im(cur_eip);
1.1.1.7 ! root     2613:     gen_helper_debug();
1.1       root     2614:     s->is_jmp = 3;
                   2615: }
                   2616: 
                   2617: /* generate a generic end of block. Trace exception is also generated
                   2618:    if needed */
                   2619: static void gen_eob(DisasContext *s)
                   2620: {
                   2621:     if (s->cc_op != CC_OP_DYNAMIC)
                   2622:         gen_op_set_cc_op(s->cc_op);
                   2623:     if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
1.1.1.7 ! root     2624:         gen_helper_reset_inhibit_irq();
1.1       root     2625:     }
                   2626:     if (s->singlestep_enabled) {
1.1.1.7 ! root     2627:         gen_helper_debug();
1.1       root     2628:     } else if (s->tf) {
1.1.1.7 ! root     2629:        gen_helper_single_step();
1.1       root     2630:     } else {
1.1.1.7 ! root     2631:         tcg_gen_exit_tb(0);
1.1       root     2632:     }
                   2633:     s->is_jmp = 3;
                   2634: }
                   2635: 
                   2636: /* generate a jump to eip. No segment change must happen before as a
                   2637:    direct call to the next block may occur */
                   2638: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
                   2639: {
                   2640:     if (s->jmp_opt) {
1.1.1.2   root     2641:         if (s->cc_op != CC_OP_DYNAMIC) {
1.1       root     2642:             gen_op_set_cc_op(s->cc_op);
1.1.1.2   root     2643:             s->cc_op = CC_OP_DYNAMIC;
                   2644:         }
                   2645:         gen_goto_tb(s, tb_num, eip);
1.1       root     2646:         s->is_jmp = 3;
                   2647:     } else {
                   2648:         gen_jmp_im(eip);
                   2649:         gen_eob(s);
                   2650:     }
                   2651: }
                   2652: 
                   2653: static void gen_jmp(DisasContext *s, target_ulong eip)
                   2654: {
                   2655:     gen_jmp_tb(s, eip, 0);
                   2656: }
                   2657: 
1.1.1.7 ! root     2658: static inline void gen_ldq_env_A0(int idx, int offset)
1.1       root     2659: {
1.1.1.7 ! root     2660:     int mem_index = (idx >> 2) - 1;
        !          2661:     tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
        !          2662:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
1.1       root     2663: }
                   2664: 
1.1.1.7 ! root     2665: static inline void gen_stq_env_A0(int idx, int offset)
1.1       root     2666: {
1.1.1.7 ! root     2667:     int mem_index = (idx >> 2) - 1;
        !          2668:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
        !          2669:     tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
1.1       root     2670: }
                   2671: 
1.1.1.7 ! root     2672: static inline void gen_ldo_env_A0(int idx, int offset)
1.1       root     2673: {
1.1.1.7 ! root     2674:     int mem_index = (idx >> 2) - 1;
        !          2675:     tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
        !          2676:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
        !          2677:     tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
        !          2678:     tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index);
        !          2679:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
1.1       root     2680: }
                   2681: 
1.1.1.7 ! root     2682: static inline void gen_sto_env_A0(int idx, int offset)
        !          2683: {
        !          2684:     int mem_index = (idx >> 2) - 1;
        !          2685:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
        !          2686:     tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
        !          2687:     tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
        !          2688:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
        !          2689:     tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index);
        !          2690: }
1.1       root     2691: 
1.1.1.7 ! root     2692: static inline void gen_op_movo(int d_offset, int s_offset)
        !          2693: {
        !          2694:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
        !          2695:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
        !          2696:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
        !          2697:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
        !          2698: }
1.1       root     2699: 
1.1.1.7 ! root     2700: static inline void gen_op_movq(int d_offset, int s_offset)
        !          2701: {
        !          2702:     tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
        !          2703:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
        !          2704: }
1.1       root     2705: 
1.1.1.7 ! root     2706: static inline void gen_op_movl(int d_offset, int s_offset)
        !          2707: {
        !          2708:     tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
        !          2709:     tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
        !          2710: }
        !          2711: 
        !          2712: static inline void gen_op_movq_env_0(int d_offset)
        !          2713: {
        !          2714:     tcg_gen_movi_i64(cpu_tmp1_i64, 0);
        !          2715:     tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
        !          2716: }
1.1       root     2717: 
1.1.1.7 ! root     2718: #define SSE_SPECIAL ((void *)1)
        !          2719: #define SSE_DUMMY ((void *)2)
1.1       root     2720: 
1.1.1.7 ! root     2721: #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
        !          2722: #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
        !          2723:                      gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
1.1       root     2724: 
1.1.1.7 ! root     2725: static void *sse_op_table1[256][4] = {
        !          2726:     /* 3DNow! extensions */
        !          2727:     [0x0e] = { SSE_DUMMY }, /* femms */
        !          2728:     [0x0f] = { SSE_DUMMY }, /* pf... */
1.1       root     2729:     /* pure SSE operations */
                   2730:     [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
                   2731:     [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
1.1.1.3   root     2732:     [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
1.1       root     2733:     [0x13] = { SSE_SPECIAL, SSE_SPECIAL },  /* movlps, movlpd */
1.1.1.7 ! root     2734:     [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
        !          2735:     [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
1.1       root     2736:     [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd, movshdup */
                   2737:     [0x17] = { SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd */
                   2738: 
                   2739:     [0x28] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
                   2740:     [0x29] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
                   2741:     [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
                   2742:     [0x2b] = { SSE_SPECIAL, SSE_SPECIAL },  /* movntps, movntpd */
                   2743:     [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
                   2744:     [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
1.1.1.7 ! root     2745:     [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
        !          2746:     [0x2f] = { gen_helper_comiss, gen_helper_comisd },
1.1       root     2747:     [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
                   2748:     [0x51] = SSE_FOP(sqrt),
1.1.1.7 ! root     2749:     [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
        !          2750:     [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
        !          2751:     [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
        !          2752:     [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
        !          2753:     [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
        !          2754:     [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
1.1       root     2755:     [0x58] = SSE_FOP(add),
                   2756:     [0x59] = SSE_FOP(mul),
1.1.1.7 ! root     2757:     [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
        !          2758:                gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
        !          2759:     [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
1.1       root     2760:     [0x5c] = SSE_FOP(sub),
                   2761:     [0x5d] = SSE_FOP(min),
                   2762:     [0x5e] = SSE_FOP(div),
                   2763:     [0x5f] = SSE_FOP(max),
                   2764: 
                   2765:     [0xc2] = SSE_FOP(cmpeq),
1.1.1.7 ! root     2766:     [0xc6] = { gen_helper_shufps, gen_helper_shufpd },
        !          2767: 
        !          2768:     [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */
        !          2769:     [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */
1.1       root     2770: 
                   2771:     /* MMX ops and their SSE extensions */
                   2772:     [0x60] = MMX_OP2(punpcklbw),
                   2773:     [0x61] = MMX_OP2(punpcklwd),
                   2774:     [0x62] = MMX_OP2(punpckldq),
                   2775:     [0x63] = MMX_OP2(packsswb),
                   2776:     [0x64] = MMX_OP2(pcmpgtb),
                   2777:     [0x65] = MMX_OP2(pcmpgtw),
                   2778:     [0x66] = MMX_OP2(pcmpgtl),
                   2779:     [0x67] = MMX_OP2(packuswb),
                   2780:     [0x68] = MMX_OP2(punpckhbw),
                   2781:     [0x69] = MMX_OP2(punpckhwd),
                   2782:     [0x6a] = MMX_OP2(punpckhdq),
                   2783:     [0x6b] = MMX_OP2(packssdw),
1.1.1.7 ! root     2784:     [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
        !          2785:     [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
1.1       root     2786:     [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
                   2787:     [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
1.1.1.7 ! root     2788:     [0x70] = { gen_helper_pshufw_mmx,
        !          2789:                gen_helper_pshufd_xmm,
        !          2790:                gen_helper_pshufhw_xmm,
        !          2791:                gen_helper_pshuflw_xmm },
1.1       root     2792:     [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
                   2793:     [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
                   2794:     [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
                   2795:     [0x74] = MMX_OP2(pcmpeqb),
                   2796:     [0x75] = MMX_OP2(pcmpeqw),
                   2797:     [0x76] = MMX_OP2(pcmpeql),
1.1.1.7 ! root     2798:     [0x77] = { SSE_DUMMY }, /* emms */
        !          2799:     [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
        !          2800:     [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
1.1       root     2801:     [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
                   2802:     [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
                   2803:     [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
                   2804:     [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
1.1.1.7 ! root     2805:     [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
1.1       root     2806:     [0xd1] = MMX_OP2(psrlw),
                   2807:     [0xd2] = MMX_OP2(psrld),
                   2808:     [0xd3] = MMX_OP2(psrlq),
                   2809:     [0xd4] = MMX_OP2(paddq),
                   2810:     [0xd5] = MMX_OP2(pmullw),
                   2811:     [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
                   2812:     [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
                   2813:     [0xd8] = MMX_OP2(psubusb),
                   2814:     [0xd9] = MMX_OP2(psubusw),
                   2815:     [0xda] = MMX_OP2(pminub),
                   2816:     [0xdb] = MMX_OP2(pand),
                   2817:     [0xdc] = MMX_OP2(paddusb),
                   2818:     [0xdd] = MMX_OP2(paddusw),
                   2819:     [0xde] = MMX_OP2(pmaxub),
                   2820:     [0xdf] = MMX_OP2(pandn),
                   2821:     [0xe0] = MMX_OP2(pavgb),
                   2822:     [0xe1] = MMX_OP2(psraw),
                   2823:     [0xe2] = MMX_OP2(psrad),
                   2824:     [0xe3] = MMX_OP2(pavgw),
                   2825:     [0xe4] = MMX_OP2(pmulhuw),
                   2826:     [0xe5] = MMX_OP2(pmulhw),
1.1.1.7 ! root     2827:     [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
1.1       root     2828:     [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
                   2829:     [0xe8] = MMX_OP2(psubsb),
                   2830:     [0xe9] = MMX_OP2(psubsw),
                   2831:     [0xea] = MMX_OP2(pminsw),
                   2832:     [0xeb] = MMX_OP2(por),
                   2833:     [0xec] = MMX_OP2(paddsb),
                   2834:     [0xed] = MMX_OP2(paddsw),
                   2835:     [0xee] = MMX_OP2(pmaxsw),
                   2836:     [0xef] = MMX_OP2(pxor),
1.1.1.3   root     2837:     [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
1.1       root     2838:     [0xf1] = MMX_OP2(psllw),
                   2839:     [0xf2] = MMX_OP2(pslld),
                   2840:     [0xf3] = MMX_OP2(psllq),
                   2841:     [0xf4] = MMX_OP2(pmuludq),
                   2842:     [0xf5] = MMX_OP2(pmaddwd),
                   2843:     [0xf6] = MMX_OP2(psadbw),
                   2844:     [0xf7] = MMX_OP2(maskmov),
                   2845:     [0xf8] = MMX_OP2(psubb),
                   2846:     [0xf9] = MMX_OP2(psubw),
                   2847:     [0xfa] = MMX_OP2(psubl),
                   2848:     [0xfb] = MMX_OP2(psubq),
                   2849:     [0xfc] = MMX_OP2(paddb),
                   2850:     [0xfd] = MMX_OP2(paddw),
                   2851:     [0xfe] = MMX_OP2(paddl),
                   2852: };
                   2853: 
1.1.1.7 ! root     2854: static void *sse_op_table2[3 * 8][2] = {
1.1       root     2855:     [0 + 2] = MMX_OP2(psrlw),
                   2856:     [0 + 4] = MMX_OP2(psraw),
                   2857:     [0 + 6] = MMX_OP2(psllw),
                   2858:     [8 + 2] = MMX_OP2(psrld),
                   2859:     [8 + 4] = MMX_OP2(psrad),
                   2860:     [8 + 6] = MMX_OP2(pslld),
                   2861:     [16 + 2] = MMX_OP2(psrlq),
1.1.1.7 ! root     2862:     [16 + 3] = { NULL, gen_helper_psrldq_xmm },
1.1       root     2863:     [16 + 6] = MMX_OP2(psllq),
1.1.1.7 ! root     2864:     [16 + 7] = { NULL, gen_helper_pslldq_xmm },
1.1       root     2865: };
                   2866: 
1.1.1.7 ! root     2867: static void *sse_op_table3[4 * 3] = {
        !          2868:     gen_helper_cvtsi2ss,
        !          2869:     gen_helper_cvtsi2sd,
        !          2870:     X86_64_ONLY(gen_helper_cvtsq2ss),
        !          2871:     X86_64_ONLY(gen_helper_cvtsq2sd),
        !          2872: 
        !          2873:     gen_helper_cvttss2si,
        !          2874:     gen_helper_cvttsd2si,
        !          2875:     X86_64_ONLY(gen_helper_cvttss2sq),
        !          2876:     X86_64_ONLY(gen_helper_cvttsd2sq),
        !          2877: 
        !          2878:     gen_helper_cvtss2si,
        !          2879:     gen_helper_cvtsd2si,
        !          2880:     X86_64_ONLY(gen_helper_cvtss2sq),
        !          2881:     X86_64_ONLY(gen_helper_cvtsd2sq),
1.1       root     2882: };
1.1.1.6   root     2883: 
1.1.1.7 ! root     2884: static void *sse_op_table4[8][4] = {
1.1       root     2885:     SSE_FOP(cmpeq),
                   2886:     SSE_FOP(cmplt),
                   2887:     SSE_FOP(cmple),
                   2888:     SSE_FOP(cmpunord),
                   2889:     SSE_FOP(cmpneq),
                   2890:     SSE_FOP(cmpnlt),
                   2891:     SSE_FOP(cmpnle),
                   2892:     SSE_FOP(cmpord),
                   2893: };
1.1.1.6   root     2894: 
1.1.1.7 ! root     2895: static void *sse_op_table5[256] = {
        !          2896:     [0x0c] = gen_helper_pi2fw,
        !          2897:     [0x0d] = gen_helper_pi2fd,
        !          2898:     [0x1c] = gen_helper_pf2iw,
        !          2899:     [0x1d] = gen_helper_pf2id,
        !          2900:     [0x8a] = gen_helper_pfnacc,
        !          2901:     [0x8e] = gen_helper_pfpnacc,
        !          2902:     [0x90] = gen_helper_pfcmpge,
        !          2903:     [0x94] = gen_helper_pfmin,
        !          2904:     [0x96] = gen_helper_pfrcp,
        !          2905:     [0x97] = gen_helper_pfrsqrt,
        !          2906:     [0x9a] = gen_helper_pfsub,
        !          2907:     [0x9e] = gen_helper_pfadd,
        !          2908:     [0xa0] = gen_helper_pfcmpgt,
        !          2909:     [0xa4] = gen_helper_pfmax,
        !          2910:     [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
        !          2911:     [0xa7] = gen_helper_movq, /* pfrsqit1 */
        !          2912:     [0xaa] = gen_helper_pfsubr,
        !          2913:     [0xae] = gen_helper_pfacc,
        !          2914:     [0xb0] = gen_helper_pfcmpeq,
        !          2915:     [0xb4] = gen_helper_pfmul,
        !          2916:     [0xb6] = gen_helper_movq, /* pfrcpit2 */
        !          2917:     [0xb7] = gen_helper_pmulhrw_mmx,
        !          2918:     [0xbb] = gen_helper_pswapd,
        !          2919:     [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
        !          2920: };
        !          2921: 
        !          2922: struct sse_op_helper_s {
        !          2923:     void *op[2]; uint32_t ext_mask;
        !          2924: };
        !          2925: #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
        !          2926: #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
        !          2927: #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
        !          2928: #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
        !          2929: static struct sse_op_helper_s sse_op_table6[256] = {
        !          2930:     [0x00] = SSSE3_OP(pshufb),
        !          2931:     [0x01] = SSSE3_OP(phaddw),
        !          2932:     [0x02] = SSSE3_OP(phaddd),
        !          2933:     [0x03] = SSSE3_OP(phaddsw),
        !          2934:     [0x04] = SSSE3_OP(pmaddubsw),
        !          2935:     [0x05] = SSSE3_OP(phsubw),
        !          2936:     [0x06] = SSSE3_OP(phsubd),
        !          2937:     [0x07] = SSSE3_OP(phsubsw),
        !          2938:     [0x08] = SSSE3_OP(psignb),
        !          2939:     [0x09] = SSSE3_OP(psignw),
        !          2940:     [0x0a] = SSSE3_OP(psignd),
        !          2941:     [0x0b] = SSSE3_OP(pmulhrsw),
        !          2942:     [0x10] = SSE41_OP(pblendvb),
        !          2943:     [0x14] = SSE41_OP(blendvps),
        !          2944:     [0x15] = SSE41_OP(blendvpd),
        !          2945:     [0x17] = SSE41_OP(ptest),
        !          2946:     [0x1c] = SSSE3_OP(pabsb),
        !          2947:     [0x1d] = SSSE3_OP(pabsw),
        !          2948:     [0x1e] = SSSE3_OP(pabsd),
        !          2949:     [0x20] = SSE41_OP(pmovsxbw),
        !          2950:     [0x21] = SSE41_OP(pmovsxbd),
        !          2951:     [0x22] = SSE41_OP(pmovsxbq),
        !          2952:     [0x23] = SSE41_OP(pmovsxwd),
        !          2953:     [0x24] = SSE41_OP(pmovsxwq),
        !          2954:     [0x25] = SSE41_OP(pmovsxdq),
        !          2955:     [0x28] = SSE41_OP(pmuldq),
        !          2956:     [0x29] = SSE41_OP(pcmpeqq),
        !          2957:     [0x2a] = SSE41_SPECIAL, /* movntqda */
        !          2958:     [0x2b] = SSE41_OP(packusdw),
        !          2959:     [0x30] = SSE41_OP(pmovzxbw),
        !          2960:     [0x31] = SSE41_OP(pmovzxbd),
        !          2961:     [0x32] = SSE41_OP(pmovzxbq),
        !          2962:     [0x33] = SSE41_OP(pmovzxwd),
        !          2963:     [0x34] = SSE41_OP(pmovzxwq),
        !          2964:     [0x35] = SSE41_OP(pmovzxdq),
        !          2965:     [0x37] = SSE42_OP(pcmpgtq),
        !          2966:     [0x38] = SSE41_OP(pminsb),
        !          2967:     [0x39] = SSE41_OP(pminsd),
        !          2968:     [0x3a] = SSE41_OP(pminuw),
        !          2969:     [0x3b] = SSE41_OP(pminud),
        !          2970:     [0x3c] = SSE41_OP(pmaxsb),
        !          2971:     [0x3d] = SSE41_OP(pmaxsd),
        !          2972:     [0x3e] = SSE41_OP(pmaxuw),
        !          2973:     [0x3f] = SSE41_OP(pmaxud),
        !          2974:     [0x40] = SSE41_OP(pmulld),
        !          2975:     [0x41] = SSE41_OP(phminposuw),
        !          2976: };
        !          2977: 
        !          2978: static struct sse_op_helper_s sse_op_table7[256] = {
        !          2979:     [0x08] = SSE41_OP(roundps),
        !          2980:     [0x09] = SSE41_OP(roundpd),
        !          2981:     [0x0a] = SSE41_OP(roundss),
        !          2982:     [0x0b] = SSE41_OP(roundsd),
        !          2983:     [0x0c] = SSE41_OP(blendps),
        !          2984:     [0x0d] = SSE41_OP(blendpd),
        !          2985:     [0x0e] = SSE41_OP(pblendw),
        !          2986:     [0x0f] = SSSE3_OP(palignr),
        !          2987:     [0x14] = SSE41_SPECIAL, /* pextrb */
        !          2988:     [0x15] = SSE41_SPECIAL, /* pextrw */
        !          2989:     [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
        !          2990:     [0x17] = SSE41_SPECIAL, /* extractps */
        !          2991:     [0x20] = SSE41_SPECIAL, /* pinsrb */
        !          2992:     [0x21] = SSE41_SPECIAL, /* insertps */
        !          2993:     [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
        !          2994:     [0x40] = SSE41_OP(dpps),
        !          2995:     [0x41] = SSE41_OP(dppd),
        !          2996:     [0x42] = SSE41_OP(mpsadbw),
        !          2997:     [0x60] = SSE42_OP(pcmpestrm),
        !          2998:     [0x61] = SSE42_OP(pcmpestri),
        !          2999:     [0x62] = SSE42_OP(pcmpistrm),
        !          3000:     [0x63] = SSE42_OP(pcmpistri),
        !          3001: };
        !          3002: 
1.1       root     3003: static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                   3004: {
                   3005:     int b1, op1_offset, op2_offset, is_xmm, val, ot;
                   3006:     int modrm, mod, rm, reg, reg_addr, offset_addr;
1.1.1.7 ! root     3007:     void *sse_op2;
1.1       root     3008: 
                   3009:     b &= 0xff;
1.1.1.6   root     3010:     if (s->prefix & PREFIX_DATA)
1.1       root     3011:         b1 = 1;
1.1.1.6   root     3012:     else if (s->prefix & PREFIX_REPZ)
1.1       root     3013:         b1 = 2;
1.1.1.6   root     3014:     else if (s->prefix & PREFIX_REPNZ)
1.1       root     3015:         b1 = 3;
                   3016:     else
                   3017:         b1 = 0;
                   3018:     sse_op2 = sse_op_table1[b][b1];
1.1.1.6   root     3019:     if (!sse_op2)
1.1       root     3020:         goto illegal_op;
1.1.1.7 ! root     3021:     if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
1.1       root     3022:         is_xmm = 1;
                   3023:     } else {
                   3024:         if (b1 == 0) {
                   3025:             /* MMX case */
                   3026:             is_xmm = 0;
                   3027:         } else {
                   3028:             is_xmm = 1;
                   3029:         }
                   3030:     }
                   3031:     /* simple MMX/SSE operation */
                   3032:     if (s->flags & HF_TS_MASK) {
                   3033:         gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   3034:         return;
                   3035:     }
                   3036:     if (s->flags & HF_EM_MASK) {
                   3037:     illegal_op:
                   3038:         gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
                   3039:         return;
                   3040:     }
                   3041:     if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
1.1.1.7 ! root     3042:         if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
        !          3043:             goto illegal_op;
        !          3044:     if (b == 0x0e) {
        !          3045:         if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
        !          3046:             goto illegal_op;
        !          3047:         /* femms */
        !          3048:         gen_helper_emms();
        !          3049:         return;
        !          3050:     }
1.1       root     3051:     if (b == 0x77) {
                   3052:         /* emms */
1.1.1.7 ! root     3053:         gen_helper_emms();
1.1       root     3054:         return;
                   3055:     }
                   3056:     /* prepare MMX state (XXX: optimize by storing fptt and fptags in
                   3057:        the static cpu state) */
                   3058:     if (!is_xmm) {
1.1.1.7 ! root     3059:         gen_helper_enter_mmx();
1.1       root     3060:     }
                   3061: 
                   3062:     modrm = ldub_code(s->pc++);
                   3063:     reg = ((modrm >> 3) & 7);
                   3064:     if (is_xmm)
                   3065:         reg |= rex_r;
                   3066:     mod = (modrm >> 6) & 3;
                   3067:     if (sse_op2 == SSE_SPECIAL) {
                   3068:         b |= (b1 << 8);
                   3069:         switch(b) {
                   3070:         case 0x0e7: /* movntq */
1.1.1.6   root     3071:             if (mod == 3)
1.1       root     3072:                 goto illegal_op;
                   3073:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3074:             gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1       root     3075:             break;
                   3076:         case 0x1e7: /* movntdq */
                   3077:         case 0x02b: /* movntps */
                   3078:         case 0x12b: /* movntps */
1.1.1.3   root     3079:         case 0x3f0: /* lddqu */
                   3080:             if (mod == 3)
1.1       root     3081:                 goto illegal_op;
                   3082:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3083:             gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1       root     3084:             break;
                   3085:         case 0x6e: /* movd mm, ea */
1.1.1.5   root     3086: #ifdef TARGET_X86_64
                   3087:             if (s->dflag == 2) {
                   3088:                 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
1.1.1.7 ! root     3089:                 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
1.1.1.6   root     3090:             } else
1.1.1.5   root     3091: #endif
                   3092:             {
                   3093:                 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
1.1.1.7 ! root     3094:                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
        !          3095:                                  offsetof(CPUX86State,fpregs[reg].mmx));
        !          3096:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          3097:                 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
1.1.1.5   root     3098:             }
1.1       root     3099:             break;
                   3100:         case 0x16e: /* movd xmm, ea */
1.1.1.5   root     3101: #ifdef TARGET_X86_64
                   3102:             if (s->dflag == 2) {
                   3103:                 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
1.1.1.7 ! root     3104:                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
        !          3105:                                  offsetof(CPUX86State,xmm_regs[reg]));
        !          3106:                 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
1.1.1.6   root     3107:             } else
1.1.1.5   root     3108: #endif
                   3109:             {
                   3110:                 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
1.1.1.7 ! root     3111:                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
        !          3112:                                  offsetof(CPUX86State,xmm_regs[reg]));
        !          3113:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          3114:                 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
1.1.1.5   root     3115:             }
1.1       root     3116:             break;
                   3117:         case 0x6f: /* movq mm, ea */
                   3118:             if (mod != 3) {
                   3119:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3120:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1       root     3121:             } else {
                   3122:                 rm = (modrm & 7);
1.1.1.7 ! root     3123:                 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
        !          3124:                                offsetof(CPUX86State,fpregs[rm].mmx));
        !          3125:                 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
        !          3126:                                offsetof(CPUX86State,fpregs[reg].mmx));
1.1       root     3127:             }
                   3128:             break;
                   3129:         case 0x010: /* movups */
                   3130:         case 0x110: /* movupd */
                   3131:         case 0x028: /* movaps */
                   3132:         case 0x128: /* movapd */
                   3133:         case 0x16f: /* movdqa xmm, ea */
                   3134:         case 0x26f: /* movdqu xmm, ea */
                   3135:             if (mod != 3) {
                   3136:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3137:                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1       root     3138:             } else {
                   3139:                 rm = (modrm & 7) | REX_B(s);
                   3140:                 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
                   3141:                             offsetof(CPUX86State,xmm_regs[rm]));
                   3142:             }
                   3143:             break;
                   3144:         case 0x210: /* movss xmm, ea */
                   3145:             if (mod != 3) {
                   3146:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3147:                 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          3148:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
1.1       root     3149:                 gen_op_movl_T0_0();
1.1.1.7 ! root     3150:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
        !          3151:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
        !          3152:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
1.1       root     3153:             } else {
                   3154:                 rm = (modrm & 7) | REX_B(s);
                   3155:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
                   3156:                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
                   3157:             }
                   3158:             break;
                   3159:         case 0x310: /* movsd xmm, ea */
                   3160:             if (mod != 3) {
                   3161:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3162:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3163:                 gen_op_movl_T0_0();
1.1.1.7 ! root     3164:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
        !          3165:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
1.1       root     3166:             } else {
                   3167:                 rm = (modrm & 7) | REX_B(s);
                   3168:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
                   3169:                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
                   3170:             }
                   3171:             break;
                   3172:         case 0x012: /* movlps */
                   3173:         case 0x112: /* movlpd */
                   3174:             if (mod != 3) {
                   3175:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3176:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3177:             } else {
                   3178:                 /* movhlps */
                   3179:                 rm = (modrm & 7) | REX_B(s);
                   3180:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
                   3181:                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
                   3182:             }
                   3183:             break;
1.1.1.3   root     3184:         case 0x212: /* movsldup */
                   3185:             if (mod != 3) {
                   3186:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3187:                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1.1.3   root     3188:             } else {
                   3189:                 rm = (modrm & 7) | REX_B(s);
                   3190:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
                   3191:                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
                   3192:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
                   3193:                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
                   3194:             }
                   3195:             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
                   3196:                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                   3197:             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
                   3198:                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
                   3199:             break;
                   3200:         case 0x312: /* movddup */
                   3201:             if (mod != 3) {
                   3202:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3203:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1.1.3   root     3204:             } else {
                   3205:                 rm = (modrm & 7) | REX_B(s);
                   3206:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
                   3207:                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
                   3208:             }
                   3209:             gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
                   3210:                         offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
                   3211:             break;
1.1       root     3212:         case 0x016: /* movhps */
                   3213:         case 0x116: /* movhpd */
                   3214:             if (mod != 3) {
                   3215:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3216:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1       root     3217:             } else {
                   3218:                 /* movlhps */
                   3219:                 rm = (modrm & 7) | REX_B(s);
                   3220:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
                   3221:                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
                   3222:             }
                   3223:             break;
                   3224:         case 0x216: /* movshdup */
                   3225:             if (mod != 3) {
                   3226:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3227:                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1       root     3228:             } else {
                   3229:                 rm = (modrm & 7) | REX_B(s);
                   3230:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
                   3231:                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
                   3232:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
                   3233:                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
                   3234:             }
                   3235:             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
                   3236:                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
                   3237:             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
                   3238:                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
                   3239:             break;
                   3240:         case 0x7e: /* movd ea, mm */
1.1.1.5   root     3241: #ifdef TARGET_X86_64
                   3242:             if (s->dflag == 2) {
1.1.1.7 ! root     3243:                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
        !          3244:                                offsetof(CPUX86State,fpregs[reg].mmx));
1.1.1.5   root     3245:                 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6   root     3246:             } else
1.1.1.5   root     3247: #endif
                   3248:             {
1.1.1.7 ! root     3249:                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
        !          3250:                                  offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
1.1.1.5   root     3251:                 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
                   3252:             }
1.1       root     3253:             break;
                   3254:         case 0x17e: /* movd ea, xmm */
1.1.1.5   root     3255: #ifdef TARGET_X86_64
                   3256:             if (s->dflag == 2) {
1.1.1.7 ! root     3257:                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
        !          3258:                                offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1.1.5   root     3259:                 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6   root     3260:             } else
1.1.1.5   root     3261: #endif
                   3262:             {
1.1.1.7 ! root     3263:                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
        !          3264:                                  offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
1.1.1.5   root     3265:                 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
                   3266:             }
1.1       root     3267:             break;
                   3268:         case 0x27e: /* movq xmm, ea */
                   3269:             if (mod != 3) {
                   3270:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3271:                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3272:             } else {
                   3273:                 rm = (modrm & 7) | REX_B(s);
                   3274:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
                   3275:                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
                   3276:             }
                   3277:             gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
                   3278:             break;
                   3279:         case 0x7f: /* movq ea, mm */
                   3280:             if (mod != 3) {
                   3281:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3282:                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1       root     3283:             } else {
                   3284:                 rm = (modrm & 7);
                   3285:                 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
                   3286:                             offsetof(CPUX86State,fpregs[reg].mmx));
                   3287:             }
                   3288:             break;
                   3289:         case 0x011: /* movups */
                   3290:         case 0x111: /* movupd */
                   3291:         case 0x029: /* movaps */
                   3292:         case 0x129: /* movapd */
                   3293:         case 0x17f: /* movdqa ea, xmm */
                   3294:         case 0x27f: /* movdqu ea, xmm */
                   3295:             if (mod != 3) {
                   3296:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3297:                 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1       root     3298:             } else {
                   3299:                 rm = (modrm & 7) | REX_B(s);
                   3300:                 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
                   3301:                             offsetof(CPUX86State,xmm_regs[reg]));
                   3302:             }
                   3303:             break;
                   3304:         case 0x211: /* movss ea, xmm */
                   3305:             if (mod != 3) {
                   3306:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3307:                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
        !          3308:                 gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1       root     3309:             } else {
                   3310:                 rm = (modrm & 7) | REX_B(s);
                   3311:                 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
                   3312:                             offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                   3313:             }
                   3314:             break;
                   3315:         case 0x311: /* movsd ea, xmm */
                   3316:             if (mod != 3) {
                   3317:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3318:                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3319:             } else {
                   3320:                 rm = (modrm & 7) | REX_B(s);
                   3321:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
                   3322:                             offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
                   3323:             }
                   3324:             break;
                   3325:         case 0x013: /* movlps */
                   3326:         case 0x113: /* movlpd */
                   3327:             if (mod != 3) {
                   3328:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3329:                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3330:             } else {
                   3331:                 goto illegal_op;
                   3332:             }
                   3333:             break;
                   3334:         case 0x017: /* movhps */
                   3335:         case 0x117: /* movhpd */
                   3336:             if (mod != 3) {
                   3337:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3338:                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1       root     3339:             } else {
                   3340:                 goto illegal_op;
                   3341:             }
                   3342:             break;
                   3343:         case 0x71: /* shift mm, im */
                   3344:         case 0x72:
                   3345:         case 0x73:
                   3346:         case 0x171: /* shift xmm, im */
                   3347:         case 0x172:
                   3348:         case 0x173:
                   3349:             val = ldub_code(s->pc++);
                   3350:             if (is_xmm) {
                   3351:                 gen_op_movl_T0_im(val);
1.1.1.7 ! root     3352:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1       root     3353:                 gen_op_movl_T0_0();
1.1.1.7 ! root     3354:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
1.1       root     3355:                 op1_offset = offsetof(CPUX86State,xmm_t0);
                   3356:             } else {
                   3357:                 gen_op_movl_T0_im(val);
1.1.1.7 ! root     3358:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
1.1       root     3359:                 gen_op_movl_T0_0();
1.1.1.7 ! root     3360:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
1.1       root     3361:                 op1_offset = offsetof(CPUX86State,mmx_t0);
                   3362:             }
                   3363:             sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
                   3364:             if (!sse_op2)
                   3365:                 goto illegal_op;
                   3366:             if (is_xmm) {
                   3367:                 rm = (modrm & 7) | REX_B(s);
                   3368:                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
                   3369:             } else {
                   3370:                 rm = (modrm & 7);
                   3371:                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                   3372:             }
1.1.1.7 ! root     3373:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
        !          3374:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
        !          3375:             ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
1.1       root     3376:             break;
                   3377:         case 0x050: /* movmskps */
                   3378:             rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     3379:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
        !          3380:                              offsetof(CPUX86State,xmm_regs[rm]));
        !          3381:             gen_helper_movmskps(cpu_tmp2_i32, cpu_ptr0);
        !          3382:             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          3383:             gen_op_mov_reg_T0(OT_LONG, reg);
1.1       root     3384:             break;
                   3385:         case 0x150: /* movmskpd */
                   3386:             rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     3387:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
        !          3388:                              offsetof(CPUX86State,xmm_regs[rm]));
        !          3389:             gen_helper_movmskpd(cpu_tmp2_i32, cpu_ptr0);
        !          3390:             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          3391:             gen_op_mov_reg_T0(OT_LONG, reg);
1.1       root     3392:             break;
                   3393:         case 0x02a: /* cvtpi2ps */
                   3394:         case 0x12a: /* cvtpi2pd */
1.1.1.7 ! root     3395:             gen_helper_enter_mmx();
1.1       root     3396:             if (mod != 3) {
                   3397:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   3398:                 op2_offset = offsetof(CPUX86State,mmx_t0);
1.1.1.7 ! root     3399:                 gen_ldq_env_A0(s->mem_index, op2_offset);
1.1       root     3400:             } else {
                   3401:                 rm = (modrm & 7);
                   3402:                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                   3403:             }
                   3404:             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
1.1.1.7 ! root     3405:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3406:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
1.1       root     3407:             switch(b >> 8) {
                   3408:             case 0x0:
1.1.1.7 ! root     3409:                 gen_helper_cvtpi2ps(cpu_ptr0, cpu_ptr1);
1.1       root     3410:                 break;
                   3411:             default:
                   3412:             case 0x1:
1.1.1.7 ! root     3413:                 gen_helper_cvtpi2pd(cpu_ptr0, cpu_ptr1);
1.1       root     3414:                 break;
                   3415:             }
                   3416:             break;
                   3417:         case 0x22a: /* cvtsi2ss */
                   3418:         case 0x32a: /* cvtsi2sd */
                   3419:             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
                   3420:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
                   3421:             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
1.1.1.7 ! root     3422:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3423:             sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)];
        !          3424:             if (ot == OT_LONG) {
        !          3425:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          3426:                 ((void (*)(TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_tmp2_i32);
        !          3427:             } else {
        !          3428:                 ((void (*)(TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_T[0]);
        !          3429:             }
1.1       root     3430:             break;
                   3431:         case 0x02c: /* cvttps2pi */
                   3432:         case 0x12c: /* cvttpd2pi */
                   3433:         case 0x02d: /* cvtps2pi */
                   3434:         case 0x12d: /* cvtpd2pi */
1.1.1.7 ! root     3435:             gen_helper_enter_mmx();
1.1       root     3436:             if (mod != 3) {
                   3437:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   3438:                 op2_offset = offsetof(CPUX86State,xmm_t0);
1.1.1.7 ! root     3439:                 gen_ldo_env_A0(s->mem_index, op2_offset);
1.1       root     3440:             } else {
                   3441:                 rm = (modrm & 7) | REX_B(s);
                   3442:                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
                   3443:             }
                   3444:             op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
1.1.1.7 ! root     3445:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3446:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
1.1       root     3447:             switch(b) {
                   3448:             case 0x02c:
1.1.1.7 ! root     3449:                 gen_helper_cvttps2pi(cpu_ptr0, cpu_ptr1);
1.1       root     3450:                 break;
                   3451:             case 0x12c:
1.1.1.7 ! root     3452:                 gen_helper_cvttpd2pi(cpu_ptr0, cpu_ptr1);
1.1       root     3453:                 break;
                   3454:             case 0x02d:
1.1.1.7 ! root     3455:                 gen_helper_cvtps2pi(cpu_ptr0, cpu_ptr1);
1.1       root     3456:                 break;
                   3457:             case 0x12d:
1.1.1.7 ! root     3458:                 gen_helper_cvtpd2pi(cpu_ptr0, cpu_ptr1);
1.1       root     3459:                 break;
                   3460:             }
                   3461:             break;
                   3462:         case 0x22c: /* cvttss2si */
                   3463:         case 0x32c: /* cvttsd2si */
                   3464:         case 0x22d: /* cvtss2si */
                   3465:         case 0x32d: /* cvtsd2si */
                   3466:             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
                   3467:             if (mod != 3) {
                   3468:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   3469:                 if ((b >> 8) & 1) {
1.1.1.7 ! root     3470:                     gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
1.1       root     3471:                 } else {
1.1.1.7 ! root     3472:                     gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          3473:                     tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1       root     3474:                 }
                   3475:                 op2_offset = offsetof(CPUX86State,xmm_t0);
                   3476:             } else {
                   3477:                 rm = (modrm & 7) | REX_B(s);
                   3478:                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
                   3479:             }
1.1.1.7 ! root     3480:             sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
        !          3481:                                     (b & 1) * 4];
        !          3482:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
        !          3483:             if (ot == OT_LONG) {
        !          3484:                 ((void (*)(TCGv_i32, TCGv_ptr))sse_op2)(cpu_tmp2_i32, cpu_ptr0);
        !          3485:                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          3486:             } else {
        !          3487:                 ((void (*)(TCGv, TCGv_ptr))sse_op2)(cpu_T[0], cpu_ptr0);
        !          3488:             }
        !          3489:             gen_op_mov_reg_T0(ot, reg);
1.1       root     3490:             break;
                   3491:         case 0xc4: /* pinsrw */
1.1.1.6   root     3492:         case 0x1c4:
1.1.1.4   root     3493:             s->rip_offset = 1;
1.1       root     3494:             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                   3495:             val = ldub_code(s->pc++);
                   3496:             if (b1) {
                   3497:                 val &= 7;
1.1.1.7 ! root     3498:                 tcg_gen_st16_tl(cpu_T[0], cpu_env,
        !          3499:                                 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
1.1       root     3500:             } else {
                   3501:                 val &= 3;
1.1.1.7 ! root     3502:                 tcg_gen_st16_tl(cpu_T[0], cpu_env,
        !          3503:                                 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
1.1       root     3504:             }
                   3505:             break;
                   3506:         case 0xc5: /* pextrw */
1.1.1.6   root     3507:         case 0x1c5:
1.1       root     3508:             if (mod != 3)
                   3509:                 goto illegal_op;
1.1.1.7 ! root     3510:             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
1.1       root     3511:             val = ldub_code(s->pc++);
                   3512:             if (b1) {
                   3513:                 val &= 7;
                   3514:                 rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     3515:                 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
        !          3516:                                  offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
1.1       root     3517:             } else {
                   3518:                 val &= 3;
                   3519:                 rm = (modrm & 7);
1.1.1.7 ! root     3520:                 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
        !          3521:                                 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
1.1       root     3522:             }
                   3523:             reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.7 ! root     3524:             gen_op_mov_reg_T0(ot, reg);
1.1       root     3525:             break;
                   3526:         case 0x1d6: /* movq ea, xmm */
                   3527:             if (mod != 3) {
                   3528:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     3529:                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1       root     3530:             } else {
                   3531:                 rm = (modrm & 7) | REX_B(s);
                   3532:                 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
                   3533:                             offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
                   3534:                 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
                   3535:             }
                   3536:             break;
                   3537:         case 0x2d6: /* movq2dq */
1.1.1.7 ! root     3538:             gen_helper_enter_mmx();
1.1.1.4   root     3539:             rm = (modrm & 7);
                   3540:             gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
                   3541:                         offsetof(CPUX86State,fpregs[rm].mmx));
                   3542:             gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1       root     3543:             break;
                   3544:         case 0x3d6: /* movdq2q */
1.1.1.7 ! root     3545:             gen_helper_enter_mmx();
1.1.1.4   root     3546:             rm = (modrm & 7) | REX_B(s);
                   3547:             gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
                   3548:                         offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
1.1       root     3549:             break;
                   3550:         case 0xd7: /* pmovmskb */
                   3551:         case 0x1d7:
                   3552:             if (mod != 3)
                   3553:                 goto illegal_op;
                   3554:             if (b1) {
                   3555:                 rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     3556:                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
        !          3557:                 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_ptr0);
1.1       root     3558:             } else {
                   3559:                 rm = (modrm & 7);
1.1.1.7 ! root     3560:                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
        !          3561:                 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_ptr0);
        !          3562:             }
        !          3563:             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          3564:             reg = ((modrm >> 3) & 7) | rex_r;
        !          3565:             gen_op_mov_reg_T0(OT_LONG, reg);
        !          3566:             break;
        !          3567:         case 0x138:
        !          3568:             if (s->prefix & PREFIX_REPNZ)
        !          3569:                 goto crc32;
        !          3570:         case 0x038:
        !          3571:             b = modrm;
        !          3572:             modrm = ldub_code(s->pc++);
        !          3573:             rm = modrm & 7;
        !          3574:             reg = ((modrm >> 3) & 7) | rex_r;
        !          3575:             mod = (modrm >> 6) & 3;
        !          3576: 
        !          3577:             sse_op2 = sse_op_table6[b].op[b1];
        !          3578:             if (!sse_op2)
        !          3579:                 goto illegal_op;
        !          3580:             if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
        !          3581:                 goto illegal_op;
        !          3582: 
        !          3583:             if (b1) {
        !          3584:                 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
        !          3585:                 if (mod == 3) {
        !          3586:                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
        !          3587:                 } else {
        !          3588:                     op2_offset = offsetof(CPUX86State,xmm_t0);
        !          3589:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          3590:                     switch (b) {
        !          3591:                     case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
        !          3592:                     case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
        !          3593:                     case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
        !          3594:                         gen_ldq_env_A0(s->mem_index, op2_offset +
        !          3595:                                         offsetof(XMMReg, XMM_Q(0)));
        !          3596:                         break;
        !          3597:                     case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
        !          3598:                     case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
        !          3599:                         tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
        !          3600:                                           (s->mem_index >> 2) - 1);
        !          3601:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
        !          3602:                         tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
        !          3603:                                         offsetof(XMMReg, XMM_L(0)));
        !          3604:                         break;
        !          3605:                     case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
        !          3606:                         tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
        !          3607:                                           (s->mem_index >> 2) - 1);
        !          3608:                         tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
        !          3609:                                         offsetof(XMMReg, XMM_W(0)));
        !          3610:                         break;
        !          3611:                     case 0x2a:            /* movntqda */
        !          3612:                         gen_ldo_env_A0(s->mem_index, op1_offset);
        !          3613:                         return;
        !          3614:                     default:
        !          3615:                         gen_ldo_env_A0(s->mem_index, op2_offset);
        !          3616:                     }
        !          3617:                 }
        !          3618:             } else {
        !          3619:                 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
        !          3620:                 if (mod == 3) {
        !          3621:                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
        !          3622:                 } else {
        !          3623:                     op2_offset = offsetof(CPUX86State,mmx_t0);
        !          3624:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          3625:                     gen_ldq_env_A0(s->mem_index, op2_offset);
        !          3626:                 }
1.1       root     3627:             }
1.1.1.7 ! root     3628:             if (sse_op2 == SSE_SPECIAL)
        !          3629:                 goto illegal_op;
        !          3630: 
        !          3631:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3632:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3633:             ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
        !          3634: 
        !          3635:             if (b == 0x17)
        !          3636:                 s->cc_op = CC_OP_EFLAGS;
        !          3637:             break;
        !          3638:         case 0x338: /* crc32 */
        !          3639:         crc32:
        !          3640:             b = modrm;
        !          3641:             modrm = ldub_code(s->pc++);
        !          3642:             reg = ((modrm >> 3) & 7) | rex_r;
        !          3643: 
        !          3644:             if (b != 0xf0 && b != 0xf1)
        !          3645:                 goto illegal_op;
        !          3646:             if (!(s->cpuid_ext_features & CPUID_EXT_SSE42))
        !          3647:                 goto illegal_op;
        !          3648: 
        !          3649:             if (b == 0xf0)
        !          3650:                 ot = OT_BYTE;
        !          3651:             else if (b == 0xf1 && s->dflag != 2)
        !          3652:                 if (s->prefix & PREFIX_DATA)
        !          3653:                     ot = OT_WORD;
        !          3654:                 else
        !          3655:                     ot = OT_LONG;
        !          3656:             else
        !          3657:                 ot = OT_QUAD;
        !          3658: 
        !          3659:             gen_op_mov_TN_reg(OT_LONG, 0, reg);
        !          3660:             tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          3661:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
        !          3662:             gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
        !          3663:                              cpu_T[0], tcg_const_i32(8 << ot));
        !          3664: 
        !          3665:             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
        !          3666:             gen_op_mov_reg_T0(ot, reg);
        !          3667:             break;
        !          3668:         case 0x03a:
        !          3669:         case 0x13a:
        !          3670:             b = modrm;
        !          3671:             modrm = ldub_code(s->pc++);
        !          3672:             rm = modrm & 7;
1.1       root     3673:             reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.7 ! root     3674:             mod = (modrm >> 6) & 3;
        !          3675: 
        !          3676:             sse_op2 = sse_op_table7[b].op[b1];
        !          3677:             if (!sse_op2)
        !          3678:                 goto illegal_op;
        !          3679:             if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
        !          3680:                 goto illegal_op;
        !          3681: 
        !          3682:             if (sse_op2 == SSE_SPECIAL) {
        !          3683:                 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
        !          3684:                 rm = (modrm & 7) | REX_B(s);
        !          3685:                 if (mod != 3)
        !          3686:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          3687:                 reg = ((modrm >> 3) & 7) | rex_r;
        !          3688:                 val = ldub_code(s->pc++);
        !          3689:                 switch (b) {
        !          3690:                 case 0x14: /* pextrb */
        !          3691:                     tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
        !          3692:                                             xmm_regs[reg].XMM_B(val & 15)));
        !          3693:                     if (mod == 3)
        !          3694:                         gen_op_mov_reg_T0(ot, rm);
        !          3695:                     else
        !          3696:                         tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
        !          3697:                                         (s->mem_index >> 2) - 1);
        !          3698:                     break;
        !          3699:                 case 0x15: /* pextrw */
        !          3700:                     tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
        !          3701:                                             xmm_regs[reg].XMM_W(val & 7)));
        !          3702:                     if (mod == 3)
        !          3703:                         gen_op_mov_reg_T0(ot, rm);
        !          3704:                     else
        !          3705:                         tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
        !          3706:                                         (s->mem_index >> 2) - 1);
        !          3707:                     break;
        !          3708:                 case 0x16:
        !          3709:                     if (ot == OT_LONG) { /* pextrd */
        !          3710:                         tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
        !          3711:                                         offsetof(CPUX86State,
        !          3712:                                                 xmm_regs[reg].XMM_L(val & 3)));
        !          3713:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          3714:                         if (mod == 3)
        !          3715:                             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
        !          3716:                         else
        !          3717:                             tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
        !          3718:                                             (s->mem_index >> 2) - 1);
        !          3719:                     } else { /* pextrq */
        !          3720: #ifdef TARGET_X86_64
        !          3721:                         tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
        !          3722:                                         offsetof(CPUX86State,
        !          3723:                                                 xmm_regs[reg].XMM_Q(val & 1)));
        !          3724:                         if (mod == 3)
        !          3725:                             gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
        !          3726:                         else
        !          3727:                             tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
        !          3728:                                             (s->mem_index >> 2) - 1);
        !          3729: #else
        !          3730:                         goto illegal_op;
        !          3731: #endif
        !          3732:                     }
        !          3733:                     break;
        !          3734:                 case 0x17: /* extractps */
        !          3735:                     tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
        !          3736:                                             xmm_regs[reg].XMM_L(val & 3)));
        !          3737:                     if (mod == 3)
        !          3738:                         gen_op_mov_reg_T0(ot, rm);
        !          3739:                     else
        !          3740:                         tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
        !          3741:                                         (s->mem_index >> 2) - 1);
        !          3742:                     break;
        !          3743:                 case 0x20: /* pinsrb */
        !          3744:                     if (mod == 3)
        !          3745:                         gen_op_mov_TN_reg(OT_LONG, 0, rm);
        !          3746:                     else
        !          3747:                         tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
        !          3748:                                         (s->mem_index >> 2) - 1);
        !          3749:                     tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
        !          3750:                                             xmm_regs[reg].XMM_B(val & 15)));
        !          3751:                     break;
        !          3752:                 case 0x21: /* insertps */
        !          3753:                     if (mod == 3) {
        !          3754:                         tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
        !          3755:                                         offsetof(CPUX86State,xmm_regs[rm]
        !          3756:                                                 .XMM_L((val >> 6) & 3)));
        !          3757:                     } else {
        !          3758:                         tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
        !          3759:                                         (s->mem_index >> 2) - 1);
        !          3760:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
        !          3761:                     }
        !          3762:                     tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
        !          3763:                                     offsetof(CPUX86State,xmm_regs[reg]
        !          3764:                                             .XMM_L((val >> 4) & 3)));
        !          3765:                     if ((val >> 0) & 1)
        !          3766:                         tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
        !          3767:                                         cpu_env, offsetof(CPUX86State,
        !          3768:                                                 xmm_regs[reg].XMM_L(0)));
        !          3769:                     if ((val >> 1) & 1)
        !          3770:                         tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
        !          3771:                                         cpu_env, offsetof(CPUX86State,
        !          3772:                                                 xmm_regs[reg].XMM_L(1)));
        !          3773:                     if ((val >> 2) & 1)
        !          3774:                         tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
        !          3775:                                         cpu_env, offsetof(CPUX86State,
        !          3776:                                                 xmm_regs[reg].XMM_L(2)));
        !          3777:                     if ((val >> 3) & 1)
        !          3778:                         tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
        !          3779:                                         cpu_env, offsetof(CPUX86State,
        !          3780:                                                 xmm_regs[reg].XMM_L(3)));
        !          3781:                     break;
        !          3782:                 case 0x22:
        !          3783:                     if (ot == OT_LONG) { /* pinsrd */
        !          3784:                         if (mod == 3)
        !          3785:                             gen_op_mov_v_reg(ot, cpu_tmp0, rm);
        !          3786:                         else
        !          3787:                             tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
        !          3788:                                             (s->mem_index >> 2) - 1);
        !          3789:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
        !          3790:                         tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
        !          3791:                                         offsetof(CPUX86State,
        !          3792:                                                 xmm_regs[reg].XMM_L(val & 3)));
        !          3793:                     } else { /* pinsrq */
        !          3794: #ifdef TARGET_X86_64
        !          3795:                         if (mod == 3)
        !          3796:                             gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
        !          3797:                         else
        !          3798:                             tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
        !          3799:                                             (s->mem_index >> 2) - 1);
        !          3800:                         tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
        !          3801:                                         offsetof(CPUX86State,
        !          3802:                                                 xmm_regs[reg].XMM_Q(val & 1)));
        !          3803: #else
        !          3804:                         goto illegal_op;
        !          3805: #endif
        !          3806:                     }
        !          3807:                     break;
        !          3808:                 }
        !          3809:                 return;
        !          3810:             }
        !          3811: 
        !          3812:             if (b1) {
        !          3813:                 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
        !          3814:                 if (mod == 3) {
        !          3815:                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
        !          3816:                 } else {
        !          3817:                     op2_offset = offsetof(CPUX86State,xmm_t0);
        !          3818:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          3819:                     gen_ldo_env_A0(s->mem_index, op2_offset);
        !          3820:                 }
        !          3821:             } else {
        !          3822:                 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
        !          3823:                 if (mod == 3) {
        !          3824:                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
        !          3825:                 } else {
        !          3826:                     op2_offset = offsetof(CPUX86State,mmx_t0);
        !          3827:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          3828:                     gen_ldq_env_A0(s->mem_index, op2_offset);
        !          3829:                 }
        !          3830:             }
        !          3831:             val = ldub_code(s->pc++);
        !          3832: 
        !          3833:             if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
        !          3834:                 s->cc_op = CC_OP_EFLAGS;
        !          3835: 
        !          3836:                 if (s->dflag == 2)
        !          3837:                     /* The helper must use entire 64-bit gp registers */
        !          3838:                     val |= 1 << 8;
        !          3839:             }
        !          3840: 
        !          3841:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3842:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3843:             ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
1.1       root     3844:             break;
                   3845:         default:
                   3846:             goto illegal_op;
                   3847:         }
                   3848:     } else {
                   3849:         /* generic MMX or SSE operation */
1.1.1.4   root     3850:         switch(b) {
                   3851:         case 0x70: /* pshufx insn */
                   3852:         case 0xc6: /* pshufx insn */
                   3853:         case 0xc2: /* compare insns */
                   3854:             s->rip_offset = 1;
                   3855:             break;
                   3856:         default:
                   3857:             break;
1.1       root     3858:         }
                   3859:         if (is_xmm) {
                   3860:             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
                   3861:             if (mod != 3) {
                   3862:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   3863:                 op2_offset = offsetof(CPUX86State,xmm_t0);
1.1.1.4   root     3864:                 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
1.1       root     3865:                                 b == 0xc2)) {
                   3866:                     /* specific case for SSE single instructions */
                   3867:                     if (b1 == 2) {
                   3868:                         /* 32 bit access */
1.1.1.7 ! root     3869:                         gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          3870:                         tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1       root     3871:                     } else {
                   3872:                         /* 64 bit access */
1.1.1.7 ! root     3873:                         gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
1.1       root     3874:                     }
                   3875:                 } else {
1.1.1.7 ! root     3876:                     gen_ldo_env_A0(s->mem_index, op2_offset);
1.1       root     3877:                 }
                   3878:             } else {
                   3879:                 rm = (modrm & 7) | REX_B(s);
                   3880:                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
                   3881:             }
                   3882:         } else {
                   3883:             op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
                   3884:             if (mod != 3) {
                   3885:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   3886:                 op2_offset = offsetof(CPUX86State,mmx_t0);
1.1.1.7 ! root     3887:                 gen_ldq_env_A0(s->mem_index, op2_offset);
1.1       root     3888:             } else {
                   3889:                 rm = (modrm & 7);
                   3890:                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                   3891:             }
                   3892:         }
                   3893:         switch(b) {
1.1.1.7 ! root     3894:         case 0x0f: /* 3DNow! data insns */
        !          3895:             if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
        !          3896:                 goto illegal_op;
        !          3897:             val = ldub_code(s->pc++);
        !          3898:             sse_op2 = sse_op_table5[val];
        !          3899:             if (!sse_op2)
        !          3900:                 goto illegal_op;
        !          3901:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3902:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3903:             ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
        !          3904:             break;
1.1       root     3905:         case 0x70: /* pshufx insn */
                   3906:         case 0xc6: /* pshufx insn */
                   3907:             val = ldub_code(s->pc++);
1.1.1.7 ! root     3908:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3909:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3910:             ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
1.1       root     3911:             break;
                   3912:         case 0xc2:
                   3913:             /* compare insns */
                   3914:             val = ldub_code(s->pc++);
                   3915:             if (val >= 8)
                   3916:                 goto illegal_op;
                   3917:             sse_op2 = sse_op_table4[val][b1];
1.1.1.7 ! root     3918:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3919:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3920:             ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
        !          3921:             break;
        !          3922:         case 0xf7:
        !          3923:             /* maskmov : we must prepare A0 */
        !          3924:             if (mod != 3)
        !          3925:                 goto illegal_op;
        !          3926: #ifdef TARGET_X86_64
        !          3927:             if (s->aflag == 2) {
        !          3928:                 gen_op_movq_A0_reg(R_EDI);
        !          3929:             } else
        !          3930: #endif
        !          3931:             {
        !          3932:                 gen_op_movl_A0_reg(R_EDI);
        !          3933:                 if (s->aflag == 0)
        !          3934:                     gen_op_andl_A0_ffff();
        !          3935:             }
        !          3936:             gen_add_A0_ds_seg(s);
        !          3937: 
        !          3938:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3939:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3940:             ((void (*)(TCGv_ptr, TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_ptr1, cpu_A0);
1.1       root     3941:             break;
                   3942:         default:
1.1.1.7 ! root     3943:             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
        !          3944:             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
        !          3945:             ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
1.1       root     3946:             break;
                   3947:         }
                   3948:         if (b == 0x2e || b == 0x2f) {
                   3949:             s->cc_op = CC_OP_EFLAGS;
                   3950:         }
                   3951:     }
                   3952: }
                   3953: 
                   3954: /* convert one instruction. s->is_jmp is set if the translation must
                   3955:    be stopped. Return the next pc value */
                   3956: static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                   3957: {
                   3958:     int b, prefixes, aflag, dflag;
                   3959:     int shift, ot;
                   3960:     int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
                   3961:     target_ulong next_eip, tval;
                   3962:     int rex_w, rex_r;
                   3963: 
1.1.1.7 ! root     3964:     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
        !          3965:         tcg_gen_debug_insn_start(pc_start);
1.1       root     3966:     s->pc = pc_start;
                   3967:     prefixes = 0;
                   3968:     aflag = s->code32;
                   3969:     dflag = s->code32;
                   3970:     s->override = -1;
                   3971:     rex_w = -1;
                   3972:     rex_r = 0;
                   3973: #ifdef TARGET_X86_64
                   3974:     s->rex_x = 0;
                   3975:     s->rex_b = 0;
1.1.1.6   root     3976:     x86_64_hregs = 0;
1.1       root     3977: #endif
                   3978:     s->rip_offset = 0; /* for relative ip address */
                   3979:  next_byte:
                   3980:     b = ldub_code(s->pc);
                   3981:     s->pc++;
                   3982:     /* check prefixes */
                   3983: #ifdef TARGET_X86_64
                   3984:     if (CODE64(s)) {
                   3985:         switch (b) {
                   3986:         case 0xf3:
                   3987:             prefixes |= PREFIX_REPZ;
                   3988:             goto next_byte;
                   3989:         case 0xf2:
                   3990:             prefixes |= PREFIX_REPNZ;
                   3991:             goto next_byte;
                   3992:         case 0xf0:
                   3993:             prefixes |= PREFIX_LOCK;
                   3994:             goto next_byte;
                   3995:         case 0x2e:
                   3996:             s->override = R_CS;
                   3997:             goto next_byte;
                   3998:         case 0x36:
                   3999:             s->override = R_SS;
                   4000:             goto next_byte;
                   4001:         case 0x3e:
                   4002:             s->override = R_DS;
                   4003:             goto next_byte;
                   4004:         case 0x26:
                   4005:             s->override = R_ES;
                   4006:             goto next_byte;
                   4007:         case 0x64:
                   4008:             s->override = R_FS;
                   4009:             goto next_byte;
                   4010:         case 0x65:
                   4011:             s->override = R_GS;
                   4012:             goto next_byte;
                   4013:         case 0x66:
                   4014:             prefixes |= PREFIX_DATA;
                   4015:             goto next_byte;
                   4016:         case 0x67:
                   4017:             prefixes |= PREFIX_ADR;
                   4018:             goto next_byte;
                   4019:         case 0x40 ... 0x4f:
                   4020:             /* REX prefix */
                   4021:             rex_w = (b >> 3) & 1;
                   4022:             rex_r = (b & 0x4) << 1;
                   4023:             s->rex_x = (b & 0x2) << 2;
                   4024:             REX_B(s) = (b & 0x1) << 3;
                   4025:             x86_64_hregs = 1; /* select uniform byte register addressing */
                   4026:             goto next_byte;
                   4027:         }
                   4028:         if (rex_w == 1) {
                   4029:             /* 0x66 is ignored if rex.w is set */
                   4030:             dflag = 2;
                   4031:         } else {
                   4032:             if (prefixes & PREFIX_DATA)
                   4033:                 dflag ^= 1;
                   4034:         }
                   4035:         if (!(prefixes & PREFIX_ADR))
                   4036:             aflag = 2;
1.1.1.6   root     4037:     } else
1.1       root     4038: #endif
                   4039:     {
                   4040:         switch (b) {
                   4041:         case 0xf3:
                   4042:             prefixes |= PREFIX_REPZ;
                   4043:             goto next_byte;
                   4044:         case 0xf2:
                   4045:             prefixes |= PREFIX_REPNZ;
                   4046:             goto next_byte;
                   4047:         case 0xf0:
                   4048:             prefixes |= PREFIX_LOCK;
                   4049:             goto next_byte;
                   4050:         case 0x2e:
                   4051:             s->override = R_CS;
                   4052:             goto next_byte;
                   4053:         case 0x36:
                   4054:             s->override = R_SS;
                   4055:             goto next_byte;
                   4056:         case 0x3e:
                   4057:             s->override = R_DS;
                   4058:             goto next_byte;
                   4059:         case 0x26:
                   4060:             s->override = R_ES;
                   4061:             goto next_byte;
                   4062:         case 0x64:
                   4063:             s->override = R_FS;
                   4064:             goto next_byte;
                   4065:         case 0x65:
                   4066:             s->override = R_GS;
                   4067:             goto next_byte;
                   4068:         case 0x66:
                   4069:             prefixes |= PREFIX_DATA;
                   4070:             goto next_byte;
                   4071:         case 0x67:
                   4072:             prefixes |= PREFIX_ADR;
                   4073:             goto next_byte;
                   4074:         }
                   4075:         if (prefixes & PREFIX_DATA)
                   4076:             dflag ^= 1;
                   4077:         if (prefixes & PREFIX_ADR)
                   4078:             aflag ^= 1;
                   4079:     }
                   4080: 
                   4081:     s->prefix = prefixes;
                   4082:     s->aflag = aflag;
                   4083:     s->dflag = dflag;
                   4084: 
                   4085:     /* lock generation */
                   4086:     if (prefixes & PREFIX_LOCK)
1.1.1.7 ! root     4087:         gen_helper_lock();
1.1       root     4088: 
                   4089:     /* now check op code */
                   4090:  reswitch:
                   4091:     switch(b) {
                   4092:     case 0x0f:
                   4093:         /**************************/
                   4094:         /* extended op code */
                   4095:         b = ldub_code(s->pc++) | 0x100;
                   4096:         goto reswitch;
1.1.1.6   root     4097: 
1.1       root     4098:         /**************************/
                   4099:         /* arith & logic */
                   4100:     case 0x00 ... 0x05:
                   4101:     case 0x08 ... 0x0d:
                   4102:     case 0x10 ... 0x15:
                   4103:     case 0x18 ... 0x1d:
                   4104:     case 0x20 ... 0x25:
                   4105:     case 0x28 ... 0x2d:
                   4106:     case 0x30 ... 0x35:
                   4107:     case 0x38 ... 0x3d:
                   4108:         {
                   4109:             int op, f, val;
                   4110:             op = (b >> 3) & 7;
                   4111:             f = (b >> 1) & 3;
                   4112: 
                   4113:             if ((b & 1) == 0)
                   4114:                 ot = OT_BYTE;
                   4115:             else
                   4116:                 ot = dflag + OT_WORD;
1.1.1.6   root     4117: 
1.1       root     4118:             switch(f) {
                   4119:             case 0: /* OP Ev, Gv */
                   4120:                 modrm = ldub_code(s->pc++);
                   4121:                 reg = ((modrm >> 3) & 7) | rex_r;
                   4122:                 mod = (modrm >> 6) & 3;
                   4123:                 rm = (modrm & 7) | REX_B(s);
                   4124:                 if (mod != 3) {
                   4125:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   4126:                     opreg = OR_TMP0;
                   4127:                 } else if (op == OP_XORL && rm == reg) {
                   4128:                 xor_zero:
                   4129:                     /* xor reg, reg optimisation */
                   4130:                     gen_op_movl_T0_0();
                   4131:                     s->cc_op = CC_OP_LOGICB + ot;
1.1.1.7 ! root     4132:                     gen_op_mov_reg_T0(ot, reg);
1.1       root     4133:                     gen_op_update1_cc();
                   4134:                     break;
                   4135:                 } else {
                   4136:                     opreg = rm;
                   4137:                 }
1.1.1.7 ! root     4138:                 gen_op_mov_TN_reg(ot, 1, reg);
1.1       root     4139:                 gen_op(s, op, ot, opreg);
                   4140:                 break;
                   4141:             case 1: /* OP Gv, Ev */
                   4142:                 modrm = ldub_code(s->pc++);
                   4143:                 mod = (modrm >> 6) & 3;
                   4144:                 reg = ((modrm >> 3) & 7) | rex_r;
                   4145:                 rm = (modrm & 7) | REX_B(s);
                   4146:                 if (mod != 3) {
                   4147:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     4148:                     gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     4149:                 } else if (op == OP_XORL && rm == reg) {
                   4150:                     goto xor_zero;
                   4151:                 } else {
1.1.1.7 ! root     4152:                     gen_op_mov_TN_reg(ot, 1, rm);
1.1       root     4153:                 }
                   4154:                 gen_op(s, op, ot, reg);
                   4155:                 break;
                   4156:             case 2: /* OP A, Iv */
                   4157:                 val = insn_get(s, ot);
                   4158:                 gen_op_movl_T1_im(val);
                   4159:                 gen_op(s, op, ot, OR_EAX);
                   4160:                 break;
                   4161:             }
                   4162:         }
                   4163:         break;
                   4164: 
1.1.1.7 ! root     4165:     case 0x82:
        !          4166:         if (CODE64(s))
        !          4167:             goto illegal_op;
1.1       root     4168:     case 0x80: /* GRP1 */
                   4169:     case 0x81:
                   4170:     case 0x83:
                   4171:         {
                   4172:             int val;
                   4173: 
                   4174:             if ((b & 1) == 0)
                   4175:                 ot = OT_BYTE;
                   4176:             else
                   4177:                 ot = dflag + OT_WORD;
1.1.1.6   root     4178: 
1.1       root     4179:             modrm = ldub_code(s->pc++);
                   4180:             mod = (modrm >> 6) & 3;
                   4181:             rm = (modrm & 7) | REX_B(s);
                   4182:             op = (modrm >> 3) & 7;
1.1.1.6   root     4183: 
1.1       root     4184:             if (mod != 3) {
                   4185:                 if (b == 0x83)
                   4186:                     s->rip_offset = 1;
                   4187:                 else
                   4188:                     s->rip_offset = insn_const_size(ot);
                   4189:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   4190:                 opreg = OR_TMP0;
                   4191:             } else {
                   4192:                 opreg = rm;
                   4193:             }
                   4194: 
                   4195:             switch(b) {
                   4196:             default:
                   4197:             case 0x80:
                   4198:             case 0x81:
                   4199:             case 0x82:
                   4200:                 val = insn_get(s, ot);
                   4201:                 break;
                   4202:             case 0x83:
                   4203:                 val = (int8_t)insn_get(s, OT_BYTE);
                   4204:                 break;
                   4205:             }
                   4206:             gen_op_movl_T1_im(val);
                   4207:             gen_op(s, op, ot, opreg);
                   4208:         }
                   4209:         break;
                   4210: 
                   4211:         /**************************/
                   4212:         /* inc, dec, and other misc arith */
                   4213:     case 0x40 ... 0x47: /* inc Gv */
                   4214:         ot = dflag ? OT_LONG : OT_WORD;
                   4215:         gen_inc(s, ot, OR_EAX + (b & 7), 1);
                   4216:         break;
                   4217:     case 0x48 ... 0x4f: /* dec Gv */
                   4218:         ot = dflag ? OT_LONG : OT_WORD;
                   4219:         gen_inc(s, ot, OR_EAX + (b & 7), -1);
                   4220:         break;
                   4221:     case 0xf6: /* GRP3 */
                   4222:     case 0xf7:
                   4223:         if ((b & 1) == 0)
                   4224:             ot = OT_BYTE;
                   4225:         else
                   4226:             ot = dflag + OT_WORD;
                   4227: 
                   4228:         modrm = ldub_code(s->pc++);
                   4229:         mod = (modrm >> 6) & 3;
                   4230:         rm = (modrm & 7) | REX_B(s);
                   4231:         op = (modrm >> 3) & 7;
                   4232:         if (mod != 3) {
                   4233:             if (op == 0)
                   4234:                 s->rip_offset = insn_const_size(ot);
                   4235:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     4236:             gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     4237:         } else {
1.1.1.7 ! root     4238:             gen_op_mov_TN_reg(ot, 0, rm);
1.1       root     4239:         }
                   4240: 
                   4241:         switch(op) {
                   4242:         case 0: /* test */
                   4243:             val = insn_get(s, ot);
                   4244:             gen_op_movl_T1_im(val);
                   4245:             gen_op_testl_T0_T1_cc();
                   4246:             s->cc_op = CC_OP_LOGICB + ot;
                   4247:             break;
                   4248:         case 2: /* not */
1.1.1.7 ! root     4249:             tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
1.1       root     4250:             if (mod != 3) {
1.1.1.7 ! root     4251:                 gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     4252:             } else {
1.1.1.7 ! root     4253:                 gen_op_mov_reg_T0(ot, rm);
1.1       root     4254:             }
                   4255:             break;
                   4256:         case 3: /* neg */
1.1.1.7 ! root     4257:             tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
1.1       root     4258:             if (mod != 3) {
1.1.1.7 ! root     4259:                 gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     4260:             } else {
1.1.1.7 ! root     4261:                 gen_op_mov_reg_T0(ot, rm);
1.1       root     4262:             }
                   4263:             gen_op_update_neg_cc();
                   4264:             s->cc_op = CC_OP_SUBB + ot;
                   4265:             break;
                   4266:         case 4: /* mul */
                   4267:             switch(ot) {
                   4268:             case OT_BYTE:
1.1.1.7 ! root     4269:                 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
        !          4270:                 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
        !          4271:                 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
        !          4272:                 /* XXX: use 32 bit mul which could be faster */
        !          4273:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4274:                 gen_op_mov_reg_T0(OT_WORD, R_EAX);
        !          4275:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4276:                 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
1.1       root     4277:                 s->cc_op = CC_OP_MULB;
                   4278:                 break;
                   4279:             case OT_WORD:
1.1.1.7 ! root     4280:                 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
        !          4281:                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
        !          4282:                 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
        !          4283:                 /* XXX: use 32 bit mul which could be faster */
        !          4284:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4285:                 gen_op_mov_reg_T0(OT_WORD, R_EAX);
        !          4286:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4287:                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
        !          4288:                 gen_op_mov_reg_T0(OT_WORD, R_EDX);
        !          4289:                 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
1.1       root     4290:                 s->cc_op = CC_OP_MULW;
                   4291:                 break;
                   4292:             default:
                   4293:             case OT_LONG:
1.1.1.7 ! root     4294: #ifdef TARGET_X86_64
        !          4295:                 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
        !          4296:                 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
        !          4297:                 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
        !          4298:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4299:                 gen_op_mov_reg_T0(OT_LONG, R_EAX);
        !          4300:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4301:                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
        !          4302:                 gen_op_mov_reg_T0(OT_LONG, R_EDX);
        !          4303:                 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
        !          4304: #else
        !          4305:                 {
        !          4306:                     TCGv_i64 t0, t1;
        !          4307:                     t0 = tcg_temp_new_i64();
        !          4308:                     t1 = tcg_temp_new_i64();
        !          4309:                     gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
        !          4310:                     tcg_gen_extu_i32_i64(t0, cpu_T[0]);
        !          4311:                     tcg_gen_extu_i32_i64(t1, cpu_T[1]);
        !          4312:                     tcg_gen_mul_i64(t0, t0, t1);
        !          4313:                     tcg_gen_trunc_i64_i32(cpu_T[0], t0);
        !          4314:                     gen_op_mov_reg_T0(OT_LONG, R_EAX);
        !          4315:                     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4316:                     tcg_gen_shri_i64(t0, t0, 32);
        !          4317:                     tcg_gen_trunc_i64_i32(cpu_T[0], t0);
        !          4318:                     gen_op_mov_reg_T0(OT_LONG, R_EDX);
        !          4319:                     tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
        !          4320:                 }
        !          4321: #endif
1.1       root     4322:                 s->cc_op = CC_OP_MULL;
                   4323:                 break;
                   4324: #ifdef TARGET_X86_64
                   4325:             case OT_QUAD:
1.1.1.7 ! root     4326:                 gen_helper_mulq_EAX_T0(cpu_T[0]);
1.1       root     4327:                 s->cc_op = CC_OP_MULQ;
                   4328:                 break;
                   4329: #endif
                   4330:             }
                   4331:             break;
                   4332:         case 5: /* imul */
                   4333:             switch(ot) {
                   4334:             case OT_BYTE:
1.1.1.7 ! root     4335:                 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
        !          4336:                 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
        !          4337:                 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
        !          4338:                 /* XXX: use 32 bit mul which could be faster */
        !          4339:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4340:                 gen_op_mov_reg_T0(OT_WORD, R_EAX);
        !          4341:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4342:                 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
        !          4343:                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
1.1       root     4344:                 s->cc_op = CC_OP_MULB;
                   4345:                 break;
                   4346:             case OT_WORD:
1.1.1.7 ! root     4347:                 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
        !          4348:                 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
        !          4349:                 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
        !          4350:                 /* XXX: use 32 bit mul which could be faster */
        !          4351:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4352:                 gen_op_mov_reg_T0(OT_WORD, R_EAX);
        !          4353:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4354:                 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
        !          4355:                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
        !          4356:                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
        !          4357:                 gen_op_mov_reg_T0(OT_WORD, R_EDX);
1.1       root     4358:                 s->cc_op = CC_OP_MULW;
                   4359:                 break;
                   4360:             default:
                   4361:             case OT_LONG:
1.1.1.7 ! root     4362: #ifdef TARGET_X86_64
        !          4363:                 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
        !          4364:                 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        !          4365:                 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        !          4366:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4367:                 gen_op_mov_reg_T0(OT_LONG, R_EAX);
        !          4368:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4369:                 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
        !          4370:                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
        !          4371:                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
        !          4372:                 gen_op_mov_reg_T0(OT_LONG, R_EDX);
        !          4373: #else
        !          4374:                 {
        !          4375:                     TCGv_i64 t0, t1;
        !          4376:                     t0 = tcg_temp_new_i64();
        !          4377:                     t1 = tcg_temp_new_i64();
        !          4378:                     gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
        !          4379:                     tcg_gen_ext_i32_i64(t0, cpu_T[0]);
        !          4380:                     tcg_gen_ext_i32_i64(t1, cpu_T[1]);
        !          4381:                     tcg_gen_mul_i64(t0, t0, t1);
        !          4382:                     tcg_gen_trunc_i64_i32(cpu_T[0], t0);
        !          4383:                     gen_op_mov_reg_T0(OT_LONG, R_EAX);
        !          4384:                     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4385:                     tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
        !          4386:                     tcg_gen_shri_i64(t0, t0, 32);
        !          4387:                     tcg_gen_trunc_i64_i32(cpu_T[0], t0);
        !          4388:                     gen_op_mov_reg_T0(OT_LONG, R_EDX);
        !          4389:                     tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
        !          4390:                 }
        !          4391: #endif
1.1       root     4392:                 s->cc_op = CC_OP_MULL;
                   4393:                 break;
                   4394: #ifdef TARGET_X86_64
                   4395:             case OT_QUAD:
1.1.1.7 ! root     4396:                 gen_helper_imulq_EAX_T0(cpu_T[0]);
1.1       root     4397:                 s->cc_op = CC_OP_MULQ;
                   4398:                 break;
                   4399: #endif
                   4400:             }
                   4401:             break;
                   4402:         case 6: /* div */
                   4403:             switch(ot) {
                   4404:             case OT_BYTE:
                   4405:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4406:                 gen_helper_divb_AL(cpu_T[0]);
1.1       root     4407:                 break;
                   4408:             case OT_WORD:
                   4409:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4410:                 gen_helper_divw_AX(cpu_T[0]);
1.1       root     4411:                 break;
                   4412:             default:
                   4413:             case OT_LONG:
                   4414:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4415:                 gen_helper_divl_EAX(cpu_T[0]);
1.1       root     4416:                 break;
                   4417: #ifdef TARGET_X86_64
                   4418:             case OT_QUAD:
                   4419:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4420:                 gen_helper_divq_EAX(cpu_T[0]);
1.1       root     4421:                 break;
                   4422: #endif
                   4423:             }
                   4424:             break;
                   4425:         case 7: /* idiv */
                   4426:             switch(ot) {
                   4427:             case OT_BYTE:
                   4428:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4429:                 gen_helper_idivb_AL(cpu_T[0]);
1.1       root     4430:                 break;
                   4431:             case OT_WORD:
                   4432:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4433:                 gen_helper_idivw_AX(cpu_T[0]);
1.1       root     4434:                 break;
                   4435:             default:
                   4436:             case OT_LONG:
                   4437:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4438:                 gen_helper_idivl_EAX(cpu_T[0]);
1.1       root     4439:                 break;
                   4440: #ifdef TARGET_X86_64
                   4441:             case OT_QUAD:
                   4442:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4443:                 gen_helper_idivq_EAX(cpu_T[0]);
1.1       root     4444:                 break;
                   4445: #endif
                   4446:             }
                   4447:             break;
                   4448:         default:
                   4449:             goto illegal_op;
                   4450:         }
                   4451:         break;
                   4452: 
                   4453:     case 0xfe: /* GRP4 */
                   4454:     case 0xff: /* GRP5 */
                   4455:         if ((b & 1) == 0)
                   4456:             ot = OT_BYTE;
                   4457:         else
                   4458:             ot = dflag + OT_WORD;
                   4459: 
                   4460:         modrm = ldub_code(s->pc++);
                   4461:         mod = (modrm >> 6) & 3;
                   4462:         rm = (modrm & 7) | REX_B(s);
                   4463:         op = (modrm >> 3) & 7;
                   4464:         if (op >= 2 && b == 0xfe) {
                   4465:             goto illegal_op;
                   4466:         }
                   4467:         if (CODE64(s)) {
                   4468:             if (op == 2 || op == 4) {
                   4469:                 /* operand size for jumps is 64 bit */
                   4470:                 ot = OT_QUAD;
                   4471:             } else if (op == 3 || op == 5) {
                   4472:                 /* for call calls, the operand is 16 or 32 bit, even
                   4473:                    in long mode */
                   4474:                 ot = dflag ? OT_LONG : OT_WORD;
                   4475:             } else if (op == 6) {
                   4476:                 /* default push size is 64 bit */
                   4477:                 ot = dflag ? OT_QUAD : OT_WORD;
                   4478:             }
                   4479:         }
                   4480:         if (mod != 3) {
                   4481:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   4482:             if (op >= 2 && op != 3 && op != 5)
1.1.1.7 ! root     4483:                 gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     4484:         } else {
1.1.1.7 ! root     4485:             gen_op_mov_TN_reg(ot, 0, rm);
1.1       root     4486:         }
                   4487: 
                   4488:         switch(op) {
                   4489:         case 0: /* inc Ev */
                   4490:             if (mod != 3)
                   4491:                 opreg = OR_TMP0;
                   4492:             else
                   4493:                 opreg = rm;
                   4494:             gen_inc(s, ot, opreg, 1);
                   4495:             break;
                   4496:         case 1: /* dec Ev */
                   4497:             if (mod != 3)
                   4498:                 opreg = OR_TMP0;
                   4499:             else
                   4500:                 opreg = rm;
                   4501:             gen_inc(s, ot, opreg, -1);
                   4502:             break;
                   4503:         case 2: /* call Ev */
                   4504:             /* XXX: optimize if memory (no 'and' is necessary) */
                   4505:             if (s->dflag == 0)
                   4506:                 gen_op_andl_T0_ffff();
                   4507:             next_eip = s->pc - s->cs_base;
                   4508:             gen_movtl_T1_im(next_eip);
                   4509:             gen_push_T1(s);
                   4510:             gen_op_jmp_T0();
                   4511:             gen_eob(s);
                   4512:             break;
                   4513:         case 3: /* lcall Ev */
1.1.1.7 ! root     4514:             gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     4515:             gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
1.1.1.7 ! root     4516:             gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1       root     4517:         do_lcall:
                   4518:             if (s->pe && !s->vm86) {
                   4519:                 if (s->cc_op != CC_OP_DYNAMIC)
                   4520:                     gen_op_set_cc_op(s->cc_op);
                   4521:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4522:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          4523:                 gen_helper_lcall_protected(cpu_tmp2_i32, cpu_T[1],
        !          4524:                                            tcg_const_i32(dflag), 
        !          4525:                                            tcg_const_i32(s->pc - pc_start));
        !          4526:             } else {
        !          4527:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          4528:                 gen_helper_lcall_real(cpu_tmp2_i32, cpu_T[1],
        !          4529:                                       tcg_const_i32(dflag), 
        !          4530:                                       tcg_const_i32(s->pc - s->cs_base));
1.1       root     4531:             }
                   4532:             gen_eob(s);
                   4533:             break;
                   4534:         case 4: /* jmp Ev */
                   4535:             if (s->dflag == 0)
                   4536:                 gen_op_andl_T0_ffff();
                   4537:             gen_op_jmp_T0();
                   4538:             gen_eob(s);
                   4539:             break;
                   4540:         case 5: /* ljmp Ev */
1.1.1.7 ! root     4541:             gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     4542:             gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
1.1.1.7 ! root     4543:             gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1       root     4544:         do_ljmp:
                   4545:             if (s->pe && !s->vm86) {
                   4546:                 if (s->cc_op != CC_OP_DYNAMIC)
                   4547:                     gen_op_set_cc_op(s->cc_op);
                   4548:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     4549:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          4550:                 gen_helper_ljmp_protected(cpu_tmp2_i32, cpu_T[1],
        !          4551:                                           tcg_const_i32(s->pc - pc_start));
1.1       root     4552:             } else {
1.1.1.7 ! root     4553:                 gen_op_movl_seg_T0_vm(R_CS);
1.1       root     4554:                 gen_op_movl_T0_T1();
                   4555:                 gen_op_jmp_T0();
                   4556:             }
                   4557:             gen_eob(s);
                   4558:             break;
                   4559:         case 6: /* push Ev */
                   4560:             gen_push_T0(s);
                   4561:             break;
                   4562:         default:
                   4563:             goto illegal_op;
                   4564:         }
                   4565:         break;
                   4566: 
                   4567:     case 0x84: /* test Ev, Gv */
1.1.1.6   root     4568:     case 0x85:
1.1       root     4569:         if ((b & 1) == 0)
                   4570:             ot = OT_BYTE;
                   4571:         else
                   4572:             ot = dflag + OT_WORD;
                   4573: 
                   4574:         modrm = ldub_code(s->pc++);
                   4575:         mod = (modrm >> 6) & 3;
                   4576:         rm = (modrm & 7) | REX_B(s);
                   4577:         reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6   root     4578: 
1.1       root     4579:         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1.1.1.7 ! root     4580:         gen_op_mov_TN_reg(ot, 1, reg);
1.1       root     4581:         gen_op_testl_T0_T1_cc();
                   4582:         s->cc_op = CC_OP_LOGICB + ot;
                   4583:         break;
1.1.1.6   root     4584: 
1.1       root     4585:     case 0xa8: /* test eAX, Iv */
                   4586:     case 0xa9:
                   4587:         if ((b & 1) == 0)
                   4588:             ot = OT_BYTE;
                   4589:         else
                   4590:             ot = dflag + OT_WORD;
                   4591:         val = insn_get(s, ot);
                   4592: 
1.1.1.7 ! root     4593:         gen_op_mov_TN_reg(ot, 0, OR_EAX);
1.1       root     4594:         gen_op_movl_T1_im(val);
                   4595:         gen_op_testl_T0_T1_cc();
                   4596:         s->cc_op = CC_OP_LOGICB + ot;
                   4597:         break;
1.1.1.6   root     4598: 
1.1       root     4599:     case 0x98: /* CWDE/CBW */
                   4600: #ifdef TARGET_X86_64
                   4601:         if (dflag == 2) {
1.1.1.7 ! root     4602:             gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
        !          4603:             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        !          4604:             gen_op_mov_reg_T0(OT_QUAD, R_EAX);
1.1       root     4605:         } else
                   4606: #endif
1.1.1.7 ! root     4607:         if (dflag == 1) {
        !          4608:             gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
        !          4609:             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
        !          4610:             gen_op_mov_reg_T0(OT_LONG, R_EAX);
        !          4611:         } else {
        !          4612:             gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
        !          4613:             tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
        !          4614:             gen_op_mov_reg_T0(OT_WORD, R_EAX);
        !          4615:         }
1.1       root     4616:         break;
                   4617:     case 0x99: /* CDQ/CWD */
                   4618: #ifdef TARGET_X86_64
                   4619:         if (dflag == 2) {
1.1.1.7 ! root     4620:             gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
        !          4621:             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
        !          4622:             gen_op_mov_reg_T0(OT_QUAD, R_EDX);
1.1       root     4623:         } else
                   4624: #endif
1.1.1.7 ! root     4625:         if (dflag == 1) {
        !          4626:             gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
        !          4627:             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        !          4628:             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
        !          4629:             gen_op_mov_reg_T0(OT_LONG, R_EDX);
        !          4630:         } else {
        !          4631:             gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
        !          4632:             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
        !          4633:             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
        !          4634:             gen_op_mov_reg_T0(OT_WORD, R_EDX);
        !          4635:         }
1.1       root     4636:         break;
                   4637:     case 0x1af: /* imul Gv, Ev */
                   4638:     case 0x69: /* imul Gv, Ev, I */
                   4639:     case 0x6b:
                   4640:         ot = dflag + OT_WORD;
                   4641:         modrm = ldub_code(s->pc++);
                   4642:         reg = ((modrm >> 3) & 7) | rex_r;
                   4643:         if (b == 0x69)
                   4644:             s->rip_offset = insn_const_size(ot);
                   4645:         else if (b == 0x6b)
                   4646:             s->rip_offset = 1;
                   4647:         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
                   4648:         if (b == 0x69) {
                   4649:             val = insn_get(s, ot);
                   4650:             gen_op_movl_T1_im(val);
                   4651:         } else if (b == 0x6b) {
                   4652:             val = (int8_t)insn_get(s, OT_BYTE);
                   4653:             gen_op_movl_T1_im(val);
                   4654:         } else {
1.1.1.7 ! root     4655:             gen_op_mov_TN_reg(ot, 1, reg);
1.1       root     4656:         }
                   4657: 
                   4658: #ifdef TARGET_X86_64
                   4659:         if (ot == OT_QUAD) {
1.1.1.7 ! root     4660:             gen_helper_imulq_T0_T1(cpu_T[0], cpu_T[0], cpu_T[1]);
1.1       root     4661:         } else
                   4662: #endif
                   4663:         if (ot == OT_LONG) {
1.1.1.7 ! root     4664: #ifdef TARGET_X86_64
        !          4665:                 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        !          4666:                 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
        !          4667:                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4668:                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4669:                 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
        !          4670:                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
        !          4671: #else
        !          4672:                 {
        !          4673:                     TCGv_i64 t0, t1;
        !          4674:                     t0 = tcg_temp_new_i64();
        !          4675:                     t1 = tcg_temp_new_i64();
        !          4676:                     tcg_gen_ext_i32_i64(t0, cpu_T[0]);
        !          4677:                     tcg_gen_ext_i32_i64(t1, cpu_T[1]);
        !          4678:                     tcg_gen_mul_i64(t0, t0, t1);
        !          4679:                     tcg_gen_trunc_i64_i32(cpu_T[0], t0);
        !          4680:                     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4681:                     tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
        !          4682:                     tcg_gen_shri_i64(t0, t0, 32);
        !          4683:                     tcg_gen_trunc_i64_i32(cpu_T[1], t0);
        !          4684:                     tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0);
        !          4685:                 }
        !          4686: #endif
1.1       root     4687:         } else {
1.1.1.7 ! root     4688:             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
        !          4689:             tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
        !          4690:             /* XXX: use 32 bit mul which could be faster */
        !          4691:             tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
        !          4692:             tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
        !          4693:             tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
        !          4694:             tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
1.1       root     4695:         }
1.1.1.7 ! root     4696:         gen_op_mov_reg_T0(ot, reg);
1.1       root     4697:         s->cc_op = CC_OP_MULB + ot;
                   4698:         break;
                   4699:     case 0x1c0:
                   4700:     case 0x1c1: /* xadd Ev, Gv */
                   4701:         if ((b & 1) == 0)
                   4702:             ot = OT_BYTE;
                   4703:         else
                   4704:             ot = dflag + OT_WORD;
                   4705:         modrm = ldub_code(s->pc++);
                   4706:         reg = ((modrm >> 3) & 7) | rex_r;
                   4707:         mod = (modrm >> 6) & 3;
                   4708:         if (mod == 3) {
                   4709:             rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     4710:             gen_op_mov_TN_reg(ot, 0, reg);
        !          4711:             gen_op_mov_TN_reg(ot, 1, rm);
1.1       root     4712:             gen_op_addl_T0_T1();
1.1.1.7 ! root     4713:             gen_op_mov_reg_T1(ot, reg);
        !          4714:             gen_op_mov_reg_T0(ot, rm);
1.1       root     4715:         } else {
                   4716:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     4717:             gen_op_mov_TN_reg(ot, 0, reg);
        !          4718:             gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     4719:             gen_op_addl_T0_T1();
1.1.1.7 ! root     4720:             gen_op_st_T0_A0(ot + s->mem_index);
        !          4721:             gen_op_mov_reg_T1(ot, reg);
1.1       root     4722:         }
                   4723:         gen_op_update2_cc();
                   4724:         s->cc_op = CC_OP_ADDB + ot;
                   4725:         break;
                   4726:     case 0x1b0:
                   4727:     case 0x1b1: /* cmpxchg Ev, Gv */
1.1.1.7 ! root     4728:         {
        !          4729:             int label1, label2;
        !          4730:             TCGv t0, t1, t2, a0;
        !          4731: 
        !          4732:             if ((b & 1) == 0)
        !          4733:                 ot = OT_BYTE;
        !          4734:             else
        !          4735:                 ot = dflag + OT_WORD;
        !          4736:             modrm = ldub_code(s->pc++);
        !          4737:             reg = ((modrm >> 3) & 7) | rex_r;
        !          4738:             mod = (modrm >> 6) & 3;
        !          4739:             t0 = tcg_temp_local_new();
        !          4740:             t1 = tcg_temp_local_new();
        !          4741:             t2 = tcg_temp_local_new();
        !          4742:             a0 = tcg_temp_local_new();
        !          4743:             gen_op_mov_v_reg(ot, t1, reg);
        !          4744:             if (mod == 3) {
        !          4745:                 rm = (modrm & 7) | REX_B(s);
        !          4746:                 gen_op_mov_v_reg(ot, t0, rm);
        !          4747:             } else {
        !          4748:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          4749:                 tcg_gen_mov_tl(a0, cpu_A0);
        !          4750:                 gen_op_ld_v(ot + s->mem_index, t0, a0);
        !          4751:                 rm = 0; /* avoid warning */
        !          4752:             }
        !          4753:             label1 = gen_new_label();
        !          4754:             tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, regs[R_EAX]));
        !          4755:             tcg_gen_sub_tl(t2, t2, t0);
        !          4756:             gen_extu(ot, t2);
        !          4757:             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
        !          4758:             if (mod == 3) {
        !          4759:                 label2 = gen_new_label();
        !          4760:                 gen_op_mov_reg_v(ot, R_EAX, t0);
        !          4761:                 tcg_gen_br(label2);
        !          4762:                 gen_set_label(label1);
        !          4763:                 gen_op_mov_reg_v(ot, rm, t1);
        !          4764:                 gen_set_label(label2);
        !          4765:             } else {
        !          4766:                 tcg_gen_mov_tl(t1, t0);
        !          4767:                 gen_op_mov_reg_v(ot, R_EAX, t0);
        !          4768:                 gen_set_label(label1);
        !          4769:                 /* always store */
        !          4770:                 gen_op_st_v(ot + s->mem_index, t1, a0);
        !          4771:             }
        !          4772:             tcg_gen_mov_tl(cpu_cc_src, t0);
        !          4773:             tcg_gen_mov_tl(cpu_cc_dst, t2);
        !          4774:             s->cc_op = CC_OP_SUBB + ot;
        !          4775:             tcg_temp_free(t0);
        !          4776:             tcg_temp_free(t1);
        !          4777:             tcg_temp_free(t2);
        !          4778:             tcg_temp_free(a0);
1.1       root     4779:         }
                   4780:         break;
                   4781:     case 0x1c7: /* cmpxchg8b */
                   4782:         modrm = ldub_code(s->pc++);
                   4783:         mod = (modrm >> 6) & 3;
1.1.1.6   root     4784:         if ((mod == 3) || ((modrm & 0x38) != 0x8))
1.1       root     4785:             goto illegal_op;
1.1.1.7 ! root     4786: #ifdef TARGET_X86_64
        !          4787:         if (dflag == 2) {
        !          4788:             if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
        !          4789:                 goto illegal_op;
        !          4790:             gen_jmp_im(pc_start - s->cs_base);
        !          4791:             if (s->cc_op != CC_OP_DYNAMIC)
        !          4792:                 gen_op_set_cc_op(s->cc_op);
        !          4793:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          4794:             gen_helper_cmpxchg16b(cpu_A0);
        !          4795:         } else
        !          4796: #endif        
        !          4797:         {
        !          4798:             if (!(s->cpuid_features & CPUID_CX8))
        !          4799:                 goto illegal_op;
        !          4800:             gen_jmp_im(pc_start - s->cs_base);
        !          4801:             if (s->cc_op != CC_OP_DYNAMIC)
        !          4802:                 gen_op_set_cc_op(s->cc_op);
        !          4803:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          4804:             gen_helper_cmpxchg8b(cpu_A0);
        !          4805:         }
1.1       root     4806:         s->cc_op = CC_OP_EFLAGS;
                   4807:         break;
1.1.1.6   root     4808: 
1.1       root     4809:         /**************************/
                   4810:         /* push/pop */
                   4811:     case 0x50 ... 0x57: /* push */
1.1.1.7 ! root     4812:         gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
1.1       root     4813:         gen_push_T0(s);
                   4814:         break;
                   4815:     case 0x58 ... 0x5f: /* pop */
                   4816:         if (CODE64(s)) {
                   4817:             ot = dflag ? OT_QUAD : OT_WORD;
                   4818:         } else {
                   4819:             ot = dflag + OT_WORD;
                   4820:         }
                   4821:         gen_pop_T0(s);
                   4822:         /* NOTE: order is important for pop %sp */
                   4823:         gen_pop_update(s);
1.1.1.7 ! root     4824:         gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
1.1       root     4825:         break;
                   4826:     case 0x60: /* pusha */
                   4827:         if (CODE64(s))
                   4828:             goto illegal_op;
                   4829:         gen_pusha(s);
                   4830:         break;
                   4831:     case 0x61: /* popa */
                   4832:         if (CODE64(s))
                   4833:             goto illegal_op;
                   4834:         gen_popa(s);
                   4835:         break;
                   4836:     case 0x68: /* push Iv */
                   4837:     case 0x6a:
                   4838:         if (CODE64(s)) {
                   4839:             ot = dflag ? OT_QUAD : OT_WORD;
                   4840:         } else {
                   4841:             ot = dflag + OT_WORD;
                   4842:         }
                   4843:         if (b == 0x68)
                   4844:             val = insn_get(s, ot);
                   4845:         else
                   4846:             val = (int8_t)insn_get(s, OT_BYTE);
                   4847:         gen_op_movl_T0_im(val);
                   4848:         gen_push_T0(s);
                   4849:         break;
                   4850:     case 0x8f: /* pop Ev */
                   4851:         if (CODE64(s)) {
                   4852:             ot = dflag ? OT_QUAD : OT_WORD;
                   4853:         } else {
                   4854:             ot = dflag + OT_WORD;
                   4855:         }
                   4856:         modrm = ldub_code(s->pc++);
                   4857:         mod = (modrm >> 6) & 3;
                   4858:         gen_pop_T0(s);
                   4859:         if (mod == 3) {
                   4860:             /* NOTE: order is important for pop %sp */
                   4861:             gen_pop_update(s);
                   4862:             rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     4863:             gen_op_mov_reg_T0(ot, rm);
1.1       root     4864:         } else {
                   4865:             /* NOTE: order is important too for MMU exceptions */
                   4866:             s->popl_esp_hack = 1 << ot;
                   4867:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
                   4868:             s->popl_esp_hack = 0;
                   4869:             gen_pop_update(s);
                   4870:         }
                   4871:         break;
                   4872:     case 0xc8: /* enter */
                   4873:         {
                   4874:             int level;
                   4875:             val = lduw_code(s->pc);
                   4876:             s->pc += 2;
                   4877:             level = ldub_code(s->pc++);
                   4878:             gen_enter(s, val, level);
                   4879:         }
                   4880:         break;
                   4881:     case 0xc9: /* leave */
                   4882:         /* XXX: exception not precise (ESP is updated before potential exception) */
                   4883:         if (CODE64(s)) {
1.1.1.7 ! root     4884:             gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
        !          4885:             gen_op_mov_reg_T0(OT_QUAD, R_ESP);
1.1       root     4886:         } else if (s->ss32) {
1.1.1.7 ! root     4887:             gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
        !          4888:             gen_op_mov_reg_T0(OT_LONG, R_ESP);
1.1       root     4889:         } else {
1.1.1.7 ! root     4890:             gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
        !          4891:             gen_op_mov_reg_T0(OT_WORD, R_ESP);
1.1       root     4892:         }
                   4893:         gen_pop_T0(s);
                   4894:         if (CODE64(s)) {
                   4895:             ot = dflag ? OT_QUAD : OT_WORD;
                   4896:         } else {
                   4897:             ot = dflag + OT_WORD;
                   4898:         }
1.1.1.7 ! root     4899:         gen_op_mov_reg_T0(ot, R_EBP);
1.1       root     4900:         gen_pop_update(s);
                   4901:         break;
                   4902:     case 0x06: /* push es */
                   4903:     case 0x0e: /* push cs */
                   4904:     case 0x16: /* push ss */
                   4905:     case 0x1e: /* push ds */
                   4906:         if (CODE64(s))
                   4907:             goto illegal_op;
                   4908:         gen_op_movl_T0_seg(b >> 3);
                   4909:         gen_push_T0(s);
                   4910:         break;
                   4911:     case 0x1a0: /* push fs */
                   4912:     case 0x1a8: /* push gs */
                   4913:         gen_op_movl_T0_seg((b >> 3) & 7);
                   4914:         gen_push_T0(s);
                   4915:         break;
                   4916:     case 0x07: /* pop es */
                   4917:     case 0x17: /* pop ss */
                   4918:     case 0x1f: /* pop ds */
                   4919:         if (CODE64(s))
                   4920:             goto illegal_op;
                   4921:         reg = b >> 3;
                   4922:         gen_pop_T0(s);
                   4923:         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
                   4924:         gen_pop_update(s);
                   4925:         if (reg == R_SS) {
                   4926:             /* if reg == SS, inhibit interrupts/trace. */
                   4927:             /* If several instructions disable interrupts, only the
                   4928:                _first_ does it */
                   4929:             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 ! root     4930:                 gen_helper_set_inhibit_irq();
1.1       root     4931:             s->tf = 0;
                   4932:         }
                   4933:         if (s->is_jmp) {
                   4934:             gen_jmp_im(s->pc - s->cs_base);
                   4935:             gen_eob(s);
                   4936:         }
                   4937:         break;
                   4938:     case 0x1a1: /* pop fs */
                   4939:     case 0x1a9: /* pop gs */
                   4940:         gen_pop_T0(s);
                   4941:         gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
                   4942:         gen_pop_update(s);
                   4943:         if (s->is_jmp) {
                   4944:             gen_jmp_im(s->pc - s->cs_base);
                   4945:             gen_eob(s);
                   4946:         }
                   4947:         break;
                   4948: 
                   4949:         /**************************/
                   4950:         /* mov */
                   4951:     case 0x88:
                   4952:     case 0x89: /* mov Gv, Ev */
                   4953:         if ((b & 1) == 0)
                   4954:             ot = OT_BYTE;
                   4955:         else
                   4956:             ot = dflag + OT_WORD;
                   4957:         modrm = ldub_code(s->pc++);
                   4958:         reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6   root     4959: 
1.1       root     4960:         /* generate a generic store */
                   4961:         gen_ldst_modrm(s, modrm, ot, reg, 1);
                   4962:         break;
                   4963:     case 0xc6:
                   4964:     case 0xc7: /* mov Ev, Iv */
                   4965:         if ((b & 1) == 0)
                   4966:             ot = OT_BYTE;
                   4967:         else
                   4968:             ot = dflag + OT_WORD;
                   4969:         modrm = ldub_code(s->pc++);
                   4970:         mod = (modrm >> 6) & 3;
                   4971:         if (mod != 3) {
                   4972:             s->rip_offset = insn_const_size(ot);
                   4973:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   4974:         }
                   4975:         val = insn_get(s, ot);
                   4976:         gen_op_movl_T0_im(val);
                   4977:         if (mod != 3)
1.1.1.7 ! root     4978:             gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     4979:         else
1.1.1.7 ! root     4980:             gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
1.1       root     4981:         break;
                   4982:     case 0x8a:
                   4983:     case 0x8b: /* mov Ev, Gv */
                   4984:         if ((b & 1) == 0)
                   4985:             ot = OT_BYTE;
                   4986:         else
                   4987:             ot = OT_WORD + dflag;
                   4988:         modrm = ldub_code(s->pc++);
                   4989:         reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6   root     4990: 
1.1       root     4991:         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1.1.1.7 ! root     4992:         gen_op_mov_reg_T0(ot, reg);
1.1       root     4993:         break;
                   4994:     case 0x8e: /* mov seg, Gv */
                   4995:         modrm = ldub_code(s->pc++);
                   4996:         reg = (modrm >> 3) & 7;
                   4997:         if (reg >= 6 || reg == R_CS)
                   4998:             goto illegal_op;
                   4999:         gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                   5000:         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
                   5001:         if (reg == R_SS) {
                   5002:             /* if reg == SS, inhibit interrupts/trace */
                   5003:             /* If several instructions disable interrupts, only the
                   5004:                _first_ does it */
                   5005:             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 ! root     5006:                 gen_helper_set_inhibit_irq();
1.1       root     5007:             s->tf = 0;
                   5008:         }
                   5009:         if (s->is_jmp) {
                   5010:             gen_jmp_im(s->pc - s->cs_base);
                   5011:             gen_eob(s);
                   5012:         }
                   5013:         break;
                   5014:     case 0x8c: /* mov Gv, seg */
                   5015:         modrm = ldub_code(s->pc++);
                   5016:         reg = (modrm >> 3) & 7;
                   5017:         mod = (modrm >> 6) & 3;
                   5018:         if (reg >= 6)
                   5019:             goto illegal_op;
                   5020:         gen_op_movl_T0_seg(reg);
                   5021:         if (mod == 3)
                   5022:             ot = OT_WORD + dflag;
                   5023:         else
                   5024:             ot = OT_WORD;
                   5025:         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
                   5026:         break;
                   5027: 
                   5028:     case 0x1b6: /* movzbS Gv, Eb */
                   5029:     case 0x1b7: /* movzwS Gv, Eb */
                   5030:     case 0x1be: /* movsbS Gv, Eb */
                   5031:     case 0x1bf: /* movswS Gv, Eb */
                   5032:         {
                   5033:             int d_ot;
                   5034:             /* d_ot is the size of destination */
                   5035:             d_ot = dflag + OT_WORD;
                   5036:             /* ot is the size of source */
                   5037:             ot = (b & 1) + OT_BYTE;
                   5038:             modrm = ldub_code(s->pc++);
                   5039:             reg = ((modrm >> 3) & 7) | rex_r;
                   5040:             mod = (modrm >> 6) & 3;
                   5041:             rm = (modrm & 7) | REX_B(s);
1.1.1.6   root     5042: 
1.1       root     5043:             if (mod == 3) {
1.1.1.7 ! root     5044:                 gen_op_mov_TN_reg(ot, 0, rm);
1.1       root     5045:                 switch(ot | (b & 8)) {
                   5046:                 case OT_BYTE:
1.1.1.7 ! root     5047:                     tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1.1       root     5048:                     break;
                   5049:                 case OT_BYTE | 8:
1.1.1.7 ! root     5050:                     tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
1.1       root     5051:                     break;
                   5052:                 case OT_WORD:
1.1.1.7 ! root     5053:                     tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
1.1       root     5054:                     break;
                   5055:                 default:
                   5056:                 case OT_WORD | 8:
1.1.1.7 ! root     5057:                     tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
1.1       root     5058:                     break;
                   5059:                 }
1.1.1.7 ! root     5060:                 gen_op_mov_reg_T0(d_ot, reg);
1.1       root     5061:             } else {
                   5062:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   5063:                 if (b & 8) {
1.1.1.7 ! root     5064:                     gen_op_lds_T0_A0(ot + s->mem_index);
1.1       root     5065:                 } else {
1.1.1.7 ! root     5066:                     gen_op_ldu_T0_A0(ot + s->mem_index);
1.1       root     5067:                 }
1.1.1.7 ! root     5068:                 gen_op_mov_reg_T0(d_ot, reg);
1.1       root     5069:             }
                   5070:         }
                   5071:         break;
                   5072: 
                   5073:     case 0x8d: /* lea */
                   5074:         ot = dflag + OT_WORD;
                   5075:         modrm = ldub_code(s->pc++);
                   5076:         mod = (modrm >> 6) & 3;
                   5077:         if (mod == 3)
                   5078:             goto illegal_op;
                   5079:         reg = ((modrm >> 3) & 7) | rex_r;
                   5080:         /* we must ensure that no segment is added */
                   5081:         s->override = -1;
                   5082:         val = s->addseg;
                   5083:         s->addseg = 0;
                   5084:         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   5085:         s->addseg = val;
1.1.1.7 ! root     5086:         gen_op_mov_reg_A0(ot - OT_WORD, reg);
1.1       root     5087:         break;
1.1.1.6   root     5088: 
1.1       root     5089:     case 0xa0: /* mov EAX, Ov */
                   5090:     case 0xa1:
                   5091:     case 0xa2: /* mov Ov, EAX */
                   5092:     case 0xa3:
                   5093:         {
                   5094:             target_ulong offset_addr;
                   5095: 
                   5096:             if ((b & 1) == 0)
                   5097:                 ot = OT_BYTE;
                   5098:             else
                   5099:                 ot = dflag + OT_WORD;
                   5100: #ifdef TARGET_X86_64
                   5101:             if (s->aflag == 2) {
                   5102:                 offset_addr = ldq_code(s->pc);
                   5103:                 s->pc += 8;
1.1.1.7 ! root     5104:                 gen_op_movq_A0_im(offset_addr);
1.1.1.6   root     5105:             } else
1.1       root     5106: #endif
                   5107:             {
                   5108:                 if (s->aflag) {
                   5109:                     offset_addr = insn_get(s, OT_LONG);
                   5110:                 } else {
                   5111:                     offset_addr = insn_get(s, OT_WORD);
                   5112:                 }
                   5113:                 gen_op_movl_A0_im(offset_addr);
                   5114:             }
                   5115:             gen_add_A0_ds_seg(s);
                   5116:             if ((b & 2) == 0) {
1.1.1.7 ! root     5117:                 gen_op_ld_T0_A0(ot + s->mem_index);
        !          5118:                 gen_op_mov_reg_T0(ot, R_EAX);
1.1       root     5119:             } else {
1.1.1.7 ! root     5120:                 gen_op_mov_TN_reg(ot, 0, R_EAX);
        !          5121:                 gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     5122:             }
                   5123:         }
                   5124:         break;
                   5125:     case 0xd7: /* xlat */
                   5126: #ifdef TARGET_X86_64
                   5127:         if (s->aflag == 2) {
1.1.1.7 ! root     5128:             gen_op_movq_A0_reg(R_EBX);
        !          5129:             gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
        !          5130:             tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
        !          5131:             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
1.1.1.6   root     5132:         } else
1.1       root     5133: #endif
                   5134:         {
1.1.1.7 ! root     5135:             gen_op_movl_A0_reg(R_EBX);
        !          5136:             gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
        !          5137:             tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
        !          5138:             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
1.1       root     5139:             if (s->aflag == 0)
                   5140:                 gen_op_andl_A0_ffff();
1.1.1.7 ! root     5141:             else
        !          5142:                 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
1.1       root     5143:         }
                   5144:         gen_add_A0_ds_seg(s);
1.1.1.7 ! root     5145:         gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
        !          5146:         gen_op_mov_reg_T0(OT_BYTE, R_EAX);
1.1       root     5147:         break;
                   5148:     case 0xb0 ... 0xb7: /* mov R, Ib */
                   5149:         val = insn_get(s, OT_BYTE);
                   5150:         gen_op_movl_T0_im(val);
1.1.1.7 ! root     5151:         gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
1.1       root     5152:         break;
                   5153:     case 0xb8 ... 0xbf: /* mov R, Iv */
                   5154: #ifdef TARGET_X86_64
                   5155:         if (dflag == 2) {
                   5156:             uint64_t tmp;
                   5157:             /* 64 bit case */
                   5158:             tmp = ldq_code(s->pc);
                   5159:             s->pc += 8;
                   5160:             reg = (b & 7) | REX_B(s);
                   5161:             gen_movtl_T0_im(tmp);
1.1.1.7 ! root     5162:             gen_op_mov_reg_T0(OT_QUAD, reg);
1.1.1.6   root     5163:         } else
1.1       root     5164: #endif
                   5165:         {
                   5166:             ot = dflag ? OT_LONG : OT_WORD;
                   5167:             val = insn_get(s, ot);
                   5168:             reg = (b & 7) | REX_B(s);
                   5169:             gen_op_movl_T0_im(val);
1.1.1.7 ! root     5170:             gen_op_mov_reg_T0(ot, reg);
1.1       root     5171:         }
                   5172:         break;
                   5173: 
                   5174:     case 0x91 ... 0x97: /* xchg R, EAX */
                   5175:         ot = dflag + OT_WORD;
                   5176:         reg = (b & 7) | REX_B(s);
                   5177:         rm = R_EAX;
                   5178:         goto do_xchg_reg;
                   5179:     case 0x86:
                   5180:     case 0x87: /* xchg Ev, Gv */
                   5181:         if ((b & 1) == 0)
                   5182:             ot = OT_BYTE;
                   5183:         else
                   5184:             ot = dflag + OT_WORD;
                   5185:         modrm = ldub_code(s->pc++);
                   5186:         reg = ((modrm >> 3) & 7) | rex_r;
                   5187:         mod = (modrm >> 6) & 3;
                   5188:         if (mod == 3) {
                   5189:             rm = (modrm & 7) | REX_B(s);
                   5190:         do_xchg_reg:
1.1.1.7 ! root     5191:             gen_op_mov_TN_reg(ot, 0, reg);
        !          5192:             gen_op_mov_TN_reg(ot, 1, rm);
        !          5193:             gen_op_mov_reg_T0(ot, rm);
        !          5194:             gen_op_mov_reg_T1(ot, reg);
1.1       root     5195:         } else {
                   5196:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     5197:             gen_op_mov_TN_reg(ot, 0, reg);
1.1       root     5198:             /* for xchg, lock is implicit */
                   5199:             if (!(prefixes & PREFIX_LOCK))
1.1.1.7 ! root     5200:                 gen_helper_lock();
        !          5201:             gen_op_ld_T1_A0(ot + s->mem_index);
        !          5202:             gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     5203:             if (!(prefixes & PREFIX_LOCK))
1.1.1.7 ! root     5204:                 gen_helper_unlock();
        !          5205:             gen_op_mov_reg_T1(ot, reg);
1.1       root     5206:         }
                   5207:         break;
                   5208:     case 0xc4: /* les Gv */
                   5209:         if (CODE64(s))
                   5210:             goto illegal_op;
                   5211:         op = R_ES;
                   5212:         goto do_lxx;
                   5213:     case 0xc5: /* lds Gv */
                   5214:         if (CODE64(s))
                   5215:             goto illegal_op;
                   5216:         op = R_DS;
                   5217:         goto do_lxx;
                   5218:     case 0x1b2: /* lss Gv */
                   5219:         op = R_SS;
                   5220:         goto do_lxx;
                   5221:     case 0x1b4: /* lfs Gv */
                   5222:         op = R_FS;
                   5223:         goto do_lxx;
                   5224:     case 0x1b5: /* lgs Gv */
                   5225:         op = R_GS;
                   5226:     do_lxx:
                   5227:         ot = dflag ? OT_LONG : OT_WORD;
                   5228:         modrm = ldub_code(s->pc++);
                   5229:         reg = ((modrm >> 3) & 7) | rex_r;
                   5230:         mod = (modrm >> 6) & 3;
                   5231:         if (mod == 3)
                   5232:             goto illegal_op;
                   5233:         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     5234:         gen_op_ld_T1_A0(ot + s->mem_index);
1.1       root     5235:         gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
                   5236:         /* load the segment first to handle exceptions properly */
1.1.1.7 ! root     5237:         gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1       root     5238:         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
                   5239:         /* then put the data */
1.1.1.7 ! root     5240:         gen_op_mov_reg_T1(ot, reg);
1.1       root     5241:         if (s->is_jmp) {
                   5242:             gen_jmp_im(s->pc - s->cs_base);
                   5243:             gen_eob(s);
                   5244:         }
                   5245:         break;
1.1.1.6   root     5246: 
1.1       root     5247:         /************************/
                   5248:         /* shifts */
                   5249:     case 0xc0:
                   5250:     case 0xc1:
                   5251:         /* shift Ev,Ib */
                   5252:         shift = 2;
                   5253:     grp2:
                   5254:         {
                   5255:             if ((b & 1) == 0)
                   5256:                 ot = OT_BYTE;
                   5257:             else
                   5258:                 ot = dflag + OT_WORD;
1.1.1.6   root     5259: 
1.1       root     5260:             modrm = ldub_code(s->pc++);
                   5261:             mod = (modrm >> 6) & 3;
                   5262:             op = (modrm >> 3) & 7;
1.1.1.6   root     5263: 
1.1       root     5264:             if (mod != 3) {
                   5265:                 if (shift == 2) {
                   5266:                     s->rip_offset = 1;
                   5267:                 }
                   5268:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   5269:                 opreg = OR_TMP0;
                   5270:             } else {
                   5271:                 opreg = (modrm & 7) | REX_B(s);
                   5272:             }
                   5273: 
                   5274:             /* simpler op */
                   5275:             if (shift == 0) {
                   5276:                 gen_shift(s, op, ot, opreg, OR_ECX);
                   5277:             } else {
                   5278:                 if (shift == 2) {
                   5279:                     shift = ldub_code(s->pc++);
                   5280:                 }
                   5281:                 gen_shifti(s, op, ot, opreg, shift);
                   5282:             }
                   5283:         }
                   5284:         break;
                   5285:     case 0xd0:
                   5286:     case 0xd1:
                   5287:         /* shift Ev,1 */
                   5288:         shift = 1;
                   5289:         goto grp2;
                   5290:     case 0xd2:
                   5291:     case 0xd3:
                   5292:         /* shift Ev,cl */
                   5293:         shift = 0;
                   5294:         goto grp2;
                   5295: 
                   5296:     case 0x1a4: /* shld imm */
                   5297:         op = 0;
                   5298:         shift = 1;
                   5299:         goto do_shiftd;
                   5300:     case 0x1a5: /* shld cl */
                   5301:         op = 0;
                   5302:         shift = 0;
                   5303:         goto do_shiftd;
                   5304:     case 0x1ac: /* shrd imm */
                   5305:         op = 1;
                   5306:         shift = 1;
                   5307:         goto do_shiftd;
                   5308:     case 0x1ad: /* shrd cl */
                   5309:         op = 1;
                   5310:         shift = 0;
                   5311:     do_shiftd:
                   5312:         ot = dflag + OT_WORD;
                   5313:         modrm = ldub_code(s->pc++);
                   5314:         mod = (modrm >> 6) & 3;
                   5315:         rm = (modrm & 7) | REX_B(s);
                   5316:         reg = ((modrm >> 3) & 7) | rex_r;
                   5317:         if (mod != 3) {
                   5318:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     5319:             opreg = OR_TMP0;
1.1       root     5320:         } else {
1.1.1.7 ! root     5321:             opreg = rm;
1.1       root     5322:         }
1.1.1.7 ! root     5323:         gen_op_mov_TN_reg(ot, 1, reg);
1.1.1.6   root     5324: 
1.1       root     5325:         if (shift) {
                   5326:             val = ldub_code(s->pc++);
1.1.1.7 ! root     5327:             tcg_gen_movi_tl(cpu_T3, val);
1.1       root     5328:         } else {
1.1.1.7 ! root     5329:             tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_ECX]));
1.1       root     5330:         }
1.1.1.7 ! root     5331:         gen_shiftd_rm_T1_T3(s, ot, opreg, op);
1.1       root     5332:         break;
                   5333: 
                   5334:         /************************/
                   5335:         /* floats */
1.1.1.6   root     5336:     case 0xd8 ... 0xdf:
1.1       root     5337:         if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
                   5338:             /* if CR0.EM or CR0.TS are set, generate an FPU exception */
                   5339:             /* XXX: what to do if illegal op ? */
                   5340:             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   5341:             break;
                   5342:         }
                   5343:         modrm = ldub_code(s->pc++);
                   5344:         mod = (modrm >> 6) & 3;
                   5345:         rm = modrm & 7;
                   5346:         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
                   5347:         if (mod != 3) {
                   5348:             /* memory op */
                   5349:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   5350:             switch(op) {
                   5351:             case 0x00 ... 0x07: /* fxxxs */
                   5352:             case 0x10 ... 0x17: /* fixxxl */
                   5353:             case 0x20 ... 0x27: /* fxxxl */
                   5354:             case 0x30 ... 0x37: /* fixxx */
                   5355:                 {
                   5356:                     int op1;
                   5357:                     op1 = op & 7;
                   5358: 
                   5359:                     switch(op >> 4) {
                   5360:                     case 0:
1.1.1.7 ! root     5361:                         gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          5362:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5363:                         gen_helper_flds_FT0(cpu_tmp2_i32);
1.1       root     5364:                         break;
                   5365:                     case 1:
1.1.1.7 ! root     5366:                         gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          5367:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5368:                         gen_helper_fildl_FT0(cpu_tmp2_i32);
1.1       root     5369:                         break;
                   5370:                     case 2:
1.1.1.7 ! root     5371:                         tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
        !          5372:                                           (s->mem_index >> 2) - 1);
        !          5373:                         gen_helper_fldl_FT0(cpu_tmp1_i64);
1.1       root     5374:                         break;
                   5375:                     case 3:
                   5376:                     default:
1.1.1.7 ! root     5377:                         gen_op_lds_T0_A0(OT_WORD + s->mem_index);
        !          5378:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5379:                         gen_helper_fildl_FT0(cpu_tmp2_i32);
1.1       root     5380:                         break;
                   5381:                     }
1.1.1.6   root     5382: 
1.1.1.7 ! root     5383:                     gen_helper_fp_arith_ST0_FT0(op1);
1.1       root     5384:                     if (op1 == 3) {
                   5385:                         /* fcomp needs pop */
1.1.1.7 ! root     5386:                         gen_helper_fpop();
1.1       root     5387:                     }
                   5388:                 }
                   5389:                 break;
                   5390:             case 0x08: /* flds */
                   5391:             case 0x0a: /* fsts */
                   5392:             case 0x0b: /* fstps */
1.1.1.3   root     5393:             case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
                   5394:             case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
                   5395:             case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
1.1       root     5396:                 switch(op & 7) {
                   5397:                 case 0:
                   5398:                     switch(op >> 4) {
                   5399:                     case 0:
1.1.1.7 ! root     5400:                         gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          5401:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5402:                         gen_helper_flds_ST0(cpu_tmp2_i32);
1.1       root     5403:                         break;
                   5404:                     case 1:
1.1.1.7 ! root     5405:                         gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          5406:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5407:                         gen_helper_fildl_ST0(cpu_tmp2_i32);
1.1       root     5408:                         break;
                   5409:                     case 2:
1.1.1.7 ! root     5410:                         tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
        !          5411:                                           (s->mem_index >> 2) - 1);
        !          5412:                         gen_helper_fldl_ST0(cpu_tmp1_i64);
1.1       root     5413:                         break;
                   5414:                     case 3:
                   5415:                     default:
1.1.1.7 ! root     5416:                         gen_op_lds_T0_A0(OT_WORD + s->mem_index);
        !          5417:                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5418:                         gen_helper_fildl_ST0(cpu_tmp2_i32);
1.1       root     5419:                         break;
                   5420:                     }
                   5421:                     break;
1.1.1.3   root     5422:                 case 1:
1.1.1.7 ! root     5423:                     /* XXX: the corresponding CPUID bit must be tested ! */
1.1.1.3   root     5424:                     switch(op >> 4) {
                   5425:                     case 1:
1.1.1.7 ! root     5426:                         gen_helper_fisttl_ST0(cpu_tmp2_i32);
        !          5427:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5428:                         gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1.1.3   root     5429:                         break;
                   5430:                     case 2:
1.1.1.7 ! root     5431:                         gen_helper_fisttll_ST0(cpu_tmp1_i64);
        !          5432:                         tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
        !          5433:                                           (s->mem_index >> 2) - 1);
1.1.1.3   root     5434:                         break;
                   5435:                     case 3:
                   5436:                     default:
1.1.1.7 ! root     5437:                         gen_helper_fistt_ST0(cpu_tmp2_i32);
        !          5438:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5439:                         gen_op_st_T0_A0(OT_WORD + s->mem_index);
        !          5440:                         break;
1.1.1.3   root     5441:                     }
1.1.1.7 ! root     5442:                     gen_helper_fpop();
1.1.1.3   root     5443:                     break;
1.1       root     5444:                 default:
                   5445:                     switch(op >> 4) {
                   5446:                     case 0:
1.1.1.7 ! root     5447:                         gen_helper_fsts_ST0(cpu_tmp2_i32);
        !          5448:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5449:                         gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1       root     5450:                         break;
                   5451:                     case 1:
1.1.1.7 ! root     5452:                         gen_helper_fistl_ST0(cpu_tmp2_i32);
        !          5453:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5454:                         gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1       root     5455:                         break;
                   5456:                     case 2:
1.1.1.7 ! root     5457:                         gen_helper_fstl_ST0(cpu_tmp1_i64);
        !          5458:                         tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
        !          5459:                                           (s->mem_index >> 2) - 1);
1.1       root     5460:                         break;
                   5461:                     case 3:
                   5462:                     default:
1.1.1.7 ! root     5463:                         gen_helper_fist_ST0(cpu_tmp2_i32);
        !          5464:                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5465:                         gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     5466:                         break;
                   5467:                     }
                   5468:                     if ((op & 7) == 3)
1.1.1.7 ! root     5469:                         gen_helper_fpop();
1.1       root     5470:                     break;
                   5471:                 }
                   5472:                 break;
                   5473:             case 0x0c: /* fldenv mem */
1.1.1.7 ! root     5474:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5475:                     gen_op_set_cc_op(s->cc_op);
        !          5476:                 gen_jmp_im(pc_start - s->cs_base);
        !          5477:                 gen_helper_fldenv(
        !          5478:                                    cpu_A0, tcg_const_i32(s->dflag));
1.1       root     5479:                 break;
                   5480:             case 0x0d: /* fldcw mem */
1.1.1.7 ! root     5481:                 gen_op_ld_T0_A0(OT_WORD + s->mem_index);
        !          5482:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5483:                 gen_helper_fldcw(cpu_tmp2_i32);
1.1       root     5484:                 break;
                   5485:             case 0x0e: /* fnstenv mem */
1.1.1.7 ! root     5486:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5487:                     gen_op_set_cc_op(s->cc_op);
        !          5488:                 gen_jmp_im(pc_start - s->cs_base);
        !          5489:                 gen_helper_fstenv(cpu_A0, tcg_const_i32(s->dflag));
1.1       root     5490:                 break;
                   5491:             case 0x0f: /* fnstcw mem */
1.1.1.7 ! root     5492:                 gen_helper_fnstcw(cpu_tmp2_i32);
        !          5493:                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5494:                 gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     5495:                 break;
                   5496:             case 0x1d: /* fldt mem */
1.1.1.7 ! root     5497:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5498:                     gen_op_set_cc_op(s->cc_op);
        !          5499:                 gen_jmp_im(pc_start - s->cs_base);
        !          5500:                 gen_helper_fldt_ST0(cpu_A0);
1.1       root     5501:                 break;
                   5502:             case 0x1f: /* fstpt mem */
1.1.1.7 ! root     5503:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5504:                     gen_op_set_cc_op(s->cc_op);
        !          5505:                 gen_jmp_im(pc_start - s->cs_base);
        !          5506:                 gen_helper_fstt_ST0(cpu_A0);
        !          5507:                 gen_helper_fpop();
1.1       root     5508:                 break;
                   5509:             case 0x2c: /* frstor mem */
1.1.1.7 ! root     5510:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5511:                     gen_op_set_cc_op(s->cc_op);
        !          5512:                 gen_jmp_im(pc_start - s->cs_base);
        !          5513:                 gen_helper_frstor(cpu_A0, tcg_const_i32(s->dflag));
1.1       root     5514:                 break;
                   5515:             case 0x2e: /* fnsave mem */
1.1.1.7 ! root     5516:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5517:                     gen_op_set_cc_op(s->cc_op);
        !          5518:                 gen_jmp_im(pc_start - s->cs_base);
        !          5519:                 gen_helper_fsave(cpu_A0, tcg_const_i32(s->dflag));
1.1       root     5520:                 break;
                   5521:             case 0x2f: /* fnstsw mem */
1.1.1.7 ! root     5522:                 gen_helper_fnstsw(cpu_tmp2_i32);
        !          5523:                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5524:                 gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     5525:                 break;
                   5526:             case 0x3c: /* fbld */
1.1.1.7 ! root     5527:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5528:                     gen_op_set_cc_op(s->cc_op);
        !          5529:                 gen_jmp_im(pc_start - s->cs_base);
        !          5530:                 gen_helper_fbld_ST0(cpu_A0);
1.1       root     5531:                 break;
                   5532:             case 0x3e: /* fbstp */
1.1.1.7 ! root     5533:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          5534:                     gen_op_set_cc_op(s->cc_op);
        !          5535:                 gen_jmp_im(pc_start - s->cs_base);
        !          5536:                 gen_helper_fbst_ST0(cpu_A0);
        !          5537:                 gen_helper_fpop();
1.1       root     5538:                 break;
                   5539:             case 0x3d: /* fildll */
1.1.1.7 ! root     5540:                 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
        !          5541:                                   (s->mem_index >> 2) - 1);
        !          5542:                 gen_helper_fildll_ST0(cpu_tmp1_i64);
1.1       root     5543:                 break;
                   5544:             case 0x3f: /* fistpll */
1.1.1.7 ! root     5545:                 gen_helper_fistll_ST0(cpu_tmp1_i64);
        !          5546:                 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
        !          5547:                                   (s->mem_index >> 2) - 1);
        !          5548:                 gen_helper_fpop();
1.1       root     5549:                 break;
                   5550:             default:
                   5551:                 goto illegal_op;
                   5552:             }
                   5553:         } else {
                   5554:             /* register float ops */
                   5555:             opreg = rm;
                   5556: 
                   5557:             switch(op) {
                   5558:             case 0x08: /* fld sti */
1.1.1.7 ! root     5559:                 gen_helper_fpush();
        !          5560:                 gen_helper_fmov_ST0_STN(tcg_const_i32((opreg + 1) & 7));
1.1       root     5561:                 break;
                   5562:             case 0x09: /* fxchg sti */
                   5563:             case 0x29: /* fxchg4 sti, undocumented op */
                   5564:             case 0x39: /* fxchg7 sti, undocumented op */
1.1.1.7 ! root     5565:                 gen_helper_fxchg_ST0_STN(tcg_const_i32(opreg));
1.1       root     5566:                 break;
                   5567:             case 0x0a: /* grp d9/2 */
                   5568:                 switch(rm) {
                   5569:                 case 0: /* fnop */
                   5570:                     /* check exceptions (FreeBSD FPU probe) */
                   5571:                     if (s->cc_op != CC_OP_DYNAMIC)
                   5572:                         gen_op_set_cc_op(s->cc_op);
                   5573:                     gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     5574:                     gen_helper_fwait();
1.1       root     5575:                     break;
                   5576:                 default:
                   5577:                     goto illegal_op;
                   5578:                 }
                   5579:                 break;
                   5580:             case 0x0c: /* grp d9/4 */
                   5581:                 switch(rm) {
                   5582:                 case 0: /* fchs */
1.1.1.7 ! root     5583:                     gen_helper_fchs_ST0();
1.1       root     5584:                     break;
                   5585:                 case 1: /* fabs */
1.1.1.7 ! root     5586:                     gen_helper_fabs_ST0();
1.1       root     5587:                     break;
                   5588:                 case 4: /* ftst */
1.1.1.7 ! root     5589:                     gen_helper_fldz_FT0();
        !          5590:                     gen_helper_fcom_ST0_FT0();
1.1       root     5591:                     break;
                   5592:                 case 5: /* fxam */
1.1.1.7 ! root     5593:                     gen_helper_fxam_ST0();
1.1       root     5594:                     break;
                   5595:                 default:
                   5596:                     goto illegal_op;
                   5597:                 }
                   5598:                 break;
                   5599:             case 0x0d: /* grp d9/5 */
                   5600:                 {
                   5601:                     switch(rm) {
                   5602:                     case 0:
1.1.1.7 ! root     5603:                         gen_helper_fpush();
        !          5604:                         gen_helper_fld1_ST0();
1.1       root     5605:                         break;
                   5606:                     case 1:
1.1.1.7 ! root     5607:                         gen_helper_fpush();
        !          5608:                         gen_helper_fldl2t_ST0();
1.1       root     5609:                         break;
                   5610:                     case 2:
1.1.1.7 ! root     5611:                         gen_helper_fpush();
        !          5612:                         gen_helper_fldl2e_ST0();
1.1       root     5613:                         break;
                   5614:                     case 3:
1.1.1.7 ! root     5615:                         gen_helper_fpush();
        !          5616:                         gen_helper_fldpi_ST0();
1.1       root     5617:                         break;
                   5618:                     case 4:
1.1.1.7 ! root     5619:                         gen_helper_fpush();
        !          5620:                         gen_helper_fldlg2_ST0();
1.1       root     5621:                         break;
                   5622:                     case 5:
1.1.1.7 ! root     5623:                         gen_helper_fpush();
        !          5624:                         gen_helper_fldln2_ST0();
1.1       root     5625:                         break;
                   5626:                     case 6:
1.1.1.7 ! root     5627:                         gen_helper_fpush();
        !          5628:                         gen_helper_fldz_ST0();
1.1       root     5629:                         break;
                   5630:                     default:
                   5631:                         goto illegal_op;
                   5632:                     }
                   5633:                 }
                   5634:                 break;
                   5635:             case 0x0e: /* grp d9/6 */
                   5636:                 switch(rm) {
                   5637:                 case 0: /* f2xm1 */
1.1.1.7 ! root     5638:                     gen_helper_f2xm1();
1.1       root     5639:                     break;
                   5640:                 case 1: /* fyl2x */
1.1.1.7 ! root     5641:                     gen_helper_fyl2x();
1.1       root     5642:                     break;
                   5643:                 case 2: /* fptan */
1.1.1.7 ! root     5644:                     gen_helper_fptan();
1.1       root     5645:                     break;
                   5646:                 case 3: /* fpatan */
1.1.1.7 ! root     5647:                     gen_helper_fpatan();
1.1       root     5648:                     break;
                   5649:                 case 4: /* fxtract */
1.1.1.7 ! root     5650:                     gen_helper_fxtract();
1.1       root     5651:                     break;
                   5652:                 case 5: /* fprem1 */
1.1.1.7 ! root     5653:                     gen_helper_fprem1();
1.1       root     5654:                     break;
                   5655:                 case 6: /* fdecstp */
1.1.1.7 ! root     5656:                     gen_helper_fdecstp();
1.1       root     5657:                     break;
                   5658:                 default:
                   5659:                 case 7: /* fincstp */
1.1.1.7 ! root     5660:                     gen_helper_fincstp();
1.1       root     5661:                     break;
                   5662:                 }
                   5663:                 break;
                   5664:             case 0x0f: /* grp d9/7 */
                   5665:                 switch(rm) {
                   5666:                 case 0: /* fprem */
1.1.1.7 ! root     5667:                     gen_helper_fprem();
1.1       root     5668:                     break;
                   5669:                 case 1: /* fyl2xp1 */
1.1.1.7 ! root     5670:                     gen_helper_fyl2xp1();
1.1       root     5671:                     break;
                   5672:                 case 2: /* fsqrt */
1.1.1.7 ! root     5673:                     gen_helper_fsqrt();
1.1       root     5674:                     break;
                   5675:                 case 3: /* fsincos */
1.1.1.7 ! root     5676:                     gen_helper_fsincos();
1.1       root     5677:                     break;
                   5678:                 case 5: /* fscale */
1.1.1.7 ! root     5679:                     gen_helper_fscale();
1.1       root     5680:                     break;
                   5681:                 case 4: /* frndint */
1.1.1.7 ! root     5682:                     gen_helper_frndint();
1.1       root     5683:                     break;
                   5684:                 case 6: /* fsin */
1.1.1.7 ! root     5685:                     gen_helper_fsin();
1.1       root     5686:                     break;
                   5687:                 default:
                   5688:                 case 7: /* fcos */
1.1.1.7 ! root     5689:                     gen_helper_fcos();
1.1       root     5690:                     break;
                   5691:                 }
                   5692:                 break;
                   5693:             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
                   5694:             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
                   5695:             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
                   5696:                 {
                   5697:                     int op1;
1.1.1.6   root     5698: 
1.1       root     5699:                     op1 = op & 7;
                   5700:                     if (op >= 0x20) {
1.1.1.7 ! root     5701:                         gen_helper_fp_arith_STN_ST0(op1, opreg);
1.1       root     5702:                         if (op >= 0x30)
1.1.1.7 ! root     5703:                             gen_helper_fpop();
1.1       root     5704:                     } else {
1.1.1.7 ! root     5705:                         gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5706:                         gen_helper_fp_arith_ST0_FT0(op1);
1.1       root     5707:                     }
                   5708:                 }
                   5709:                 break;
                   5710:             case 0x02: /* fcom */
                   5711:             case 0x22: /* fcom2, undocumented op */
1.1.1.7 ! root     5712:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5713:                 gen_helper_fcom_ST0_FT0();
1.1       root     5714:                 break;
                   5715:             case 0x03: /* fcomp */
                   5716:             case 0x23: /* fcomp3, undocumented op */
                   5717:             case 0x32: /* fcomp5, undocumented op */
1.1.1.7 ! root     5718:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5719:                 gen_helper_fcom_ST0_FT0();
        !          5720:                 gen_helper_fpop();
1.1       root     5721:                 break;
                   5722:             case 0x15: /* da/5 */
                   5723:                 switch(rm) {
                   5724:                 case 1: /* fucompp */
1.1.1.7 ! root     5725:                     gen_helper_fmov_FT0_STN(tcg_const_i32(1));
        !          5726:                     gen_helper_fucom_ST0_FT0();
        !          5727:                     gen_helper_fpop();
        !          5728:                     gen_helper_fpop();
1.1       root     5729:                     break;
                   5730:                 default:
                   5731:                     goto illegal_op;
                   5732:                 }
                   5733:                 break;
                   5734:             case 0x1c:
                   5735:                 switch(rm) {
                   5736:                 case 0: /* feni (287 only, just do nop here) */
                   5737:                     break;
                   5738:                 case 1: /* fdisi (287 only, just do nop here) */
                   5739:                     break;
                   5740:                 case 2: /* fclex */
1.1.1.7 ! root     5741:                     gen_helper_fclex();
1.1       root     5742:                     break;
                   5743:                 case 3: /* fninit */
1.1.1.7 ! root     5744:                     gen_helper_fninit();
1.1       root     5745:                     break;
                   5746:                 case 4: /* fsetpm (287 only, just do nop here) */
                   5747:                     break;
                   5748:                 default:
                   5749:                     goto illegal_op;
                   5750:                 }
                   5751:                 break;
                   5752:             case 0x1d: /* fucomi */
                   5753:                 if (s->cc_op != CC_OP_DYNAMIC)
                   5754:                     gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     5755:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5756:                 gen_helper_fucomi_ST0_FT0();
1.1       root     5757:                 s->cc_op = CC_OP_EFLAGS;
                   5758:                 break;
                   5759:             case 0x1e: /* fcomi */
                   5760:                 if (s->cc_op != CC_OP_DYNAMIC)
                   5761:                     gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     5762:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5763:                 gen_helper_fcomi_ST0_FT0();
1.1       root     5764:                 s->cc_op = CC_OP_EFLAGS;
                   5765:                 break;
                   5766:             case 0x28: /* ffree sti */
1.1.1.7 ! root     5767:                 gen_helper_ffree_STN(tcg_const_i32(opreg));
1.1.1.6   root     5768:                 break;
1.1       root     5769:             case 0x2a: /* fst sti */
1.1.1.7 ! root     5770:                 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg));
1.1       root     5771:                 break;
                   5772:             case 0x2b: /* fstp sti */
                   5773:             case 0x0b: /* fstp1 sti, undocumented op */
                   5774:             case 0x3a: /* fstp8 sti, undocumented op */
                   5775:             case 0x3b: /* fstp9 sti, undocumented op */
1.1.1.7 ! root     5776:                 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg));
        !          5777:                 gen_helper_fpop();
1.1       root     5778:                 break;
                   5779:             case 0x2c: /* fucom st(i) */
1.1.1.7 ! root     5780:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5781:                 gen_helper_fucom_ST0_FT0();
1.1       root     5782:                 break;
                   5783:             case 0x2d: /* fucomp st(i) */
1.1.1.7 ! root     5784:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5785:                 gen_helper_fucom_ST0_FT0();
        !          5786:                 gen_helper_fpop();
1.1       root     5787:                 break;
                   5788:             case 0x33: /* de/3 */
                   5789:                 switch(rm) {
                   5790:                 case 1: /* fcompp */
1.1.1.7 ! root     5791:                     gen_helper_fmov_FT0_STN(tcg_const_i32(1));
        !          5792:                     gen_helper_fcom_ST0_FT0();
        !          5793:                     gen_helper_fpop();
        !          5794:                     gen_helper_fpop();
1.1       root     5795:                     break;
                   5796:                 default:
                   5797:                     goto illegal_op;
                   5798:                 }
                   5799:                 break;
                   5800:             case 0x38: /* ffreep sti, undocumented op */
1.1.1.7 ! root     5801:                 gen_helper_ffree_STN(tcg_const_i32(opreg));
        !          5802:                 gen_helper_fpop();
1.1       root     5803:                 break;
                   5804:             case 0x3c: /* df/4 */
                   5805:                 switch(rm) {
                   5806:                 case 0:
1.1.1.7 ! root     5807:                     gen_helper_fnstsw(cpu_tmp2_i32);
        !          5808:                     tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
        !          5809:                     gen_op_mov_reg_T0(OT_WORD, R_EAX);
1.1       root     5810:                     break;
                   5811:                 default:
                   5812:                     goto illegal_op;
                   5813:                 }
                   5814:                 break;
                   5815:             case 0x3d: /* fucomip */
                   5816:                 if (s->cc_op != CC_OP_DYNAMIC)
                   5817:                     gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     5818:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5819:                 gen_helper_fucomi_ST0_FT0();
        !          5820:                 gen_helper_fpop();
1.1       root     5821:                 s->cc_op = CC_OP_EFLAGS;
                   5822:                 break;
                   5823:             case 0x3e: /* fcomip */
                   5824:                 if (s->cc_op != CC_OP_DYNAMIC)
                   5825:                     gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     5826:                 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
        !          5827:                 gen_helper_fcomi_ST0_FT0();
        !          5828:                 gen_helper_fpop();
1.1       root     5829:                 s->cc_op = CC_OP_EFLAGS;
                   5830:                 break;
                   5831:             case 0x10 ... 0x13: /* fcmovxx */
                   5832:             case 0x18 ... 0x1b:
                   5833:                 {
1.1.1.7 ! root     5834:                     int op1, l1;
        !          5835:                     static const uint8_t fcmov_cc[8] = {
1.1       root     5836:                         (JCC_B << 1),
                   5837:                         (JCC_Z << 1),
                   5838:                         (JCC_BE << 1),
                   5839:                         (JCC_P << 1),
                   5840:                     };
1.1.1.7 ! root     5841:                     op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
        !          5842:                     l1 = gen_new_label();
        !          5843:                     gen_jcc1(s, s->cc_op, op1, l1);
        !          5844:                     gen_helper_fmov_ST0_STN(tcg_const_i32(opreg));
        !          5845:                     gen_set_label(l1);
1.1       root     5846:                 }
                   5847:                 break;
                   5848:             default:
                   5849:                 goto illegal_op;
                   5850:             }
                   5851:         }
                   5852:         break;
                   5853:         /************************/
                   5854:         /* string ops */
                   5855: 
                   5856:     case 0xa4: /* movsS */
                   5857:     case 0xa5:
                   5858:         if ((b & 1) == 0)
                   5859:             ot = OT_BYTE;
                   5860:         else
                   5861:             ot = dflag + OT_WORD;
                   5862: 
                   5863:         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
                   5864:             gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
                   5865:         } else {
                   5866:             gen_movs(s, ot);
                   5867:         }
                   5868:         break;
1.1.1.6   root     5869: 
1.1       root     5870:     case 0xaa: /* stosS */
                   5871:     case 0xab:
                   5872:         if ((b & 1) == 0)
                   5873:             ot = OT_BYTE;
                   5874:         else
                   5875:             ot = dflag + OT_WORD;
                   5876: 
                   5877:         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
                   5878:             gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
                   5879:         } else {
                   5880:             gen_stos(s, ot);
                   5881:         }
                   5882:         break;
                   5883:     case 0xac: /* lodsS */
                   5884:     case 0xad:
                   5885:         if ((b & 1) == 0)
                   5886:             ot = OT_BYTE;
                   5887:         else
                   5888:             ot = dflag + OT_WORD;
                   5889:         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
                   5890:             gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
                   5891:         } else {
                   5892:             gen_lods(s, ot);
                   5893:         }
                   5894:         break;
                   5895:     case 0xae: /* scasS */
                   5896:     case 0xaf:
                   5897:         if ((b & 1) == 0)
                   5898:             ot = OT_BYTE;
                   5899:         else
                   5900:             ot = dflag + OT_WORD;
                   5901:         if (prefixes & PREFIX_REPNZ) {
                   5902:             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
                   5903:         } else if (prefixes & PREFIX_REPZ) {
                   5904:             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
                   5905:         } else {
                   5906:             gen_scas(s, ot);
                   5907:             s->cc_op = CC_OP_SUBB + ot;
                   5908:         }
                   5909:         break;
                   5910: 
                   5911:     case 0xa6: /* cmpsS */
                   5912:     case 0xa7:
                   5913:         if ((b & 1) == 0)
                   5914:             ot = OT_BYTE;
                   5915:         else
                   5916:             ot = dflag + OT_WORD;
                   5917:         if (prefixes & PREFIX_REPNZ) {
                   5918:             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
                   5919:         } else if (prefixes & PREFIX_REPZ) {
                   5920:             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
                   5921:         } else {
                   5922:             gen_cmps(s, ot);
                   5923:             s->cc_op = CC_OP_SUBB + ot;
                   5924:         }
                   5925:         break;
                   5926:     case 0x6c: /* insS */
                   5927:     case 0x6d:
                   5928:         if ((b & 1) == 0)
                   5929:             ot = OT_BYTE;
                   5930:         else
                   5931:             ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 ! root     5932:         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1.1.6   root     5933:         gen_op_andl_T0_ffff();
1.1.1.7 ! root     5934:         gen_check_io(s, ot, pc_start - s->cs_base, 
        !          5935:                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
1.1       root     5936:         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
                   5937:             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
                   5938:         } else {
                   5939:             gen_ins(s, ot);
1.1.1.7 ! root     5940:             if (use_icount) {
        !          5941:                 gen_jmp(s, s->pc - s->cs_base);
        !          5942:             }
1.1       root     5943:         }
                   5944:         break;
                   5945:     case 0x6e: /* outsS */
                   5946:     case 0x6f:
                   5947:         if ((b & 1) == 0)
                   5948:             ot = OT_BYTE;
                   5949:         else
                   5950:             ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 ! root     5951:         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1.1.6   root     5952:         gen_op_andl_T0_ffff();
1.1.1.7 ! root     5953:         gen_check_io(s, ot, pc_start - s->cs_base,
        !          5954:                      svm_is_rep(prefixes) | 4);
1.1       root     5955:         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
                   5956:             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
                   5957:         } else {
                   5958:             gen_outs(s, ot);
1.1.1.7 ! root     5959:             if (use_icount) {
        !          5960:                 gen_jmp(s, s->pc - s->cs_base);
        !          5961:             }
1.1       root     5962:         }
                   5963:         break;
                   5964: 
                   5965:         /************************/
                   5966:         /* port I/O */
1.1.1.6   root     5967: 
1.1       root     5968:     case 0xe4:
                   5969:     case 0xe5:
                   5970:         if ((b & 1) == 0)
                   5971:             ot = OT_BYTE;
                   5972:         else
                   5973:             ot = dflag ? OT_LONG : OT_WORD;
                   5974:         val = ldub_code(s->pc++);
                   5975:         gen_op_movl_T0_im(val);
1.1.1.7 ! root     5976:         gen_check_io(s, ot, pc_start - s->cs_base,
        !          5977:                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
        !          5978:         if (use_icount)
        !          5979:             gen_io_start();
        !          5980:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          5981:         gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
        !          5982:         gen_op_mov_reg_T1(ot, R_EAX);
        !          5983:         if (use_icount) {
        !          5984:             gen_io_end();
        !          5985:             gen_jmp(s, s->pc - s->cs_base);
        !          5986:         }
1.1       root     5987:         break;
                   5988:     case 0xe6:
                   5989:     case 0xe7:
                   5990:         if ((b & 1) == 0)
                   5991:             ot = OT_BYTE;
                   5992:         else
                   5993:             ot = dflag ? OT_LONG : OT_WORD;
                   5994:         val = ldub_code(s->pc++);
                   5995:         gen_op_movl_T0_im(val);
1.1.1.7 ! root     5996:         gen_check_io(s, ot, pc_start - s->cs_base,
        !          5997:                      svm_is_rep(prefixes));
        !          5998:         gen_op_mov_TN_reg(ot, 1, R_EAX);
        !          5999: 
        !          6000:         if (use_icount)
        !          6001:             gen_io_start();
        !          6002:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          6003:         tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
        !          6004:         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
        !          6005:         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
        !          6006:         if (use_icount) {
        !          6007:             gen_io_end();
        !          6008:             gen_jmp(s, s->pc - s->cs_base);
        !          6009:         }
1.1       root     6010:         break;
                   6011:     case 0xec:
                   6012:     case 0xed:
                   6013:         if ((b & 1) == 0)
                   6014:             ot = OT_BYTE;
                   6015:         else
                   6016:             ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 ! root     6017:         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1       root     6018:         gen_op_andl_T0_ffff();
1.1.1.7 ! root     6019:         gen_check_io(s, ot, pc_start - s->cs_base,
        !          6020:                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
        !          6021:         if (use_icount)
        !          6022:             gen_io_start();
        !          6023:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          6024:         gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
        !          6025:         gen_op_mov_reg_T1(ot, R_EAX);
        !          6026:         if (use_icount) {
        !          6027:             gen_io_end();
        !          6028:             gen_jmp(s, s->pc - s->cs_base);
        !          6029:         }
1.1       root     6030:         break;
                   6031:     case 0xee:
                   6032:     case 0xef:
                   6033:         if ((b & 1) == 0)
                   6034:             ot = OT_BYTE;
                   6035:         else
                   6036:             ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 ! root     6037:         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1       root     6038:         gen_op_andl_T0_ffff();
1.1.1.7 ! root     6039:         gen_check_io(s, ot, pc_start - s->cs_base,
        !          6040:                      svm_is_rep(prefixes));
        !          6041:         gen_op_mov_TN_reg(ot, 1, R_EAX);
        !          6042: 
        !          6043:         if (use_icount)
        !          6044:             gen_io_start();
        !          6045:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          6046:         tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
        !          6047:         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
        !          6048:         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
        !          6049:         if (use_icount) {
        !          6050:             gen_io_end();
        !          6051:             gen_jmp(s, s->pc - s->cs_base);
        !          6052:         }
1.1       root     6053:         break;
                   6054: 
                   6055:         /************************/
                   6056:         /* control */
                   6057:     case 0xc2: /* ret im */
                   6058:         val = ldsw_code(s->pc);
                   6059:         s->pc += 2;
                   6060:         gen_pop_T0(s);
                   6061:         if (CODE64(s) && s->dflag)
                   6062:             s->dflag = 2;
                   6063:         gen_stack_update(s, val + (2 << s->dflag));
                   6064:         if (s->dflag == 0)
                   6065:             gen_op_andl_T0_ffff();
                   6066:         gen_op_jmp_T0();
                   6067:         gen_eob(s);
                   6068:         break;
                   6069:     case 0xc3: /* ret */
                   6070:         gen_pop_T0(s);
                   6071:         gen_pop_update(s);
                   6072:         if (s->dflag == 0)
                   6073:             gen_op_andl_T0_ffff();
                   6074:         gen_op_jmp_T0();
                   6075:         gen_eob(s);
                   6076:         break;
                   6077:     case 0xca: /* lret im */
                   6078:         val = ldsw_code(s->pc);
                   6079:         s->pc += 2;
                   6080:     do_lret:
                   6081:         if (s->pe && !s->vm86) {
                   6082:             if (s->cc_op != CC_OP_DYNAMIC)
                   6083:                 gen_op_set_cc_op(s->cc_op);
                   6084:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6085:             gen_helper_lret_protected(tcg_const_i32(s->dflag),
        !          6086:                                       tcg_const_i32(val));
1.1       root     6087:         } else {
                   6088:             gen_stack_A0(s);
                   6089:             /* pop offset */
1.1.1.7 ! root     6090:             gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
1.1       root     6091:             if (s->dflag == 0)
                   6092:                 gen_op_andl_T0_ffff();
                   6093:             /* NOTE: keeping EIP updated is not a problem in case of
                   6094:                exception */
                   6095:             gen_op_jmp_T0();
                   6096:             /* pop selector */
                   6097:             gen_op_addl_A0_im(2 << s->dflag);
1.1.1.7 ! root     6098:             gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
        !          6099:             gen_op_movl_seg_T0_vm(R_CS);
1.1       root     6100:             /* add stack offset */
                   6101:             gen_stack_update(s, val + (4 << s->dflag));
                   6102:         }
                   6103:         gen_eob(s);
                   6104:         break;
                   6105:     case 0xcb: /* lret */
                   6106:         val = 0;
                   6107:         goto do_lret;
                   6108:     case 0xcf: /* iret */
1.1.1.7 ! root     6109:         gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
1.1       root     6110:         if (!s->pe) {
                   6111:             /* real mode */
1.1.1.7 ! root     6112:             gen_helper_iret_real(tcg_const_i32(s->dflag));
1.1       root     6113:             s->cc_op = CC_OP_EFLAGS;
                   6114:         } else if (s->vm86) {
                   6115:             if (s->iopl != 3) {
                   6116:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6117:             } else {
1.1.1.7 ! root     6118:                 gen_helper_iret_real(tcg_const_i32(s->dflag));
1.1       root     6119:                 s->cc_op = CC_OP_EFLAGS;
                   6120:             }
                   6121:         } else {
                   6122:             if (s->cc_op != CC_OP_DYNAMIC)
                   6123:                 gen_op_set_cc_op(s->cc_op);
                   6124:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6125:             gen_helper_iret_protected(tcg_const_i32(s->dflag), 
        !          6126:                                       tcg_const_i32(s->pc - s->cs_base));
1.1       root     6127:             s->cc_op = CC_OP_EFLAGS;
                   6128:         }
                   6129:         gen_eob(s);
                   6130:         break;
                   6131:     case 0xe8: /* call im */
                   6132:         {
                   6133:             if (dflag)
                   6134:                 tval = (int32_t)insn_get(s, OT_LONG);
                   6135:             else
                   6136:                 tval = (int16_t)insn_get(s, OT_WORD);
                   6137:             next_eip = s->pc - s->cs_base;
                   6138:             tval += next_eip;
                   6139:             if (s->dflag == 0)
                   6140:                 tval &= 0xffff;
                   6141:             gen_movtl_T0_im(next_eip);
                   6142:             gen_push_T0(s);
                   6143:             gen_jmp(s, tval);
                   6144:         }
                   6145:         break;
                   6146:     case 0x9a: /* lcall im */
                   6147:         {
                   6148:             unsigned int selector, offset;
1.1.1.6   root     6149: 
1.1       root     6150:             if (CODE64(s))
                   6151:                 goto illegal_op;
                   6152:             ot = dflag ? OT_LONG : OT_WORD;
                   6153:             offset = insn_get(s, ot);
                   6154:             selector = insn_get(s, OT_WORD);
1.1.1.6   root     6155: 
1.1       root     6156:             gen_op_movl_T0_im(selector);
                   6157:             gen_op_movl_T1_imu(offset);
                   6158:         }
                   6159:         goto do_lcall;
                   6160:     case 0xe9: /* jmp im */
                   6161:         if (dflag)
                   6162:             tval = (int32_t)insn_get(s, OT_LONG);
                   6163:         else
                   6164:             tval = (int16_t)insn_get(s, OT_WORD);
                   6165:         tval += s->pc - s->cs_base;
                   6166:         if (s->dflag == 0)
                   6167:             tval &= 0xffff;
1.1.1.7 ! root     6168:         else if(!CODE64(s))
        !          6169:             tval &= 0xffffffff;
1.1       root     6170:         gen_jmp(s, tval);
                   6171:         break;
                   6172:     case 0xea: /* ljmp im */
                   6173:         {
                   6174:             unsigned int selector, offset;
                   6175: 
                   6176:             if (CODE64(s))
                   6177:                 goto illegal_op;
                   6178:             ot = dflag ? OT_LONG : OT_WORD;
                   6179:             offset = insn_get(s, ot);
                   6180:             selector = insn_get(s, OT_WORD);
1.1.1.6   root     6181: 
1.1       root     6182:             gen_op_movl_T0_im(selector);
                   6183:             gen_op_movl_T1_imu(offset);
                   6184:         }
                   6185:         goto do_ljmp;
                   6186:     case 0xeb: /* jmp Jb */
                   6187:         tval = (int8_t)insn_get(s, OT_BYTE);
                   6188:         tval += s->pc - s->cs_base;
                   6189:         if (s->dflag == 0)
                   6190:             tval &= 0xffff;
                   6191:         gen_jmp(s, tval);
                   6192:         break;
                   6193:     case 0x70 ... 0x7f: /* jcc Jb */
                   6194:         tval = (int8_t)insn_get(s, OT_BYTE);
                   6195:         goto do_jcc;
                   6196:     case 0x180 ... 0x18f: /* jcc Jv */
                   6197:         if (dflag) {
                   6198:             tval = (int32_t)insn_get(s, OT_LONG);
                   6199:         } else {
1.1.1.6   root     6200:             tval = (int16_t)insn_get(s, OT_WORD);
1.1       root     6201:         }
                   6202:     do_jcc:
                   6203:         next_eip = s->pc - s->cs_base;
                   6204:         tval += next_eip;
                   6205:         if (s->dflag == 0)
                   6206:             tval &= 0xffff;
                   6207:         gen_jcc(s, b, tval, next_eip);
                   6208:         break;
                   6209: 
                   6210:     case 0x190 ... 0x19f: /* setcc Gv */
                   6211:         modrm = ldub_code(s->pc++);
                   6212:         gen_setcc(s, b);
                   6213:         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
                   6214:         break;
                   6215:     case 0x140 ... 0x14f: /* cmov Gv, Ev */
1.1.1.7 ! root     6216:         {
        !          6217:             int l1;
        !          6218:             TCGv t0;
        !          6219: 
        !          6220:             ot = dflag + OT_WORD;
        !          6221:             modrm = ldub_code(s->pc++);
        !          6222:             reg = ((modrm >> 3) & 7) | rex_r;
        !          6223:             mod = (modrm >> 6) & 3;
        !          6224:             t0 = tcg_temp_local_new();
        !          6225:             if (mod != 3) {
        !          6226:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
        !          6227:                 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
        !          6228:             } else {
        !          6229:                 rm = (modrm & 7) | REX_B(s);
        !          6230:                 gen_op_mov_v_reg(ot, t0, rm);
        !          6231:             }
        !          6232: #ifdef TARGET_X86_64
        !          6233:             if (ot == OT_LONG) {
        !          6234:                 /* XXX: specific Intel behaviour ? */
        !          6235:                 l1 = gen_new_label();
        !          6236:                 gen_jcc1(s, s->cc_op, b ^ 1, l1);
        !          6237:                 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
        !          6238:                 gen_set_label(l1);
        !          6239:                 tcg_gen_movi_tl(cpu_tmp0, 0);
        !          6240:                 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
        !          6241:             } else
        !          6242: #endif
        !          6243:             {
        !          6244:                 l1 = gen_new_label();
        !          6245:                 gen_jcc1(s, s->cc_op, b ^ 1, l1);
        !          6246:                 gen_op_mov_reg_v(ot, reg, t0);
        !          6247:                 gen_set_label(l1);
        !          6248:             }
        !          6249:             tcg_temp_free(t0);
1.1       root     6250:         }
                   6251:         break;
1.1.1.6   root     6252: 
1.1       root     6253:         /************************/
                   6254:         /* flags */
                   6255:     case 0x9c: /* pushf */
1.1.1.7 ! root     6256:         gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
1.1       root     6257:         if (s->vm86 && s->iopl != 3) {
                   6258:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6259:         } else {
                   6260:             if (s->cc_op != CC_OP_DYNAMIC)
                   6261:                 gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6262:             gen_helper_read_eflags(cpu_T[0]);
1.1       root     6263:             gen_push_T0(s);
                   6264:         }
                   6265:         break;
                   6266:     case 0x9d: /* popf */
1.1.1.7 ! root     6267:         gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
1.1       root     6268:         if (s->vm86 && s->iopl != 3) {
                   6269:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6270:         } else {
                   6271:             gen_pop_T0(s);
                   6272:             if (s->cpl == 0) {
                   6273:                 if (s->dflag) {
1.1.1.7 ! root     6274:                     gen_helper_write_eflags(cpu_T[0],
        !          6275:                                        tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)));
1.1       root     6276:                 } else {
1.1.1.7 ! root     6277:                     gen_helper_write_eflags(cpu_T[0],
        !          6278:                                        tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff));
1.1       root     6279:                 }
                   6280:             } else {
                   6281:                 if (s->cpl <= s->iopl) {
                   6282:                     if (s->dflag) {
1.1.1.7 ! root     6283:                         gen_helper_write_eflags(cpu_T[0],
        !          6284:                                            tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)));
1.1       root     6285:                     } else {
1.1.1.7 ! root     6286:                         gen_helper_write_eflags(cpu_T[0],
        !          6287:                                            tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff));
1.1       root     6288:                     }
                   6289:                 } else {
                   6290:                     if (s->dflag) {
1.1.1.7 ! root     6291:                         gen_helper_write_eflags(cpu_T[0],
        !          6292:                                            tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK)));
1.1       root     6293:                     } else {
1.1.1.7 ! root     6294:                         gen_helper_write_eflags(cpu_T[0],
        !          6295:                                            tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff));
1.1       root     6296:                     }
                   6297:                 }
                   6298:             }
                   6299:             gen_pop_update(s);
                   6300:             s->cc_op = CC_OP_EFLAGS;
                   6301:             /* abort translation because TF flag may change */
                   6302:             gen_jmp_im(s->pc - s->cs_base);
                   6303:             gen_eob(s);
                   6304:         }
                   6305:         break;
                   6306:     case 0x9e: /* sahf */
1.1.1.7 ! root     6307:         if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
1.1       root     6308:             goto illegal_op;
1.1.1.7 ! root     6309:         gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
1.1       root     6310:         if (s->cc_op != CC_OP_DYNAMIC)
                   6311:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6312:         gen_compute_eflags(cpu_cc_src);
        !          6313:         tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
        !          6314:         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
        !          6315:         tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
1.1       root     6316:         s->cc_op = CC_OP_EFLAGS;
                   6317:         break;
                   6318:     case 0x9f: /* lahf */
1.1.1.7 ! root     6319:         if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
1.1       root     6320:             goto illegal_op;
                   6321:         if (s->cc_op != CC_OP_DYNAMIC)
                   6322:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6323:         gen_compute_eflags(cpu_T[0]);
        !          6324:         /* Note: gen_compute_eflags() only gives the condition codes */
        !          6325:         tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02);
        !          6326:         gen_op_mov_reg_T0(OT_BYTE, R_AH);
1.1       root     6327:         break;
                   6328:     case 0xf5: /* cmc */
                   6329:         if (s->cc_op != CC_OP_DYNAMIC)
                   6330:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6331:         gen_compute_eflags(cpu_cc_src);
        !          6332:         tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
1.1       root     6333:         s->cc_op = CC_OP_EFLAGS;
                   6334:         break;
                   6335:     case 0xf8: /* clc */
                   6336:         if (s->cc_op != CC_OP_DYNAMIC)
                   6337:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6338:         gen_compute_eflags(cpu_cc_src);
        !          6339:         tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
1.1       root     6340:         s->cc_op = CC_OP_EFLAGS;
                   6341:         break;
                   6342:     case 0xf9: /* stc */
                   6343:         if (s->cc_op != CC_OP_DYNAMIC)
                   6344:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6345:         gen_compute_eflags(cpu_cc_src);
        !          6346:         tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
1.1       root     6347:         s->cc_op = CC_OP_EFLAGS;
                   6348:         break;
                   6349:     case 0xfc: /* cld */
1.1.1.7 ! root     6350:         tcg_gen_movi_i32(cpu_tmp2_i32, 1);
        !          6351:         tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
1.1       root     6352:         break;
                   6353:     case 0xfd: /* std */
1.1.1.7 ! root     6354:         tcg_gen_movi_i32(cpu_tmp2_i32, -1);
        !          6355:         tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
1.1       root     6356:         break;
                   6357: 
                   6358:         /************************/
                   6359:         /* bit operations */
                   6360:     case 0x1ba: /* bt/bts/btr/btc Gv, im */
                   6361:         ot = dflag + OT_WORD;
                   6362:         modrm = ldub_code(s->pc++);
1.1.1.3   root     6363:         op = (modrm >> 3) & 7;
1.1       root     6364:         mod = (modrm >> 6) & 3;
                   6365:         rm = (modrm & 7) | REX_B(s);
                   6366:         if (mod != 3) {
                   6367:             s->rip_offset = 1;
                   6368:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     6369:             gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     6370:         } else {
1.1.1.7 ! root     6371:             gen_op_mov_TN_reg(ot, 0, rm);
1.1       root     6372:         }
                   6373:         /* load shift */
                   6374:         val = ldub_code(s->pc++);
                   6375:         gen_op_movl_T1_im(val);
                   6376:         if (op < 4)
                   6377:             goto illegal_op;
                   6378:         op -= 4;
1.1.1.7 ! root     6379:         goto bt_op;
1.1       root     6380:     case 0x1a3: /* bt Gv, Ev */
                   6381:         op = 0;
                   6382:         goto do_btx;
                   6383:     case 0x1ab: /* bts */
                   6384:         op = 1;
                   6385:         goto do_btx;
                   6386:     case 0x1b3: /* btr */
                   6387:         op = 2;
                   6388:         goto do_btx;
                   6389:     case 0x1bb: /* btc */
                   6390:         op = 3;
                   6391:     do_btx:
                   6392:         ot = dflag + OT_WORD;
                   6393:         modrm = ldub_code(s->pc++);
                   6394:         reg = ((modrm >> 3) & 7) | rex_r;
                   6395:         mod = (modrm >> 6) & 3;
                   6396:         rm = (modrm & 7) | REX_B(s);
1.1.1.7 ! root     6397:         gen_op_mov_TN_reg(OT_LONG, 1, reg);
1.1       root     6398:         if (mod != 3) {
                   6399:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   6400:             /* specific case: we need to add a displacement */
1.1.1.7 ! root     6401:             gen_exts(ot, cpu_T[1]);
        !          6402:             tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
        !          6403:             tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
        !          6404:             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
        !          6405:             gen_op_ld_T0_A0(ot + s->mem_index);
1.1       root     6406:         } else {
1.1.1.7 ! root     6407:             gen_op_mov_TN_reg(ot, 0, rm);
        !          6408:         }
        !          6409:     bt_op:
        !          6410:         tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
        !          6411:         switch(op) {
        !          6412:         case 0:
        !          6413:             tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
        !          6414:             tcg_gen_movi_tl(cpu_cc_dst, 0);
        !          6415:             break;
        !          6416:         case 1:
        !          6417:             tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
        !          6418:             tcg_gen_movi_tl(cpu_tmp0, 1);
        !          6419:             tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
        !          6420:             tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !          6421:             break;
        !          6422:         case 2:
        !          6423:             tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
        !          6424:             tcg_gen_movi_tl(cpu_tmp0, 1);
        !          6425:             tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
        !          6426:             tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
        !          6427:             tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !          6428:             break;
        !          6429:         default:
        !          6430:         case 3:
        !          6431:             tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
        !          6432:             tcg_gen_movi_tl(cpu_tmp0, 1);
        !          6433:             tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
        !          6434:             tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
        !          6435:             break;
1.1       root     6436:         }
                   6437:         s->cc_op = CC_OP_SARB + ot;
                   6438:         if (op != 0) {
                   6439:             if (mod != 3)
1.1.1.7 ! root     6440:                 gen_op_st_T0_A0(ot + s->mem_index);
1.1       root     6441:             else
1.1.1.7 ! root     6442:                 gen_op_mov_reg_T0(ot, rm);
        !          6443:             tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
        !          6444:             tcg_gen_movi_tl(cpu_cc_dst, 0);
1.1       root     6445:         }
                   6446:         break;
                   6447:     case 0x1bc: /* bsf */
                   6448:     case 0x1bd: /* bsr */
1.1.1.7 ! root     6449:         {
        !          6450:             int label1;
        !          6451:             TCGv t0;
        !          6452: 
        !          6453:             ot = dflag + OT_WORD;
        !          6454:             modrm = ldub_code(s->pc++);
        !          6455:             reg = ((modrm >> 3) & 7) | rex_r;
        !          6456:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
        !          6457:             gen_extu(ot, cpu_T[0]);
        !          6458:             label1 = gen_new_label();
        !          6459:             tcg_gen_movi_tl(cpu_cc_dst, 0);
        !          6460:             t0 = tcg_temp_local_new();
        !          6461:             tcg_gen_mov_tl(t0, cpu_T[0]);
        !          6462:             tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1);
        !          6463:             if (b & 1) {
        !          6464:                 gen_helper_bsr(cpu_T[0], t0);
        !          6465:             } else {
        !          6466:                 gen_helper_bsf(cpu_T[0], t0);
        !          6467:             }
        !          6468:             gen_op_mov_reg_T0(ot, reg);
        !          6469:             tcg_gen_movi_tl(cpu_cc_dst, 1);
        !          6470:             gen_set_label(label1);
        !          6471:             tcg_gen_discard_tl(cpu_cc_src);
        !          6472:             s->cc_op = CC_OP_LOGICB + ot;
        !          6473:             tcg_temp_free(t0);
        !          6474:         }
1.1       root     6475:         break;
                   6476:         /************************/
                   6477:         /* bcd */
                   6478:     case 0x27: /* daa */
                   6479:         if (CODE64(s))
                   6480:             goto illegal_op;
                   6481:         if (s->cc_op != CC_OP_DYNAMIC)
                   6482:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6483:         gen_helper_daa();
1.1       root     6484:         s->cc_op = CC_OP_EFLAGS;
                   6485:         break;
                   6486:     case 0x2f: /* das */
                   6487:         if (CODE64(s))
                   6488:             goto illegal_op;
                   6489:         if (s->cc_op != CC_OP_DYNAMIC)
                   6490:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6491:         gen_helper_das();
1.1       root     6492:         s->cc_op = CC_OP_EFLAGS;
                   6493:         break;
                   6494:     case 0x37: /* aaa */
                   6495:         if (CODE64(s))
                   6496:             goto illegal_op;
                   6497:         if (s->cc_op != CC_OP_DYNAMIC)
                   6498:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6499:         gen_helper_aaa();
1.1       root     6500:         s->cc_op = CC_OP_EFLAGS;
                   6501:         break;
                   6502:     case 0x3f: /* aas */
                   6503:         if (CODE64(s))
                   6504:             goto illegal_op;
                   6505:         if (s->cc_op != CC_OP_DYNAMIC)
                   6506:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6507:         gen_helper_aas();
1.1       root     6508:         s->cc_op = CC_OP_EFLAGS;
                   6509:         break;
                   6510:     case 0xd4: /* aam */
                   6511:         if (CODE64(s))
                   6512:             goto illegal_op;
                   6513:         val = ldub_code(s->pc++);
1.1.1.6   root     6514:         if (val == 0) {
                   6515:             gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
                   6516:         } else {
1.1.1.7 ! root     6517:             gen_helper_aam(tcg_const_i32(val));
1.1.1.6   root     6518:             s->cc_op = CC_OP_LOGICB;
                   6519:         }
1.1       root     6520:         break;
                   6521:     case 0xd5: /* aad */
                   6522:         if (CODE64(s))
                   6523:             goto illegal_op;
                   6524:         val = ldub_code(s->pc++);
1.1.1.7 ! root     6525:         gen_helper_aad(tcg_const_i32(val));
1.1       root     6526:         s->cc_op = CC_OP_LOGICB;
                   6527:         break;
                   6528:         /************************/
                   6529:         /* misc */
                   6530:     case 0x90: /* nop */
                   6531:         /* XXX: xchg + rex handling */
                   6532:         /* XXX: correct lock test for all insn */
                   6533:         if (prefixes & PREFIX_LOCK)
                   6534:             goto illegal_op;
1.1.1.6   root     6535:         if (prefixes & PREFIX_REPZ) {
                   6536:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
                   6537:         }
1.1       root     6538:         break;
                   6539:     case 0x9b: /* fwait */
1.1.1.6   root     6540:         if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
1.1       root     6541:             (HF_MP_MASK | HF_TS_MASK)) {
                   6542:             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   6543:         } else {
                   6544:             if (s->cc_op != CC_OP_DYNAMIC)
                   6545:                 gen_op_set_cc_op(s->cc_op);
                   6546:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6547:             gen_helper_fwait();
1.1       root     6548:         }
                   6549:         break;
                   6550:     case 0xcc: /* int3 */
                   6551:         gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
                   6552:         break;
                   6553:     case 0xcd: /* int N */
                   6554:         val = ldub_code(s->pc++);
                   6555:         if (s->vm86 && s->iopl != 3) {
1.1.1.6   root     6556:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1.1       root     6557:         } else {
                   6558:             gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
                   6559:         }
                   6560:         break;
                   6561:     case 0xce: /* into */
                   6562:         if (CODE64(s))
                   6563:             goto illegal_op;
                   6564:         if (s->cc_op != CC_OP_DYNAMIC)
                   6565:             gen_op_set_cc_op(s->cc_op);
                   6566:         gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6567:         gen_helper_into(tcg_const_i32(s->pc - pc_start));
1.1       root     6568:         break;
1.1.1.7 ! root     6569: #ifdef WANT_ICEBP
1.1       root     6570:     case 0xf1: /* icebp (undocumented, exits to external debugger) */
1.1.1.7 ! root     6571:         gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
1.1       root     6572: #if 1
                   6573:         gen_debug(s, pc_start - s->cs_base);
                   6574: #else
                   6575:         /* start debug */
                   6576:         tb_flush(cpu_single_env);
                   6577:         cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
                   6578: #endif
                   6579:         break;
1.1.1.7 ! root     6580: #endif
1.1       root     6581:     case 0xfa: /* cli */
                   6582:         if (!s->vm86) {
                   6583:             if (s->cpl <= s->iopl) {
1.1.1.7 ! root     6584:                 gen_helper_cli();
1.1       root     6585:             } else {
                   6586:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6587:             }
                   6588:         } else {
                   6589:             if (s->iopl == 3) {
1.1.1.7 ! root     6590:                 gen_helper_cli();
1.1       root     6591:             } else {
                   6592:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6593:             }
                   6594:         }
                   6595:         break;
                   6596:     case 0xfb: /* sti */
                   6597:         if (!s->vm86) {
                   6598:             if (s->cpl <= s->iopl) {
                   6599:             gen_sti:
1.1.1.7 ! root     6600:                 gen_helper_sti();
1.1       root     6601:                 /* interruptions are enabled only the first insn after sti */
                   6602:                 /* If several instructions disable interrupts, only the
                   6603:                    _first_ does it */
                   6604:                 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 ! root     6605:                     gen_helper_set_inhibit_irq();
1.1       root     6606:                 /* give a chance to handle pending irqs */
                   6607:                 gen_jmp_im(s->pc - s->cs_base);
                   6608:                 gen_eob(s);
                   6609:             } else {
                   6610:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6611:             }
                   6612:         } else {
                   6613:             if (s->iopl == 3) {
                   6614:                 goto gen_sti;
                   6615:             } else {
                   6616:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6617:             }
                   6618:         }
                   6619:         break;
                   6620:     case 0x62: /* bound */
                   6621:         if (CODE64(s))
                   6622:             goto illegal_op;
                   6623:         ot = dflag ? OT_LONG : OT_WORD;
                   6624:         modrm = ldub_code(s->pc++);
                   6625:         reg = (modrm >> 3) & 7;
                   6626:         mod = (modrm >> 6) & 3;
                   6627:         if (mod == 3)
                   6628:             goto illegal_op;
1.1.1.7 ! root     6629:         gen_op_mov_TN_reg(ot, 0, reg);
1.1       root     6630:         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   6631:         gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6632:         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1.1       root     6633:         if (ot == OT_WORD)
1.1.1.7 ! root     6634:             gen_helper_boundw(cpu_A0, cpu_tmp2_i32);
1.1       root     6635:         else
1.1.1.7 ! root     6636:             gen_helper_boundl(cpu_A0, cpu_tmp2_i32);
1.1       root     6637:         break;
                   6638:     case 0x1c8 ... 0x1cf: /* bswap reg */
                   6639:         reg = (b & 7) | REX_B(s);
                   6640: #ifdef TARGET_X86_64
                   6641:         if (dflag == 2) {
1.1.1.7 ! root     6642:             gen_op_mov_TN_reg(OT_QUAD, 0, reg);
        !          6643:             tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]);
        !          6644:             gen_op_mov_reg_T0(OT_QUAD, reg);
1.1.1.6   root     6645:         } else
1.1       root     6646:         {
1.1.1.7 ! root     6647:             TCGv_i32 tmp0;
        !          6648:             gen_op_mov_TN_reg(OT_LONG, 0, reg);
        !          6649:             
        !          6650:             tmp0 = tcg_temp_new_i32();
        !          6651:             tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]);
        !          6652:             tcg_gen_bswap_i32(tmp0, tmp0);
        !          6653:             tcg_gen_extu_i32_i64(cpu_T[0], tmp0);
        !          6654:             gen_op_mov_reg_T0(OT_LONG, reg);
        !          6655:         }
        !          6656: #else
        !          6657:         {
        !          6658:             gen_op_mov_TN_reg(OT_LONG, 0, reg);
        !          6659:             tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]);
        !          6660:             gen_op_mov_reg_T0(OT_LONG, reg);
1.1       root     6661:         }
1.1.1.7 ! root     6662: #endif
1.1       root     6663:         break;
                   6664:     case 0xd6: /* salc */
                   6665:         if (CODE64(s))
                   6666:             goto illegal_op;
                   6667:         if (s->cc_op != CC_OP_DYNAMIC)
                   6668:             gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6669:         gen_compute_eflags_c(cpu_T[0]);
        !          6670:         tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
        !          6671:         gen_op_mov_reg_T0(OT_BYTE, R_EAX);
1.1       root     6672:         break;
                   6673:     case 0xe0: /* loopnz */
                   6674:     case 0xe1: /* loopz */
                   6675:     case 0xe2: /* loop */
                   6676:     case 0xe3: /* jecxz */
                   6677:         {
1.1.1.7 ! root     6678:             int l1, l2, l3;
1.1       root     6679: 
                   6680:             tval = (int8_t)insn_get(s, OT_BYTE);
                   6681:             next_eip = s->pc - s->cs_base;
                   6682:             tval += next_eip;
                   6683:             if (s->dflag == 0)
                   6684:                 tval &= 0xffff;
1.1.1.6   root     6685: 
1.1       root     6686:             l1 = gen_new_label();
                   6687:             l2 = gen_new_label();
1.1.1.7 ! root     6688:             l3 = gen_new_label();
1.1       root     6689:             b &= 3;
1.1.1.7 ! root     6690:             switch(b) {
        !          6691:             case 0: /* loopnz */
        !          6692:             case 1: /* loopz */
        !          6693:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          6694:                     gen_op_set_cc_op(s->cc_op);
        !          6695:                 gen_op_add_reg_im(s->aflag, R_ECX, -1);
        !          6696:                 gen_op_jz_ecx(s->aflag, l3);
        !          6697:                 gen_compute_eflags(cpu_tmp0);
        !          6698:                 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z);
        !          6699:                 if (b == 0) {
        !          6700:                     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
        !          6701:                 } else {
        !          6702:                     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, l1);
        !          6703:                 }
        !          6704:                 break;
        !          6705:             case 2: /* loop */
        !          6706:                 gen_op_add_reg_im(s->aflag, R_ECX, -1);
        !          6707:                 gen_op_jnz_ecx(s->aflag, l1);
        !          6708:                 break;
        !          6709:             default:
        !          6710:             case 3: /* jcxz */
        !          6711:                 gen_op_jz_ecx(s->aflag, l1);
        !          6712:                 break;
1.1       root     6713:             }
                   6714: 
1.1.1.7 ! root     6715:             gen_set_label(l3);
1.1       root     6716:             gen_jmp_im(next_eip);
1.1.1.7 ! root     6717:             tcg_gen_br(l2);
        !          6718: 
1.1       root     6719:             gen_set_label(l1);
                   6720:             gen_jmp_im(tval);
                   6721:             gen_set_label(l2);
                   6722:             gen_eob(s);
                   6723:         }
                   6724:         break;
                   6725:     case 0x130: /* wrmsr */
                   6726:     case 0x132: /* rdmsr */
                   6727:         if (s->cpl != 0) {
                   6728:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6729:         } else {
1.1.1.7 ! root     6730:             if (s->cc_op != CC_OP_DYNAMIC)
        !          6731:                 gen_op_set_cc_op(s->cc_op);
        !          6732:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.6   root     6733:             if (b & 2) {
1.1.1.7 ! root     6734:                 gen_helper_rdmsr();
1.1.1.6   root     6735:             } else {
1.1.1.7 ! root     6736:                 gen_helper_wrmsr();
1.1.1.6   root     6737:             }
1.1       root     6738:         }
                   6739:         break;
                   6740:     case 0x131: /* rdtsc */
1.1.1.7 ! root     6741:         if (s->cc_op != CC_OP_DYNAMIC)
        !          6742:             gen_op_set_cc_op(s->cc_op);
1.1       root     6743:         gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6744:         if (use_icount)
        !          6745:             gen_io_start();
        !          6746:         gen_helper_rdtsc();
        !          6747:         if (use_icount) {
        !          6748:             gen_io_end();
        !          6749:             gen_jmp(s, s->pc - s->cs_base);
        !          6750:         }
1.1       root     6751:         break;
1.1.1.6   root     6752:     case 0x133: /* rdpmc */
1.1.1.7 ! root     6753:         if (s->cc_op != CC_OP_DYNAMIC)
        !          6754:             gen_op_set_cc_op(s->cc_op);
1.1.1.6   root     6755:         gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6756:         gen_helper_rdpmc();
1.1.1.6   root     6757:         break;
1.1       root     6758:     case 0x134: /* sysenter */
1.1.1.7 ! root     6759:         /* For Intel SYSENTER is valid on 64-bit */
        !          6760:         if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
1.1       root     6761:             goto illegal_op;
                   6762:         if (!s->pe) {
                   6763:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6764:         } else {
                   6765:             if (s->cc_op != CC_OP_DYNAMIC) {
                   6766:                 gen_op_set_cc_op(s->cc_op);
                   6767:                 s->cc_op = CC_OP_DYNAMIC;
                   6768:             }
                   6769:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6770:             gen_helper_sysenter();
1.1       root     6771:             gen_eob(s);
                   6772:         }
                   6773:         break;
                   6774:     case 0x135: /* sysexit */
1.1.1.7 ! root     6775:         /* For Intel SYSEXIT is valid on 64-bit */
        !          6776:         if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
1.1       root     6777:             goto illegal_op;
                   6778:         if (!s->pe) {
                   6779:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6780:         } else {
                   6781:             if (s->cc_op != CC_OP_DYNAMIC) {
                   6782:                 gen_op_set_cc_op(s->cc_op);
                   6783:                 s->cc_op = CC_OP_DYNAMIC;
                   6784:             }
                   6785:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6786:             gen_helper_sysexit(tcg_const_i32(dflag));
1.1       root     6787:             gen_eob(s);
                   6788:         }
                   6789:         break;
                   6790: #ifdef TARGET_X86_64
                   6791:     case 0x105: /* syscall */
                   6792:         /* XXX: is it usable in real mode ? */
                   6793:         if (s->cc_op != CC_OP_DYNAMIC) {
                   6794:             gen_op_set_cc_op(s->cc_op);
                   6795:             s->cc_op = CC_OP_DYNAMIC;
                   6796:         }
                   6797:         gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6798:         gen_helper_syscall(tcg_const_i32(s->pc - pc_start));
1.1       root     6799:         gen_eob(s);
                   6800:         break;
                   6801:     case 0x107: /* sysret */
                   6802:         if (!s->pe) {
                   6803:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6804:         } else {
                   6805:             if (s->cc_op != CC_OP_DYNAMIC) {
                   6806:                 gen_op_set_cc_op(s->cc_op);
                   6807:                 s->cc_op = CC_OP_DYNAMIC;
                   6808:             }
                   6809:             gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6810:             gen_helper_sysret(tcg_const_i32(s->dflag));
1.1       root     6811:             /* condition codes are modified only in long mode */
                   6812:             if (s->lma)
                   6813:                 s->cc_op = CC_OP_EFLAGS;
                   6814:             gen_eob(s);
                   6815:         }
                   6816:         break;
                   6817: #endif
                   6818:     case 0x1a2: /* cpuid */
1.1.1.7 ! root     6819:         if (s->cc_op != CC_OP_DYNAMIC)
        !          6820:             gen_op_set_cc_op(s->cc_op);
        !          6821:         gen_jmp_im(pc_start - s->cs_base);
        !          6822:         gen_helper_cpuid();
1.1       root     6823:         break;
                   6824:     case 0xf4: /* hlt */
                   6825:         if (s->cpl != 0) {
                   6826:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6827:         } else {
                   6828:             if (s->cc_op != CC_OP_DYNAMIC)
                   6829:                 gen_op_set_cc_op(s->cc_op);
1.1.1.7 ! root     6830:             gen_jmp_im(pc_start - s->cs_base);
        !          6831:             gen_helper_hlt(tcg_const_i32(s->pc - pc_start));
1.1       root     6832:             s->is_jmp = 3;
                   6833:         }
                   6834:         break;
                   6835:     case 0x100:
                   6836:         modrm = ldub_code(s->pc++);
                   6837:         mod = (modrm >> 6) & 3;
                   6838:         op = (modrm >> 3) & 7;
                   6839:         switch(op) {
                   6840:         case 0: /* sldt */
                   6841:             if (!s->pe || s->vm86)
                   6842:                 goto illegal_op;
1.1.1.7 ! root     6843:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
        !          6844:             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
1.1       root     6845:             ot = OT_WORD;
                   6846:             if (mod == 3)
                   6847:                 ot += s->dflag;
                   6848:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
                   6849:             break;
                   6850:         case 2: /* lldt */
                   6851:             if (!s->pe || s->vm86)
                   6852:                 goto illegal_op;
                   6853:             if (s->cpl != 0) {
                   6854:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6855:             } else {
1.1.1.7 ! root     6856:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
1.1       root     6857:                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                   6858:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6859:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          6860:                 gen_helper_lldt(cpu_tmp2_i32);
1.1       root     6861:             }
                   6862:             break;
                   6863:         case 1: /* str */
                   6864:             if (!s->pe || s->vm86)
                   6865:                 goto illegal_op;
1.1.1.7 ! root     6866:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
        !          6867:             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
1.1       root     6868:             ot = OT_WORD;
                   6869:             if (mod == 3)
                   6870:                 ot += s->dflag;
                   6871:             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
                   6872:             break;
                   6873:         case 3: /* ltr */
                   6874:             if (!s->pe || s->vm86)
                   6875:                 goto illegal_op;
                   6876:             if (s->cpl != 0) {
                   6877:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   6878:             } else {
1.1.1.7 ! root     6879:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
1.1       root     6880:                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                   6881:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 ! root     6882:                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
        !          6883:                 gen_helper_ltr(cpu_tmp2_i32);
1.1       root     6884:             }
                   6885:             break;
                   6886:         case 4: /* verr */
                   6887:         case 5: /* verw */
                   6888:             if (!s->pe || s->vm86)
                   6889:                 goto illegal_op;
                   6890:             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                   6891:             if (s->cc_op != CC_OP_DYNAMIC)
                   6892:                 gen_op_set_cc_op(s->cc_op);
                   6893:             if (op == 4)
1.1.1.7 ! root     6894:                 gen_helper_verr(cpu_T[0]);
1.1       root     6895:             else
1.1.1.7 ! root     6896:                 gen_helper_verw(cpu_T[0]);
1.1       root     6897:             s->cc_op = CC_OP_EFLAGS;
                   6898:             break;
                   6899:         default:
                   6900:             goto illegal_op;
                   6901:         }
                   6902:         break;
                   6903:     case 0x101:
                   6904:         modrm = ldub_code(s->pc++);
                   6905:         mod = (modrm >> 6) & 3;
                   6906:         op = (modrm >> 3) & 7;
1.1.1.4   root     6907:         rm = modrm & 7;
1.1       root     6908:         switch(op) {
                   6909:         case 0: /* sgdt */
                   6910:             if (mod == 3)
                   6911:                 goto illegal_op;
1.1.1.7 ! root     6912:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
1.1       root     6913:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     6914:             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
        !          6915:             gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1       root     6916:             gen_add_A0_im(s, 2);
1.1.1.7 ! root     6917:             tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
1.1       root     6918:             if (!s->dflag)
                   6919:                 gen_op_andl_T0_im(0xffffff);
1.1.1.7 ! root     6920:             gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1       root     6921:             break;
1.1.1.4   root     6922:         case 1:
                   6923:             if (mod == 3) {
                   6924:                 switch (rm) {
                   6925:                 case 0: /* monitor */
                   6926:                     if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
                   6927:                         s->cpl != 0)
                   6928:                         goto illegal_op;
1.1.1.7 ! root     6929:                     if (s->cc_op != CC_OP_DYNAMIC)
        !          6930:                         gen_op_set_cc_op(s->cc_op);
1.1.1.4   root     6931:                     gen_jmp_im(pc_start - s->cs_base);
                   6932: #ifdef TARGET_X86_64
                   6933:                     if (s->aflag == 2) {
1.1.1.7 ! root     6934:                         gen_op_movq_A0_reg(R_EAX);
1.1.1.6   root     6935:                     } else
1.1.1.4   root     6936: #endif
                   6937:                     {
1.1.1.7 ! root     6938:                         gen_op_movl_A0_reg(R_EAX);
1.1.1.4   root     6939:                         if (s->aflag == 0)
                   6940:                             gen_op_andl_A0_ffff();
                   6941:                     }
                   6942:                     gen_add_A0_ds_seg(s);
1.1.1.7 ! root     6943:                     gen_helper_monitor(cpu_A0);
1.1.1.4   root     6944:                     break;
                   6945:                 case 1: /* mwait */
                   6946:                     if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
                   6947:                         s->cpl != 0)
                   6948:                         goto illegal_op;
                   6949:                     if (s->cc_op != CC_OP_DYNAMIC) {
                   6950:                         gen_op_set_cc_op(s->cc_op);
                   6951:                         s->cc_op = CC_OP_DYNAMIC;
                   6952:                     }
1.1.1.7 ! root     6953:                     gen_jmp_im(pc_start - s->cs_base);
        !          6954:                     gen_helper_mwait(tcg_const_i32(s->pc - pc_start));
1.1.1.4   root     6955:                     gen_eob(s);
                   6956:                     break;
                   6957:                 default:
                   6958:                     goto illegal_op;
                   6959:                 }
                   6960:             } else { /* sidt */
1.1.1.7 ! root     6961:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
1.1.1.4   root     6962:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     6963:                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
        !          6964:                 gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1.1.4   root     6965:                 gen_add_A0_im(s, 2);
1.1.1.7 ! root     6966:                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
1.1.1.4   root     6967:                 if (!s->dflag)
                   6968:                     gen_op_andl_T0_im(0xffffff);
1.1.1.7 ! root     6969:                 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1.1.4   root     6970:             }
                   6971:             break;
1.1       root     6972:         case 2: /* lgdt */
                   6973:         case 3: /* lidt */
1.1.1.6   root     6974:             if (mod == 3) {
1.1.1.7 ! root     6975:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          6976:                     gen_op_set_cc_op(s->cc_op);
        !          6977:                 gen_jmp_im(pc_start - s->cs_base);
1.1.1.6   root     6978:                 switch(rm) {
                   6979:                 case 0: /* VMRUN */
1.1.1.7 ! root     6980:                     if (!(s->flags & HF_SVME_MASK) || !s->pe)
        !          6981:                         goto illegal_op;
        !          6982:                     if (s->cpl != 0) {
        !          6983:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1.1.1.6   root     6984:                         break;
1.1.1.7 ! root     6985:                     } else {
        !          6986:                         gen_helper_vmrun(tcg_const_i32(s->aflag),
        !          6987:                                          tcg_const_i32(s->pc - pc_start));
        !          6988:                         tcg_gen_exit_tb(0);
        !          6989:                         s->is_jmp = 3;
        !          6990:                     }
1.1.1.6   root     6991:                     break;
                   6992:                 case 1: /* VMMCALL */
1.1.1.7 ! root     6993:                     if (!(s->flags & HF_SVME_MASK))
        !          6994:                         goto illegal_op;
        !          6995:                     gen_helper_vmmcall();
1.1.1.6   root     6996:                     break;
                   6997:                 case 2: /* VMLOAD */
1.1.1.7 ! root     6998:                     if (!(s->flags & HF_SVME_MASK) || !s->pe)
        !          6999:                         goto illegal_op;
        !          7000:                     if (s->cpl != 0) {
        !          7001:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
        !          7002:                         break;
        !          7003:                     } else {
        !          7004:                         gen_helper_vmload(tcg_const_i32(s->aflag));
        !          7005:                     }
1.1.1.6   root     7006:                     break;
                   7007:                 case 3: /* VMSAVE */
1.1.1.7 ! root     7008:                     if (!(s->flags & HF_SVME_MASK) || !s->pe)
        !          7009:                         goto illegal_op;
        !          7010:                     if (s->cpl != 0) {
        !          7011:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
        !          7012:                         break;
        !          7013:                     } else {
        !          7014:                         gen_helper_vmsave(tcg_const_i32(s->aflag));
        !          7015:                     }
1.1.1.6   root     7016:                     break;
                   7017:                 case 4: /* STGI */
1.1.1.7 ! root     7018:                     if ((!(s->flags & HF_SVME_MASK) &&
        !          7019:                          !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 
        !          7020:                         !s->pe)
        !          7021:                         goto illegal_op;
        !          7022:                     if (s->cpl != 0) {
        !          7023:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
        !          7024:                         break;
        !          7025:                     } else {
        !          7026:                         gen_helper_stgi();
        !          7027:                     }
1.1.1.6   root     7028:                     break;
                   7029:                 case 5: /* CLGI */
1.1.1.7 ! root     7030:                     if (!(s->flags & HF_SVME_MASK) || !s->pe)
        !          7031:                         goto illegal_op;
        !          7032:                     if (s->cpl != 0) {
        !          7033:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
        !          7034:                         break;
        !          7035:                     } else {
        !          7036:                         gen_helper_clgi();
        !          7037:                     }
1.1.1.6   root     7038:                     break;
                   7039:                 case 6: /* SKINIT */
1.1.1.7 ! root     7040:                     if ((!(s->flags & HF_SVME_MASK) && 
        !          7041:                          !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 
        !          7042:                         !s->pe)
        !          7043:                         goto illegal_op;
        !          7044:                     gen_helper_skinit();
1.1.1.6   root     7045:                     break;
                   7046:                 case 7: /* INVLPGA */
1.1.1.7 ! root     7047:                     if (!(s->flags & HF_SVME_MASK) || !s->pe)
        !          7048:                         goto illegal_op;
        !          7049:                     if (s->cpl != 0) {
        !          7050:                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
        !          7051:                         break;
        !          7052:                     } else {
        !          7053:                         gen_helper_invlpga(tcg_const_i32(s->aflag));
        !          7054:                     }
1.1.1.6   root     7055:                     break;
                   7056:                 default:
                   7057:                     goto illegal_op;
                   7058:                 }
                   7059:             } else if (s->cpl != 0) {
1.1       root     7060:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7061:             } else {
1.1.1.7 ! root     7062:                 gen_svm_check_intercept(s, pc_start,
        !          7063:                                         op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
1.1       root     7064:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     7065:                 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
1.1       root     7066:                 gen_add_A0_im(s, 2);
1.1.1.7 ! root     7067:                 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1       root     7068:                 if (!s->dflag)
                   7069:                     gen_op_andl_T0_im(0xffffff);
                   7070:                 if (op == 2) {
1.1.1.7 ! root     7071:                     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
        !          7072:                     tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
1.1       root     7073:                 } else {
1.1.1.7 ! root     7074:                     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
        !          7075:                     tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
1.1       root     7076:                 }
                   7077:             }
                   7078:             break;
                   7079:         case 4: /* smsw */
1.1.1.7 ! root     7080:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
        !          7081: #if defined TARGET_X86_64 && defined WORDS_BIGENDIAN
        !          7082:             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
        !          7083: #else
        !          7084:             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
        !          7085: #endif
1.1       root     7086:             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
                   7087:             break;
                   7088:         case 6: /* lmsw */
                   7089:             if (s->cpl != 0) {
                   7090:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7091:             } else {
1.1.1.7 ! root     7092:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
1.1       root     7093:                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
1.1.1.7 ! root     7094:                 gen_helper_lmsw(cpu_T[0]);
1.1       root     7095:                 gen_jmp_im(s->pc - s->cs_base);
                   7096:                 gen_eob(s);
                   7097:             }
                   7098:             break;
                   7099:         case 7: /* invlpg */
                   7100:             if (s->cpl != 0) {
                   7101:                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7102:             } else {
                   7103:                 if (mod == 3) {
                   7104: #ifdef TARGET_X86_64
1.1.1.4   root     7105:                     if (CODE64(s) && rm == 0) {
1.1       root     7106:                         /* swapgs */
1.1.1.7 ! root     7107:                         tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,segs[R_GS].base));
        !          7108:                         tcg_gen_ld_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,kernelgsbase));
        !          7109:                         tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,segs[R_GS].base));
        !          7110:                         tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,kernelgsbase));
1.1.1.6   root     7111:                     } else
1.1       root     7112: #endif
                   7113:                     {
                   7114:                         goto illegal_op;
                   7115:                     }
                   7116:                 } else {
1.1.1.7 ! root     7117:                     if (s->cc_op != CC_OP_DYNAMIC)
        !          7118:                         gen_op_set_cc_op(s->cc_op);
        !          7119:                     gen_jmp_im(pc_start - s->cs_base);
1.1       root     7120:                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     7121:                     gen_helper_invlpg(cpu_A0);
1.1       root     7122:                     gen_jmp_im(s->pc - s->cs_base);
                   7123:                     gen_eob(s);
                   7124:                 }
                   7125:             }
                   7126:             break;
                   7127:         default:
                   7128:             goto illegal_op;
                   7129:         }
                   7130:         break;
                   7131:     case 0x108: /* invd */
                   7132:     case 0x109: /* wbinvd */
                   7133:         if (s->cpl != 0) {
                   7134:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7135:         } else {
1.1.1.7 ! root     7136:             gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
1.1       root     7137:             /* nothing to do */
                   7138:         }
                   7139:         break;
                   7140:     case 0x63: /* arpl or movslS (x86_64) */
                   7141: #ifdef TARGET_X86_64
                   7142:         if (CODE64(s)) {
                   7143:             int d_ot;
                   7144:             /* d_ot is the size of destination */
                   7145:             d_ot = dflag + OT_WORD;
                   7146: 
                   7147:             modrm = ldub_code(s->pc++);
                   7148:             reg = ((modrm >> 3) & 7) | rex_r;
                   7149:             mod = (modrm >> 6) & 3;
                   7150:             rm = (modrm & 7) | REX_B(s);
1.1.1.6   root     7151: 
1.1       root     7152:             if (mod == 3) {
1.1.1.7 ! root     7153:                 gen_op_mov_TN_reg(OT_LONG, 0, rm);
1.1       root     7154:                 /* sign extend */
                   7155:                 if (d_ot == OT_QUAD)
1.1.1.7 ! root     7156:                     tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
        !          7157:                 gen_op_mov_reg_T0(d_ot, reg);
1.1       root     7158:             } else {
                   7159:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   7160:                 if (d_ot == OT_QUAD) {
1.1.1.7 ! root     7161:                     gen_op_lds_T0_A0(OT_LONG + s->mem_index);
1.1       root     7162:                 } else {
1.1.1.7 ! root     7163:                     gen_op_ld_T0_A0(OT_LONG + s->mem_index);
1.1       root     7164:                 }
1.1.1.7 ! root     7165:                 gen_op_mov_reg_T0(d_ot, reg);
1.1       root     7166:             }
1.1.1.6   root     7167:         } else
1.1       root     7168: #endif
                   7169:         {
1.1.1.7 ! root     7170:             int label1;
        !          7171:             TCGv t0, t1, t2;
        !          7172: 
1.1       root     7173:             if (!s->pe || s->vm86)
                   7174:                 goto illegal_op;
1.1.1.7 ! root     7175:             t0 = tcg_temp_local_new();
        !          7176:             t1 = tcg_temp_local_new();
        !          7177:             t2 = tcg_temp_local_new();
        !          7178:             ot = OT_WORD;
1.1       root     7179:             modrm = ldub_code(s->pc++);
                   7180:             reg = (modrm >> 3) & 7;
                   7181:             mod = (modrm >> 6) & 3;
                   7182:             rm = modrm & 7;
                   7183:             if (mod != 3) {
                   7184:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     7185:                 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
1.1       root     7186:             } else {
1.1.1.7 ! root     7187:                 gen_op_mov_v_reg(ot, t0, rm);
1.1       root     7188:             }
1.1.1.7 ! root     7189:             gen_op_mov_v_reg(ot, t1, reg);
        !          7190:             tcg_gen_andi_tl(cpu_tmp0, t0, 3);
        !          7191:             tcg_gen_andi_tl(t1, t1, 3);
        !          7192:             tcg_gen_movi_tl(t2, 0);
        !          7193:             label1 = gen_new_label();
        !          7194:             tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
        !          7195:             tcg_gen_andi_tl(t0, t0, ~3);
        !          7196:             tcg_gen_or_tl(t0, t0, t1);
        !          7197:             tcg_gen_movi_tl(t2, CC_Z);
        !          7198:             gen_set_label(label1);
1.1       root     7199:             if (mod != 3) {
1.1.1.7 ! root     7200:                 gen_op_st_v(ot + s->mem_index, t0, cpu_A0);
1.1       root     7201:             } else {
1.1.1.7 ! root     7202:                 gen_op_mov_reg_v(ot, rm, t0);
1.1       root     7203:             }
1.1.1.7 ! root     7204:             if (s->cc_op != CC_OP_DYNAMIC)
        !          7205:                 gen_op_set_cc_op(s->cc_op);
        !          7206:             gen_compute_eflags(cpu_cc_src);
        !          7207:             tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
        !          7208:             tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
        !          7209:             s->cc_op = CC_OP_EFLAGS;
        !          7210:             tcg_temp_free(t0);
        !          7211:             tcg_temp_free(t1);
        !          7212:             tcg_temp_free(t2);
1.1       root     7213:         }
                   7214:         break;
                   7215:     case 0x102: /* lar */
                   7216:     case 0x103: /* lsl */
1.1.1.7 ! root     7217:         {
        !          7218:             int label1;
        !          7219:             TCGv t0;
        !          7220:             if (!s->pe || s->vm86)
        !          7221:                 goto illegal_op;
        !          7222:             ot = dflag ? OT_LONG : OT_WORD;
        !          7223:             modrm = ldub_code(s->pc++);
        !          7224:             reg = ((modrm >> 3) & 7) | rex_r;
        !          7225:             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
        !          7226:             t0 = tcg_temp_local_new();
        !          7227:             if (s->cc_op != CC_OP_DYNAMIC)
        !          7228:                 gen_op_set_cc_op(s->cc_op);
        !          7229:             if (b == 0x102)
        !          7230:                 gen_helper_lar(t0, cpu_T[0]);
        !          7231:             else
        !          7232:                 gen_helper_lsl(t0, cpu_T[0]);
        !          7233:             tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
        !          7234:             label1 = gen_new_label();
        !          7235:             tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
        !          7236:             gen_op_mov_reg_v(ot, reg, t0);
        !          7237:             gen_set_label(label1);
        !          7238:             s->cc_op = CC_OP_EFLAGS;
        !          7239:             tcg_temp_free(t0);
        !          7240:         }
1.1       root     7241:         break;
                   7242:     case 0x118:
                   7243:         modrm = ldub_code(s->pc++);
                   7244:         mod = (modrm >> 6) & 3;
                   7245:         op = (modrm >> 3) & 7;
                   7246:         switch(op) {
                   7247:         case 0: /* prefetchnta */
                   7248:         case 1: /* prefetchnt0 */
                   7249:         case 2: /* prefetchnt0 */
                   7250:         case 3: /* prefetchnt0 */
                   7251:             if (mod == 3)
                   7252:                 goto illegal_op;
                   7253:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   7254:             /* nothing more to do */
                   7255:             break;
1.1.1.5   root     7256:         default: /* nop (multi byte) */
                   7257:             gen_nop_modrm(s, modrm);
                   7258:             break;
1.1       root     7259:         }
                   7260:         break;
1.1.1.5   root     7261:     case 0x119 ... 0x11f: /* nop (multi byte) */
                   7262:         modrm = ldub_code(s->pc++);
                   7263:         gen_nop_modrm(s, modrm);
                   7264:         break;
1.1       root     7265:     case 0x120: /* mov reg, crN */
                   7266:     case 0x122: /* mov crN, reg */
                   7267:         if (s->cpl != 0) {
                   7268:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7269:         } else {
                   7270:             modrm = ldub_code(s->pc++);
                   7271:             if ((modrm & 0xc0) != 0xc0)
                   7272:                 goto illegal_op;
                   7273:             rm = (modrm & 7) | REX_B(s);
                   7274:             reg = ((modrm >> 3) & 7) | rex_r;
                   7275:             if (CODE64(s))
                   7276:                 ot = OT_QUAD;
                   7277:             else
                   7278:                 ot = OT_LONG;
                   7279:             switch(reg) {
                   7280:             case 0:
                   7281:             case 2:
                   7282:             case 3:
                   7283:             case 4:
                   7284:             case 8:
1.1.1.7 ! root     7285:                 if (s->cc_op != CC_OP_DYNAMIC)
        !          7286:                     gen_op_set_cc_op(s->cc_op);
        !          7287:                 gen_jmp_im(pc_start - s->cs_base);
1.1       root     7288:                 if (b & 2) {
1.1.1.7 ! root     7289:                     gen_op_mov_TN_reg(ot, 0, rm);
        !          7290:                     gen_helper_write_crN(tcg_const_i32(reg), cpu_T[0]);
1.1       root     7291:                     gen_jmp_im(s->pc - s->cs_base);
                   7292:                     gen_eob(s);
                   7293:                 } else {
1.1.1.7 ! root     7294:                     gen_helper_read_crN(cpu_T[0], tcg_const_i32(reg));
        !          7295:                     gen_op_mov_reg_T0(ot, rm);
1.1       root     7296:                 }
                   7297:                 break;
                   7298:             default:
                   7299:                 goto illegal_op;
                   7300:             }
                   7301:         }
                   7302:         break;
                   7303:     case 0x121: /* mov reg, drN */
                   7304:     case 0x123: /* mov drN, reg */
                   7305:         if (s->cpl != 0) {
                   7306:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7307:         } else {
                   7308:             modrm = ldub_code(s->pc++);
                   7309:             if ((modrm & 0xc0) != 0xc0)
                   7310:                 goto illegal_op;
                   7311:             rm = (modrm & 7) | REX_B(s);
                   7312:             reg = ((modrm >> 3) & 7) | rex_r;
                   7313:             if (CODE64(s))
                   7314:                 ot = OT_QUAD;
                   7315:             else
                   7316:                 ot = OT_LONG;
                   7317:             /* XXX: do it dynamically with CR4.DE bit */
                   7318:             if (reg == 4 || reg == 5 || reg >= 8)
                   7319:                 goto illegal_op;
                   7320:             if (b & 2) {
1.1.1.6   root     7321:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
1.1.1.7 ! root     7322:                 gen_op_mov_TN_reg(ot, 0, rm);
        !          7323:                 gen_helper_movl_drN_T0(tcg_const_i32(reg), cpu_T[0]);
1.1       root     7324:                 gen_jmp_im(s->pc - s->cs_base);
                   7325:                 gen_eob(s);
                   7326:             } else {
1.1.1.6   root     7327:                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
1.1.1.7 ! root     7328:                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
        !          7329:                 gen_op_mov_reg_T0(ot, rm);
1.1       root     7330:             }
                   7331:         }
                   7332:         break;
                   7333:     case 0x106: /* clts */
                   7334:         if (s->cpl != 0) {
                   7335:             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                   7336:         } else {
1.1.1.6   root     7337:             gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
1.1.1.7 ! root     7338:             gen_helper_clts();
1.1       root     7339:             /* abort block because static cpu state changed */
                   7340:             gen_jmp_im(s->pc - s->cs_base);
                   7341:             gen_eob(s);
                   7342:         }
                   7343:         break;
1.1.1.7 ! root     7344:     /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
1.1       root     7345:     case 0x1c3: /* MOVNTI reg, mem */
                   7346:         if (!(s->cpuid_features & CPUID_SSE2))
                   7347:             goto illegal_op;
                   7348:         ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
                   7349:         modrm = ldub_code(s->pc++);
                   7350:         mod = (modrm >> 6) & 3;
                   7351:         if (mod == 3)
                   7352:             goto illegal_op;
                   7353:         reg = ((modrm >> 3) & 7) | rex_r;
                   7354:         /* generate a generic store */
                   7355:         gen_ldst_modrm(s, modrm, ot, reg, 1);
                   7356:         break;
                   7357:     case 0x1ae:
                   7358:         modrm = ldub_code(s->pc++);
                   7359:         mod = (modrm >> 6) & 3;
                   7360:         op = (modrm >> 3) & 7;
                   7361:         switch(op) {
                   7362:         case 0: /* fxsave */
1.1.1.6   root     7363:             if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.3   root     7364:                 (s->flags & HF_EM_MASK))
1.1       root     7365:                 goto illegal_op;
1.1.1.3   root     7366:             if (s->flags & HF_TS_MASK) {
                   7367:                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   7368:                 break;
                   7369:             }
1.1       root     7370:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     7371:             if (s->cc_op != CC_OP_DYNAMIC)
        !          7372:                 gen_op_set_cc_op(s->cc_op);
        !          7373:             gen_jmp_im(pc_start - s->cs_base);
        !          7374:             gen_helper_fxsave(cpu_A0, tcg_const_i32((s->dflag == 2)));
1.1       root     7375:             break;
                   7376:         case 1: /* fxrstor */
1.1.1.6   root     7377:             if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.3   root     7378:                 (s->flags & HF_EM_MASK))
1.1       root     7379:                 goto illegal_op;
1.1.1.3   root     7380:             if (s->flags & HF_TS_MASK) {
                   7381:                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   7382:                 break;
                   7383:             }
1.1       root     7384:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1.1.1.7 ! root     7385:             if (s->cc_op != CC_OP_DYNAMIC)
        !          7386:                 gen_op_set_cc_op(s->cc_op);
        !          7387:             gen_jmp_im(pc_start - s->cs_base);
        !          7388:             gen_helper_fxrstor(cpu_A0, tcg_const_i32((s->dflag == 2)));
1.1       root     7389:             break;
                   7390:         case 2: /* ldmxcsr */
                   7391:         case 3: /* stmxcsr */
                   7392:             if (s->flags & HF_TS_MASK) {
                   7393:                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                   7394:                 break;
                   7395:             }
                   7396:             if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
                   7397:                 mod == 3)
                   7398:                 goto illegal_op;
                   7399:             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   7400:             if (op == 2) {
1.1.1.7 ! root     7401:                 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
        !          7402:                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
1.1       root     7403:             } else {
1.1.1.7 ! root     7404:                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
        !          7405:                 gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1       root     7406:             }
                   7407:             break;
                   7408:         case 5: /* lfence */
                   7409:         case 6: /* mfence */
                   7410:             if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
                   7411:                 goto illegal_op;
                   7412:             break;
                   7413:         case 7: /* sfence / clflush */
                   7414:             if ((modrm & 0xc7) == 0xc0) {
                   7415:                 /* sfence */
1.1.1.7 ! root     7416:                 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
1.1       root     7417:                 if (!(s->cpuid_features & CPUID_SSE))
                   7418:                     goto illegal_op;
                   7419:             } else {
                   7420:                 /* clflush */
                   7421:                 if (!(s->cpuid_features & CPUID_CLFLUSH))
                   7422:                     goto illegal_op;
                   7423:                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   7424:             }
                   7425:             break;
                   7426:         default:
                   7427:             goto illegal_op;
                   7428:         }
                   7429:         break;
1.1.1.7 ! root     7430:     case 0x10d: /* 3DNow! prefetch(w) */
1.1       root     7431:         modrm = ldub_code(s->pc++);
1.1.1.7 ! root     7432:         mod = (modrm >> 6) & 3;
        !          7433:         if (mod == 3)
        !          7434:             goto illegal_op;
1.1       root     7435:         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                   7436:         /* ignore for now */
                   7437:         break;
1.1.1.5   root     7438:     case 0x1aa: /* rsm */
1.1.1.7 ! root     7439:         gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
1.1.1.5   root     7440:         if (!(s->flags & HF_SMM_MASK))
                   7441:             goto illegal_op;
                   7442:         if (s->cc_op != CC_OP_DYNAMIC) {
                   7443:             gen_op_set_cc_op(s->cc_op);
                   7444:             s->cc_op = CC_OP_DYNAMIC;
                   7445:         }
                   7446:         gen_jmp_im(s->pc - s->cs_base);
1.1.1.7 ! root     7447:         gen_helper_rsm();
1.1.1.5   root     7448:         gen_eob(s);
                   7449:         break;
1.1.1.7 ! root     7450:     case 0x1b8: /* SSE4.2 popcnt */
        !          7451:         if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
        !          7452:              PREFIX_REPZ)
        !          7453:             goto illegal_op;
        !          7454:         if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
        !          7455:             goto illegal_op;
        !          7456: 
        !          7457:         modrm = ldub_code(s->pc++);
        !          7458:         reg = ((modrm >> 3) & 7);
        !          7459: 
        !          7460:         if (s->prefix & PREFIX_DATA)
        !          7461:             ot = OT_WORD;
        !          7462:         else if (s->dflag != 2)
        !          7463:             ot = OT_LONG;
        !          7464:         else
        !          7465:             ot = OT_QUAD;
        !          7466: 
        !          7467:         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
        !          7468:         gen_helper_popcnt(cpu_T[0], cpu_T[0], tcg_const_i32(ot));
        !          7469:         gen_op_mov_reg_T0(ot, reg);
        !          7470: 
        !          7471:         s->cc_op = CC_OP_EFLAGS;
        !          7472:         break;
        !          7473:     case 0x10e ... 0x10f:
        !          7474:         /* 3DNow! instructions, ignore prefixes */
        !          7475:         s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
1.1       root     7476:     case 0x110 ... 0x117:
                   7477:     case 0x128 ... 0x12f:
1.1.1.7 ! root     7478:     case 0x138 ... 0x13a:
1.1       root     7479:     case 0x150 ... 0x177:
                   7480:     case 0x17c ... 0x17f:
                   7481:     case 0x1c2:
                   7482:     case 0x1c4 ... 0x1c6:
                   7483:     case 0x1d0 ... 0x1fe:
                   7484:         gen_sse(s, b, pc_start, rex_r);
                   7485:         break;
                   7486:     default:
                   7487:         goto illegal_op;
                   7488:     }
                   7489:     /* lock generation */
                   7490:     if (s->prefix & PREFIX_LOCK)
1.1.1.7 ! root     7491:         gen_helper_unlock();
1.1       root     7492:     return s->pc;
                   7493:  illegal_op:
                   7494:     if (s->prefix & PREFIX_LOCK)
1.1.1.7 ! root     7495:         gen_helper_unlock();
1.1       root     7496:     /* XXX: ensure that no lock was generated */
                   7497:     gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
                   7498:     return s->pc;
                   7499: }
                   7500: 
                   7501: void optimize_flags_init(void)
                   7502: {
1.1.1.7 ! root     7503: #if TCG_TARGET_REG_BITS == 32
        !          7504:     assert(sizeof(CCTable) == (1 << 3));
        !          7505: #else
        !          7506:     assert(sizeof(CCTable) == (1 << 4));
        !          7507: #endif
        !          7508:     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
        !          7509:     cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
        !          7510:                                        offsetof(CPUState, cc_op), "cc_op");
        !          7511:     cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src),
        !          7512:                                     "cc_src");
        !          7513:     cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst),
        !          7514:                                     "cc_dst");
        !          7515:     cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_tmp),
        !          7516:                                     "cc_tmp");
        !          7517: 
        !          7518:     /* register helpers */
        !          7519: #define GEN_HELPER 2
        !          7520: #include "helper.h"
1.1       root     7521: }
                   7522: 
                   7523: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
                   7524:    basic block 'tb'. If search_pc is TRUE, also generate PC
                   7525:    information for each intermediate instruction. */
1.1.1.7 ! root     7526: static inline void gen_intermediate_code_internal(CPUState *env,
        !          7527:                                                   TranslationBlock *tb,
        !          7528:                                                   int search_pc)
1.1       root     7529: {
                   7530:     DisasContext dc1, *dc = &dc1;
                   7531:     target_ulong pc_ptr;
                   7532:     uint16_t *gen_opc_end;
1.1.1.7 ! root     7533:     CPUBreakpoint *bp;
1.1.1.6   root     7534:     int j, lj, cflags;
                   7535:     uint64_t flags;
1.1       root     7536:     target_ulong pc_start;
                   7537:     target_ulong cs_base;
1.1.1.7 ! root     7538:     int num_insns;
        !          7539:     int max_insns;
1.1.1.6   root     7540: 
1.1       root     7541:     /* generate intermediate code */
                   7542:     pc_start = tb->pc;
                   7543:     cs_base = tb->cs_base;
                   7544:     flags = tb->flags;
                   7545:     cflags = tb->cflags;
                   7546: 
                   7547:     dc->pe = (flags >> HF_PE_SHIFT) & 1;
                   7548:     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
                   7549:     dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
                   7550:     dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
                   7551:     dc->f_st = 0;
                   7552:     dc->vm86 = (flags >> VM_SHIFT) & 1;
                   7553:     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
                   7554:     dc->iopl = (flags >> IOPL_SHIFT) & 3;
                   7555:     dc->tf = (flags >> TF_SHIFT) & 1;
                   7556:     dc->singlestep_enabled = env->singlestep_enabled;
                   7557:     dc->cc_op = CC_OP_DYNAMIC;
                   7558:     dc->cs_base = cs_base;
                   7559:     dc->tb = tb;
                   7560:     dc->popl_esp_hack = 0;
                   7561:     /* select memory access functions */
                   7562:     dc->mem_index = 0;
                   7563:     if (flags & HF_SOFTMMU_MASK) {
                   7564:         if (dc->cpl == 3)
                   7565:             dc->mem_index = 2 * 4;
                   7566:         else
                   7567:             dc->mem_index = 1 * 4;
                   7568:     }
                   7569:     dc->cpuid_features = env->cpuid_features;
1.1.1.4   root     7570:     dc->cpuid_ext_features = env->cpuid_ext_features;
1.1.1.7 ! root     7571:     dc->cpuid_ext2_features = env->cpuid_ext2_features;
        !          7572:     dc->cpuid_ext3_features = env->cpuid_ext3_features;
1.1       root     7573: #ifdef TARGET_X86_64
                   7574:     dc->lma = (flags >> HF_LMA_SHIFT) & 1;
                   7575:     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
                   7576: #endif
                   7577:     dc->flags = flags;
                   7578:     dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
                   7579:                     (flags & HF_INHIBIT_IRQ_MASK)
                   7580: #ifndef CONFIG_SOFTMMU
                   7581:                     || (flags & HF_SOFTMMU_MASK)
                   7582: #endif
                   7583:                     );
                   7584: #if 0
                   7585:     /* check addseg logic */
                   7586:     if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
                   7587:         printf("ERROR addseg\n");
                   7588: #endif
                   7589: 
1.1.1.7 ! root     7590:     cpu_T[0] = tcg_temp_new();
        !          7591:     cpu_T[1] = tcg_temp_new();
        !          7592:     cpu_A0 = tcg_temp_new();
        !          7593:     cpu_T3 = tcg_temp_new();
        !          7594: 
        !          7595:     cpu_tmp0 = tcg_temp_new();
        !          7596:     cpu_tmp1_i64 = tcg_temp_new_i64();
        !          7597:     cpu_tmp2_i32 = tcg_temp_new_i32();
        !          7598:     cpu_tmp3_i32 = tcg_temp_new_i32();
        !          7599:     cpu_tmp4 = tcg_temp_new();
        !          7600:     cpu_tmp5 = tcg_temp_new();
        !          7601:     cpu_tmp6 = tcg_temp_new();
        !          7602:     cpu_ptr0 = tcg_temp_new_ptr();
        !          7603:     cpu_ptr1 = tcg_temp_new_ptr();
        !          7604: 
1.1       root     7605:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   7606: 
                   7607:     dc->is_jmp = DISAS_NEXT;
                   7608:     pc_ptr = pc_start;
                   7609:     lj = -1;
1.1.1.7 ! root     7610:     num_insns = 0;
        !          7611:     max_insns = tb->cflags & CF_COUNT_MASK;
        !          7612:     if (max_insns == 0)
        !          7613:         max_insns = CF_COUNT_MASK;
1.1       root     7614: 
1.1.1.7 ! root     7615:     gen_icount_start();
1.1       root     7616:     for(;;) {
1.1.1.7 ! root     7617:         if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
        !          7618:             TAILQ_FOREACH(bp, &env->breakpoints, entry) {
        !          7619:                 if (bp->pc == pc_ptr) {
1.1       root     7620:                     gen_debug(dc, pc_ptr - dc->cs_base);
                   7621:                     break;
                   7622:                 }
                   7623:             }
                   7624:         }
                   7625:         if (search_pc) {
                   7626:             j = gen_opc_ptr - gen_opc_buf;
                   7627:             if (lj < j) {
                   7628:                 lj++;
                   7629:                 while (lj < j)
                   7630:                     gen_opc_instr_start[lj++] = 0;
                   7631:             }
                   7632:             gen_opc_pc[lj] = pc_ptr;
                   7633:             gen_opc_cc_op[lj] = dc->cc_op;
                   7634:             gen_opc_instr_start[lj] = 1;
1.1.1.7 ! root     7635:             gen_opc_icount[lj] = num_insns;
1.1       root     7636:         }
1.1.1.7 ! root     7637:         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
        !          7638:             gen_io_start();
        !          7639: 
1.1       root     7640:         pc_ptr = disas_insn(dc, pc_ptr);
1.1.1.7 ! root     7641:         num_insns++;
1.1       root     7642:         /* stop translation if indicated */
                   7643:         if (dc->is_jmp)
                   7644:             break;
                   7645:         /* if single step mode, we generate only one instruction and
                   7646:            generate an exception */
                   7647:         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
                   7648:            the flag and abort the translation to give the irqs a
                   7649:            change to be happen */
1.1.1.6   root     7650:         if (dc->tf || dc->singlestep_enabled ||
1.1.1.7 ! root     7651:             (flags & HF_INHIBIT_IRQ_MASK)) {
1.1       root     7652:             gen_jmp_im(pc_ptr - dc->cs_base);
                   7653:             gen_eob(dc);
                   7654:             break;
                   7655:         }
                   7656:         /* if too long translation, stop generation too */
                   7657:         if (gen_opc_ptr >= gen_opc_end ||
1.1.1.7 ! root     7658:             (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
        !          7659:             num_insns >= max_insns) {
1.1       root     7660:             gen_jmp_im(pc_ptr - dc->cs_base);
                   7661:             gen_eob(dc);
                   7662:             break;
                   7663:         }
                   7664:     }
1.1.1.7 ! root     7665:     if (tb->cflags & CF_LAST_IO)
        !          7666:         gen_io_end();
        !          7667:     gen_icount_end(tb, num_insns);
1.1       root     7668:     *gen_opc_ptr = INDEX_op_end;
                   7669:     /* we don't forget to fill the last values */
                   7670:     if (search_pc) {
                   7671:         j = gen_opc_ptr - gen_opc_buf;
                   7672:         lj++;
                   7673:         while (lj <= j)
                   7674:             gen_opc_instr_start[lj++] = 0;
                   7675:     }
1.1.1.6   root     7676: 
1.1       root     7677: #ifdef DEBUG_DISAS
1.1.1.7 ! root     7678:     log_cpu_state_mask(CPU_LOG_TB_CPU, env, X86_DUMP_CCOP);
        !          7679:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1.1       root     7680:         int disas_flags;
1.1.1.7 ! root     7681:         qemu_log("----------------\n");
        !          7682:         qemu_log("IN: %s\n", lookup_symbol(pc_start));
1.1       root     7683: #ifdef TARGET_X86_64
                   7684:         if (dc->code64)
                   7685:             disas_flags = 2;
                   7686:         else
                   7687: #endif
                   7688:             disas_flags = !dc->code32;
1.1.1.7 ! root     7689:         log_target_disas(pc_start, pc_ptr - pc_start, disas_flags);
        !          7690:         qemu_log("\n");
1.1       root     7691:     }
                   7692: #endif
                   7693: 
1.1.1.7 ! root     7694:     if (!search_pc) {
1.1       root     7695:         tb->size = pc_ptr - pc_start;
1.1.1.7 ! root     7696:         tb->icount = num_insns;
        !          7697:     }
1.1       root     7698: }
                   7699: 
1.1.1.7 ! root     7700: void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1.1       root     7701: {
1.1.1.7 ! root     7702:     gen_intermediate_code_internal(env, tb, 0);
1.1       root     7703: }
                   7704: 
1.1.1.7 ! root     7705: void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1.1       root     7706: {
1.1.1.7 ! root     7707:     gen_intermediate_code_internal(env, tb, 1);
1.1       root     7708: }
                   7709: 
1.1.1.7 ! root     7710: void gen_pc_load(CPUState *env, TranslationBlock *tb,
        !          7711:                 unsigned long searched_pc, int pc_pos, void *puc)
        !          7712: {
        !          7713:     int cc_op;
        !          7714: #ifdef DEBUG_DISAS
        !          7715:     if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
        !          7716:         int i;
        !          7717:         qemu_log("RESTORE:\n");
        !          7718:         for(i = 0;i <= pc_pos; i++) {
        !          7719:             if (gen_opc_instr_start[i]) {
        !          7720:                 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
        !          7721:             }
        !          7722:         }
        !          7723:         qemu_log("spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
        !          7724:                 searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
        !          7725:                 (uint32_t)tb->cs_base);
        !          7726:     }
        !          7727: #endif
        !          7728:     env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
        !          7729:     cc_op = gen_opc_cc_op[pc_pos];
        !          7730:     if (cc_op != CC_OP_DYNAMIC)
        !          7731:         env->cc_op = cc_op;
        !          7732: }

unix.superglobalmegacorp.com

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