Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 222a3336

History | View | Annotate | Download (252.9 kB)

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