Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ efade670

History | View | Annotate | Download (237.1 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 2c0262af bellard
/* 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 664e0f19 bellard
    /* MMX ops and their SSE extensions */
2774 664e0f19 bellard
    [0x60] = MMX_OP2(punpcklbw),
2775 664e0f19 bellard
    [0x61] = MMX_OP2(punpcklwd),
2776 664e0f19 bellard
    [0x62] = MMX_OP2(punpckldq),
2777 664e0f19 bellard
    [0x63] = MMX_OP2(packsswb),
2778 664e0f19 bellard
    [0x64] = MMX_OP2(pcmpgtb),
2779 664e0f19 bellard
    [0x65] = MMX_OP2(pcmpgtw),
2780 664e0f19 bellard
    [0x66] = MMX_OP2(pcmpgtl),
2781 664e0f19 bellard
    [0x67] = MMX_OP2(packuswb),
2782 664e0f19 bellard
    [0x68] = MMX_OP2(punpckhbw),
2783 664e0f19 bellard
    [0x69] = MMX_OP2(punpckhwd),
2784 664e0f19 bellard
    [0x6a] = MMX_OP2(punpckhdq),
2785 664e0f19 bellard
    [0x6b] = MMX_OP2(packssdw),
2786 5af45186 bellard
    [0x6c] = { NULL, helper_punpcklqdq_xmm },
2787 5af45186 bellard
    [0x6d] = { NULL, helper_punpckhqdq_xmm },
2788 664e0f19 bellard
    [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2789 664e0f19 bellard
    [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2790 5af45186 bellard
    [0x70] = { helper_pshufw_mmx,
2791 5af45186 bellard
               helper_pshufd_xmm,
2792 5af45186 bellard
               helper_pshufhw_xmm,
2793 5af45186 bellard
               helper_pshuflw_xmm },
2794 664e0f19 bellard
    [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2795 664e0f19 bellard
    [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2796 664e0f19 bellard
    [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2797 664e0f19 bellard
    [0x74] = MMX_OP2(pcmpeqb),
2798 664e0f19 bellard
    [0x75] = MMX_OP2(pcmpeqw),
2799 664e0f19 bellard
    [0x76] = MMX_OP2(pcmpeql),
2800 a35f3ec7 aurel32
    [0x77] = { SSE_DUMMY }, /* emms */
2801 5af45186 bellard
    [0x7c] = { NULL, helper_haddpd, NULL, helper_haddps },
2802 5af45186 bellard
    [0x7d] = { NULL, helper_hsubpd, NULL, helper_hsubps },
2803 664e0f19 bellard
    [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2804 664e0f19 bellard
    [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2805 664e0f19 bellard
    [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2806 664e0f19 bellard
    [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2807 5af45186 bellard
    [0xd0] = { NULL, helper_addsubpd, NULL, helper_addsubps },
2808 664e0f19 bellard
    [0xd1] = MMX_OP2(psrlw),
2809 664e0f19 bellard
    [0xd2] = MMX_OP2(psrld),
2810 664e0f19 bellard
    [0xd3] = MMX_OP2(psrlq),
2811 664e0f19 bellard
    [0xd4] = MMX_OP2(paddq),
2812 664e0f19 bellard
    [0xd5] = MMX_OP2(pmullw),
2813 664e0f19 bellard
    [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2814 664e0f19 bellard
    [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2815 664e0f19 bellard
    [0xd8] = MMX_OP2(psubusb),
2816 664e0f19 bellard
    [0xd9] = MMX_OP2(psubusw),
2817 664e0f19 bellard
    [0xda] = MMX_OP2(pminub),
2818 664e0f19 bellard
    [0xdb] = MMX_OP2(pand),
2819 664e0f19 bellard
    [0xdc] = MMX_OP2(paddusb),
2820 664e0f19 bellard
    [0xdd] = MMX_OP2(paddusw),
2821 664e0f19 bellard
    [0xde] = MMX_OP2(pmaxub),
2822 664e0f19 bellard
    [0xdf] = MMX_OP2(pandn),
2823 664e0f19 bellard
    [0xe0] = MMX_OP2(pavgb),
2824 664e0f19 bellard
    [0xe1] = MMX_OP2(psraw),
2825 664e0f19 bellard
    [0xe2] = MMX_OP2(psrad),
2826 664e0f19 bellard
    [0xe3] = MMX_OP2(pavgw),
2827 664e0f19 bellard
    [0xe4] = MMX_OP2(pmulhuw),
2828 664e0f19 bellard
    [0xe5] = MMX_OP2(pmulhw),
2829 5af45186 bellard
    [0xe6] = { NULL, helper_cvttpd2dq, helper_cvtdq2pd, helper_cvtpd2dq },
2830 664e0f19 bellard
    [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
2831 664e0f19 bellard
    [0xe8] = MMX_OP2(psubsb),
2832 664e0f19 bellard
    [0xe9] = MMX_OP2(psubsw),
2833 664e0f19 bellard
    [0xea] = MMX_OP2(pminsw),
2834 664e0f19 bellard
    [0xeb] = MMX_OP2(por),
2835 664e0f19 bellard
    [0xec] = MMX_OP2(paddsb),
2836 664e0f19 bellard
    [0xed] = MMX_OP2(paddsw),
2837 664e0f19 bellard
    [0xee] = MMX_OP2(pmaxsw),
2838 664e0f19 bellard
    [0xef] = MMX_OP2(pxor),
2839 465e9838 bellard
    [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2840 664e0f19 bellard
    [0xf1] = MMX_OP2(psllw),
2841 664e0f19 bellard
    [0xf2] = MMX_OP2(pslld),
2842 664e0f19 bellard
    [0xf3] = MMX_OP2(psllq),
2843 664e0f19 bellard
    [0xf4] = MMX_OP2(pmuludq),
2844 664e0f19 bellard
    [0xf5] = MMX_OP2(pmaddwd),
2845 664e0f19 bellard
    [0xf6] = MMX_OP2(psadbw),
2846 664e0f19 bellard
    [0xf7] = MMX_OP2(maskmov),
2847 664e0f19 bellard
    [0xf8] = MMX_OP2(psubb),
2848 664e0f19 bellard
    [0xf9] = MMX_OP2(psubw),
2849 664e0f19 bellard
    [0xfa] = MMX_OP2(psubl),
2850 664e0f19 bellard
    [0xfb] = MMX_OP2(psubq),
2851 664e0f19 bellard
    [0xfc] = MMX_OP2(paddb),
2852 664e0f19 bellard
    [0xfd] = MMX_OP2(paddw),
2853 664e0f19 bellard
    [0xfe] = MMX_OP2(paddl),
2854 664e0f19 bellard
};
2855 664e0f19 bellard
2856 5af45186 bellard
static void *sse_op_table2[3 * 8][2] = {
2857 664e0f19 bellard
    [0 + 2] = MMX_OP2(psrlw),
2858 664e0f19 bellard
    [0 + 4] = MMX_OP2(psraw),
2859 664e0f19 bellard
    [0 + 6] = MMX_OP2(psllw),
2860 664e0f19 bellard
    [8 + 2] = MMX_OP2(psrld),
2861 664e0f19 bellard
    [8 + 4] = MMX_OP2(psrad),
2862 664e0f19 bellard
    [8 + 6] = MMX_OP2(pslld),
2863 664e0f19 bellard
    [16 + 2] = MMX_OP2(psrlq),
2864 5af45186 bellard
    [16 + 3] = { NULL, helper_psrldq_xmm },
2865 664e0f19 bellard
    [16 + 6] = MMX_OP2(psllq),
2866 5af45186 bellard
    [16 + 7] = { NULL, helper_pslldq_xmm },
2867 664e0f19 bellard
};
2868 664e0f19 bellard
2869 5af45186 bellard
static void *sse_op_table3[4 * 3] = {
2870 5af45186 bellard
    helper_cvtsi2ss,
2871 5af45186 bellard
    helper_cvtsi2sd,
2872 5af45186 bellard
    X86_64_ONLY(helper_cvtsq2ss),
2873 5af45186 bellard
    X86_64_ONLY(helper_cvtsq2sd),
2874 5af45186 bellard
2875 5af45186 bellard
    helper_cvttss2si,
2876 5af45186 bellard
    helper_cvttsd2si,
2877 5af45186 bellard
    X86_64_ONLY(helper_cvttss2sq),
2878 5af45186 bellard
    X86_64_ONLY(helper_cvttsd2sq),
2879 5af45186 bellard
2880 5af45186 bellard
    helper_cvtss2si,
2881 5af45186 bellard
    helper_cvtsd2si,
2882 5af45186 bellard
    X86_64_ONLY(helper_cvtss2sq),
2883 5af45186 bellard
    X86_64_ONLY(helper_cvtsd2sq),
2884 664e0f19 bellard
};
2885 3b46e624 ths
2886 5af45186 bellard
static void *sse_op_table4[8][4] = {
2887 664e0f19 bellard
    SSE_FOP(cmpeq),
2888 664e0f19 bellard
    SSE_FOP(cmplt),
2889 664e0f19 bellard
    SSE_FOP(cmple),
2890 664e0f19 bellard
    SSE_FOP(cmpunord),
2891 664e0f19 bellard
    SSE_FOP(cmpneq),
2892 664e0f19 bellard
    SSE_FOP(cmpnlt),
2893 664e0f19 bellard
    SSE_FOP(cmpnle),
2894 664e0f19 bellard
    SSE_FOP(cmpord),
2895 664e0f19 bellard
};
2896 3b46e624 ths
2897 5af45186 bellard
static void *sse_op_table5[256] = {
2898 5af45186 bellard
    [0x0c] = helper_pi2fw,
2899 5af45186 bellard
    [0x0d] = helper_pi2fd,
2900 5af45186 bellard
    [0x1c] = helper_pf2iw,
2901 5af45186 bellard
    [0x1d] = helper_pf2id,
2902 5af45186 bellard
    [0x8a] = helper_pfnacc,
2903 5af45186 bellard
    [0x8e] = helper_pfpnacc,
2904 5af45186 bellard
    [0x90] = helper_pfcmpge,
2905 5af45186 bellard
    [0x94] = helper_pfmin,
2906 5af45186 bellard
    [0x96] = helper_pfrcp,
2907 5af45186 bellard
    [0x97] = helper_pfrsqrt,
2908 5af45186 bellard
    [0x9a] = helper_pfsub,
2909 5af45186 bellard
    [0x9e] = helper_pfadd,
2910 5af45186 bellard
    [0xa0] = helper_pfcmpgt,
2911 5af45186 bellard
    [0xa4] = helper_pfmax,
2912 5af45186 bellard
    [0xa6] = helper_movq, /* pfrcpit1; no need to actually increase precision */
2913 5af45186 bellard
    [0xa7] = helper_movq, /* pfrsqit1 */
2914 5af45186 bellard
    [0xaa] = helper_pfsubr,
2915 5af45186 bellard
    [0xae] = helper_pfacc,
2916 5af45186 bellard
    [0xb0] = helper_pfcmpeq,
2917 5af45186 bellard
    [0xb4] = helper_pfmul,
2918 5af45186 bellard
    [0xb6] = helper_movq, /* pfrcpit2 */
2919 5af45186 bellard
    [0xb7] = helper_pmulhrw_mmx,
2920 5af45186 bellard
    [0xbb] = helper_pswapd,
2921 5af45186 bellard
    [0xbf] = helper_pavgb_mmx /* pavgusb */
2922 a35f3ec7 aurel32
};
2923 a35f3ec7 aurel32
2924 664e0f19 bellard
static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2925 664e0f19 bellard
{
2926 664e0f19 bellard
    int b1, op1_offset, op2_offset, is_xmm, val, ot;
2927 664e0f19 bellard
    int modrm, mod, rm, reg, reg_addr, offset_addr;
2928 5af45186 bellard
    void *sse_op2;
2929 664e0f19 bellard
2930 664e0f19 bellard
    b &= 0xff;
2931 5fafdf24 ths
    if (s->prefix & PREFIX_DATA)
2932 664e0f19 bellard
        b1 = 1;
2933 5fafdf24 ths
    else if (s->prefix & PREFIX_REPZ)
2934 664e0f19 bellard
        b1 = 2;
2935 5fafdf24 ths
    else if (s->prefix & PREFIX_REPNZ)
2936 664e0f19 bellard
        b1 = 3;
2937 664e0f19 bellard
    else
2938 664e0f19 bellard
        b1 = 0;
2939 664e0f19 bellard
    sse_op2 = sse_op_table1[b][b1];
2940 5fafdf24 ths
    if (!sse_op2)
2941 664e0f19 bellard
        goto illegal_op;
2942 a35f3ec7 aurel32
    if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2943 664e0f19 bellard
        is_xmm = 1;
2944 664e0f19 bellard
    } else {
2945 664e0f19 bellard
        if (b1 == 0) {
2946 664e0f19 bellard
            /* MMX case */
2947 664e0f19 bellard
            is_xmm = 0;
2948 664e0f19 bellard
        } else {
2949 664e0f19 bellard
            is_xmm = 1;
2950 664e0f19 bellard
        }
2951 664e0f19 bellard
    }
2952 664e0f19 bellard
    /* simple MMX/SSE operation */
2953 664e0f19 bellard
    if (s->flags & HF_TS_MASK) {
2954 664e0f19 bellard
        gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2955 664e0f19 bellard
        return;
2956 664e0f19 bellard
    }
2957 664e0f19 bellard
    if (s->flags & HF_EM_MASK) {
2958 664e0f19 bellard
    illegal_op:
2959 664e0f19 bellard
        gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2960 664e0f19 bellard
        return;
2961 664e0f19 bellard
    }
2962 664e0f19 bellard
    if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2963 664e0f19 bellard
        goto illegal_op;
2964 e771edab aurel32
    if (b == 0x0e) {
2965 e771edab aurel32
        if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
2966 e771edab aurel32
            goto illegal_op;
2967 e771edab aurel32
        /* femms */
2968 5af45186 bellard
        tcg_gen_helper_0_0(helper_emms);
2969 e771edab aurel32
        return;
2970 e771edab aurel32
    }
2971 e771edab aurel32
    if (b == 0x77) {
2972 e771edab aurel32
        /* emms */
2973 5af45186 bellard
        tcg_gen_helper_0_0(helper_emms);
2974 664e0f19 bellard
        return;
2975 664e0f19 bellard
    }
2976 664e0f19 bellard
    /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2977 664e0f19 bellard
       the static cpu state) */
2978 664e0f19 bellard
    if (!is_xmm) {
2979 5af45186 bellard
        tcg_gen_helper_0_0(helper_enter_mmx);
2980 664e0f19 bellard
    }
2981 664e0f19 bellard
2982 664e0f19 bellard
    modrm = ldub_code(s->pc++);
2983 664e0f19 bellard
    reg = ((modrm >> 3) & 7);
2984 664e0f19 bellard
    if (is_xmm)
2985 664e0f19 bellard
        reg |= rex_r;
2986 664e0f19 bellard
    mod = (modrm >> 6) & 3;
2987 664e0f19 bellard
    if (sse_op2 == SSE_SPECIAL) {
2988 664e0f19 bellard
        b |= (b1 << 8);
2989 664e0f19 bellard
        switch(b) {
2990 664e0f19 bellard
        case 0x0e7: /* movntq */
2991 5fafdf24 ths
            if (mod == 3)
2992 664e0f19 bellard
                goto illegal_op;
2993 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2994 8686c490 bellard
            gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
2995 664e0f19 bellard
            break;
2996 664e0f19 bellard
        case 0x1e7: /* movntdq */
2997 664e0f19 bellard
        case 0x02b: /* movntps */
2998 664e0f19 bellard
        case 0x12b: /* movntps */
2999 465e9838 bellard
        case 0x3f0: /* lddqu */
3000 465e9838 bellard
            if (mod == 3)
3001 664e0f19 bellard
                goto illegal_op;
3002 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3003 8686c490 bellard
            gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3004 664e0f19 bellard
            break;
3005 664e0f19 bellard
        case 0x6e: /* movd mm, ea */
3006 dabd98dd bellard
#ifdef TARGET_X86_64
3007 dabd98dd bellard
            if (s->dflag == 2) {
3008 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
3009 5af45186 bellard
                tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3010 5fafdf24 ths
            } else
3011 dabd98dd bellard
#endif
3012 dabd98dd bellard
            {
3013 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
3014 5af45186 bellard
                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
3015 5af45186 bellard
                                 offsetof(CPUX86State,fpregs[reg].mmx));
3016 5af45186 bellard
                tcg_gen_helper_0_2(helper_movl_mm_T0_mmx, cpu_ptr0, cpu_T[0]);
3017 dabd98dd bellard
            }
3018 664e0f19 bellard
            break;
3019 664e0f19 bellard
        case 0x16e: /* movd xmm, ea */
3020 dabd98dd bellard
#ifdef TARGET_X86_64
3021 dabd98dd bellard
            if (s->dflag == 2) {
3022 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
3023 5af45186 bellard
                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
3024 5af45186 bellard
                                 offsetof(CPUX86State,xmm_regs[reg]));
3025 5af45186 bellard
                tcg_gen_helper_0_2(helper_movq_mm_T0_xmm, cpu_ptr0, cpu_T[0]);
3026 5fafdf24 ths
            } else
3027 dabd98dd bellard
#endif
3028 dabd98dd bellard
            {
3029 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
3030 5af45186 bellard
                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
3031 5af45186 bellard
                                 offsetof(CPUX86State,xmm_regs[reg]));
3032 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3033 b6abf97d bellard
                tcg_gen_helper_0_2(helper_movl_mm_T0_xmm, cpu_ptr0, cpu_tmp2_i32);
3034 dabd98dd bellard
            }
3035 664e0f19 bellard
            break;
3036 664e0f19 bellard
        case 0x6f: /* movq mm, ea */
3037 664e0f19 bellard
            if (mod != 3) {
3038 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3039 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3040 664e0f19 bellard
            } else {
3041 664e0f19 bellard
                rm = (modrm & 7);
3042 b6abf97d bellard
                tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3043 5af45186 bellard
                               offsetof(CPUX86State,fpregs[rm].mmx));
3044 b6abf97d bellard
                tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3045 5af45186 bellard
                               offsetof(CPUX86State,fpregs[reg].mmx));
3046 664e0f19 bellard
            }
3047 664e0f19 bellard
            break;
3048 664e0f19 bellard
        case 0x010: /* movups */
3049 664e0f19 bellard
        case 0x110: /* movupd */
3050 664e0f19 bellard
        case 0x028: /* movaps */
3051 664e0f19 bellard
        case 0x128: /* movapd */
3052 664e0f19 bellard
        case 0x16f: /* movdqa xmm, ea */
3053 664e0f19 bellard
        case 0x26f: /* movdqu xmm, ea */
3054 664e0f19 bellard
            if (mod != 3) {
3055 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3056 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3057 664e0f19 bellard
            } else {
3058 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3059 664e0f19 bellard
                gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3060 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm]));
3061 664e0f19 bellard
            }
3062 664e0f19 bellard
            break;
3063 664e0f19 bellard
        case 0x210: /* movss xmm, ea */
3064 664e0f19 bellard
            if (mod != 3) {
3065 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3066 57fec1fe bellard
                gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3067 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3068 664e0f19 bellard
                gen_op_movl_T0_0();
3069 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3070 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3071 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3072 664e0f19 bellard
            } else {
3073 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3074 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3075 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3076 664e0f19 bellard
            }
3077 664e0f19 bellard
            break;
3078 664e0f19 bellard
        case 0x310: /* movsd xmm, ea */
3079 664e0f19 bellard
            if (mod != 3) {
3080 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3081 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3082 664e0f19 bellard
                gen_op_movl_T0_0();
3083 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3084 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3085 664e0f19 bellard
            } else {
3086 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3087 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3088 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3089 664e0f19 bellard
            }
3090 664e0f19 bellard
            break;
3091 664e0f19 bellard
        case 0x012: /* movlps */
3092 664e0f19 bellard
        case 0x112: /* movlpd */
3093 664e0f19 bellard
            if (mod != 3) {
3094 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3095 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3096 664e0f19 bellard
            } else {
3097 664e0f19 bellard
                /* movhlps */
3098 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3099 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3100 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3101 664e0f19 bellard
            }
3102 664e0f19 bellard
            break;
3103 465e9838 bellard
        case 0x212: /* movsldup */
3104 465e9838 bellard
            if (mod != 3) {
3105 465e9838 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3106 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3107 465e9838 bellard
            } else {
3108 465e9838 bellard
                rm = (modrm & 7) | REX_B(s);
3109 465e9838 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3110 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3111 465e9838 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3112 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3113 465e9838 bellard
            }
3114 465e9838 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3115 465e9838 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3116 465e9838 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3117 465e9838 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3118 465e9838 bellard
            break;
3119 465e9838 bellard
        case 0x312: /* movddup */
3120 465e9838 bellard
            if (mod != 3) {
3121 465e9838 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3122 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3123 465e9838 bellard
            } else {
3124 465e9838 bellard
                rm = (modrm & 7) | REX_B(s);
3125 465e9838 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3126 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3127 465e9838 bellard
            }
3128 465e9838 bellard
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3129 ba6526df bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3130 465e9838 bellard
            break;
3131 664e0f19 bellard
        case 0x016: /* movhps */
3132 664e0f19 bellard
        case 0x116: /* movhpd */
3133 664e0f19 bellard
            if (mod != 3) {
3134 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3135 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3136 664e0f19 bellard
            } else {
3137 664e0f19 bellard
                /* movlhps */
3138 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3139 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3140 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3141 664e0f19 bellard
            }
3142 664e0f19 bellard
            break;
3143 664e0f19 bellard
        case 0x216: /* movshdup */
3144 664e0f19 bellard
            if (mod != 3) {
3145 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3146 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3147 664e0f19 bellard
            } else {
3148 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3149 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3150 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3151 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3152 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3153 664e0f19 bellard
            }
3154 664e0f19 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3155 664e0f19 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3156 664e0f19 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3157 664e0f19 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3158 664e0f19 bellard
            break;
3159 664e0f19 bellard
        case 0x7e: /* movd ea, mm */
3160 dabd98dd bellard
#ifdef TARGET_X86_64
3161 dabd98dd bellard
            if (s->dflag == 2) {
3162 5af45186 bellard
                tcg_gen_ld_i64(cpu_T[0], cpu_env, 
3163 5af45186 bellard
                               offsetof(CPUX86State,fpregs[reg].mmx));
3164 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
3165 5fafdf24 ths
            } else
3166 dabd98dd bellard
#endif
3167 dabd98dd bellard
            {
3168 5af45186 bellard
                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
3169 5af45186 bellard
                                 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3170 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
3171 dabd98dd bellard
            }
3172 664e0f19 bellard
            break;
3173 664e0f19 bellard
        case 0x17e: /* movd ea, xmm */
3174 dabd98dd bellard
#ifdef TARGET_X86_64
3175 dabd98dd bellard
            if (s->dflag == 2) {
3176 5af45186 bellard
                tcg_gen_ld_i64(cpu_T[0], cpu_env, 
3177 5af45186 bellard
                               offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3178 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
3179 5fafdf24 ths
            } else
3180 dabd98dd bellard
#endif
3181 dabd98dd bellard
            {
3182 5af45186 bellard
                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
3183 5af45186 bellard
                                 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3184 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
3185 dabd98dd bellard
            }
3186 664e0f19 bellard
            break;
3187 664e0f19 bellard
        case 0x27e: /* movq xmm, ea */
3188 664e0f19 bellard
            if (mod != 3) {
3189 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3190 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3191 664e0f19 bellard
            } else {
3192 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3193 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3194 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3195 664e0f19 bellard
            }
3196 664e0f19 bellard
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3197 664e0f19 bellard
            break;
3198 664e0f19 bellard
        case 0x7f: /* movq ea, mm */
3199 664e0f19 bellard
            if (mod != 3) {
3200 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3201 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3202 664e0f19 bellard
            } else {
3203 664e0f19 bellard
                rm = (modrm & 7);
3204 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3205 664e0f19 bellard
                            offsetof(CPUX86State,fpregs[reg].mmx));
3206 664e0f19 bellard
            }
3207 664e0f19 bellard
            break;
3208 664e0f19 bellard
        case 0x011: /* movups */
3209 664e0f19 bellard
        case 0x111: /* movupd */
3210 664e0f19 bellard
        case 0x029: /* movaps */
3211 664e0f19 bellard
        case 0x129: /* movapd */
3212 664e0f19 bellard
        case 0x17f: /* movdqa ea, xmm */
3213 664e0f19 bellard
        case 0x27f: /* movdqu ea, xmm */
3214 664e0f19 bellard
            if (mod != 3) {
3215 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3216 8686c490 bellard
                gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3217 664e0f19 bellard
            } else {
3218 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3219 664e0f19 bellard
                gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3220 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg]));
3221 664e0f19 bellard
            }
3222 664e0f19 bellard
            break;
3223 664e0f19 bellard
        case 0x211: /* movss ea, xmm */
3224 664e0f19 bellard
            if (mod != 3) {
3225 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3226 651ba608 bellard
                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3227 57fec1fe bellard
                gen_op_st_T0_A0(OT_LONG + s->mem_index);
3228 664e0f19 bellard
            } else {
3229 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3230 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3231 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3232 664e0f19 bellard
            }
3233 664e0f19 bellard
            break;
3234 664e0f19 bellard
        case 0x311: /* movsd ea, xmm */
3235 664e0f19 bellard
            if (mod != 3) {
3236 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3237 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3238 664e0f19 bellard
            } else {
3239 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3240 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3241 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3242 664e0f19 bellard
            }
3243 664e0f19 bellard
            break;
3244 664e0f19 bellard
        case 0x013: /* movlps */
3245 664e0f19 bellard
        case 0x113: /* movlpd */
3246 664e0f19 bellard
            if (mod != 3) {
3247 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3248 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3249 664e0f19 bellard
            } else {
3250 664e0f19 bellard
                goto illegal_op;
3251 664e0f19 bellard
            }
3252 664e0f19 bellard
            break;
3253 664e0f19 bellard
        case 0x017: /* movhps */
3254 664e0f19 bellard
        case 0x117: /* movhpd */
3255 664e0f19 bellard
            if (mod != 3) {
3256 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3257 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3258 664e0f19 bellard
            } else {
3259 664e0f19 bellard
                goto illegal_op;
3260 664e0f19 bellard
            }
3261 664e0f19 bellard
            break;
3262 664e0f19 bellard
        case 0x71: /* shift mm, im */
3263 664e0f19 bellard
        case 0x72:
3264 664e0f19 bellard
        case 0x73:
3265 664e0f19 bellard
        case 0x171: /* shift xmm, im */
3266 664e0f19 bellard
        case 0x172:
3267 664e0f19 bellard
        case 0x173:
3268 664e0f19 bellard
            val = ldub_code(s->pc++);
3269 664e0f19 bellard
            if (is_xmm) {
3270 664e0f19 bellard
                gen_op_movl_T0_im(val);
3271 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3272 664e0f19 bellard
                gen_op_movl_T0_0();
3273 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
3274 664e0f19 bellard
                op1_offset = offsetof(CPUX86State,xmm_t0);
3275 664e0f19 bellard
            } else {
3276 664e0f19 bellard
                gen_op_movl_T0_im(val);
3277 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3278 664e0f19 bellard
                gen_op_movl_T0_0();
3279 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3280 664e0f19 bellard
                op1_offset = offsetof(CPUX86State,mmx_t0);
3281 664e0f19 bellard
            }
3282 664e0f19 bellard
            sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
3283 664e0f19 bellard
            if (!sse_op2)
3284 664e0f19 bellard
                goto illegal_op;
3285 664e0f19 bellard
            if (is_xmm) {
3286 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3287 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3288 664e0f19 bellard
            } else {
3289 664e0f19 bellard
                rm = (modrm & 7);
3290 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3291 664e0f19 bellard
            }
3292 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3293 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3294 5af45186 bellard
            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
3295 664e0f19 bellard
            break;
3296 664e0f19 bellard
        case 0x050: /* movmskps */
3297 664e0f19 bellard
            rm = (modrm & 7) | REX_B(s);
3298 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
3299 5af45186 bellard
                             offsetof(CPUX86State,xmm_regs[rm]));
3300 b6abf97d bellard
            tcg_gen_helper_1_1(helper_movmskps, cpu_tmp2_i32, cpu_ptr0);
3301 b6abf97d bellard
            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3302 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3303 664e0f19 bellard
            break;
3304 664e0f19 bellard
        case 0x150: /* movmskpd */
3305 664e0f19 bellard
            rm = (modrm & 7) | REX_B(s);
3306 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
3307 5af45186 bellard
                             offsetof(CPUX86State,xmm_regs[rm]));
3308 b6abf97d bellard
            tcg_gen_helper_1_1(helper_movmskpd, cpu_tmp2_i32, cpu_ptr0);
3309 b6abf97d bellard
            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3310 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3311 664e0f19 bellard
            break;
3312 664e0f19 bellard
        case 0x02a: /* cvtpi2ps */
3313 664e0f19 bellard
        case 0x12a: /* cvtpi2pd */
3314 5af45186 bellard
            tcg_gen_helper_0_0(helper_enter_mmx);
3315 664e0f19 bellard
            if (mod != 3) {
3316 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3317 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,mmx_t0);
3318 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, op2_offset);
3319 664e0f19 bellard
            } else {
3320 664e0f19 bellard
                rm = (modrm & 7);
3321 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3322 664e0f19 bellard
            }
3323 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3324 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3325 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3326 664e0f19 bellard
            switch(b >> 8) {
3327 664e0f19 bellard
            case 0x0:
3328 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvtpi2ps, cpu_ptr0, cpu_ptr1);
3329 664e0f19 bellard
                break;
3330 664e0f19 bellard
            default:
3331 664e0f19 bellard
            case 0x1:
3332 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvtpi2pd, cpu_ptr0, cpu_ptr1);
3333 664e0f19 bellard
                break;
3334 664e0f19 bellard
            }
3335 664e0f19 bellard
            break;
3336 664e0f19 bellard
        case 0x22a: /* cvtsi2ss */
3337 664e0f19 bellard
        case 0x32a: /* cvtsi2sd */
3338 664e0f19 bellard
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3339 664e0f19 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3340 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3341 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3342 5af45186 bellard
            sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)];
3343 b6abf97d bellard
            tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3344 b6abf97d bellard
            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_tmp2_i32);
3345 664e0f19 bellard
            break;
3346 664e0f19 bellard
        case 0x02c: /* cvttps2pi */
3347 664e0f19 bellard
        case 0x12c: /* cvttpd2pi */
3348 664e0f19 bellard
        case 0x02d: /* cvtps2pi */
3349 664e0f19 bellard
        case 0x12d: /* cvtpd2pi */
3350 5af45186 bellard
            tcg_gen_helper_0_0(helper_enter_mmx);
3351 664e0f19 bellard
            if (mod != 3) {
3352 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3353 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3354 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, op2_offset);
3355 664e0f19 bellard
            } else {
3356 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3357 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3358 664e0f19 bellard
            }
3359 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3360 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3361 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3362 664e0f19 bellard
            switch(b) {
3363 664e0f19 bellard
            case 0x02c:
3364 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvttps2pi, cpu_ptr0, cpu_ptr1);
3365 664e0f19 bellard
                break;
3366 664e0f19 bellard
            case 0x12c:
3367 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvttpd2pi, cpu_ptr0, cpu_ptr1);
3368 664e0f19 bellard
                break;
3369 664e0f19 bellard
            case 0x02d:
3370 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvtps2pi, cpu_ptr0, cpu_ptr1);
3371 664e0f19 bellard
                break;
3372 664e0f19 bellard
            case 0x12d:
3373 5af45186 bellard
                tcg_gen_helper_0_2(helper_cvtpd2pi, cpu_ptr0, cpu_ptr1);
3374 664e0f19 bellard
                break;
3375 664e0f19 bellard
            }
3376 664e0f19 bellard
            break;
3377 664e0f19 bellard
        case 0x22c: /* cvttss2si */
3378 664e0f19 bellard
        case 0x32c: /* cvttsd2si */
3379 664e0f19 bellard
        case 0x22d: /* cvtss2si */
3380 664e0f19 bellard
        case 0x32d: /* cvtsd2si */
3381 664e0f19 bellard
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3382 31313213 bellard
            if (mod != 3) {
3383 31313213 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3384 31313213 bellard
                if ((b >> 8) & 1) {
3385 8686c490 bellard
                    gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3386 31313213 bellard
                } else {
3387 57fec1fe bellard
                    gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3388 651ba608 bellard
                    tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3389 31313213 bellard
                }
3390 31313213 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3391 31313213 bellard
            } else {
3392 31313213 bellard
                rm = (modrm & 7) | REX_B(s);
3393 31313213 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3394 31313213 bellard
            }
3395 5af45186 bellard
            sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
3396 5af45186 bellard
                                    (b & 1) * 4];
3397 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3398 5af45186 bellard
            if (ot == OT_LONG) {
3399 b6abf97d bellard
                tcg_gen_helper_1_1(sse_op2, cpu_tmp2_i32, cpu_ptr0);
3400 b6abf97d bellard
                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3401 5af45186 bellard
            } else {
3402 5af45186 bellard
                tcg_gen_helper_1_1(sse_op2, cpu_T[0], cpu_ptr0);
3403 5af45186 bellard
            }
3404 57fec1fe bellard
            gen_op_mov_reg_T0(ot, reg);
3405 664e0f19 bellard
            break;
3406 664e0f19 bellard
        case 0xc4: /* pinsrw */
3407 5fafdf24 ths
        case 0x1c4:
3408 d1e42c5c bellard
            s->rip_offset = 1;
3409 664e0f19 bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3410 664e0f19 bellard
            val = ldub_code(s->pc++);
3411 664e0f19 bellard
            if (b1) {
3412 664e0f19 bellard
                val &= 7;
3413 5af45186 bellard
                tcg_gen_st16_tl(cpu_T[0], cpu_env,
3414 5af45186 bellard
                                offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
3415 664e0f19 bellard
            } else {
3416 664e0f19 bellard
                val &= 3;
3417 5af45186 bellard
                tcg_gen_st16_tl(cpu_T[0], cpu_env,
3418 5af45186 bellard
                                offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3419 664e0f19 bellard
            }
3420 664e0f19 bellard
            break;
3421 664e0f19 bellard
        case 0xc5: /* pextrw */
3422 5fafdf24 ths
        case 0x1c5:
3423 664e0f19 bellard
            if (mod != 3)
3424 664e0f19 bellard
                goto illegal_op;
3425 664e0f19 bellard
            val = ldub_code(s->pc++);
3426 664e0f19 bellard
            if (b1) {
3427 664e0f19 bellard
                val &= 7;
3428 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3429 5af45186 bellard
                tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3430 5af45186 bellard
                                 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
3431 664e0f19 bellard
            } else {
3432 664e0f19 bellard
                val &= 3;
3433 664e0f19 bellard
                rm = (modrm & 7);
3434 5af45186 bellard
                tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3435 5af45186 bellard
                                offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3436 664e0f19 bellard
            }
3437 664e0f19 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
3438 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3439 664e0f19 bellard
            break;
3440 664e0f19 bellard
        case 0x1d6: /* movq ea, xmm */
3441 664e0f19 bellard
            if (mod != 3) {
3442 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3443 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3444 664e0f19 bellard
            } else {
3445 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3446 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3447 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3448 664e0f19 bellard
                gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3449 664e0f19 bellard
            }
3450 664e0f19 bellard
            break;
3451 664e0f19 bellard
        case 0x2d6: /* movq2dq */
3452 5af45186 bellard
            tcg_gen_helper_0_0(helper_enter_mmx);
3453 480c1cdb bellard
            rm = (modrm & 7);
3454 480c1cdb bellard
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3455 480c1cdb bellard
                        offsetof(CPUX86State,fpregs[rm].mmx));
3456 480c1cdb bellard
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3457 664e0f19 bellard
            break;
3458 664e0f19 bellard
        case 0x3d6: /* movdq2q */
3459 5af45186 bellard
            tcg_gen_helper_0_0(helper_enter_mmx);
3460 480c1cdb bellard
            rm = (modrm & 7) | REX_B(s);
3461 480c1cdb bellard
            gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3462 480c1cdb bellard
                        offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3463 664e0f19 bellard
            break;
3464 664e0f19 bellard
        case 0xd7: /* pmovmskb */
3465 664e0f19 bellard
        case 0x1d7:
3466 664e0f19 bellard
            if (mod != 3)
3467 664e0f19 bellard
                goto illegal_op;
3468 664e0f19 bellard
            if (b1) {
3469 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3470 5af45186 bellard
                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3471 b6abf97d bellard
                tcg_gen_helper_1_1(helper_pmovmskb_xmm, cpu_tmp2_i32, cpu_ptr0);
3472 664e0f19 bellard
            } else {
3473 664e0f19 bellard
                rm = (modrm & 7);
3474 5af45186 bellard
                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3475 b6abf97d bellard
                tcg_gen_helper_1_1(helper_pmovmskb_mmx, cpu_tmp2_i32, cpu_ptr0);
3476 664e0f19 bellard
            }
3477 b6abf97d bellard
            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3478 664e0f19 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
3479 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3480 664e0f19 bellard
            break;
3481 664e0f19 bellard
        default:
3482 664e0f19 bellard
            goto illegal_op;
3483 664e0f19 bellard
        }
3484 664e0f19 bellard
    } else {
3485 664e0f19 bellard
        /* generic MMX or SSE operation */
3486 d1e42c5c bellard
        switch(b) {
3487 d1e42c5c bellard
        case 0x70: /* pshufx insn */
3488 d1e42c5c bellard
        case 0xc6: /* pshufx insn */
3489 d1e42c5c bellard
        case 0xc2: /* compare insns */
3490 d1e42c5c bellard
            s->rip_offset = 1;
3491 d1e42c5c bellard
            break;
3492 d1e42c5c bellard
        default:
3493 d1e42c5c bellard
            break;
3494 664e0f19 bellard
        }
3495 664e0f19 bellard
        if (is_xmm) {
3496 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3497 664e0f19 bellard
            if (mod != 3) {
3498 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3499 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3500 480c1cdb bellard
                if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
3501 664e0f19 bellard
                                b == 0xc2)) {
3502 664e0f19 bellard
                    /* specific case for SSE single instructions */
3503 664e0f19 bellard
                    if (b1 == 2) {
3504 664e0f19 bellard
                        /* 32 bit access */
3505 57fec1fe bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3506 651ba608 bellard
                        tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3507 664e0f19 bellard
                    } else {
3508 664e0f19 bellard
                        /* 64 bit access */
3509 8686c490 bellard
                        gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3510 664e0f19 bellard
                    }
3511 664e0f19 bellard
                } else {
3512 8686c490 bellard
                    gen_ldo_env_A0(s->mem_index, op2_offset);
3513 664e0f19 bellard
                }
3514 664e0f19 bellard
            } else {
3515 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3516 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3517 664e0f19 bellard
            }
3518 664e0f19 bellard
        } else {
3519 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3520 664e0f19 bellard
            if (mod != 3) {
3521 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3522 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,mmx_t0);
3523 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, op2_offset);
3524 664e0f19 bellard
            } else {
3525 664e0f19 bellard
                rm = (modrm & 7);
3526 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3527 664e0f19 bellard
            }
3528 664e0f19 bellard
        }
3529 664e0f19 bellard
        switch(b) {
3530 a35f3ec7 aurel32
        case 0x0f: /* 3DNow! data insns */
3531 e771edab aurel32
            if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3532 e771edab aurel32
                goto illegal_op;
3533 a35f3ec7 aurel32
            val = ldub_code(s->pc++);
3534 a35f3ec7 aurel32
            sse_op2 = sse_op_table5[val];
3535 a35f3ec7 aurel32
            if (!sse_op2)
3536 a35f3ec7 aurel32
                goto illegal_op;
3537 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3538 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3539 5af45186 bellard
            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
3540 a35f3ec7 aurel32
            break;
3541 664e0f19 bellard
        case 0x70: /* pshufx insn */
3542 664e0f19 bellard
        case 0xc6: /* pshufx insn */
3543 664e0f19 bellard
            val = ldub_code(s->pc++);
3544 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3545 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3546 5af45186 bellard
            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
3547 664e0f19 bellard
            break;
3548 664e0f19 bellard
        case 0xc2:
3549 664e0f19 bellard
            /* compare insns */
3550 664e0f19 bellard
            val = ldub_code(s->pc++);
3551 664e0f19 bellard
            if (val >= 8)
3552 664e0f19 bellard
                goto illegal_op;
3553 664e0f19 bellard
            sse_op2 = sse_op_table4[val][b1];
3554 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3555 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3556 5af45186 bellard
            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
3557 664e0f19 bellard
            break;
3558 b8b6a50b bellard
        case 0xf7:
3559 b8b6a50b bellard
            /* maskmov : we must prepare A0 */
3560 b8b6a50b bellard
            if (mod != 3)
3561 b8b6a50b bellard
                goto illegal_op;
3562 b8b6a50b bellard
#ifdef TARGET_X86_64
3563 b8b6a50b bellard
            if (s->aflag == 2) {
3564 b8b6a50b bellard
                gen_op_movq_A0_reg(R_EDI);
3565 b8b6a50b bellard
            } else
3566 b8b6a50b bellard
#endif
3567 b8b6a50b bellard
            {
3568 b8b6a50b bellard
                gen_op_movl_A0_reg(R_EDI);
3569 b8b6a50b bellard
                if (s->aflag == 0)
3570 b8b6a50b bellard
                    gen_op_andl_A0_ffff();
3571 b8b6a50b bellard
            }
3572 b8b6a50b bellard
            gen_add_A0_ds_seg(s);
3573 b8b6a50b bellard
3574 b8b6a50b bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3575 b8b6a50b bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3576 b8b6a50b bellard
            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, cpu_A0);
3577 b8b6a50b bellard
            break;
3578 664e0f19 bellard
        default:
3579 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3580 5af45186 bellard
            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3581 5af45186 bellard
            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
3582 664e0f19 bellard
            break;
3583 664e0f19 bellard
        }
3584 664e0f19 bellard
        if (b == 0x2e || b == 0x2f) {
3585 664e0f19 bellard
            s->cc_op = CC_OP_EFLAGS;
3586 664e0f19 bellard
        }
3587 664e0f19 bellard
    }
3588 664e0f19 bellard
}
3589 664e0f19 bellard
3590 2c0262af bellard
/* convert one instruction. s->is_jmp is set if the translation must
3591 2c0262af bellard
   be stopped. Return the next pc value */
3592 14ce26e7 bellard
static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3593 2c0262af bellard
{
3594 2c0262af bellard
    int b, prefixes, aflag, dflag;
3595 2c0262af bellard
    int shift, ot;
3596 2c0262af bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3597 14ce26e7 bellard
    target_ulong next_eip, tval;
3598 14ce26e7 bellard
    int rex_w, rex_r;
3599 2c0262af bellard
3600 70cff25e bellard
    if (unlikely(loglevel & CPU_LOG_TB_OP))
3601 70cff25e bellard
        tcg_gen_debug_insn_start(pc_start);
3602 2c0262af bellard
    s->pc = pc_start;
3603 2c0262af bellard
    prefixes = 0;
3604 2c0262af bellard
    aflag = s->code32;
3605 2c0262af bellard
    dflag = s->code32;
3606 2c0262af bellard
    s->override = -1;
3607 14ce26e7 bellard
    rex_w = -1;
3608 14ce26e7 bellard
    rex_r = 0;
3609 14ce26e7 bellard
#ifdef TARGET_X86_64
3610 14ce26e7 bellard
    s->rex_x = 0;
3611 14ce26e7 bellard
    s->rex_b = 0;
3612 5fafdf24 ths
    x86_64_hregs = 0;
3613 14ce26e7 bellard
#endif
3614 14ce26e7 bellard
    s->rip_offset = 0; /* for relative ip address */
3615 2c0262af bellard
 next_byte:
3616 61382a50 bellard
    b = ldub_code(s->pc);
3617 2c0262af bellard
    s->pc++;
3618 2c0262af bellard
    /* check prefixes */
3619 14ce26e7 bellard
#ifdef TARGET_X86_64
3620 14ce26e7 bellard
    if (CODE64(s)) {
3621 14ce26e7 bellard
        switch (b) {
3622 14ce26e7 bellard
        case 0xf3:
3623 14ce26e7 bellard
            prefixes |= PREFIX_REPZ;
3624 14ce26e7 bellard
            goto next_byte;
3625 14ce26e7 bellard
        case 0xf2:
3626 14ce26e7 bellard
            prefixes |= PREFIX_REPNZ;
3627 14ce26e7 bellard
            goto next_byte;
3628 14ce26e7 bellard
        case 0xf0:
3629 14ce26e7 bellard
            prefixes |= PREFIX_LOCK;
3630 14ce26e7 bellard
            goto next_byte;
3631 14ce26e7 bellard
        case 0x2e:
3632 14ce26e7 bellard
            s->override = R_CS;
3633 14ce26e7 bellard
            goto next_byte;
3634 14ce26e7 bellard
        case 0x36:
3635 14ce26e7 bellard
            s->override = R_SS;
3636 14ce26e7 bellard
            goto next_byte;
3637 14ce26e7 bellard
        case 0x3e:
3638 14ce26e7 bellard
            s->override = R_DS;
3639 14ce26e7 bellard
            goto next_byte;
3640 14ce26e7 bellard
        case 0x26:
3641 14ce26e7 bellard
            s->override = R_ES;
3642 14ce26e7 bellard
            goto next_byte;
3643 14ce26e7 bellard
        case 0x64:
3644 14ce26e7 bellard
            s->override = R_FS;
3645 14ce26e7 bellard
            goto next_byte;
3646 14ce26e7 bellard
        case 0x65:
3647 14ce26e7 bellard
            s->override = R_GS;
3648 14ce26e7 bellard
            goto next_byte;
3649 14ce26e7 bellard
        case 0x66:
3650 14ce26e7 bellard
            prefixes |= PREFIX_DATA;
3651 14ce26e7 bellard
            goto next_byte;
3652 14ce26e7 bellard
        case 0x67:
3653 14ce26e7 bellard
            prefixes |= PREFIX_ADR;
3654 14ce26e7 bellard
            goto next_byte;
3655 14ce26e7 bellard
        case 0x40 ... 0x4f:
3656 14ce26e7 bellard
            /* REX prefix */
3657 14ce26e7 bellard
            rex_w = (b >> 3) & 1;
3658 14ce26e7 bellard
            rex_r = (b & 0x4) << 1;
3659 14ce26e7 bellard
            s->rex_x = (b & 0x2) << 2;
3660 14ce26e7 bellard
            REX_B(s) = (b & 0x1) << 3;
3661 14ce26e7 bellard
            x86_64_hregs = 1; /* select uniform byte register addressing */
3662 14ce26e7 bellard
            goto next_byte;
3663 14ce26e7 bellard
        }
3664 14ce26e7 bellard
        if (rex_w == 1) {
3665 14ce26e7 bellard
            /* 0x66 is ignored if rex.w is set */
3666 14ce26e7 bellard
            dflag = 2;
3667 14ce26e7 bellard
        } else {
3668 14ce26e7 bellard
            if (prefixes & PREFIX_DATA)
3669 14ce26e7 bellard
                dflag ^= 1;
3670 14ce26e7 bellard
        }
3671 14ce26e7 bellard
        if (!(prefixes & PREFIX_ADR))
3672 14ce26e7 bellard
            aflag = 2;
3673 5fafdf24 ths
    } else
3674 14ce26e7 bellard
#endif
3675 14ce26e7 bellard
    {
3676 14ce26e7 bellard
        switch (b) {
3677 14ce26e7 bellard
        case 0xf3:
3678 14ce26e7 bellard
            prefixes |= PREFIX_REPZ;
3679 14ce26e7 bellard
            goto next_byte;
3680 14ce26e7 bellard
        case 0xf2:
3681 14ce26e7 bellard
            prefixes |= PREFIX_REPNZ;
3682 14ce26e7 bellard
            goto next_byte;
3683 14ce26e7 bellard
        case 0xf0:
3684 14ce26e7 bellard
            prefixes |= PREFIX_LOCK;
3685 14ce26e7 bellard
            goto next_byte;
3686 14ce26e7 bellard
        case 0x2e:
3687 14ce26e7 bellard
            s->override = R_CS;
3688 14ce26e7 bellard
            goto next_byte;
3689 14ce26e7 bellard
        case 0x36:
3690 14ce26e7 bellard
            s->override = R_SS;
3691 14ce26e7 bellard
            goto next_byte;
3692 14ce26e7 bellard
        case 0x3e:
3693 14ce26e7 bellard
            s->override = R_DS;
3694 14ce26e7 bellard
            goto next_byte;
3695 14ce26e7 bellard
        case 0x26:
3696 14ce26e7 bellard
            s->override = R_ES;
3697 14ce26e7 bellard
            goto next_byte;
3698 14ce26e7 bellard
        case 0x64:
3699 14ce26e7 bellard
            s->override = R_FS;
3700 14ce26e7 bellard
            goto next_byte;
3701 14ce26e7 bellard
        case 0x65:
3702 14ce26e7 bellard
            s->override = R_GS;
3703 14ce26e7 bellard
            goto next_byte;
3704 14ce26e7 bellard
        case 0x66:
3705 14ce26e7 bellard
            prefixes |= PREFIX_DATA;
3706 14ce26e7 bellard
            goto next_byte;
3707 14ce26e7 bellard
        case 0x67:
3708 14ce26e7 bellard
            prefixes |= PREFIX_ADR;
3709 14ce26e7 bellard
            goto next_byte;
3710 14ce26e7 bellard
        }
3711 14ce26e7 bellard
        if (prefixes & PREFIX_DATA)
3712 14ce26e7 bellard
            dflag ^= 1;
3713 14ce26e7 bellard
        if (prefixes & PREFIX_ADR)
3714 14ce26e7 bellard
            aflag ^= 1;
3715 2c0262af bellard
    }
3716 2c0262af bellard
3717 2c0262af bellard
    s->prefix = prefixes;
3718 2c0262af bellard
    s->aflag = aflag;
3719 2c0262af bellard
    s->dflag = dflag;
3720 2c0262af bellard
3721 2c0262af bellard
    /* lock generation */
3722 2c0262af bellard
    if (prefixes & PREFIX_LOCK)
3723 b8b6a50b bellard
        tcg_gen_helper_0_0(helper_lock);
3724 2c0262af bellard
3725 2c0262af bellard
    /* now check op code */
3726 2c0262af bellard
 reswitch:
3727 2c0262af bellard
    switch(b) {
3728 2c0262af bellard
    case 0x0f:
3729 2c0262af bellard
        /**************************/
3730 2c0262af bellard
        /* extended op code */
3731 61382a50 bellard
        b = ldub_code(s->pc++) | 0x100;
3732 2c0262af bellard
        goto reswitch;
3733 3b46e624 ths
3734 2c0262af bellard
        /**************************/
3735 2c0262af bellard
        /* arith & logic */
3736 2c0262af bellard
    case 0x00 ... 0x05:
3737 2c0262af bellard
    case 0x08 ... 0x0d:
3738 2c0262af bellard
    case 0x10 ... 0x15:
3739 2c0262af bellard
    case 0x18 ... 0x1d:
3740 2c0262af bellard
    case 0x20 ... 0x25:
3741 2c0262af bellard
    case 0x28 ... 0x2d:
3742 2c0262af bellard
    case 0x30 ... 0x35:
3743 2c0262af bellard
    case 0x38 ... 0x3d:
3744 2c0262af bellard
        {
3745 2c0262af bellard
            int op, f, val;
3746 2c0262af bellard
            op = (b >> 3) & 7;
3747 2c0262af bellard
            f = (b >> 1) & 3;
3748 2c0262af bellard
3749 2c0262af bellard
            if ((b & 1) == 0)
3750 2c0262af bellard
                ot = OT_BYTE;
3751 2c0262af bellard
            else
3752 14ce26e7 bellard
                ot = dflag + OT_WORD;
3753 3b46e624 ths
3754 2c0262af bellard
            switch(f) {
3755 2c0262af bellard
            case 0: /* OP Ev, Gv */
3756 61382a50 bellard
                modrm = ldub_code(s->pc++);
3757 14ce26e7 bellard
                reg = ((modrm >> 3) & 7) | rex_r;
3758 2c0262af bellard
                mod = (modrm >> 6) & 3;
3759 14ce26e7 bellard
                rm = (modrm & 7) | REX_B(s);
3760 2c0262af bellard
                if (mod != 3) {
3761 2c0262af bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3762 2c0262af bellard
                    opreg = OR_TMP0;
3763 2c0262af bellard
                } else if (op == OP_XORL && rm == reg) {
3764 2c0262af bellard
                xor_zero:
3765 2c0262af bellard
                    /* xor reg, reg optimisation */
3766 2c0262af bellard
                    gen_op_movl_T0_0();
3767 2c0262af bellard
                    s->cc_op = CC_OP_LOGICB + ot;
3768 57fec1fe bellard
                    gen_op_mov_reg_T0(ot, reg);
3769 2c0262af bellard
                    gen_op_update1_cc();
3770 2c0262af bellard
                    break;
3771 2c0262af bellard
                } else {
3772 2c0262af bellard
                    opreg = rm;
3773 2c0262af bellard
                }
3774 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 1, reg);
3775 2c0262af bellard
                gen_op(s, op, ot, opreg);
3776 2c0262af bellard
                break;
3777 2c0262af bellard
            case 1: /* OP Gv, Ev */
3778 61382a50 bellard
                modrm = ldub_code(s->pc++);
3779 2c0262af bellard
                mod = (modrm >> 6) & 3;
3780 14ce26e7 bellard
                reg = ((modrm >> 3) & 7) | rex_r;
3781 14ce26e7 bellard
                rm = (modrm & 7) | REX_B(s);
3782 2c0262af bellard
                if (mod != 3) {
3783 2c0262af bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3784 57fec1fe bellard
                    gen_op_ld_T1_A0(ot + s->mem_index);
3785 2c0262af bellard
                } else if (op == OP_XORL && rm == reg) {
3786 2c0262af bellard
                    goto xor_zero;
3787 2c0262af bellard
                } else {
3788 57fec1fe bellard
                    gen_op_mov_TN_reg(ot, 1, rm);
3789 2c0262af bellard
                }
3790 2c0262af bellard
                gen_op(s, op, ot, reg);
3791 2c0262af bellard
                break;
3792 2c0262af bellard
            case 2: /* OP A, Iv */
3793 2c0262af bellard
                val = insn_get(s, ot);
3794 2c0262af bellard
                gen_op_movl_T1_im(val);
3795 2c0262af bellard
                gen_op(s, op, ot, OR_EAX);
3796 2c0262af bellard
                break;
3797 2c0262af bellard
            }
3798 2c0262af bellard
        }
3799 2c0262af bellard
        break;
3800 2c0262af bellard
3801 ec9d6075 bellard
    case 0x82:
3802 ec9d6075 bellard
        if (CODE64(s))
3803 ec9d6075 bellard
            goto illegal_op;
3804 2c0262af bellard
    case 0x80: /* GRP1 */
3805 2c0262af bellard
    case 0x81:
3806 2c0262af bellard
    case 0x83:
3807 2c0262af bellard
        {
3808 2c0262af bellard
            int val;
3809 2c0262af bellard
3810 2c0262af bellard
            if ((b & 1) == 0)
3811 2c0262af bellard
                ot = OT_BYTE;
3812 2c0262af bellard
            else
3813 14ce26e7 bellard
                ot = dflag + OT_WORD;
3814 3b46e624 ths
3815 61382a50 bellard
            modrm = ldub_code(s->pc++);
3816 2c0262af bellard
            mod = (modrm >> 6) & 3;
3817 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
3818 2c0262af bellard
            op = (modrm >> 3) & 7;
3819 3b46e624 ths
3820 2c0262af bellard
            if (mod != 3) {
3821 14ce26e7 bellard
                if (b == 0x83)
3822 14ce26e7 bellard
                    s->rip_offset = 1;
3823 14ce26e7 bellard
                else
3824 14ce26e7 bellard
                    s->rip_offset = insn_const_size(ot);
3825 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3826 2c0262af bellard
                opreg = OR_TMP0;
3827 2c0262af bellard
            } else {
3828 14ce26e7 bellard
                opreg = rm;
3829 2c0262af bellard
            }
3830 2c0262af bellard
3831 2c0262af bellard
            switch(b) {
3832 2c0262af bellard
            default:
3833 2c0262af bellard
            case 0x80:
3834 2c0262af bellard
            case 0x81:
3835 d64477af bellard
            case 0x82:
3836 2c0262af bellard
                val = insn_get(s, ot);
3837 2c0262af bellard
                break;
3838 2c0262af bellard
            case 0x83:
3839 2c0262af bellard
                val = (int8_t)insn_get(s, OT_BYTE);
3840 2c0262af bellard
                break;
3841 2c0262af bellard
            }
3842 2c0262af bellard
            gen_op_movl_T1_im(val);
3843 2c0262af bellard
            gen_op(s, op, ot, opreg);
3844 2c0262af bellard
        }
3845 2c0262af bellard
        break;
3846 2c0262af bellard
3847 2c0262af bellard
        /**************************/
3848 2c0262af bellard
        /* inc, dec, and other misc arith */
3849 2c0262af bellard
    case 0x40 ... 0x47: /* inc Gv */
3850 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
3851 2c0262af bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
3852 2c0262af bellard
        break;
3853 2c0262af bellard
    case 0x48 ... 0x4f: /* dec Gv */
3854 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
3855 2c0262af bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
3856 2c0262af bellard
        break;
3857 2c0262af bellard
    case 0xf6: /* GRP3 */
3858 2c0262af bellard
    case 0xf7:
3859 2c0262af bellard
        if ((b & 1) == 0)
3860 2c0262af bellard
            ot = OT_BYTE;
3861 2c0262af bellard
        else
3862 14ce26e7 bellard
            ot = dflag + OT_WORD;
3863 2c0262af bellard
3864 61382a50 bellard
        modrm = ldub_code(s->pc++);
3865 2c0262af bellard
        mod = (modrm >> 6) & 3;
3866 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
3867 2c0262af bellard
        op = (modrm >> 3) & 7;
3868 2c0262af bellard
        if (mod != 3) {
3869 14ce26e7 bellard
            if (op == 0)
3870 14ce26e7 bellard
                s->rip_offset = insn_const_size(ot);
3871 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3872 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
3873 2c0262af bellard
        } else {
3874 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
3875 2c0262af bellard
        }
3876 2c0262af bellard
3877 2c0262af bellard
        switch(op) {
3878 2c0262af bellard
        case 0: /* test */
3879 2c0262af bellard
            val = insn_get(s, ot);
3880 2c0262af bellard
            gen_op_movl_T1_im(val);
3881 2c0262af bellard
            gen_op_testl_T0_T1_cc();
3882 2c0262af bellard
            s->cc_op = CC_OP_LOGICB + ot;
3883 2c0262af bellard
            break;
3884 2c0262af bellard
        case 2: /* not */
3885 b6abf97d bellard
            tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
3886 2c0262af bellard
            if (mod != 3) {
3887 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
3888 2c0262af bellard
            } else {
3889 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
3890 2c0262af bellard
            }
3891 2c0262af bellard
            break;
3892 2c0262af bellard
        case 3: /* neg */
3893 b6abf97d bellard
            tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
3894 2c0262af bellard
            if (mod != 3) {
3895 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
3896 2c0262af bellard
            } else {
3897 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
3898 2c0262af bellard
            }
3899 2c0262af bellard
            gen_op_update_neg_cc();
3900 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
3901 2c0262af bellard
            break;
3902 2c0262af bellard
        case 4: /* mul */
3903 2c0262af bellard
            switch(ot) {
3904 2c0262af bellard
            case OT_BYTE:
3905 0211e5af bellard
                gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
3906 0211e5af bellard
                tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
3907 0211e5af bellard
                tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
3908 0211e5af bellard
                /* XXX: use 32 bit mul which could be faster */
3909 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3910 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EAX);
3911 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3912 0211e5af bellard
                tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
3913 d36cd60e bellard
                s->cc_op = CC_OP_MULB;
3914 2c0262af bellard
                break;
3915 2c0262af bellard
            case OT_WORD:
3916 0211e5af bellard
                gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
3917 0211e5af bellard
                tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
3918 0211e5af bellard
                tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
3919 0211e5af bellard
                /* XXX: use 32 bit mul which could be faster */
3920 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3921 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EAX);
3922 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3923 0211e5af bellard
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
3924 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EDX);
3925 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3926 d36cd60e bellard
                s->cc_op = CC_OP_MULW;
3927 2c0262af bellard
                break;
3928 2c0262af bellard
            default:
3929 2c0262af bellard
            case OT_LONG:
3930 0211e5af bellard
#ifdef TARGET_X86_64
3931 0211e5af bellard
                gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
3932 0211e5af bellard
                tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
3933 0211e5af bellard
                tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
3934 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3935 0211e5af bellard
                gen_op_mov_reg_T0(OT_LONG, R_EAX);
3936 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3937 0211e5af bellard
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
3938 0211e5af bellard
                gen_op_mov_reg_T0(OT_LONG, R_EDX);
3939 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3940 0211e5af bellard
#else
3941 0211e5af bellard
                {
3942 0211e5af bellard
                    TCGv t0, t1;
3943 0211e5af bellard
                    t0 = tcg_temp_new(TCG_TYPE_I64);
3944 0211e5af bellard
                    t1 = tcg_temp_new(TCG_TYPE_I64);
3945 0211e5af bellard
                    gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
3946 0211e5af bellard
                    tcg_gen_extu_i32_i64(t0, cpu_T[0]);
3947 0211e5af bellard
                    tcg_gen_extu_i32_i64(t1, cpu_T[1]);
3948 0211e5af bellard
                    tcg_gen_mul_i64(t0, t0, t1);
3949 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[0], t0);
3950 0211e5af bellard
                    gen_op_mov_reg_T0(OT_LONG, R_EAX);
3951 0211e5af bellard
                    tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3952 0211e5af bellard
                    tcg_gen_shri_i64(t0, t0, 32);
3953 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[0], t0);
3954 0211e5af bellard
                    gen_op_mov_reg_T0(OT_LONG, R_EDX);
3955 0211e5af bellard
                    tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3956 0211e5af bellard
                }
3957 0211e5af bellard
#endif
3958 d36cd60e bellard
                s->cc_op = CC_OP_MULL;
3959 2c0262af bellard
                break;
3960 14ce26e7 bellard
#ifdef TARGET_X86_64
3961 14ce26e7 bellard
            case OT_QUAD:
3962 0211e5af bellard
                tcg_gen_helper_0_1(helper_mulq_EAX_T0, cpu_T[0]);
3963 14ce26e7 bellard
                s->cc_op = CC_OP_MULQ;
3964 14ce26e7 bellard
                break;
3965 14ce26e7 bellard
#endif
3966 2c0262af bellard
            }
3967 2c0262af bellard
            break;
3968 2c0262af bellard
        case 5: /* imul */
3969 2c0262af bellard
            switch(ot) {
3970 2c0262af bellard
            case OT_BYTE:
3971 0211e5af bellard
                gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
3972 0211e5af bellard
                tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
3973 0211e5af bellard
                tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
3974 0211e5af bellard
                /* XXX: use 32 bit mul which could be faster */
3975 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3976 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EAX);
3977 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3978 0211e5af bellard
                tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
3979 0211e5af bellard
                tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3980 d36cd60e bellard
                s->cc_op = CC_OP_MULB;
3981 2c0262af bellard
                break;
3982 2c0262af bellard
            case OT_WORD:
3983 0211e5af bellard
                gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
3984 0211e5af bellard
                tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
3985 0211e5af bellard
                tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
3986 0211e5af bellard
                /* XXX: use 32 bit mul which could be faster */
3987 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3988 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EAX);
3989 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3990 0211e5af bellard
                tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
3991 0211e5af bellard
                tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3992 0211e5af bellard
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
3993 0211e5af bellard
                gen_op_mov_reg_T0(OT_WORD, R_EDX);
3994 d36cd60e bellard
                s->cc_op = CC_OP_MULW;
3995 2c0262af bellard
                break;
3996 2c0262af bellard
            default:
3997 2c0262af bellard
            case OT_LONG:
3998 0211e5af bellard
#ifdef TARGET_X86_64
3999 0211e5af bellard
                gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4000 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4001 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4002 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4003 0211e5af bellard
                gen_op_mov_reg_T0(OT_LONG, R_EAX);
4004 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4005 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4006 0211e5af bellard
                tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4007 0211e5af bellard
                tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4008 0211e5af bellard
                gen_op_mov_reg_T0(OT_LONG, R_EDX);
4009 0211e5af bellard
#else
4010 0211e5af bellard
                {
4011 0211e5af bellard
                    TCGv t0, t1;
4012 0211e5af bellard
                    t0 = tcg_temp_new(TCG_TYPE_I64);
4013 0211e5af bellard
                    t1 = tcg_temp_new(TCG_TYPE_I64);
4014 0211e5af bellard
                    gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4015 0211e5af bellard
                    tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4016 0211e5af bellard
                    tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4017 0211e5af bellard
                    tcg_gen_mul_i64(t0, t0, t1);
4018 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4019 0211e5af bellard
                    gen_op_mov_reg_T0(OT_LONG, R_EAX);
4020 0211e5af bellard
                    tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4021 0211e5af bellard
                    tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4022 0211e5af bellard
                    tcg_gen_shri_i64(t0, t0, 32);
4023 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4024 0211e5af bellard
                    gen_op_mov_reg_T0(OT_LONG, R_EDX);
4025 0211e5af bellard
                    tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4026 0211e5af bellard
                }
4027 0211e5af bellard
#endif
4028 d36cd60e bellard
                s->cc_op = CC_OP_MULL;
4029 2c0262af bellard
                break;
4030 14ce26e7 bellard
#ifdef TARGET_X86_64
4031 14ce26e7 bellard
            case OT_QUAD:
4032 0211e5af bellard
                tcg_gen_helper_0_1(helper_imulq_EAX_T0, cpu_T[0]);
4033 14ce26e7 bellard
                s->cc_op = CC_OP_MULQ;
4034 14ce26e7 bellard
                break;
4035 14ce26e7 bellard
#endif
4036 2c0262af bellard
            }
4037 2c0262af bellard
            break;
4038 2c0262af bellard
        case 6: /* div */
4039 2c0262af bellard
            switch(ot) {
4040 2c0262af bellard
            case OT_BYTE:
4041 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4042 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_divb_AL, cpu_T[0]);
4043 2c0262af bellard
                break;
4044 2c0262af bellard
            case OT_WORD:
4045 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4046 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_divw_AX, cpu_T[0]);
4047 2c0262af bellard
                break;
4048 2c0262af bellard
            default:
4049 2c0262af bellard
            case OT_LONG:
4050 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4051 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_divl_EAX, cpu_T[0]);
4052 14ce26e7 bellard
                break;
4053 14ce26e7 bellard
#ifdef TARGET_X86_64
4054 14ce26e7 bellard
            case OT_QUAD:
4055 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4056 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_divq_EAX, cpu_T[0]);
4057 2c0262af bellard
                break;
4058 14ce26e7 bellard
#endif
4059 2c0262af bellard
            }
4060 2c0262af bellard
            break;
4061 2c0262af bellard
        case 7: /* idiv */
4062 2c0262af bellard
            switch(ot) {
4063 2c0262af bellard
            case OT_BYTE:
4064 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4065 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_idivb_AL, cpu_T[0]);
4066 2c0262af bellard
                break;
4067 2c0262af bellard
            case OT_WORD:
4068 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4069 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_idivw_AX, cpu_T[0]);
4070 2c0262af bellard
                break;
4071 2c0262af bellard
            default:
4072 2c0262af bellard
            case OT_LONG:
4073 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4074 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_idivl_EAX, cpu_T[0]);
4075 14ce26e7 bellard
                break;
4076 14ce26e7 bellard
#ifdef TARGET_X86_64
4077 14ce26e7 bellard
            case OT_QUAD:
4078 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4079 b5b38f61 bellard
                tcg_gen_helper_0_1(helper_idivq_EAX, cpu_T[0]);
4080 2c0262af bellard
                break;
4081 14ce26e7 bellard
#endif
4082 2c0262af bellard
            }
4083 2c0262af bellard
            break;
4084 2c0262af bellard
        default:
4085 2c0262af bellard
            goto illegal_op;
4086 2c0262af bellard
        }
4087 2c0262af bellard
        break;
4088 2c0262af bellard
4089 2c0262af bellard
    case 0xfe: /* GRP4 */
4090 2c0262af bellard
    case 0xff: /* GRP5 */
4091 2c0262af bellard
        if ((b & 1) == 0)
4092 2c0262af bellard
            ot = OT_BYTE;
4093 2c0262af bellard
        else
4094 14ce26e7 bellard
            ot = dflag + OT_WORD;
4095 2c0262af bellard
4096 61382a50 bellard
        modrm = ldub_code(s->pc++);
4097 2c0262af bellard
        mod = (modrm >> 6) & 3;
4098 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
4099 2c0262af bellard
        op = (modrm >> 3) & 7;
4100 2c0262af bellard
        if (op >= 2 && b == 0xfe) {
4101 2c0262af bellard
            goto illegal_op;
4102 2c0262af bellard
        }
4103 14ce26e7 bellard
        if (CODE64(s)) {
4104 aba9d61e bellard
            if (op == 2 || op == 4) {
4105 14ce26e7 bellard
                /* operand size for jumps is 64 bit */
4106 14ce26e7 bellard
                ot = OT_QUAD;
4107 aba9d61e bellard
            } else if (op == 3 || op == 5) {
4108 aba9d61e bellard
                /* for call calls, the operand is 16 or 32 bit, even
4109 aba9d61e bellard
                   in long mode */
4110 aba9d61e bellard
                ot = dflag ? OT_LONG : OT_WORD;
4111 14ce26e7 bellard
            } else if (op == 6) {
4112 14ce26e7 bellard
                /* default push size is 64 bit */
4113 14ce26e7 bellard
                ot = dflag ? OT_QUAD : OT_WORD;
4114 14ce26e7 bellard
            }
4115 14ce26e7 bellard
        }
4116 2c0262af bellard
        if (mod != 3) {
4117 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4118 2c0262af bellard
            if (op >= 2 && op != 3 && op != 5)
4119 57fec1fe bellard
                gen_op_ld_T0_A0(ot + s->mem_index);
4120 2c0262af bellard
        } else {
4121 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
4122 2c0262af bellard
        }
4123 2c0262af bellard
4124 2c0262af bellard
        switch(op) {
4125 2c0262af bellard
        case 0: /* inc Ev */
4126 2c0262af bellard
            if (mod != 3)
4127 2c0262af bellard
                opreg = OR_TMP0;
4128 2c0262af bellard
            else
4129 2c0262af bellard
                opreg = rm;
4130 2c0262af bellard
            gen_inc(s, ot, opreg, 1);
4131 2c0262af bellard
            break;
4132 2c0262af bellard
        case 1: /* dec Ev */
4133 2c0262af bellard
            if (mod != 3)
4134 2c0262af bellard
                opreg = OR_TMP0;
4135 2c0262af bellard
            else
4136 2c0262af bellard
                opreg = rm;
4137 2c0262af bellard
            gen_inc(s, ot, opreg, -1);
4138 2c0262af bellard
            break;
4139 2c0262af bellard
        case 2: /* call Ev */
4140 4f31916f bellard
            /* XXX: optimize if memory (no 'and' is necessary) */
4141 2c0262af bellard
            if (s->dflag == 0)
4142 2c0262af bellard
                gen_op_andl_T0_ffff();
4143 2c0262af bellard
            next_eip = s->pc - s->cs_base;
4144 1ef38687 bellard
            gen_movtl_T1_im(next_eip);
4145 4f31916f bellard
            gen_push_T1(s);
4146 4f31916f bellard
            gen_op_jmp_T0();
4147 2c0262af bellard
            gen_eob(s);
4148 2c0262af bellard
            break;
4149 61382a50 bellard
        case 3: /* lcall Ev */
4150 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
4151 aba9d61e bellard
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4152 57fec1fe bellard
            gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4153 2c0262af bellard
        do_lcall:
4154 2c0262af bellard
            if (s->pe && !s->vm86) {
4155 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4156 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4157 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4158 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4159 b8b6a50b bellard
                tcg_gen_helper_0_4(helper_lcall_protected,
4160 b6abf97d bellard
                                   cpu_tmp2_i32, cpu_T[1],
4161 b8b6a50b bellard
                                   tcg_const_i32(dflag), 
4162 b8b6a50b bellard
                                   tcg_const_i32(s->pc - pc_start));
4163 2c0262af bellard
            } else {
4164 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4165 b8b6a50b bellard
                tcg_gen_helper_0_4(helper_lcall_real,
4166 b6abf97d bellard
                                   cpu_tmp2_i32, cpu_T[1],
4167 b8b6a50b bellard
                                   tcg_const_i32(dflag), 
4168 b8b6a50b bellard
                                   tcg_const_i32(s->pc - s->cs_base));
4169 2c0262af bellard
            }
4170 2c0262af bellard
            gen_eob(s);
4171 2c0262af bellard
            break;
4172 2c0262af bellard
        case 4: /* jmp Ev */
4173 2c0262af bellard
            if (s->dflag == 0)
4174 2c0262af bellard
                gen_op_andl_T0_ffff();
4175 2c0262af bellard
            gen_op_jmp_T0();
4176 2c0262af bellard
            gen_eob(s);
4177 2c0262af bellard
            break;
4178 2c0262af bellard
        case 5: /* ljmp Ev */
4179 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
4180 aba9d61e bellard
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4181 57fec1fe bellard
            gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4182 2c0262af bellard
        do_ljmp:
4183 2c0262af bellard
            if (s->pe && !s->vm86) {
4184 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4185 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4186 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
4187 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4188 b8b6a50b bellard
                tcg_gen_helper_0_3(helper_ljmp_protected,
4189 b6abf97d bellard
                                   cpu_tmp2_i32,
4190 b8b6a50b bellard
                                   cpu_T[1],
4191 b8b6a50b bellard
                                   tcg_const_i32(s->pc - pc_start));
4192 2c0262af bellard
            } else {
4193 3bd7da9e bellard
                gen_op_movl_seg_T0_vm(R_CS);
4194 2c0262af bellard
                gen_op_movl_T0_T1();
4195 2c0262af bellard
                gen_op_jmp_T0();
4196 2c0262af bellard
            }
4197 2c0262af bellard
            gen_eob(s);
4198 2c0262af bellard
            break;
4199 2c0262af bellard
        case 6: /* push Ev */
4200 2c0262af bellard
            gen_push_T0(s);
4201 2c0262af bellard
            break;
4202 2c0262af bellard
        default:
4203 2c0262af bellard
            goto illegal_op;
4204 2c0262af bellard
        }
4205 2c0262af bellard
        break;
4206 2c0262af bellard
4207 2c0262af bellard
    case 0x84: /* test Ev, Gv */
4208 5fafdf24 ths
    case 0x85:
4209 2c0262af bellard
        if ((b & 1) == 0)
4210 2c0262af bellard
            ot = OT_BYTE;
4211 2c0262af bellard
        else
4212 14ce26e7 bellard
            ot = dflag + OT_WORD;
4213 2c0262af bellard
4214 61382a50 bellard
        modrm = ldub_code(s->pc++);
4215 2c0262af bellard
        mod = (modrm >> 6) & 3;
4216 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
4217 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4218 3b46e624 ths
4219 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4220 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
4221 2c0262af bellard
        gen_op_testl_T0_T1_cc();
4222 2c0262af bellard
        s->cc_op = CC_OP_LOGICB + ot;
4223 2c0262af bellard
        break;
4224 3b46e624 ths
4225 2c0262af bellard
    case 0xa8: /* test eAX, Iv */
4226 2c0262af bellard
    case 0xa9:
4227 2c0262af bellard
        if ((b & 1) == 0)
4228 2c0262af bellard
            ot = OT_BYTE;
4229 2c0262af bellard
        else
4230 14ce26e7 bellard
            ot = dflag + OT_WORD;
4231 2c0262af bellard
        val = insn_get(s, ot);
4232 2c0262af bellard
4233 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, OR_EAX);
4234 2c0262af bellard
        gen_op_movl_T1_im(val);
4235 2c0262af bellard
        gen_op_testl_T0_T1_cc();
4236 2c0262af bellard
        s->cc_op = CC_OP_LOGICB + ot;
4237 2c0262af bellard
        break;
4238 3b46e624 ths
4239 2c0262af bellard
    case 0x98: /* CWDE/CBW */
4240 14ce26e7 bellard
#ifdef TARGET_X86_64
4241 14ce26e7 bellard
        if (dflag == 2) {
4242 e108dd01 bellard
            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
4243 e108dd01 bellard
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4244 e108dd01 bellard
            gen_op_mov_reg_T0(OT_QUAD, R_EAX);
4245 14ce26e7 bellard
        } else
4246 14ce26e7 bellard
#endif
4247 e108dd01 bellard
        if (dflag == 1) {
4248 e108dd01 bellard
            gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
4249 e108dd01 bellard
            tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4250 e108dd01 bellard
            gen_op_mov_reg_T0(OT_LONG, R_EAX);
4251 e108dd01 bellard
        } else {
4252 e108dd01 bellard
            gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
4253 e108dd01 bellard
            tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4254 e108dd01 bellard
            gen_op_mov_reg_T0(OT_WORD, R_EAX);
4255 e108dd01 bellard
        }
4256 2c0262af bellard
        break;
4257 2c0262af bellard
    case 0x99: /* CDQ/CWD */
4258 14ce26e7 bellard
#ifdef TARGET_X86_64
4259 14ce26e7 bellard
        if (dflag == 2) {
4260 e108dd01 bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
4261 e108dd01 bellard
            tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
4262 e108dd01 bellard
            gen_op_mov_reg_T0(OT_QUAD, R_EDX);
4263 14ce26e7 bellard
        } else
4264 14ce26e7 bellard
#endif
4265 e108dd01 bellard
        if (dflag == 1) {
4266 e108dd01 bellard
            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
4267 e108dd01 bellard
            tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4268 e108dd01 bellard
            tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
4269 e108dd01 bellard
            gen_op_mov_reg_T0(OT_LONG, R_EDX);
4270 e108dd01 bellard
        } else {
4271 e108dd01 bellard
            gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
4272 e108dd01 bellard
            tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4273 e108dd01 bellard
            tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
4274 e108dd01 bellard
            gen_op_mov_reg_T0(OT_WORD, R_EDX);
4275 e108dd01 bellard
        }
4276 2c0262af bellard
        break;
4277 2c0262af bellard
    case 0x1af: /* imul Gv, Ev */
4278 2c0262af bellard
    case 0x69: /* imul Gv, Ev, I */
4279 2c0262af bellard
    case 0x6b:
4280 14ce26e7 bellard
        ot = dflag + OT_WORD;
4281 61382a50 bellard
        modrm = ldub_code(s->pc++);
4282 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4283 14ce26e7 bellard
        if (b == 0x69)
4284 14ce26e7 bellard
            s->rip_offset = insn_const_size(ot);
4285 14ce26e7 bellard
        else if (b == 0x6b)
4286 14ce26e7 bellard
            s->rip_offset = 1;
4287 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4288 2c0262af bellard
        if (b == 0x69) {
4289 2c0262af bellard
            val = insn_get(s, ot);
4290 2c0262af bellard
            gen_op_movl_T1_im(val);
4291 2c0262af bellard
        } else if (b == 0x6b) {
4292 d64477af bellard
            val = (int8_t)insn_get(s, OT_BYTE);
4293 2c0262af bellard
            gen_op_movl_T1_im(val);
4294 2c0262af bellard
        } else {
4295 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, reg);
4296 2c0262af bellard
        }
4297 2c0262af bellard
4298 14ce26e7 bellard
#ifdef TARGET_X86_64
4299 14ce26e7 bellard
        if (ot == OT_QUAD) {
4300 0211e5af bellard
            tcg_gen_helper_1_2(helper_imulq_T0_T1, cpu_T[0], cpu_T[0], cpu_T[1]);
4301 14ce26e7 bellard
        } else
4302 14ce26e7 bellard
#endif
4303 2c0262af bellard
        if (ot == OT_LONG) {
4304 0211e5af bellard
#ifdef TARGET_X86_64
4305 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4306 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4307 0211e5af bellard
                tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4308 0211e5af bellard
                tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4309 0211e5af bellard
                tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4310 0211e5af bellard
                tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4311 0211e5af bellard
#else
4312 0211e5af bellard
                {
4313 0211e5af bellard
                    TCGv t0, t1;
4314 0211e5af bellard
                    t0 = tcg_temp_new(TCG_TYPE_I64);
4315 0211e5af bellard
                    t1 = tcg_temp_new(TCG_TYPE_I64);
4316 0211e5af bellard
                    tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4317 0211e5af bellard
                    tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4318 0211e5af bellard
                    tcg_gen_mul_i64(t0, t0, t1);
4319 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4320 0211e5af bellard
                    tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4321 0211e5af bellard
                    tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4322 0211e5af bellard
                    tcg_gen_shri_i64(t0, t0, 32);
4323 0211e5af bellard
                    tcg_gen_trunc_i64_i32(cpu_T[1], t0);
4324 0211e5af bellard
                    tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0);
4325 0211e5af bellard
                }
4326 0211e5af bellard
#endif
4327 2c0262af bellard
        } else {
4328 0211e5af bellard
            tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4329 0211e5af bellard
            tcg_gen_ext16s_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
            tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4333 0211e5af bellard
            tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4334 0211e5af bellard
            tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4335 2c0262af bellard
        }
4336 57fec1fe bellard
        gen_op_mov_reg_T0(ot, reg);
4337 d36cd60e bellard
        s->cc_op = CC_OP_MULB + ot;
4338 2c0262af bellard
        break;
4339 2c0262af bellard
    case 0x1c0:
4340 2c0262af bellard
    case 0x1c1: /* xadd Ev, Gv */
4341 2c0262af bellard
        if ((b & 1) == 0)
4342 2c0262af bellard
            ot = OT_BYTE;
4343 2c0262af bellard
        else
4344 14ce26e7 bellard
            ot = dflag + OT_WORD;
4345 61382a50 bellard
        modrm = ldub_code(s->pc++);
4346 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4347 2c0262af bellard
        mod = (modrm >> 6) & 3;
4348 2c0262af bellard
        if (mod == 3) {
4349 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4350 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4351 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, rm);
4352 2c0262af bellard
            gen_op_addl_T0_T1();
4353 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4354 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
4355 2c0262af bellard
        } else {
4356 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4357 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4358 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
4359 2c0262af bellard
            gen_op_addl_T0_T1();
4360 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
4361 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4362 2c0262af bellard
        }
4363 2c0262af bellard
        gen_op_update2_cc();
4364 2c0262af bellard
        s->cc_op = CC_OP_ADDB + ot;
4365 2c0262af bellard
        break;
4366 2c0262af bellard
    case 0x1b0:
4367 2c0262af bellard
    case 0x1b1: /* cmpxchg Ev, Gv */
4368 cad3a37d bellard
        {
4369 1130328e bellard
            int label1, label2;
4370 1e4840bf bellard
            TCGv t0, t1, t2, a0;
4371 cad3a37d bellard
4372 cad3a37d bellard
            if ((b & 1) == 0)
4373 cad3a37d bellard
                ot = OT_BYTE;
4374 cad3a37d bellard
            else
4375 cad3a37d bellard
                ot = dflag + OT_WORD;
4376 cad3a37d bellard
            modrm = ldub_code(s->pc++);
4377 cad3a37d bellard
            reg = ((modrm >> 3) & 7) | rex_r;
4378 cad3a37d bellard
            mod = (modrm >> 6) & 3;
4379 1e4840bf bellard
            t0 = tcg_temp_local_new(TCG_TYPE_TL);
4380 1e4840bf bellard
            t1 = tcg_temp_local_new(TCG_TYPE_TL);
4381 1e4840bf bellard
            t2 = tcg_temp_local_new(TCG_TYPE_TL);
4382 1e4840bf bellard
            a0 = tcg_temp_local_new(TCG_TYPE_TL);
4383 1e4840bf bellard
            gen_op_mov_v_reg(ot, t1, reg);
4384 cad3a37d bellard
            if (mod == 3) {
4385 cad3a37d bellard
                rm = (modrm & 7) | REX_B(s);
4386 1e4840bf bellard
                gen_op_mov_v_reg(ot, t0, rm);
4387 cad3a37d bellard
            } else {
4388 cad3a37d bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4389 1e4840bf bellard
                tcg_gen_mov_tl(a0, cpu_A0);
4390 1e4840bf bellard
                gen_op_ld_v(ot + s->mem_index, t0, a0);
4391 cad3a37d bellard
                rm = 0; /* avoid warning */
4392 cad3a37d bellard
            }
4393 cad3a37d bellard
            label1 = gen_new_label();
4394 1e4840bf bellard
            tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, regs[R_EAX]));
4395 1e4840bf bellard
            tcg_gen_sub_tl(t2, t2, t0);
4396 1e4840bf bellard
            gen_extu(ot, t2);
4397 1e4840bf bellard
            tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
4398 cad3a37d bellard
            if (mod == 3) {
4399 1130328e bellard
                label2 = gen_new_label();
4400 1e4840bf bellard
                gen_op_mov_reg_v(ot, R_EAX, t0);
4401 1130328e bellard
                tcg_gen_br(label2);
4402 1130328e bellard
                gen_set_label(label1);
4403 1e4840bf bellard
                gen_op_mov_reg_v(ot, rm, t1);
4404 1130328e bellard
                gen_set_label(label2);
4405 cad3a37d bellard
            } else {
4406 1e4840bf bellard
                tcg_gen_mov_tl(t1, t0);
4407 1e4840bf bellard
                gen_op_mov_reg_v(ot, R_EAX, t0);
4408 1130328e bellard
                gen_set_label(label1);
4409 1130328e bellard
                /* always store */
4410 1e4840bf bellard
                gen_op_st_v(ot + s->mem_index, t1, a0);
4411 cad3a37d bellard
            }
4412 1e4840bf bellard
            tcg_gen_mov_tl(cpu_cc_src, t0);
4413 1e4840bf bellard
            tcg_gen_mov_tl(cpu_cc_dst, t2);
4414 cad3a37d bellard
            s->cc_op = CC_OP_SUBB + ot;
4415 1e4840bf bellard
            tcg_temp_free(t0);
4416 1e4840bf bellard
            tcg_temp_free(t1);
4417 1e4840bf bellard
            tcg_temp_free(t2);
4418 1e4840bf bellard
            tcg_temp_free(a0);
4419 2c0262af bellard
        }
4420 2c0262af bellard
        break;
4421 2c0262af bellard
    case 0x1c7: /* cmpxchg8b */
4422 61382a50 bellard
        modrm = ldub_code(s->pc++);
4423 2c0262af bellard
        mod = (modrm >> 6) & 3;
4424 71c3558e balrog
        if ((mod == 3) || ((modrm & 0x38) != 0x8))
4425 2c0262af bellard
            goto illegal_op;
4426 1b9d9ebb bellard
#ifdef TARGET_X86_64
4427 1b9d9ebb bellard
        if (dflag == 2) {
4428 1b9d9ebb bellard
            if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
4429 1b9d9ebb bellard
                goto illegal_op;
4430 1b9d9ebb bellard
            gen_jmp_im(pc_start - s->cs_base);
4431 1b9d9ebb bellard
            if (s->cc_op != CC_OP_DYNAMIC)
4432 1b9d9ebb bellard
                gen_op_set_cc_op(s->cc_op);
4433 1b9d9ebb bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4434 1b9d9ebb bellard
            tcg_gen_helper_0_1(helper_cmpxchg16b, cpu_A0);
4435 1b9d9ebb bellard
        } else
4436 1b9d9ebb bellard
#endif        
4437 1b9d9ebb bellard
        {
4438 1b9d9ebb bellard
            if (!(s->cpuid_features & CPUID_CX8))
4439 1b9d9ebb bellard
                goto illegal_op;
4440 1b9d9ebb bellard
            gen_jmp_im(pc_start - s->cs_base);
4441 1b9d9ebb bellard
            if (s->cc_op != CC_OP_DYNAMIC)
4442 1b9d9ebb bellard
                gen_op_set_cc_op(s->cc_op);
4443 1b9d9ebb bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4444 1b9d9ebb bellard
            tcg_gen_helper_0_1(helper_cmpxchg8b, cpu_A0);
4445 1b9d9ebb bellard
        }
4446 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
4447 2c0262af bellard
        break;
4448 3b46e624 ths
4449 2c0262af bellard
        /**************************/
4450 2c0262af bellard
        /* push/pop */
4451 2c0262af bellard
    case 0x50 ... 0x57: /* push */
4452 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
4453 2c0262af bellard
        gen_push_T0(s);
4454 2c0262af bellard
        break;
4455 2c0262af bellard
    case 0x58 ... 0x5f: /* pop */
4456 14ce26e7 bellard
        if (CODE64(s)) {
4457 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
4458 14ce26e7 bellard
        } else {
4459 14ce26e7 bellard
            ot = dflag + OT_WORD;
4460 14ce26e7 bellard
        }
4461 2c0262af bellard
        gen_pop_T0(s);
4462 77729c24 bellard
        /* NOTE: order is important for pop %sp */
4463 2c0262af bellard
        gen_pop_update(s);
4464 57fec1fe bellard
        gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
4465 2c0262af bellard
        break;
4466 2c0262af bellard
    case 0x60: /* pusha */
4467 14ce26e7 bellard
        if (CODE64(s))
4468 14ce26e7 bellard
            goto illegal_op;
4469 2c0262af bellard
        gen_pusha(s);
4470 2c0262af bellard
        break;
4471 2c0262af bellard
    case 0x61: /* popa */
4472 14ce26e7 bellard
        if (CODE64(s))
4473 14ce26e7 bellard
            goto illegal_op;
4474 2c0262af bellard
        gen_popa(s);
4475 2c0262af bellard
        break;
4476 2c0262af bellard
    case 0x68: /* push Iv */
4477 2c0262af bellard
    case 0x6a:
4478 14ce26e7 bellard
        if (CODE64(s)) {
4479 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
4480 14ce26e7 bellard
        } else {
4481 14ce26e7 bellard
            ot = dflag + OT_WORD;
4482 14ce26e7 bellard
        }
4483 2c0262af bellard
        if (b == 0x68)
4484 2c0262af bellard
            val = insn_get(s, ot);
4485 2c0262af bellard
        else
4486 2c0262af bellard
            val = (int8_t)insn_get(s, OT_BYTE);
4487 2c0262af bellard
        gen_op_movl_T0_im(val);
4488 2c0262af bellard
        gen_push_T0(s);
4489 2c0262af bellard
        break;
4490 2c0262af bellard
    case 0x8f: /* pop Ev */
4491 14ce26e7 bellard
        if (CODE64(s)) {
4492 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
4493 14ce26e7 bellard
        } else {
4494 14ce26e7 bellard
            ot = dflag + OT_WORD;
4495 14ce26e7 bellard
        }
4496 61382a50 bellard
        modrm = ldub_code(s->pc++);
4497 77729c24 bellard
        mod = (modrm >> 6) & 3;
4498 2c0262af bellard
        gen_pop_T0(s);
4499 77729c24 bellard
        if (mod == 3) {
4500 77729c24 bellard
            /* NOTE: order is important for pop %sp */
4501 77729c24 bellard
            gen_pop_update(s);
4502 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4503 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
4504 77729c24 bellard
        } else {
4505 77729c24 bellard
            /* NOTE: order is important too for MMU exceptions */
4506 14ce26e7 bellard
            s->popl_esp_hack = 1 << ot;
4507 77729c24 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4508 77729c24 bellard
            s->popl_esp_hack = 0;
4509 77729c24 bellard
            gen_pop_update(s);
4510 77729c24 bellard
        }
4511 2c0262af bellard
        break;
4512 2c0262af bellard
    case 0xc8: /* enter */
4513 2c0262af bellard
        {
4514 2c0262af bellard
            int level;
4515 61382a50 bellard
            val = lduw_code(s->pc);
4516 2c0262af bellard
            s->pc += 2;
4517 61382a50 bellard
            level = ldub_code(s->pc++);
4518 2c0262af bellard
            gen_enter(s, val, level);
4519 2c0262af bellard
        }
4520 2c0262af bellard
        break;
4521 2c0262af bellard
    case 0xc9: /* leave */
4522 2c0262af bellard
        /* XXX: exception not precise (ESP is updated before potential exception) */
4523 14ce26e7 bellard
        if (CODE64(s)) {
4524 57fec1fe bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
4525 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, R_ESP);
4526 14ce26e7 bellard
        } else if (s->ss32) {
4527 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
4528 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, R_ESP);
4529 2c0262af bellard
        } else {
4530 57fec1fe bellard
            gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
4531 57fec1fe bellard
            gen_op_mov_reg_T0(OT_WORD, R_ESP);
4532 2c0262af bellard
        }
4533 2c0262af bellard
        gen_pop_T0(s);
4534 14ce26e7 bellard
        if (CODE64(s)) {
4535 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
4536 14ce26e7 bellard
        } else {
4537 14ce26e7 bellard
            ot = dflag + OT_WORD;
4538 14ce26e7 bellard
        }
4539 57fec1fe bellard
        gen_op_mov_reg_T0(ot, R_EBP);
4540 2c0262af bellard
        gen_pop_update(s);
4541 2c0262af bellard
        break;
4542 2c0262af bellard
    case 0x06: /* push es */
4543 2c0262af bellard
    case 0x0e: /* push cs */
4544 2c0262af bellard
    case 0x16: /* push ss */
4545 2c0262af bellard
    case 0x1e: /* push ds */
4546 14ce26e7 bellard
        if (CODE64(s))
4547 14ce26e7 bellard
            goto illegal_op;
4548 2c0262af bellard
        gen_op_movl_T0_seg(b >> 3);
4549 2c0262af bellard
        gen_push_T0(s);
4550 2c0262af bellard
        break;
4551 2c0262af bellard
    case 0x1a0: /* push fs */
4552 2c0262af bellard
    case 0x1a8: /* push gs */
4553 2c0262af bellard
        gen_op_movl_T0_seg((b >> 3) & 7);
4554 2c0262af bellard
        gen_push_T0(s);
4555 2c0262af bellard
        break;
4556 2c0262af bellard
    case 0x07: /* pop es */
4557 2c0262af bellard
    case 0x17: /* pop ss */
4558 2c0262af bellard
    case 0x1f: /* pop ds */
4559 14ce26e7 bellard
        if (CODE64(s))
4560 14ce26e7 bellard
            goto illegal_op;
4561 2c0262af bellard
        reg = b >> 3;
4562 2c0262af bellard
        gen_pop_T0(s);
4563 2c0262af bellard
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4564 2c0262af bellard
        gen_pop_update(s);
4565 2c0262af bellard
        if (reg == R_SS) {
4566 a2cc3b24 bellard
            /* if reg == SS, inhibit interrupts/trace. */
4567 a2cc3b24 bellard
            /* If several instructions disable interrupts, only the
4568 a2cc3b24 bellard
               _first_ does it */
4569 a2cc3b24 bellard
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4570 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_set_inhibit_irq);
4571 2c0262af bellard
            s->tf = 0;
4572 2c0262af bellard
        }
4573 2c0262af bellard
        if (s->is_jmp) {
4574 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4575 2c0262af bellard
            gen_eob(s);
4576 2c0262af bellard
        }
4577 2c0262af bellard
        break;
4578 2c0262af bellard
    case 0x1a1: /* pop fs */
4579 2c0262af bellard
    case 0x1a9: /* pop gs */
4580 2c0262af bellard
        gen_pop_T0(s);
4581 2c0262af bellard
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4582 2c0262af bellard
        gen_pop_update(s);
4583 2c0262af bellard
        if (s->is_jmp) {
4584 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4585 2c0262af bellard
            gen_eob(s);
4586 2c0262af bellard
        }
4587 2c0262af bellard
        break;
4588 2c0262af bellard
4589 2c0262af bellard
        /**************************/
4590 2c0262af bellard
        /* mov */
4591 2c0262af bellard
    case 0x88:
4592 2c0262af bellard
    case 0x89: /* mov Gv, Ev */
4593 2c0262af bellard
        if ((b & 1) == 0)
4594 2c0262af bellard
            ot = OT_BYTE;
4595 2c0262af bellard
        else
4596 14ce26e7 bellard
            ot = dflag + OT_WORD;
4597 61382a50 bellard
        modrm = ldub_code(s->pc++);
4598 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4599 3b46e624 ths
4600 2c0262af bellard
        /* generate a generic store */
4601 14ce26e7 bellard
        gen_ldst_modrm(s, modrm, ot, reg, 1);
4602 2c0262af bellard
        break;
4603 2c0262af bellard
    case 0xc6:
4604 2c0262af bellard
    case 0xc7: /* mov Ev, Iv */
4605 2c0262af bellard
        if ((b & 1) == 0)
4606 2c0262af bellard
            ot = OT_BYTE;
4607 2c0262af bellard
        else
4608 14ce26e7 bellard
            ot = dflag + OT_WORD;
4609 61382a50 bellard
        modrm = ldub_code(s->pc++);
4610 2c0262af bellard
        mod = (modrm >> 6) & 3;
4611 14ce26e7 bellard
        if (mod != 3) {
4612 14ce26e7 bellard
            s->rip_offset = insn_const_size(ot);
4613 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4614 14ce26e7 bellard
        }
4615 2c0262af bellard
        val = insn_get(s, ot);
4616 2c0262af bellard
        gen_op_movl_T0_im(val);
4617 2c0262af bellard
        if (mod != 3)
4618 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
4619 2c0262af bellard
        else
4620 57fec1fe bellard
            gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
4621 2c0262af bellard
        break;
4622 2c0262af bellard
    case 0x8a:
4623 2c0262af bellard
    case 0x8b: /* mov Ev, Gv */
4624 2c0262af bellard
        if ((b & 1) == 0)
4625 2c0262af bellard
            ot = OT_BYTE;
4626 2c0262af bellard
        else
4627 14ce26e7 bellard
            ot = OT_WORD + dflag;
4628 61382a50 bellard
        modrm = ldub_code(s->pc++);
4629 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4630 3b46e624 ths
4631 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4632 57fec1fe bellard
        gen_op_mov_reg_T0(ot, reg);
4633 2c0262af bellard
        break;
4634 2c0262af bellard
    case 0x8e: /* mov seg, Gv */
4635 61382a50 bellard
        modrm = ldub_code(s->pc++);
4636 2c0262af bellard
        reg = (modrm >> 3) & 7;
4637 2c0262af bellard
        if (reg >= 6 || reg == R_CS)
4638 2c0262af bellard
            goto illegal_op;
4639 2c0262af bellard
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4640 2c0262af bellard
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4641 2c0262af bellard
        if (reg == R_SS) {
4642 2c0262af bellard
            /* if reg == SS, inhibit interrupts/trace */
4643 a2cc3b24 bellard
            /* If several instructions disable interrupts, only the
4644 a2cc3b24 bellard
               _first_ does it */
4645 a2cc3b24 bellard
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4646 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_set_inhibit_irq);
4647 2c0262af bellard
            s->tf = 0;
4648 2c0262af bellard
        }
4649 2c0262af bellard
        if (s->is_jmp) {
4650 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4651 2c0262af bellard
            gen_eob(s);
4652 2c0262af bellard
        }
4653 2c0262af bellard
        break;
4654 2c0262af bellard
    case 0x8c: /* mov Gv, seg */
4655 61382a50 bellard
        modrm = ldub_code(s->pc++);
4656 2c0262af bellard
        reg = (modrm >> 3) & 7;
4657 2c0262af bellard
        mod = (modrm >> 6) & 3;
4658 2c0262af bellard
        if (reg >= 6)
4659 2c0262af bellard
            goto illegal_op;
4660 2c0262af bellard
        gen_op_movl_T0_seg(reg);
4661 14ce26e7 bellard
        if (mod == 3)
4662 14ce26e7 bellard
            ot = OT_WORD + dflag;
4663 14ce26e7 bellard
        else
4664 14ce26e7 bellard
            ot = OT_WORD;
4665 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4666 2c0262af bellard
        break;
4667 2c0262af bellard
4668 2c0262af bellard
    case 0x1b6: /* movzbS Gv, Eb */
4669 2c0262af bellard
    case 0x1b7: /* movzwS Gv, Eb */
4670 2c0262af bellard
    case 0x1be: /* movsbS Gv, Eb */
4671 2c0262af bellard
    case 0x1bf: /* movswS Gv, Eb */
4672 2c0262af bellard
        {
4673 2c0262af bellard
            int d_ot;
4674 2c0262af bellard
            /* d_ot is the size of destination */
4675 2c0262af bellard
            d_ot = dflag + OT_WORD;
4676 2c0262af bellard
            /* ot is the size of source */
4677 2c0262af bellard
            ot = (b & 1) + OT_BYTE;
4678 61382a50 bellard
            modrm = ldub_code(s->pc++);
4679 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
4680 2c0262af bellard
            mod = (modrm >> 6) & 3;
4681 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4682 3b46e624 ths
4683 2c0262af bellard
            if (mod == 3) {
4684 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, rm);
4685 2c0262af bellard
                switch(ot | (b & 8)) {
4686 2c0262af bellard
                case OT_BYTE:
4687 e108dd01 bellard
                    tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4688 2c0262af bellard
                    break;
4689 2c0262af bellard
                case OT_BYTE | 8:
4690 e108dd01 bellard
                    tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4691 2c0262af bellard
                    break;
4692 2c0262af bellard
                case OT_WORD:
4693 e108dd01 bellard
                    tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4694 2c0262af bellard
                    break;
4695 2c0262af bellard
                default:
4696 2c0262af bellard
                case OT_WORD | 8:
4697 e108dd01 bellard
                    tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4698 2c0262af bellard
                    break;
4699 2c0262af bellard
                }
4700 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
4701 2c0262af bellard
            } else {
4702 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4703 2c0262af bellard
                if (b & 8) {
4704 57fec1fe bellard
                    gen_op_lds_T0_A0(ot + s->mem_index);
4705 2c0262af bellard
                } else {
4706 57fec1fe bellard
                    gen_op_ldu_T0_A0(ot + s->mem_index);
4707 2c0262af bellard
                }
4708 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
4709 2c0262af bellard
            }
4710 2c0262af bellard
        }
4711 2c0262af bellard
        break;
4712 2c0262af bellard
4713 2c0262af bellard
    case 0x8d: /* lea */
4714 14ce26e7 bellard
        ot = dflag + OT_WORD;
4715 61382a50 bellard
        modrm = ldub_code(s->pc++);
4716 3a1d9b8b bellard
        mod = (modrm >> 6) & 3;
4717 3a1d9b8b bellard
        if (mod == 3)
4718 3a1d9b8b bellard
            goto illegal_op;
4719 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4720 2c0262af bellard
        /* we must ensure that no segment is added */
4721 2c0262af bellard
        s->override = -1;
4722 2c0262af bellard
        val = s->addseg;
4723 2c0262af bellard
        s->addseg = 0;
4724 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4725 2c0262af bellard
        s->addseg = val;
4726 57fec1fe bellard
        gen_op_mov_reg_A0(ot - OT_WORD, reg);
4727 2c0262af bellard
        break;
4728 3b46e624 ths
4729 2c0262af bellard
    case 0xa0: /* mov EAX, Ov */
4730 2c0262af bellard
    case 0xa1:
4731 2c0262af bellard
    case 0xa2: /* mov Ov, EAX */
4732 2c0262af bellard
    case 0xa3:
4733 2c0262af bellard
        {
4734 14ce26e7 bellard
            target_ulong offset_addr;
4735 14ce26e7 bellard
4736 14ce26e7 bellard
            if ((b & 1) == 0)
4737 14ce26e7 bellard
                ot = OT_BYTE;
4738 14ce26e7 bellard
            else
4739 14ce26e7 bellard
                ot = dflag + OT_WORD;
4740 14ce26e7 bellard
#ifdef TARGET_X86_64
4741 8f091a59 bellard
            if (s->aflag == 2) {
4742 14ce26e7 bellard
                offset_addr = ldq_code(s->pc);
4743 14ce26e7 bellard
                s->pc += 8;
4744 57fec1fe bellard
                gen_op_movq_A0_im(offset_addr);
4745 5fafdf24 ths
            } else
4746 14ce26e7 bellard
#endif
4747 14ce26e7 bellard
            {
4748 14ce26e7 bellard
                if (s->aflag) {
4749 14ce26e7 bellard
                    offset_addr = insn_get(s, OT_LONG);
4750 14ce26e7 bellard
                } else {
4751 14ce26e7 bellard
                    offset_addr = insn_get(s, OT_WORD);
4752 14ce26e7 bellard
                }
4753 14ce26e7 bellard
                gen_op_movl_A0_im(offset_addr);
4754 14ce26e7 bellard
            }
4755 664e0f19 bellard
            gen_add_A0_ds_seg(s);
4756 14ce26e7 bellard
            if ((b & 2) == 0) {
4757 57fec1fe bellard
                gen_op_ld_T0_A0(ot + s->mem_index);
4758 57fec1fe bellard
                gen_op_mov_reg_T0(ot, R_EAX);
4759 14ce26e7 bellard
            } else {
4760 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, R_EAX);
4761 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
4762 2c0262af bellard
            }
4763 2c0262af bellard
        }
4764 2c0262af bellard
        break;
4765 2c0262af bellard
    case 0xd7: /* xlat */
4766 14ce26e7 bellard
#ifdef TARGET_X86_64
4767 8f091a59 bellard
        if (s->aflag == 2) {
4768 57fec1fe bellard
            gen_op_movq_A0_reg(R_EBX);
4769 bbf662ee bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
4770 bbf662ee bellard
            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
4771 bbf662ee bellard
            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
4772 5fafdf24 ths
        } else
4773 14ce26e7 bellard
#endif
4774 14ce26e7 bellard
        {
4775 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBX);
4776 bbf662ee bellard
            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
4777 bbf662ee bellard
            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
4778 bbf662ee bellard
            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
4779 14ce26e7 bellard
            if (s->aflag == 0)
4780 14ce26e7 bellard
                gen_op_andl_A0_ffff();
4781 bbf662ee bellard
            else
4782 bbf662ee bellard
                tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
4783 14ce26e7 bellard
        }
4784 664e0f19 bellard
        gen_add_A0_ds_seg(s);
4785 57fec1fe bellard
        gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
4786 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, R_EAX);
4787 2c0262af bellard
        break;
4788 2c0262af bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
4789 2c0262af bellard
        val = insn_get(s, OT_BYTE);
4790 2c0262af bellard
        gen_op_movl_T0_im(val);
4791 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
4792 2c0262af bellard
        break;
4793 2c0262af bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
4794 14ce26e7 bellard
#ifdef TARGET_X86_64
4795 14ce26e7 bellard
        if (dflag == 2) {
4796 14ce26e7 bellard
            uint64_t tmp;
4797 14ce26e7 bellard
            /* 64 bit case */
4798 14ce26e7 bellard
            tmp = ldq_code(s->pc);
4799 14ce26e7 bellard
            s->pc += 8;
4800 14ce26e7 bellard
            reg = (b & 7) | REX_B(s);
4801 14ce26e7 bellard
            gen_movtl_T0_im(tmp);
4802 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, reg);
4803 5fafdf24 ths
        } else
4804 14ce26e7 bellard
#endif
4805 14ce26e7 bellard
        {
4806 14ce26e7 bellard
            ot = dflag ? OT_LONG : OT_WORD;
4807 14ce26e7 bellard
            val = insn_get(s, ot);
4808 14ce26e7 bellard
            reg = (b & 7) | REX_B(s);
4809 14ce26e7 bellard
            gen_op_movl_T0_im(val);
4810 57fec1fe bellard
            gen_op_mov_reg_T0(ot, reg);
4811 14ce26e7 bellard
        }
4812 2c0262af bellard
        break;
4813 2c0262af bellard
4814 2c0262af bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
4815 14ce26e7 bellard
        ot = dflag + OT_WORD;
4816 14ce26e7 bellard
        reg = (b & 7) | REX_B(s);
4817 2c0262af bellard
        rm = R_EAX;
4818 2c0262af bellard
        goto do_xchg_reg;
4819 2c0262af bellard
    case 0x86:
4820 2c0262af bellard
    case 0x87: /* xchg Ev, Gv */
4821 2c0262af bellard
        if ((b & 1) == 0)
4822 2c0262af bellard
            ot = OT_BYTE;
4823 2c0262af bellard
        else
4824 14ce26e7 bellard
            ot = dflag + OT_WORD;
4825 61382a50 bellard
        modrm = ldub_code(s->pc++);
4826 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4827 2c0262af bellard
        mod = (modrm >> 6) & 3;
4828 2c0262af bellard
        if (mod == 3) {
4829 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4830 2c0262af bellard
        do_xchg_reg:
4831 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4832 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, rm);
4833 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
4834 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4835 2c0262af bellard
        } else {
4836 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4837 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4838 2c0262af bellard
            /* for xchg, lock is implicit */
4839 2c0262af bellard
            if (!(prefixes & PREFIX_LOCK))
4840 b8b6a50b bellard
                tcg_gen_helper_0_0(helper_lock);
4841 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
4842 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
4843 2c0262af bellard
            if (!(prefixes & PREFIX_LOCK))
4844 b8b6a50b bellard
                tcg_gen_helper_0_0(helper_unlock);
4845 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4846 2c0262af bellard
        }
4847 2c0262af bellard
        break;
4848 2c0262af bellard
    case 0xc4: /* les Gv */
4849 14ce26e7 bellard
        if (CODE64(s))
4850 14ce26e7 bellard
            goto illegal_op;
4851 2c0262af bellard
        op = R_ES;
4852 2c0262af bellard
        goto do_lxx;
4853 2c0262af bellard
    case 0xc5: /* lds Gv */
4854 14ce26e7 bellard
        if (CODE64(s))
4855 14ce26e7 bellard
            goto illegal_op;
4856 2c0262af bellard
        op = R_DS;
4857 2c0262af bellard
        goto do_lxx;
4858 2c0262af bellard
    case 0x1b2: /* lss Gv */
4859 2c0262af bellard
        op = R_SS;
4860 2c0262af bellard
        goto do_lxx;
4861 2c0262af bellard
    case 0x1b4: /* lfs Gv */
4862 2c0262af bellard
        op = R_FS;
4863 2c0262af bellard
        goto do_lxx;
4864 2c0262af bellard
    case 0x1b5: /* lgs Gv */
4865 2c0262af bellard
        op = R_GS;
4866 2c0262af bellard
    do_lxx:
4867 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
4868 61382a50 bellard
        modrm = ldub_code(s->pc++);
4869 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4870 2c0262af bellard
        mod = (modrm >> 6) & 3;
4871 2c0262af bellard
        if (mod == 3)
4872 2c0262af bellard
            goto illegal_op;
4873 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4874 57fec1fe bellard
        gen_op_ld_T1_A0(ot + s->mem_index);
4875 aba9d61e bellard
        gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4876 2c0262af bellard
        /* load the segment first to handle exceptions properly */
4877 57fec1fe bellard
        gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4878 2c0262af bellard
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4879 2c0262af bellard
        /* then put the data */
4880 57fec1fe bellard
        gen_op_mov_reg_T1(ot, reg);
4881 2c0262af bellard
        if (s->is_jmp) {
4882 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4883 2c0262af bellard
            gen_eob(s);
4884 2c0262af bellard
        }
4885 2c0262af bellard
        break;
4886 3b46e624 ths
4887 2c0262af bellard
        /************************/
4888 2c0262af bellard
        /* shifts */
4889 2c0262af bellard
    case 0xc0:
4890 2c0262af bellard
    case 0xc1:
4891 2c0262af bellard
        /* shift Ev,Ib */
4892 2c0262af bellard
        shift = 2;
4893 2c0262af bellard
    grp2:
4894 2c0262af bellard
        {
4895 2c0262af bellard
            if ((b & 1) == 0)
4896 2c0262af bellard
                ot = OT_BYTE;
4897 2c0262af bellard
            else
4898 14ce26e7 bellard
                ot = dflag + OT_WORD;
4899 3b46e624 ths
4900 61382a50 bellard
            modrm = ldub_code(s->pc++);
4901 2c0262af bellard
            mod = (modrm >> 6) & 3;
4902 2c0262af bellard
            op = (modrm >> 3) & 7;
4903 3b46e624 ths
4904 2c0262af bellard
            if (mod != 3) {
4905 14ce26e7 bellard
                if (shift == 2) {
4906 14ce26e7 bellard
                    s->rip_offset = 1;
4907 14ce26e7 bellard
                }
4908 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4909 2c0262af bellard
                opreg = OR_TMP0;
4910 2c0262af bellard
            } else {
4911 14ce26e7 bellard
                opreg = (modrm & 7) | REX_B(s);
4912 2c0262af bellard
            }
4913 2c0262af bellard
4914 2c0262af bellard
            /* simpler op */
4915 2c0262af bellard
            if (shift == 0) {
4916 2c0262af bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
4917 2c0262af bellard
            } else {
4918 2c0262af bellard
                if (shift == 2) {
4919 61382a50 bellard
                    shift = ldub_code(s->pc++);
4920 2c0262af bellard
                }
4921 2c0262af bellard
                gen_shifti(s, op, ot, opreg, shift);
4922 2c0262af bellard
            }
4923 2c0262af bellard
        }
4924 2c0262af bellard
        break;
4925 2c0262af bellard
    case 0xd0:
4926 2c0262af bellard
    case 0xd1:
4927 2c0262af bellard
        /* shift Ev,1 */
4928 2c0262af bellard
        shift = 1;
4929 2c0262af bellard
        goto grp2;
4930 2c0262af bellard
    case 0xd2:
4931 2c0262af bellard
    case 0xd3:
4932 2c0262af bellard
        /* shift Ev,cl */
4933 2c0262af bellard
        shift = 0;
4934 2c0262af bellard
        goto grp2;
4935 2c0262af bellard
4936 2c0262af bellard
    case 0x1a4: /* shld imm */
4937 2c0262af bellard
        op = 0;
4938 2c0262af bellard
        shift = 1;
4939 2c0262af bellard
        goto do_shiftd;
4940 2c0262af bellard
    case 0x1a5: /* shld cl */
4941 2c0262af bellard
        op = 0;
4942 2c0262af bellard
        shift = 0;
4943 2c0262af bellard
        goto do_shiftd;
4944 2c0262af bellard
    case 0x1ac: /* shrd imm */
4945 2c0262af bellard
        op = 1;
4946 2c0262af bellard
        shift = 1;
4947 2c0262af bellard
        goto do_shiftd;
4948 2c0262af bellard
    case 0x1ad: /* shrd cl */
4949 2c0262af bellard
        op = 1;
4950 2c0262af bellard
        shift = 0;
4951 2c0262af bellard
    do_shiftd:
4952 14ce26e7 bellard
        ot = dflag + OT_WORD;
4953 61382a50 bellard
        modrm = ldub_code(s->pc++);
4954 2c0262af bellard
        mod = (modrm >> 6) & 3;
4955 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
4956 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4957 2c0262af bellard
        if (mod != 3) {
4958 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4959 b6abf97d bellard
            opreg = OR_TMP0;
4960 2c0262af bellard
        } else {
4961 b6abf97d bellard
            opreg = rm;
4962 2c0262af bellard
        }
4963 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
4964 3b46e624 ths
4965 2c0262af bellard
        if (shift) {
4966 61382a50 bellard
            val = ldub_code(s->pc++);
4967 b6abf97d bellard
            tcg_gen_movi_tl(cpu_T3, val);
4968 2c0262af bellard
        } else {
4969 b6abf97d bellard
            tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_ECX]));
4970 2c0262af bellard
        }
4971 b6abf97d bellard
        gen_shiftd_rm_T1_T3(s, ot, opreg, op);
4972 2c0262af bellard
        break;
4973 2c0262af bellard
4974 2c0262af bellard
        /************************/
4975 2c0262af bellard
        /* floats */
4976 5fafdf24 ths
    case 0xd8 ... 0xdf:
4977 7eee2a50 bellard
        if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4978 7eee2a50 bellard
            /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4979 7eee2a50 bellard
            /* XXX: what to do if illegal op ? */
4980 7eee2a50 bellard
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4981 7eee2a50 bellard
            break;
4982 7eee2a50 bellard
        }
4983 61382a50 bellard
        modrm = ldub_code(s->pc++);
4984 2c0262af bellard
        mod = (modrm >> 6) & 3;
4985 2c0262af bellard
        rm = modrm & 7;
4986 2c0262af bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4987 2c0262af bellard
        if (mod != 3) {
4988 2c0262af bellard
            /* memory op */
4989 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4990 2c0262af bellard
            switch(op) {
4991 2c0262af bellard
            case 0x00 ... 0x07: /* fxxxs */
4992 2c0262af bellard
            case 0x10 ... 0x17: /* fixxxl */
4993 2c0262af bellard
            case 0x20 ... 0x27: /* fxxxl */
4994 2c0262af bellard
            case 0x30 ... 0x37: /* fixxx */
4995 2c0262af bellard
                {
4996 2c0262af bellard
                    int op1;
4997 2c0262af bellard
                    op1 = op & 7;
4998 2c0262af bellard
4999 2c0262af bellard
                    switch(op >> 4) {
5000 2c0262af bellard
                    case 0:
5001 ba7cd150 bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5002 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5003 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_flds_FT0, cpu_tmp2_i32);
5004 2c0262af bellard
                        break;
5005 2c0262af bellard
                    case 1:
5006 ba7cd150 bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5007 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5008 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fildl_FT0, cpu_tmp2_i32);
5009 2c0262af bellard
                        break;
5010 2c0262af bellard
                    case 2:
5011 b6abf97d bellard
                        tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
5012 19e6c4b8 bellard
                                          (s->mem_index >> 2) - 1);
5013 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fldl_FT0, cpu_tmp1_i64);
5014 2c0262af bellard
                        break;
5015 2c0262af bellard
                    case 3:
5016 2c0262af bellard
                    default:
5017 ba7cd150 bellard
                        gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5018 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5019 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fildl_FT0, cpu_tmp2_i32);
5020 2c0262af bellard
                        break;
5021 2c0262af bellard
                    }
5022 3b46e624 ths
5023 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fp_arith_ST0_FT0[op1]);
5024 2c0262af bellard
                    if (op1 == 3) {
5025 2c0262af bellard
                        /* fcomp needs pop */
5026 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpop);
5027 2c0262af bellard
                    }
5028 2c0262af bellard
                }
5029 2c0262af bellard
                break;
5030 2c0262af bellard
            case 0x08: /* flds */
5031 2c0262af bellard
            case 0x0a: /* fsts */
5032 2c0262af bellard
            case 0x0b: /* fstps */
5033 465e9838 bellard
            case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5034 465e9838 bellard
            case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5035 465e9838 bellard
            case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5036 2c0262af bellard
                switch(op & 7) {
5037 2c0262af bellard
                case 0:
5038 2c0262af bellard
                    switch(op >> 4) {
5039 2c0262af bellard
                    case 0:
5040 ba7cd150 bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5041 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5042 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_flds_ST0, cpu_tmp2_i32);
5043 2c0262af bellard
                        break;
5044 2c0262af bellard
                    case 1:
5045 ba7cd150 bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5046 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5047 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fildl_ST0, cpu_tmp2_i32);
5048 2c0262af bellard
                        break;
5049 2c0262af bellard
                    case 2:
5050 b6abf97d bellard
                        tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
5051 19e6c4b8 bellard
                                          (s->mem_index >> 2) - 1);
5052 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fldl_ST0, cpu_tmp1_i64);
5053 2c0262af bellard
                        break;
5054 2c0262af bellard
                    case 3:
5055 2c0262af bellard
                    default:
5056 ba7cd150 bellard
                        gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5057 b6abf97d bellard
                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5058 b6abf97d bellard
                        tcg_gen_helper_0_1(helper_fildl_ST0, cpu_tmp2_i32);
5059 2c0262af bellard
                        break;
5060 2c0262af bellard
                    }
5061 2c0262af bellard
                    break;
5062 465e9838 bellard
                case 1:
5063 19e6c4b8 bellard
                    /* XXX: the corresponding CPUID bit must be tested ! */
5064 465e9838 bellard
                    switch(op >> 4) {
5065 465e9838 bellard
                    case 1:
5066 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fisttl_ST0, cpu_tmp2_i32);
5067 b6abf97d bellard
                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5068 ba7cd150 bellard
                        gen_op_st_T0_A0(OT_LONG + s->mem_index);
5069 465e9838 bellard
                        break;
5070 465e9838 bellard
                    case 2:
5071 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fisttll_ST0, cpu_tmp1_i64);
5072 b6abf97d bellard
                        tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
5073 19e6c4b8 bellard
                                          (s->mem_index >> 2) - 1);
5074 465e9838 bellard
                        break;
5075 465e9838 bellard
                    case 3:
5076 465e9838 bellard
                    default:
5077 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fistt_ST0, cpu_tmp2_i32);
5078 b6abf97d bellard
                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5079 ba7cd150 bellard
                        gen_op_st_T0_A0(OT_WORD + s->mem_index);
5080 19e6c4b8 bellard
                        break;
5081 465e9838 bellard
                    }
5082 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpop);
5083 465e9838 bellard
                    break;
5084 2c0262af bellard
                default:
5085 2c0262af bellard
                    switch(op >> 4) {
5086 2c0262af bellard
                    case 0:
5087 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fsts_ST0, cpu_tmp2_i32);
5088 b6abf97d bellard
                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5089 ba7cd150 bellard
                        gen_op_st_T0_A0(OT_LONG + s->mem_index);
5090 2c0262af bellard
                        break;
5091 2c0262af bellard
                    case 1:
5092 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fistl_ST0, cpu_tmp2_i32);
5093 b6abf97d bellard
                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5094 ba7cd150 bellard
                        gen_op_st_T0_A0(OT_LONG + s->mem_index);
5095 2c0262af bellard
                        break;
5096 2c0262af bellard
                    case 2:
5097 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fstl_ST0, cpu_tmp1_i64);
5098 b6abf97d bellard
                        tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
5099 19e6c4b8 bellard
                                          (s->mem_index >> 2) - 1);
5100 2c0262af bellard
                        break;
5101 2c0262af bellard
                    case 3:
5102 2c0262af bellard
                    default:
5103 b6abf97d bellard
                        tcg_gen_helper_1_0(helper_fist_ST0, cpu_tmp2_i32);
5104 b6abf97d bellard
                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5105 ba7cd150 bellard
                        gen_op_st_T0_A0(OT_WORD + s->mem_index);
5106 2c0262af bellard
                        break;
5107 2c0262af bellard
                    }
5108 2c0262af bellard
                    if ((op & 7) == 3)
5109 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpop);
5110 2c0262af bellard
                    break;
5111 2c0262af bellard
                }
5112 2c0262af bellard
                break;
5113 2c0262af bellard
            case 0x0c: /* fldenv mem */
5114 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5115 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5116 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5117 19e6c4b8 bellard
                tcg_gen_helper_0_2(helper_fldenv, 
5118 19e6c4b8 bellard
                                   cpu_A0, tcg_const_i32(s->dflag));
5119 2c0262af bellard
                break;
5120 2c0262af bellard
            case 0x0d: /* fldcw mem */
5121 19e6c4b8 bellard
                gen_op_ld_T0_A0(OT_WORD + s->mem_index);
5122 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5123 b6abf97d bellard
                tcg_gen_helper_0_1(helper_fldcw, cpu_tmp2_i32);
5124 2c0262af bellard
                break;
5125 2c0262af bellard
            case 0x0e: /* fnstenv mem */
5126 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5127 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5128 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5129 19e6c4b8 bellard
                tcg_gen_helper_0_2(helper_fstenv,
5130 19e6c4b8 bellard
                                   cpu_A0, tcg_const_i32(s->dflag));
5131 2c0262af bellard
                break;
5132 2c0262af bellard
            case 0x0f: /* fnstcw mem */
5133 b6abf97d bellard
                tcg_gen_helper_1_0(helper_fnstcw, cpu_tmp2_i32);
5134 b6abf97d bellard
                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5135 19e6c4b8 bellard
                gen_op_st_T0_A0(OT_WORD + s->mem_index);
5136 2c0262af bellard
                break;
5137 2c0262af bellard
            case 0x1d: /* fldt mem */
5138 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5139 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5140 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5141 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fldt_ST0, cpu_A0);
5142 2c0262af bellard
                break;
5143 2c0262af bellard
            case 0x1f: /* fstpt mem */
5144 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5145 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5146 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5147 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fstt_ST0, cpu_A0);
5148 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5149 2c0262af bellard
                break;
5150 2c0262af bellard
            case 0x2c: /* frstor mem */
5151 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5152 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5153 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5154 19e6c4b8 bellard
                tcg_gen_helper_0_2(helper_frstor,
5155 19e6c4b8 bellard
                                   cpu_A0, tcg_const_i32(s->dflag));
5156 2c0262af bellard
                break;
5157 2c0262af bellard
            case 0x2e: /* fnsave mem */
5158 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5159 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5160 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5161 19e6c4b8 bellard
                tcg_gen_helper_0_2(helper_fsave,
5162 19e6c4b8 bellard
                                   cpu_A0, tcg_const_i32(s->dflag));
5163 2c0262af bellard
                break;
5164 2c0262af bellard
            case 0x2f: /* fnstsw mem */
5165 b6abf97d bellard
                tcg_gen_helper_1_0(helper_fnstsw, cpu_tmp2_i32);
5166 b6abf97d bellard
                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5167 19e6c4b8 bellard
                gen_op_st_T0_A0(OT_WORD + s->mem_index);
5168 2c0262af bellard
                break;
5169 2c0262af bellard
            case 0x3c: /* fbld */
5170 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5171 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5172 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5173 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fbld_ST0, cpu_A0);
5174 2c0262af bellard
                break;
5175 2c0262af bellard
            case 0x3e: /* fbstp */
5176 19e6c4b8 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5177 19e6c4b8 bellard
                    gen_op_set_cc_op(s->cc_op);
5178 19e6c4b8 bellard
                gen_jmp_im(pc_start - s->cs_base);
5179 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fbst_ST0, cpu_A0);
5180 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5181 2c0262af bellard
                break;
5182 2c0262af bellard
            case 0x3d: /* fildll */
5183 b6abf97d bellard
                tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 
5184 19e6c4b8 bellard
                                  (s->mem_index >> 2) - 1);
5185 b6abf97d bellard
                tcg_gen_helper_0_1(helper_fildll_ST0, cpu_tmp1_i64);
5186 2c0262af bellard
                break;
5187 2c0262af bellard
            case 0x3f: /* fistpll */
5188 b6abf97d bellard
                tcg_gen_helper_1_0(helper_fistll_ST0, cpu_tmp1_i64);
5189 b6abf97d bellard
                tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 
5190 19e6c4b8 bellard
                                  (s->mem_index >> 2) - 1);
5191 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5192 2c0262af bellard
                break;
5193 2c0262af bellard
            default:
5194 2c0262af bellard
                goto illegal_op;
5195 2c0262af bellard
            }
5196 2c0262af bellard
        } else {
5197 2c0262af bellard
            /* register float ops */
5198 2c0262af bellard
            opreg = rm;
5199 2c0262af bellard
5200 2c0262af bellard
            switch(op) {
5201 2c0262af bellard
            case 0x08: /* fld sti */
5202 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpush);
5203 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_ST0_STN, tcg_const_i32((opreg + 1) & 7));
5204 2c0262af bellard
                break;
5205 2c0262af bellard
            case 0x09: /* fxchg sti */
5206 c169c906 bellard
            case 0x29: /* fxchg4 sti, undocumented op */
5207 c169c906 bellard
            case 0x39: /* fxchg7 sti, undocumented op */
5208 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fxchg_ST0_STN, tcg_const_i32(opreg));
5209 2c0262af bellard
                break;
5210 2c0262af bellard
            case 0x0a: /* grp d9/2 */
5211 2c0262af bellard
                switch(rm) {
5212 2c0262af bellard
                case 0: /* fnop */
5213 023fe10d bellard
                    /* check exceptions (FreeBSD FPU probe) */
5214 023fe10d bellard
                    if (s->cc_op != CC_OP_DYNAMIC)
5215 023fe10d bellard
                        gen_op_set_cc_op(s->cc_op);
5216 14ce26e7 bellard
                    gen_jmp_im(pc_start - s->cs_base);
5217 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fwait);
5218 2c0262af bellard
                    break;
5219 2c0262af bellard
                default:
5220 2c0262af bellard
                    goto illegal_op;
5221 2c0262af bellard
                }
5222 2c0262af bellard
                break;
5223 2c0262af bellard
            case 0x0c: /* grp d9/4 */
5224 2c0262af bellard
                switch(rm) {
5225 2c0262af bellard
                case 0: /* fchs */
5226 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fchs_ST0);
5227 2c0262af bellard
                    break;
5228 2c0262af bellard
                case 1: /* fabs */
5229 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fabs_ST0);
5230 2c0262af bellard
                    break;
5231 2c0262af bellard
                case 4: /* ftst */
5232 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fldz_FT0);
5233 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fcom_ST0_FT0);
5234 2c0262af bellard
                    break;
5235 2c0262af bellard
                case 5: /* fxam */
5236 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fxam_ST0);
5237 2c0262af bellard
                    break;
5238 2c0262af bellard
                default:
5239 2c0262af bellard
                    goto illegal_op;
5240 2c0262af bellard
                }
5241 2c0262af bellard
                break;
5242 2c0262af bellard
            case 0x0d: /* grp d9/5 */
5243 2c0262af bellard
                {
5244 2c0262af bellard
                    switch(rm) {
5245 2c0262af bellard
                    case 0:
5246 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5247 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fld1_ST0);
5248 2c0262af bellard
                        break;
5249 2c0262af bellard
                    case 1:
5250 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5251 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldl2t_ST0);
5252 2c0262af bellard
                        break;
5253 2c0262af bellard
                    case 2:
5254 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5255 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldl2e_ST0);
5256 2c0262af bellard
                        break;
5257 2c0262af bellard
                    case 3:
5258 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5259 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldpi_ST0);
5260 2c0262af bellard
                        break;
5261 2c0262af bellard
                    case 4:
5262 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5263 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldlg2_ST0);
5264 2c0262af bellard
                        break;
5265 2c0262af bellard
                    case 5:
5266 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5267 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldln2_ST0);
5268 2c0262af bellard
                        break;
5269 2c0262af bellard
                    case 6:
5270 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fpush);
5271 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fldz_ST0);
5272 2c0262af bellard
                        break;
5273 2c0262af bellard
                    default:
5274 2c0262af bellard
                        goto illegal_op;
5275 2c0262af bellard
                    }
5276 2c0262af bellard
                }
5277 2c0262af bellard
                break;
5278 2c0262af bellard
            case 0x0e: /* grp d9/6 */
5279 2c0262af bellard
                switch(rm) {
5280 2c0262af bellard
                case 0: /* f2xm1 */
5281 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_f2xm1);
5282 2c0262af bellard
                    break;
5283 2c0262af bellard
                case 1: /* fyl2x */
5284 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fyl2x);
5285 2c0262af bellard
                    break;
5286 2c0262af bellard
                case 2: /* fptan */
5287 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fptan);
5288 2c0262af bellard
                    break;
5289 2c0262af bellard
                case 3: /* fpatan */
5290 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpatan);
5291 2c0262af bellard
                    break;
5292 2c0262af bellard
                case 4: /* fxtract */
5293 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fxtract);
5294 2c0262af bellard
                    break;
5295 2c0262af bellard
                case 5: /* fprem1 */
5296 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fprem1);
5297 2c0262af bellard
                    break;
5298 2c0262af bellard
                case 6: /* fdecstp */
5299 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fdecstp);
5300 2c0262af bellard
                    break;
5301 2c0262af bellard
                default:
5302 2c0262af bellard
                case 7: /* fincstp */
5303 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fincstp);
5304 2c0262af bellard
                    break;
5305 2c0262af bellard
                }
5306 2c0262af bellard
                break;
5307 2c0262af bellard
            case 0x0f: /* grp d9/7 */
5308 2c0262af bellard
                switch(rm) {
5309 2c0262af bellard
                case 0: /* fprem */
5310 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fprem);
5311 2c0262af bellard
                    break;
5312 2c0262af bellard
                case 1: /* fyl2xp1 */
5313 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fyl2xp1);
5314 2c0262af bellard
                    break;
5315 2c0262af bellard
                case 2: /* fsqrt */
5316 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fsqrt);
5317 2c0262af bellard
                    break;
5318 2c0262af bellard
                case 3: /* fsincos */
5319 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fsincos);
5320 2c0262af bellard
                    break;
5321 2c0262af bellard
                case 5: /* fscale */
5322 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fscale);
5323 2c0262af bellard
                    break;
5324 2c0262af bellard
                case 4: /* frndint */
5325 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_frndint);
5326 2c0262af bellard
                    break;
5327 2c0262af bellard
                case 6: /* fsin */
5328 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fsin);
5329 2c0262af bellard
                    break;
5330 2c0262af bellard
                default:
5331 2c0262af bellard
                case 7: /* fcos */
5332 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fcos);
5333 2c0262af bellard
                    break;
5334 2c0262af bellard
                }
5335 2c0262af bellard
                break;
5336 2c0262af bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
5337 2c0262af bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
5338 2c0262af bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
5339 2c0262af bellard
                {
5340 2c0262af bellard
                    int op1;
5341 3b46e624 ths
5342 2c0262af bellard
                    op1 = op & 7;
5343 2c0262af bellard
                    if (op >= 0x20) {
5344 19e6c4b8 bellard
                        tcg_gen_helper_0_1(helper_fp_arith_STN_ST0[op1], tcg_const_i32(opreg));
5345 2c0262af bellard
                        if (op >= 0x30)
5346 19e6c4b8 bellard
                            tcg_gen_helper_0_0(helper_fpop);
5347 2c0262af bellard
                    } else {
5348 19e6c4b8 bellard
                        tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5349 19e6c4b8 bellard
                        tcg_gen_helper_0_0(helper_fp_arith_ST0_FT0[op1]);
5350 2c0262af bellard
                    }
5351 2c0262af bellard
                }
5352 2c0262af bellard
                break;
5353 2c0262af bellard
            case 0x02: /* fcom */
5354 c169c906 bellard
            case 0x22: /* fcom2, undocumented op */
5355 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5356 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fcom_ST0_FT0);
5357 2c0262af bellard
                break;
5358 2c0262af bellard
            case 0x03: /* fcomp */
5359 c169c906 bellard
            case 0x23: /* fcomp3, undocumented op */
5360 c169c906 bellard
            case 0x32: /* fcomp5, undocumented op */
5361 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5362 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fcom_ST0_FT0);
5363 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5364 2c0262af bellard
                break;
5365 2c0262af bellard
            case 0x15: /* da/5 */
5366 2c0262af bellard
                switch(rm) {
5367 2c0262af bellard
                case 1: /* fucompp */
5368 19e6c4b8 bellard
                    tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(1));
5369 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fucom_ST0_FT0);
5370 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpop);
5371 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpop);
5372 2c0262af bellard
                    break;
5373 2c0262af bellard
                default:
5374 2c0262af bellard
                    goto illegal_op;
5375 2c0262af bellard
                }
5376 2c0262af bellard
                break;
5377 2c0262af bellard
            case 0x1c:
5378 2c0262af bellard
                switch(rm) {
5379 2c0262af bellard
                case 0: /* feni (287 only, just do nop here) */
5380 2c0262af bellard
                    break;
5381 2c0262af bellard
                case 1: /* fdisi (287 only, just do nop here) */
5382 2c0262af bellard
                    break;
5383 2c0262af bellard
                case 2: /* fclex */
5384 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fclex);
5385 2c0262af bellard
                    break;
5386 2c0262af bellard
                case 3: /* fninit */
5387 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fninit);
5388 2c0262af bellard
                    break;
5389 2c0262af bellard
                case 4: /* fsetpm (287 only, just do nop here) */
5390 2c0262af bellard
                    break;
5391 2c0262af bellard
                default:
5392 2c0262af bellard
                    goto illegal_op;
5393 2c0262af bellard
                }
5394 2c0262af bellard
                break;
5395 2c0262af bellard
            case 0x1d: /* fucomi */
5396 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5397 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
5398 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5399 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fucomi_ST0_FT0);
5400 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
5401 2c0262af bellard
                break;
5402 2c0262af bellard
            case 0x1e: /* fcomi */
5403 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5404 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
5405 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5406 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fcomi_ST0_FT0);
5407 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
5408 2c0262af bellard
                break;
5409 658c8bda bellard
            case 0x28: /* ffree sti */
5410 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_ffree_STN, tcg_const_i32(opreg));
5411 5fafdf24 ths
                break;
5412 2c0262af bellard
            case 0x2a: /* fst sti */
5413 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_STN_ST0, tcg_const_i32(opreg));
5414 2c0262af bellard
                break;
5415 2c0262af bellard
            case 0x2b: /* fstp sti */
5416 c169c906 bellard
            case 0x0b: /* fstp1 sti, undocumented op */
5417 c169c906 bellard
            case 0x3a: /* fstp8 sti, undocumented op */
5418 c169c906 bellard
            case 0x3b: /* fstp9 sti, undocumented op */
5419 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_STN_ST0, tcg_const_i32(opreg));
5420 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5421 2c0262af bellard
                break;
5422 2c0262af bellard
            case 0x2c: /* fucom st(i) */
5423 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5424 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fucom_ST0_FT0);
5425 2c0262af bellard
                break;
5426 2c0262af bellard
            case 0x2d: /* fucomp st(i) */
5427 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5428 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fucom_ST0_FT0);
5429 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5430 2c0262af bellard
                break;
5431 2c0262af bellard
            case 0x33: /* de/3 */
5432 2c0262af bellard
                switch(rm) {
5433 2c0262af bellard
                case 1: /* fcompp */
5434 19e6c4b8 bellard
                    tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(1));
5435 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fcom_ST0_FT0);
5436 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpop);
5437 19e6c4b8 bellard
                    tcg_gen_helper_0_0(helper_fpop);
5438 2c0262af bellard
                    break;
5439 2c0262af bellard
                default:
5440 2c0262af bellard
                    goto illegal_op;
5441 2c0262af bellard
                }
5442 2c0262af bellard
                break;
5443 c169c906 bellard
            case 0x38: /* ffreep sti, undocumented op */
5444 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_ffree_STN, tcg_const_i32(opreg));
5445 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5446 c169c906 bellard
                break;
5447 2c0262af bellard
            case 0x3c: /* df/4 */
5448 2c0262af bellard
                switch(rm) {
5449 2c0262af bellard
                case 0:
5450 b6abf97d bellard
                    tcg_gen_helper_1_0(helper_fnstsw, cpu_tmp2_i32);
5451 b6abf97d bellard
                    tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5452 19e6c4b8 bellard
                    gen_op_mov_reg_T0(OT_WORD, R_EAX);
5453 2c0262af bellard
                    break;
5454 2c0262af bellard
                default:
5455 2c0262af bellard
                    goto illegal_op;
5456 2c0262af bellard
                }
5457 2c0262af bellard
                break;
5458 2c0262af bellard
            case 0x3d: /* fucomip */
5459 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5460 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
5461 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5462 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fucomi_ST0_FT0);
5463 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5464 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
5465 2c0262af bellard
                break;
5466 2c0262af bellard
            case 0x3e: /* fcomip */
5467 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
5468 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
5469 19e6c4b8 bellard
                tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg));
5470 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fcomi_ST0_FT0);
5471 19e6c4b8 bellard
                tcg_gen_helper_0_0(helper_fpop);
5472 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
5473 2c0262af bellard
                break;
5474 a2cc3b24 bellard
            case 0x10 ... 0x13: /* fcmovxx */
5475 a2cc3b24 bellard
            case 0x18 ... 0x1b:
5476 a2cc3b24 bellard
                {
5477 19e6c4b8 bellard
                    int op1, l1;
5478 a2cc3b24 bellard
                    const static uint8_t fcmov_cc[8] = {
5479 a2cc3b24 bellard
                        (JCC_B << 1),
5480 a2cc3b24 bellard
                        (JCC_Z << 1),
5481 a2cc3b24 bellard
                        (JCC_BE << 1),
5482 a2cc3b24 bellard
                        (JCC_P << 1),
5483 a2cc3b24 bellard
                    };
5484 1e4840bf bellard
                    op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
5485 19e6c4b8 bellard
                    l1 = gen_new_label();
5486 1e4840bf bellard
                    gen_jcc1(s, s->cc_op, op1, l1);
5487 19e6c4b8 bellard
                    tcg_gen_helper_0_1(helper_fmov_ST0_STN, tcg_const_i32(opreg));
5488 19e6c4b8 bellard
                    gen_set_label(l1);
5489 a2cc3b24 bellard
                }
5490 a2cc3b24 bellard
                break;
5491 2c0262af bellard
            default:
5492 2c0262af bellard
                goto illegal_op;
5493 2c0262af bellard
            }
5494 2c0262af bellard
        }
5495 2c0262af bellard
        break;
5496 2c0262af bellard
        /************************/
5497 2c0262af bellard
        /* string ops */
5498 2c0262af bellard
5499 2c0262af bellard
    case 0xa4: /* movsS */
5500 2c0262af bellard
    case 0xa5:
5501 2c0262af bellard
        if ((b & 1) == 0)
5502 2c0262af bellard
            ot = OT_BYTE;
5503 2c0262af bellard
        else
5504 14ce26e7 bellard
            ot = dflag + OT_WORD;
5505 2c0262af bellard
5506 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5507 2c0262af bellard
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5508 2c0262af bellard
        } else {
5509 2c0262af bellard
            gen_movs(s, ot);
5510 2c0262af bellard
        }
5511 2c0262af bellard
        break;
5512 3b46e624 ths
5513 2c0262af bellard
    case 0xaa: /* stosS */
5514 2c0262af bellard
    case 0xab:
5515 2c0262af bellard
        if ((b & 1) == 0)
5516 2c0262af bellard
            ot = OT_BYTE;
5517 2c0262af bellard
        else
5518 14ce26e7 bellard
            ot = dflag + OT_WORD;
5519 2c0262af bellard
5520 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5521 2c0262af bellard
            gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5522 2c0262af bellard
        } else {
5523 2c0262af bellard
            gen_stos(s, ot);
5524 2c0262af bellard
        }
5525 2c0262af bellard
        break;
5526 2c0262af bellard
    case 0xac: /* lodsS */
5527 2c0262af bellard
    case 0xad:
5528 2c0262af bellard
        if ((b & 1) == 0)
5529 2c0262af bellard
            ot = OT_BYTE;
5530 2c0262af bellard
        else
5531 14ce26e7 bellard
            ot = dflag + OT_WORD;
5532 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5533 2c0262af bellard
            gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5534 2c0262af bellard
        } else {
5535 2c0262af bellard
            gen_lods(s, ot);
5536 2c0262af bellard
        }
5537 2c0262af bellard
        break;
5538 2c0262af bellard
    case 0xae: /* scasS */
5539 2c0262af bellard
    case 0xaf:
5540 2c0262af bellard
        if ((b & 1) == 0)
5541 2c0262af bellard
            ot = OT_BYTE;
5542 2c0262af bellard
        else
5543 14ce26e7 bellard
            ot = dflag + OT_WORD;
5544 2c0262af bellard
        if (prefixes & PREFIX_REPNZ) {
5545 2c0262af bellard
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
5546 2c0262af bellard
        } else if (prefixes & PREFIX_REPZ) {
5547 2c0262af bellard
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
5548 2c0262af bellard
        } else {
5549 2c0262af bellard
            gen_scas(s, ot);
5550 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
5551 2c0262af bellard
        }
5552 2c0262af bellard
        break;
5553 2c0262af bellard
5554 2c0262af bellard
    case 0xa6: /* cmpsS */
5555 2c0262af bellard
    case 0xa7:
5556 2c0262af bellard
        if ((b & 1) == 0)
5557 2c0262af bellard
            ot = OT_BYTE;
5558 2c0262af bellard
        else
5559 14ce26e7 bellard
            ot = dflag + OT_WORD;
5560 2c0262af bellard
        if (prefixes & PREFIX_REPNZ) {
5561 2c0262af bellard
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
5562 2c0262af bellard
        } else if (prefixes & PREFIX_REPZ) {
5563 2c0262af bellard
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
5564 2c0262af bellard
        } else {
5565 2c0262af bellard
            gen_cmps(s, ot);
5566 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
5567 2c0262af bellard
        }
5568 2c0262af bellard
        break;
5569 2c0262af bellard
    case 0x6c: /* insS */
5570 2c0262af bellard
    case 0x6d:
5571 f115e911 bellard
        if ((b & 1) == 0)
5572 f115e911 bellard
            ot = OT_BYTE;
5573 f115e911 bellard
        else
5574 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5575 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5576 0573fbfc ths
        gen_op_andl_T0_ffff();
5577 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base, 
5578 b8b6a50b bellard
                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
5579 f115e911 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5580 f115e911 bellard
            gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5581 2c0262af bellard
        } else {
5582 f115e911 bellard
            gen_ins(s, ot);
5583 2e70f6ef pbrook
            if (use_icount) {
5584 2e70f6ef pbrook
                gen_jmp(s, s->pc - s->cs_base);
5585 2e70f6ef pbrook
            }
5586 2c0262af bellard
        }
5587 2c0262af bellard
        break;
5588 2c0262af bellard
    case 0x6e: /* outsS */
5589 2c0262af bellard
    case 0x6f:
5590 f115e911 bellard
        if ((b & 1) == 0)
5591 f115e911 bellard
            ot = OT_BYTE;
5592 f115e911 bellard
        else
5593 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5594 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5595 0573fbfc ths
        gen_op_andl_T0_ffff();
5596 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base,
5597 b8b6a50b bellard
                     svm_is_rep(prefixes) | 4);
5598 f115e911 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5599 f115e911 bellard
            gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5600 2c0262af bellard
        } else {
5601 f115e911 bellard
            gen_outs(s, ot);
5602 2e70f6ef pbrook
            if (use_icount) {
5603 2e70f6ef pbrook
                gen_jmp(s, s->pc - s->cs_base);
5604 2e70f6ef pbrook
            }
5605 2c0262af bellard
        }
5606 2c0262af bellard
        break;
5607 2c0262af bellard
5608 2c0262af bellard
        /************************/
5609 2c0262af bellard
        /* port I/O */
5610 0573fbfc ths
5611 2c0262af bellard
    case 0xe4:
5612 2c0262af bellard
    case 0xe5:
5613 f115e911 bellard
        if ((b & 1) == 0)
5614 f115e911 bellard
            ot = OT_BYTE;
5615 f115e911 bellard
        else
5616 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5617 f115e911 bellard
        val = ldub_code(s->pc++);
5618 f115e911 bellard
        gen_op_movl_T0_im(val);
5619 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base,
5620 b8b6a50b bellard
                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
5621 2e70f6ef pbrook
        if (use_icount)
5622 2e70f6ef pbrook
            gen_io_start();
5623 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5624 b6abf97d bellard
        tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2_i32);
5625 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EAX);
5626 2e70f6ef pbrook
        if (use_icount) {
5627 2e70f6ef pbrook
            gen_io_end();
5628 2e70f6ef pbrook
            gen_jmp(s, s->pc - s->cs_base);
5629 2e70f6ef pbrook
        }
5630 2c0262af bellard
        break;
5631 2c0262af bellard
    case 0xe6:
5632 2c0262af bellard
    case 0xe7:
5633 f115e911 bellard
        if ((b & 1) == 0)
5634 f115e911 bellard
            ot = OT_BYTE;
5635 f115e911 bellard
        else
5636 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5637 f115e911 bellard
        val = ldub_code(s->pc++);
5638 f115e911 bellard
        gen_op_movl_T0_im(val);
5639 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base,
5640 b8b6a50b bellard
                     svm_is_rep(prefixes));
5641 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, R_EAX);
5642 b8b6a50b bellard
5643 2e70f6ef pbrook
        if (use_icount)
5644 2e70f6ef pbrook
            gen_io_start();
5645 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5646 b6abf97d bellard
        tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
5647 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5648 b6abf97d bellard
        tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32);
5649 2e70f6ef pbrook
        if (use_icount) {
5650 2e70f6ef pbrook
            gen_io_end();
5651 2e70f6ef pbrook
            gen_jmp(s, s->pc - s->cs_base);
5652 2e70f6ef pbrook
        }
5653 2c0262af bellard
        break;
5654 2c0262af bellard
    case 0xec:
5655 2c0262af bellard
    case 0xed:
5656 f115e911 bellard
        if ((b & 1) == 0)
5657 f115e911 bellard
            ot = OT_BYTE;
5658 f115e911 bellard
        else
5659 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5660 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5661 4f31916f bellard
        gen_op_andl_T0_ffff();
5662 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base,
5663 b8b6a50b bellard
                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
5664 2e70f6ef pbrook
        if (use_icount)
5665 2e70f6ef pbrook
            gen_io_start();
5666 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5667 b6abf97d bellard
        tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2_i32);
5668 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EAX);
5669 2e70f6ef pbrook
        if (use_icount) {
5670 2e70f6ef pbrook
            gen_io_end();
5671 2e70f6ef pbrook
            gen_jmp(s, s->pc - s->cs_base);
5672 2e70f6ef pbrook
        }
5673 2c0262af bellard
        break;
5674 2c0262af bellard
    case 0xee:
5675 2c0262af bellard
    case 0xef:
5676 f115e911 bellard
        if ((b & 1) == 0)
5677 f115e911 bellard
            ot = OT_BYTE;
5678 f115e911 bellard
        else
5679 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5680 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5681 4f31916f bellard
        gen_op_andl_T0_ffff();
5682 b8b6a50b bellard
        gen_check_io(s, ot, pc_start - s->cs_base,
5683 b8b6a50b bellard
                     svm_is_rep(prefixes));
5684 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, R_EAX);
5685 b8b6a50b bellard
5686 2e70f6ef pbrook
        if (use_icount)
5687 2e70f6ef pbrook
            gen_io_start();
5688 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5689 b6abf97d bellard
        tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
5690 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5691 b6abf97d bellard
        tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32);
5692 2e70f6ef pbrook
        if (use_icount) {
5693 2e70f6ef pbrook
            gen_io_end();
5694 2e70f6ef pbrook
            gen_jmp(s, s->pc - s->cs_base);
5695 2e70f6ef pbrook
        }
5696 2c0262af bellard
        break;
5697 2c0262af bellard
5698 2c0262af bellard
        /************************/
5699 2c0262af bellard
        /* control */
5700 2c0262af bellard
    case 0xc2: /* ret im */
5701 61382a50 bellard
        val = ldsw_code(s->pc);
5702 2c0262af bellard
        s->pc += 2;
5703 2c0262af bellard
        gen_pop_T0(s);
5704 8f091a59 bellard
        if (CODE64(s) && s->dflag)
5705 8f091a59 bellard
            s->dflag = 2;
5706 2c0262af bellard
        gen_stack_update(s, val + (2 << s->dflag));
5707 2c0262af bellard
        if (s->dflag == 0)
5708 2c0262af bellard
            gen_op_andl_T0_ffff();
5709 2c0262af bellard
        gen_op_jmp_T0();
5710 2c0262af bellard
        gen_eob(s);
5711 2c0262af bellard
        break;
5712 2c0262af bellard
    case 0xc3: /* ret */
5713 2c0262af bellard
        gen_pop_T0(s);
5714 2c0262af bellard
        gen_pop_update(s);
5715 2c0262af bellard
        if (s->dflag == 0)
5716 2c0262af bellard
            gen_op_andl_T0_ffff();
5717 2c0262af bellard
        gen_op_jmp_T0();
5718 2c0262af bellard
        gen_eob(s);
5719 2c0262af bellard
        break;
5720 2c0262af bellard
    case 0xca: /* lret im */
5721 61382a50 bellard
        val = ldsw_code(s->pc);
5722 2c0262af bellard
        s->pc += 2;
5723 2c0262af bellard
    do_lret:
5724 2c0262af bellard
        if (s->pe && !s->vm86) {
5725 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5726 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5727 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5728 b8b6a50b bellard
            tcg_gen_helper_0_2(helper_lret_protected,
5729 b8b6a50b bellard
                               tcg_const_i32(s->dflag), 
5730 b8b6a50b bellard
                               tcg_const_i32(val));
5731 2c0262af bellard
        } else {
5732 2c0262af bellard
            gen_stack_A0(s);
5733 2c0262af bellard
            /* pop offset */
5734 57fec1fe bellard
            gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
5735 2c0262af bellard
            if (s->dflag == 0)
5736 2c0262af bellard
                gen_op_andl_T0_ffff();
5737 2c0262af bellard
            /* NOTE: keeping EIP updated is not a problem in case of
5738 2c0262af bellard
               exception */
5739 2c0262af bellard
            gen_op_jmp_T0();
5740 2c0262af bellard
            /* pop selector */
5741 2c0262af bellard
            gen_op_addl_A0_im(2 << s->dflag);
5742 57fec1fe bellard
            gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
5743 3bd7da9e bellard
            gen_op_movl_seg_T0_vm(R_CS);
5744 2c0262af bellard
            /* add stack offset */
5745 2c0262af bellard
            gen_stack_update(s, val + (4 << s->dflag));
5746 2c0262af bellard
        }
5747 2c0262af bellard
        gen_eob(s);
5748 2c0262af bellard
        break;
5749 2c0262af bellard
    case 0xcb: /* lret */
5750 2c0262af bellard
        val = 0;
5751 2c0262af bellard
        goto do_lret;
5752 2c0262af bellard
    case 0xcf: /* iret */
5753 872929aa bellard
        gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
5754 2c0262af bellard
        if (!s->pe) {
5755 2c0262af bellard
            /* real mode */
5756 b8b6a50b bellard
            tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag));
5757 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5758 f115e911 bellard
        } else if (s->vm86) {
5759 f115e911 bellard
            if (s->iopl != 3) {
5760 f115e911 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5761 f115e911 bellard
            } else {
5762 b8b6a50b bellard
                tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag));
5763 f115e911 bellard
                s->cc_op = CC_OP_EFLAGS;
5764 f115e911 bellard
            }
5765 2c0262af bellard
        } else {
5766 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5767 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5768 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5769 b8b6a50b bellard
            tcg_gen_helper_0_2(helper_iret_protected,
5770 b8b6a50b bellard
                               tcg_const_i32(s->dflag), 
5771 b8b6a50b bellard
                               tcg_const_i32(s->pc - s->cs_base));
5772 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5773 2c0262af bellard
        }
5774 2c0262af bellard
        gen_eob(s);
5775 2c0262af bellard
        break;
5776 2c0262af bellard
    case 0xe8: /* call im */
5777 2c0262af bellard
        {
5778 14ce26e7 bellard
            if (dflag)
5779 14ce26e7 bellard
                tval = (int32_t)insn_get(s, OT_LONG);
5780 14ce26e7 bellard
            else
5781 14ce26e7 bellard
                tval = (int16_t)insn_get(s, OT_WORD);
5782 2c0262af bellard
            next_eip = s->pc - s->cs_base;
5783 14ce26e7 bellard
            tval += next_eip;
5784 2c0262af bellard
            if (s->dflag == 0)
5785 14ce26e7 bellard
                tval &= 0xffff;
5786 14ce26e7 bellard
            gen_movtl_T0_im(next_eip);
5787 2c0262af bellard
            gen_push_T0(s);
5788 14ce26e7 bellard
            gen_jmp(s, tval);
5789 2c0262af bellard
        }
5790 2c0262af bellard
        break;
5791 2c0262af bellard
    case 0x9a: /* lcall im */
5792 2c0262af bellard
        {
5793 2c0262af bellard
            unsigned int selector, offset;
5794 3b46e624 ths
5795 14ce26e7 bellard
            if (CODE64(s))
5796 14ce26e7 bellard
                goto illegal_op;
5797 2c0262af bellard
            ot = dflag ? OT_LONG : OT_WORD;
5798 2c0262af bellard
            offset = insn_get(s, ot);
5799 2c0262af bellard
            selector = insn_get(s, OT_WORD);
5800 3b46e624 ths
5801 2c0262af bellard
            gen_op_movl_T0_im(selector);
5802 14ce26e7 bellard
            gen_op_movl_T1_imu(offset);
5803 2c0262af bellard
        }
5804 2c0262af bellard
        goto do_lcall;
5805 ecada8a2 bellard
    case 0xe9: /* jmp im */
5806 14ce26e7 bellard
        if (dflag)
5807 14ce26e7 bellard
            tval = (int32_t)insn_get(s, OT_LONG);
5808 14ce26e7 bellard
        else
5809 14ce26e7 bellard
            tval = (int16_t)insn_get(s, OT_WORD);
5810 14ce26e7 bellard
        tval += s->pc - s->cs_base;
5811 2c0262af bellard
        if (s->dflag == 0)
5812 14ce26e7 bellard
            tval &= 0xffff;
5813 14ce26e7 bellard
        gen_jmp(s, tval);
5814 2c0262af bellard
        break;
5815 2c0262af bellard
    case 0xea: /* ljmp im */
5816 2c0262af bellard
        {
5817 2c0262af bellard
            unsigned int selector, offset;
5818 2c0262af bellard
5819 14ce26e7 bellard
            if (CODE64(s))
5820 14ce26e7 bellard
                goto illegal_op;
5821 2c0262af bellard
            ot = dflag ? OT_LONG : OT_WORD;
5822 2c0262af bellard
            offset = insn_get(s, ot);
5823 2c0262af bellard
            selector = insn_get(s, OT_WORD);
5824 3b46e624 ths
5825 2c0262af bellard
            gen_op_movl_T0_im(selector);
5826 14ce26e7 bellard
            gen_op_movl_T1_imu(offset);
5827 2c0262af bellard
        }
5828 2c0262af bellard
        goto do_ljmp;
5829 2c0262af bellard
    case 0xeb: /* jmp Jb */
5830 14ce26e7 bellard
        tval = (int8_t)insn_get(s, OT_BYTE);
5831 14ce26e7 bellard
        tval += s->pc - s->cs_base;
5832 2c0262af bellard
        if (s->dflag == 0)
5833 14ce26e7 bellard
            tval &= 0xffff;
5834 14ce26e7 bellard
        gen_jmp(s, tval);
5835 2c0262af bellard
        break;
5836 2c0262af bellard
    case 0x70 ... 0x7f: /* jcc Jb */
5837 14ce26e7 bellard
        tval = (int8_t)insn_get(s, OT_BYTE);
5838 2c0262af bellard
        goto do_jcc;
5839 2c0262af bellard
    case 0x180 ... 0x18f: /* jcc Jv */
5840 2c0262af bellard
        if (dflag) {
5841 14ce26e7 bellard
            tval = (int32_t)insn_get(s, OT_LONG);
5842 2c0262af bellard
        } else {
5843 5fafdf24 ths
            tval = (int16_t)insn_get(s, OT_WORD);
5844 2c0262af bellard
        }
5845 2c0262af bellard
    do_jcc:
5846 2c0262af bellard
        next_eip = s->pc - s->cs_base;
5847 14ce26e7 bellard
        tval += next_eip;
5848 2c0262af bellard
        if (s->dflag == 0)
5849 14ce26e7 bellard
            tval &= 0xffff;
5850 14ce26e7 bellard
        gen_jcc(s, b, tval, next_eip);
5851 2c0262af bellard
        break;
5852 2c0262af bellard
5853 2c0262af bellard
    case 0x190 ... 0x19f: /* setcc Gv */
5854 61382a50 bellard
        modrm = ldub_code(s->pc++);
5855 2c0262af bellard
        gen_setcc(s, b);
5856 2c0262af bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5857 2c0262af bellard
        break;
5858 2c0262af bellard
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
5859 8e1c85e3 bellard
        {
5860 8e1c85e3 bellard
            int l1;
5861 1e4840bf bellard
            TCGv t0;
5862 1e4840bf bellard
5863 8e1c85e3 bellard
            ot = dflag + OT_WORD;
5864 8e1c85e3 bellard
            modrm = ldub_code(s->pc++);
5865 8e1c85e3 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
5866 8e1c85e3 bellard
            mod = (modrm >> 6) & 3;
5867 1e4840bf bellard
            t0 = tcg_temp_local_new(TCG_TYPE_TL);
5868 8e1c85e3 bellard
            if (mod != 3) {
5869 8e1c85e3 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5870 1e4840bf bellard
                gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
5871 8e1c85e3 bellard
            } else {
5872 8e1c85e3 bellard
                rm = (modrm & 7) | REX_B(s);
5873 1e4840bf bellard
                gen_op_mov_v_reg(ot, t0, rm);
5874 8e1c85e3 bellard
            }
5875 8e1c85e3 bellard
#ifdef TARGET_X86_64
5876 8e1c85e3 bellard
            if (ot == OT_LONG) {
5877 8e1c85e3 bellard
                /* XXX: specific Intel behaviour ? */
5878 8e1c85e3 bellard
                l1 = gen_new_label();
5879 8e1c85e3 bellard
                gen_jcc1(s, s->cc_op, b ^ 1, l1);
5880 1e4840bf bellard
                tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
5881 8e1c85e3 bellard
                gen_set_label(l1);
5882 8e1c85e3 bellard
                tcg_gen_movi_tl(cpu_tmp0, 0);
5883 8e1c85e3 bellard
                tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
5884 8e1c85e3 bellard
            } else
5885 8e1c85e3 bellard
#endif
5886 8e1c85e3 bellard
            {
5887 8e1c85e3 bellard
                l1 = gen_new_label();
5888 8e1c85e3 bellard
                gen_jcc1(s, s->cc_op, b ^ 1, l1);
5889 1e4840bf bellard
                gen_op_mov_reg_v(ot, reg, t0);
5890 8e1c85e3 bellard
                gen_set_label(l1);
5891 8e1c85e3 bellard
            }
5892 1e4840bf bellard
            tcg_temp_free(t0);
5893 2c0262af bellard
        }
5894 2c0262af bellard
        break;
5895 3b46e624 ths
5896 2c0262af bellard
        /************************/
5897 2c0262af bellard
        /* flags */
5898 2c0262af bellard
    case 0x9c: /* pushf */
5899 872929aa bellard
        gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
5900 2c0262af bellard
        if (s->vm86 && s->iopl != 3) {
5901 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5902 2c0262af bellard
        } else {
5903 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5904 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5905 bd7a7b33 bellard
            tcg_gen_helper_1_0(helper_read_eflags, cpu_T[0]);
5906 2c0262af bellard
            gen_push_T0(s);
5907 2c0262af bellard
        }
5908 2c0262af bellard
        break;
5909 2c0262af bellard
    case 0x9d: /* popf */
5910 872929aa bellard
        gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
5911 2c0262af bellard
        if (s->vm86 && s->iopl != 3) {
5912 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5913 2c0262af bellard
        } else {
5914 2c0262af bellard
            gen_pop_T0(s);
5915 2c0262af bellard
            if (s->cpl == 0) {
5916 2c0262af bellard
                if (s->dflag) {
5917 bd7a7b33 bellard
                    tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5918 bd7a7b33 bellard
                                       tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)));
5919 2c0262af bellard
                } else {
5920 bd7a7b33 bellard
                    tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5921 bd7a7b33 bellard
                                       tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff));
5922 2c0262af bellard
                }
5923 2c0262af bellard
            } else {
5924 4136f33c bellard
                if (s->cpl <= s->iopl) {
5925 4136f33c bellard
                    if (s->dflag) {
5926 bd7a7b33 bellard
                        tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5927 bd7a7b33 bellard
                                           tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)));
5928 4136f33c bellard
                    } else {
5929 bd7a7b33 bellard
                        tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5930 bd7a7b33 bellard
                                           tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff));
5931 4136f33c bellard
                    }
5932 2c0262af bellard
                } else {
5933 4136f33c bellard
                    if (s->dflag) {
5934 bd7a7b33 bellard
                        tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5935 bd7a7b33 bellard
                                           tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK)));
5936 4136f33c bellard
                    } else {
5937 bd7a7b33 bellard
                        tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0],
5938 bd7a7b33 bellard
                                           tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff));
5939 4136f33c bellard
                    }
5940 2c0262af bellard
                }
5941 2c0262af bellard
            }
5942 2c0262af bellard
            gen_pop_update(s);
5943 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5944 2c0262af bellard
            /* abort translation because TF flag may change */
5945 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
5946 2c0262af bellard
            gen_eob(s);
5947 2c0262af bellard
        }
5948 2c0262af bellard
        break;
5949 2c0262af bellard
    case 0x9e: /* sahf */
5950 12e26b75 bellard
        if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
5951 14ce26e7 bellard
            goto illegal_op;
5952 57fec1fe bellard
        gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
5953 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5954 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5955 bd7a7b33 bellard
        gen_compute_eflags(cpu_cc_src);
5956 bd7a7b33 bellard
        tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
5957 bd7a7b33 bellard
        tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
5958 bd7a7b33 bellard
        tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
5959 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5960 2c0262af bellard
        break;
5961 2c0262af bellard
    case 0x9f: /* lahf */
5962 12e26b75 bellard
        if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
5963 14ce26e7 bellard
            goto illegal_op;
5964 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5965 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5966 bd7a7b33 bellard
        gen_compute_eflags(cpu_T[0]);
5967 bd7a7b33 bellard
        /* Note: gen_compute_eflags() only gives the condition codes */
5968 bd7a7b33 bellard
        tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02);
5969 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, R_AH);
5970 2c0262af bellard
        break;
5971 2c0262af bellard
    case 0xf5: /* cmc */
5972 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5973 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5974 bd7a7b33 bellard
        gen_compute_eflags(cpu_cc_src);
5975 bd7a7b33 bellard
        tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5976 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5977 2c0262af bellard
        break;
5978 2c0262af bellard
    case 0xf8: /* clc */
5979 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5980 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5981 bd7a7b33 bellard
        gen_compute_eflags(cpu_cc_src);
5982 bd7a7b33 bellard
        tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
5983 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5984 2c0262af bellard
        break;
5985 2c0262af bellard
    case 0xf9: /* stc */
5986 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5987 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5988 bd7a7b33 bellard
        gen_compute_eflags(cpu_cc_src);
5989 bd7a7b33 bellard
        tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
5990 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5991 2c0262af bellard
        break;
5992 2c0262af bellard
    case 0xfc: /* cld */
5993 b6abf97d bellard
        tcg_gen_movi_i32(cpu_tmp2_i32, 1);
5994 b6abf97d bellard
        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
5995 2c0262af bellard
        break;
5996 2c0262af bellard
    case 0xfd: /* std */
5997 b6abf97d bellard
        tcg_gen_movi_i32(cpu_tmp2_i32, -1);
5998 b6abf97d bellard
        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
5999 2c0262af bellard
        break;
6000 2c0262af bellard
6001 2c0262af bellard
        /************************/
6002 2c0262af bellard
        /* bit operations */
6003 2c0262af bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
6004 14ce26e7 bellard
        ot = dflag + OT_WORD;
6005 61382a50 bellard
        modrm = ldub_code(s->pc++);
6006 33698e5f bellard
        op = (modrm >> 3) & 7;
6007 2c0262af bellard
        mod = (modrm >> 6) & 3;
6008 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
6009 2c0262af bellard
        if (mod != 3) {
6010 14ce26e7 bellard
            s->rip_offset = 1;
6011 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6012 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
6013 2c0262af bellard
        } else {
6014 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
6015 2c0262af bellard
        }
6016 2c0262af bellard
        /* load shift */
6017 61382a50 bellard
        val = ldub_code(s->pc++);
6018 2c0262af bellard
        gen_op_movl_T1_im(val);
6019 2c0262af bellard
        if (op < 4)
6020 2c0262af bellard
            goto illegal_op;
6021 2c0262af bellard
        op -= 4;
6022 f484d386 bellard
        goto bt_op;
6023 2c0262af bellard
    case 0x1a3: /* bt Gv, Ev */
6024 2c0262af bellard
        op = 0;
6025 2c0262af bellard
        goto do_btx;
6026 2c0262af bellard
    case 0x1ab: /* bts */
6027 2c0262af bellard
        op = 1;
6028 2c0262af bellard
        goto do_btx;
6029 2c0262af bellard
    case 0x1b3: /* btr */
6030 2c0262af bellard
        op = 2;
6031 2c0262af bellard
        goto do_btx;
6032 2c0262af bellard
    case 0x1bb: /* btc */
6033 2c0262af bellard
        op = 3;
6034 2c0262af bellard
    do_btx:
6035 14ce26e7 bellard
        ot = dflag + OT_WORD;
6036 61382a50 bellard
        modrm = ldub_code(s->pc++);
6037 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
6038 2c0262af bellard
        mod = (modrm >> 6) & 3;
6039 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
6040 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 1, reg);
6041 2c0262af bellard
        if (mod != 3) {
6042 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6043 2c0262af bellard
            /* specific case: we need to add a displacement */
6044 f484d386 bellard
            gen_exts(ot, cpu_T[1]);
6045 f484d386 bellard
            tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6046 f484d386 bellard
            tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6047 f484d386 bellard
            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6048 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
6049 2c0262af bellard
        } else {
6050 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
6051 2c0262af bellard
        }
6052 f484d386 bellard
    bt_op:
6053 f484d386 bellard
        tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6054 f484d386 bellard
        switch(op) {
6055 f484d386 bellard
        case 0:
6056 f484d386 bellard
            tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
6057 f484d386 bellard
            tcg_gen_movi_tl(cpu_cc_dst, 0);
6058 f484d386 bellard
            break;
6059 f484d386 bellard
        case 1:
6060 f484d386 bellard
            tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6061 f484d386 bellard
            tcg_gen_movi_tl(cpu_tmp0, 1);
6062 f484d386 bellard
            tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6063 f484d386 bellard
            tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6064 f484d386 bellard
            break;
6065 f484d386 bellard
        case 2:
6066 f484d386 bellard
            tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6067 f484d386 bellard
            tcg_gen_movi_tl(cpu_tmp0, 1);
6068 f484d386 bellard
            tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6069 f484d386 bellard
            tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6070 f484d386 bellard
            tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6071 f484d386 bellard
            break;
6072 f484d386 bellard
        default:
6073 f484d386 bellard
        case 3:
6074 f484d386 bellard
            tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6075 f484d386 bellard
            tcg_gen_movi_tl(cpu_tmp0, 1);
6076 f484d386 bellard
            tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6077 f484d386 bellard
            tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6078 f484d386 bellard
            break;
6079 f484d386 bellard
        }
6080 2c0262af bellard
        s->cc_op = CC_OP_SARB + ot;
6081 2c0262af bellard
        if (op != 0) {
6082 2c0262af bellard
            if (mod != 3)
6083 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
6084 2c0262af bellard
            else
6085 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
6086 f484d386 bellard
            tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6087 f484d386 bellard
            tcg_gen_movi_tl(cpu_cc_dst, 0);
6088 2c0262af bellard
        }
6089 2c0262af bellard
        break;
6090 2c0262af bellard
    case 0x1bc: /* bsf */
6091 2c0262af bellard
    case 0x1bd: /* bsr */
6092 6191b059 bellard
        {
6093 6191b059 bellard
            int label1;
6094 1e4840bf bellard
            TCGv t0;
6095 1e4840bf bellard
6096 6191b059 bellard
            ot = dflag + OT_WORD;
6097 6191b059 bellard
            modrm = ldub_code(s->pc++);
6098 6191b059 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6099 6191b059 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6100 6191b059 bellard
            gen_extu(ot, cpu_T[0]);
6101 6191b059 bellard
            label1 = gen_new_label();
6102 6191b059 bellard
            tcg_gen_movi_tl(cpu_cc_dst, 0);
6103 1e4840bf bellard
            t0 = tcg_temp_local_new(TCG_TYPE_TL);
6104 1e4840bf bellard
            tcg_gen_mov_tl(t0, cpu_T[0]);
6105 1e4840bf bellard
            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1);
6106 6191b059 bellard
            if (b & 1) {
6107 1e4840bf bellard
                tcg_gen_helper_1_1(helper_bsr, cpu_T[0], t0);
6108 6191b059 bellard
            } else {
6109 1e4840bf bellard
                tcg_gen_helper_1_1(helper_bsf, cpu_T[0], t0);
6110 6191b059 bellard
            }
6111 6191b059 bellard
            gen_op_mov_reg_T0(ot, reg);
6112 6191b059 bellard
            tcg_gen_movi_tl(cpu_cc_dst, 1);
6113 6191b059 bellard
            gen_set_label(label1);
6114 6191b059 bellard
            tcg_gen_discard_tl(cpu_cc_src);
6115 6191b059 bellard
            s->cc_op = CC_OP_LOGICB + ot;
6116 1e4840bf bellard
            tcg_temp_free(t0);
6117 6191b059 bellard
        }
6118 2c0262af bellard
        break;
6119 2c0262af bellard
        /************************/
6120 2c0262af bellard
        /* bcd */
6121 2c0262af bellard
    case 0x27: /* daa */
6122 14ce26e7 bellard
        if (CODE64(s))
6123 14ce26e7 bellard
            goto illegal_op;
6124 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6125 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6126 9d0763c4 bellard
        tcg_gen_helper_0_0(helper_daa);
6127 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
6128 2c0262af bellard
        break;
6129 2c0262af bellard
    case 0x2f: /* das */
6130 14ce26e7 bellard
        if (CODE64(s))
6131 14ce26e7 bellard
            goto illegal_op;
6132 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6133 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6134 9d0763c4 bellard
        tcg_gen_helper_0_0(helper_das);
6135 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
6136 2c0262af bellard
        break;
6137 2c0262af bellard
    case 0x37: /* aaa */
6138 14ce26e7 bellard
        if (CODE64(s))
6139 14ce26e7 bellard
            goto illegal_op;
6140 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6141 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6142 9d0763c4 bellard
        tcg_gen_helper_0_0(helper_aaa);
6143 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
6144 2c0262af bellard
        break;
6145 2c0262af bellard
    case 0x3f: /* aas */
6146 14ce26e7 bellard
        if (CODE64(s))
6147 14ce26e7 bellard
            goto illegal_op;
6148 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6149 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6150 9d0763c4 bellard
        tcg_gen_helper_0_0(helper_aas);
6151 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
6152 2c0262af bellard
        break;
6153 2c0262af bellard
    case 0xd4: /* aam */
6154 14ce26e7 bellard
        if (CODE64(s))
6155 14ce26e7 bellard
            goto illegal_op;
6156 61382a50 bellard
        val = ldub_code(s->pc++);
6157 b6d7c3db ths
        if (val == 0) {
6158 b6d7c3db ths
            gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6159 b6d7c3db ths
        } else {
6160 9d0763c4 bellard
            tcg_gen_helper_0_1(helper_aam, tcg_const_i32(val));
6161 b6d7c3db ths
            s->cc_op = CC_OP_LOGICB;
6162 b6d7c3db ths
        }
6163 2c0262af bellard
        break;
6164 2c0262af bellard
    case 0xd5: /* aad */
6165 14ce26e7 bellard
        if (CODE64(s))
6166 14ce26e7 bellard
            goto illegal_op;
6167 61382a50 bellard
        val = ldub_code(s->pc++);
6168 9d0763c4 bellard
        tcg_gen_helper_0_1(helper_aad, tcg_const_i32(val));
6169 2c0262af bellard
        s->cc_op = CC_OP_LOGICB;
6170 2c0262af bellard
        break;
6171 2c0262af bellard
        /************************/
6172 2c0262af bellard
        /* misc */
6173 2c0262af bellard
    case 0x90: /* nop */
6174 14ce26e7 bellard
        /* XXX: xchg + rex handling */
6175 ab1f142b bellard
        /* XXX: correct lock test for all insn */
6176 ab1f142b bellard
        if (prefixes & PREFIX_LOCK)
6177 ab1f142b bellard
            goto illegal_op;
6178 0573fbfc ths
        if (prefixes & PREFIX_REPZ) {
6179 0573fbfc ths
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
6180 0573fbfc ths
        }
6181 2c0262af bellard
        break;
6182 2c0262af bellard
    case 0x9b: /* fwait */
6183 5fafdf24 ths
        if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6184 7eee2a50 bellard
            (HF_MP_MASK | HF_TS_MASK)) {
6185 7eee2a50 bellard
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6186 2ee73ac3 bellard
        } else {
6187 2ee73ac3 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6188 2ee73ac3 bellard
                gen_op_set_cc_op(s->cc_op);
6189 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
6190 19e6c4b8 bellard
            tcg_gen_helper_0_0(helper_fwait);
6191 7eee2a50 bellard
        }
6192 2c0262af bellard
        break;
6193 2c0262af bellard
    case 0xcc: /* int3 */
6194 2c0262af bellard
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6195 2c0262af bellard
        break;
6196 2c0262af bellard
    case 0xcd: /* int N */
6197 61382a50 bellard
        val = ldub_code(s->pc++);
6198 f115e911 bellard
        if (s->vm86 && s->iopl != 3) {
6199 5fafdf24 ths
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6200 f115e911 bellard
        } else {
6201 f115e911 bellard
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6202 f115e911 bellard
        }
6203 2c0262af bellard
        break;
6204 2c0262af bellard
    case 0xce: /* into */
6205 14ce26e7 bellard
        if (CODE64(s))
6206 14ce26e7 bellard
            goto illegal_op;
6207 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6208 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6209 a8ede8ba bellard
        gen_jmp_im(pc_start - s->cs_base);
6210 07be379f bellard
        tcg_gen_helper_0_1(helper_into, tcg_const_i32(s->pc - pc_start));
6211 2c0262af bellard
        break;
6212 2c0262af bellard
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
6213 872929aa bellard
        gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6214 aba9d61e bellard
#if 1
6215 2c0262af bellard
        gen_debug(s, pc_start - s->cs_base);
6216 aba9d61e bellard
#else
6217 aba9d61e bellard
        /* start debug */
6218 aba9d61e bellard
        tb_flush(cpu_single_env);
6219 aba9d61e bellard
        cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6220 aba9d61e bellard
#endif
6221 2c0262af bellard
        break;
6222 2c0262af bellard
    case 0xfa: /* cli */
6223 2c0262af bellard
        if (!s->vm86) {
6224 2c0262af bellard
            if (s->cpl <= s->iopl) {
6225 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_cli);
6226 2c0262af bellard
            } else {
6227 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6228 2c0262af bellard
            }
6229 2c0262af bellard
        } else {
6230 2c0262af bellard
            if (s->iopl == 3) {
6231 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_cli);
6232 2c0262af bellard
            } else {
6233 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6234 2c0262af bellard
            }
6235 2c0262af bellard
        }
6236 2c0262af bellard
        break;
6237 2c0262af bellard
    case 0xfb: /* sti */
6238 2c0262af bellard
        if (!s->vm86) {
6239 2c0262af bellard
            if (s->cpl <= s->iopl) {
6240 2c0262af bellard
            gen_sti:
6241 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_sti);
6242 2c0262af bellard
                /* interruptions are enabled only the first insn after sti */
6243 a2cc3b24 bellard
                /* If several instructions disable interrupts, only the
6244 a2cc3b24 bellard
                   _first_ does it */
6245 a2cc3b24 bellard
                if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6246 b5b38f61 bellard
                    tcg_gen_helper_0_0(helper_set_inhibit_irq);
6247 2c0262af bellard
                /* give a chance to handle pending irqs */
6248 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
6249 2c0262af bellard
                gen_eob(s);
6250 2c0262af bellard
            } else {
6251 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6252 2c0262af bellard
            }
6253 2c0262af bellard
        } else {
6254 2c0262af bellard
            if (s->iopl == 3) {
6255 2c0262af bellard
                goto gen_sti;
6256 2c0262af bellard
            } else {
6257 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6258 2c0262af bellard
            }
6259 2c0262af bellard
        }
6260 2c0262af bellard
        break;
6261 2c0262af bellard
    case 0x62: /* bound */
6262 14ce26e7 bellard
        if (CODE64(s))
6263 14ce26e7 bellard
            goto illegal_op;
6264 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
6265 61382a50 bellard
        modrm = ldub_code(s->pc++);
6266 2c0262af bellard
        reg = (modrm >> 3) & 7;
6267 2c0262af bellard
        mod = (modrm >> 6) & 3;
6268 2c0262af bellard
        if (mod == 3)
6269 2c0262af bellard
            goto illegal_op;
6270 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, reg);
6271 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6272 14ce26e7 bellard
        gen_jmp_im(pc_start - s->cs_base);
6273 b6abf97d bellard
        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6274 2c0262af bellard
        if (ot == OT_WORD)
6275 b6abf97d bellard
            tcg_gen_helper_0_2(helper_boundw, cpu_A0, cpu_tmp2_i32);
6276 2c0262af bellard
        else
6277 b6abf97d bellard
            tcg_gen_helper_0_2(helper_boundl, cpu_A0, cpu_tmp2_i32);
6278 2c0262af bellard
        break;
6279 2c0262af bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
6280 14ce26e7 bellard
        reg = (b & 7) | REX_B(s);
6281 14ce26e7 bellard
#ifdef TARGET_X86_64
6282 14ce26e7 bellard
        if (dflag == 2) {
6283 57fec1fe bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, reg);
6284 57fec1fe bellard
            tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]);
6285 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, reg);
6286 5fafdf24 ths
        } else
6287 14ce26e7 bellard
        {
6288 ac56dd48 pbrook
            TCGv tmp0;
6289 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, reg);
6290 57fec1fe bellard
            
6291 57fec1fe bellard
            tmp0 = tcg_temp_new(TCG_TYPE_I32);
6292 57fec1fe bellard
            tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]);
6293 57fec1fe bellard
            tcg_gen_bswap_i32(tmp0, tmp0);
6294 57fec1fe bellard
            tcg_gen_extu_i32_i64(cpu_T[0], tmp0);
6295 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
6296 57fec1fe bellard
        }
6297 57fec1fe bellard
#else
6298 57fec1fe bellard
        {
6299 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, reg);
6300 57fec1fe bellard
            tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]);
6301 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
6302 14ce26e7 bellard
        }
6303 57fec1fe bellard
#endif
6304 2c0262af bellard
        break;
6305 2c0262af bellard
    case 0xd6: /* salc */
6306 14ce26e7 bellard
        if (CODE64(s))
6307 14ce26e7 bellard
            goto illegal_op;
6308 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6309 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6310 bd7a7b33 bellard
        gen_compute_eflags_c(cpu_T[0]);
6311 bd7a7b33 bellard
        tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
6312 bd7a7b33 bellard
        gen_op_mov_reg_T0(OT_BYTE, R_EAX);
6313 2c0262af bellard
        break;
6314 2c0262af bellard
    case 0xe0: /* loopnz */
6315 2c0262af bellard
    case 0xe1: /* loopz */
6316 2c0262af bellard
    case 0xe2: /* loop */
6317 2c0262af bellard
    case 0xe3: /* jecxz */
6318 14ce26e7 bellard
        {
6319 6e0d8677 bellard
            int l1, l2, l3;
6320 14ce26e7 bellard
6321 14ce26e7 bellard
            tval = (int8_t)insn_get(s, OT_BYTE);
6322 14ce26e7 bellard
            next_eip = s->pc - s->cs_base;
6323 14ce26e7 bellard
            tval += next_eip;
6324 14ce26e7 bellard
            if (s->dflag == 0)
6325 14ce26e7 bellard
                tval &= 0xffff;
6326 3b46e624 ths
6327 14ce26e7 bellard
            l1 = gen_new_label();
6328 14ce26e7 bellard
            l2 = gen_new_label();
6329 6e0d8677 bellard
            l3 = gen_new_label();
6330 14ce26e7 bellard
            b &= 3;
6331 6e0d8677 bellard
            switch(b) {
6332 6e0d8677 bellard
            case 0: /* loopnz */
6333 6e0d8677 bellard
            case 1: /* loopz */
6334 6e0d8677 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
6335 6e0d8677 bellard
                    gen_op_set_cc_op(s->cc_op);
6336 6e0d8677 bellard
                gen_op_add_reg_im(s->aflag, R_ECX, -1);
6337 6e0d8677 bellard
                gen_op_jz_ecx(s->aflag, l3);
6338 6e0d8677 bellard
                gen_compute_eflags(cpu_tmp0);
6339 6e0d8677 bellard
                tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z);
6340 6e0d8677 bellard
                if (b == 0) {
6341 cb63669a pbrook
                    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
6342 6e0d8677 bellard
                } else {
6343 cb63669a pbrook
                    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, l1);
6344 6e0d8677 bellard
                }
6345 6e0d8677 bellard
                break;
6346 6e0d8677 bellard
            case 2: /* loop */
6347 6e0d8677 bellard
                gen_op_add_reg_im(s->aflag, R_ECX, -1);
6348 6e0d8677 bellard
                gen_op_jnz_ecx(s->aflag, l1);
6349 6e0d8677 bellard
                break;
6350 6e0d8677 bellard
            default:
6351 6e0d8677 bellard
            case 3: /* jcxz */
6352 6e0d8677 bellard
                gen_op_jz_ecx(s->aflag, l1);
6353 6e0d8677 bellard
                break;
6354 14ce26e7 bellard
            }
6355 14ce26e7 bellard
6356 6e0d8677 bellard
            gen_set_label(l3);
6357 14ce26e7 bellard
            gen_jmp_im(next_eip);
6358 8e1c85e3 bellard
            tcg_gen_br(l2);
6359 6e0d8677 bellard
6360 14ce26e7 bellard
            gen_set_label(l1);
6361 14ce26e7 bellard
            gen_jmp_im(tval);
6362 14ce26e7 bellard
            gen_set_label(l2);
6363 14ce26e7 bellard
            gen_eob(s);
6364 14ce26e7 bellard
        }
6365 2c0262af bellard
        break;
6366 2c0262af bellard
    case 0x130: /* wrmsr */
6367 2c0262af bellard
    case 0x132: /* rdmsr */
6368 2c0262af bellard
        if (s->cpl != 0) {
6369 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6370 2c0262af bellard
        } else {
6371 872929aa bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6372 872929aa bellard
                gen_op_set_cc_op(s->cc_op);
6373 872929aa bellard
            gen_jmp_im(pc_start - s->cs_base);
6374 0573fbfc ths
            if (b & 2) {
6375 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_rdmsr);
6376 0573fbfc ths
            } else {
6377 b5b38f61 bellard
                tcg_gen_helper_0_0(helper_wrmsr);
6378 0573fbfc ths
            }
6379 2c0262af bellard
        }
6380 2c0262af bellard
        break;
6381 2c0262af bellard
    case 0x131: /* rdtsc */
6382 872929aa bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6383 872929aa bellard
            gen_op_set_cc_op(s->cc_op);
6384 ecada8a2 bellard
        gen_jmp_im(pc_start - s->cs_base);
6385 efade670 pbrook
        if (use_icount)
6386 efade670 pbrook
            gen_io_start();
6387 b5b38f61 bellard
        tcg_gen_helper_0_0(helper_rdtsc);
6388 efade670 pbrook
        if (use_icount) {
6389 efade670 pbrook
            gen_io_end();
6390 efade670 pbrook
            gen_jmp(s, s->pc - s->cs_base);
6391 efade670 pbrook
        }
6392 2c0262af bellard
        break;
6393 df01e0fc balrog
    case 0x133: /* rdpmc */
6394 872929aa bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6395 872929aa bellard
            gen_op_set_cc_op(s->cc_op);
6396 df01e0fc balrog
        gen_jmp_im(pc_start - s->cs_base);
6397 b5b38f61 bellard
        tcg_gen_helper_0_0(helper_rdpmc);
6398 df01e0fc balrog
        break;
6399 023fe10d bellard
    case 0x134: /* sysenter */
6400 14ce26e7 bellard
        if (CODE64(s))
6401 14ce26e7 bellard
            goto illegal_op;
6402 023fe10d bellard
        if (!s->pe) {
6403 023fe10d bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6404 023fe10d bellard
        } else {
6405 023fe10d bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
6406 023fe10d bellard
                gen_op_set_cc_op(s->cc_op);
6407 023fe10d bellard
                s->cc_op = CC_OP_DYNAMIC;
6408 023fe10d bellard
            }
6409 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
6410 b5b38f61 bellard
            tcg_gen_helper_0_0(helper_sysenter);
6411 023fe10d bellard
            gen_eob(s);
6412 023fe10d bellard
        }
6413 023fe10d bellard
        break;
6414 023fe10d bellard
    case 0x135: /* sysexit */
6415 14ce26e7 bellard
        if (CODE64(s))
6416 14ce26e7 bellard
            goto illegal_op;
6417 023fe10d bellard
        if (!s->pe) {
6418 023fe10d bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6419 023fe10d bellard
        } else {
6420 023fe10d bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
6421 023fe10d bellard
                gen_op_set_cc_op(s->cc_op);
6422 023fe10d bellard
                s->cc_op = CC_OP_DYNAMIC;
6423 023fe10d bellard
            }
6424 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
6425 b5b38f61 bellard
            tcg_gen_helper_0_0(helper_sysexit);
6426 023fe10d bellard
            gen_eob(s);
6427 023fe10d bellard
        }
6428 023fe10d bellard
        break;
6429 14ce26e7 bellard
#ifdef TARGET_X86_64
6430 14ce26e7 bellard
    case 0x105: /* syscall */
6431 14ce26e7 bellard
        /* XXX: is it usable in real mode ? */
6432 14ce26e7 bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
6433 14ce26e7 bellard
            gen_op_set_cc_op(s->cc_op);
6434 14ce26e7 bellard
            s->cc_op = CC_OP_DYNAMIC;
6435 14ce26e7 bellard
        }
6436 14ce26e7 bellard
        gen_jmp_im(pc_start - s->cs_base);
6437 b5b38f61 bellard
        tcg_gen_helper_0_1(helper_syscall, tcg_const_i32(s->pc - pc_start));
6438 14ce26e7 bellard
        gen_eob(s);
6439 14ce26e7 bellard
        break;
6440 14ce26e7 bellard
    case 0x107: /* sysret */
6441 14ce26e7 bellard
        if (!s->pe) {
6442 14ce26e7 bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6443 14ce26e7 bellard
        } else {
6444 14ce26e7 bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
6445 14ce26e7 bellard
                gen_op_set_cc_op(s->cc_op);
6446 14ce26e7 bellard
                s->cc_op = CC_OP_DYNAMIC;
6447 14ce26e7 bellard
            }
6448 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
6449 b5b38f61 bellard
            tcg_gen_helper_0_1(helper_sysret, tcg_const_i32(s->dflag));
6450 aba9d61e bellard
            /* condition codes are modified only in long mode */
6451 aba9d61e bellard
            if (s->lma)
6452 aba9d61e bellard
                s->cc_op = CC_OP_EFLAGS;
6453 14ce26e7 bellard
            gen_eob(s);
6454 14ce26e7 bellard
        }
6455 14ce26e7 bellard
        break;
6456 14ce26e7 bellard
#endif
6457 2c0262af bellard
    case 0x1a2: /* cpuid */
6458 9575cb94 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6459 9575cb94 bellard
            gen_op_set_cc_op(s->cc_op);
6460 9575cb94 bellard
        gen_jmp_im(pc_start - s->cs_base);
6461 b5b38f61 bellard
        tcg_gen_helper_0_0(helper_cpuid);
6462 2c0262af bellard
        break;
6463 2c0262af bellard
    case 0xf4: /* hlt */
6464 2c0262af bellard
        if (s->cpl != 0) {
6465 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6466 2c0262af bellard
        } else {
6467 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6468 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
6469 94451178 bellard
            gen_jmp_im(pc_start - s->cs_base);
6470 94451178 bellard
            tcg_gen_helper_0_1(helper_hlt, tcg_const_i32(s->pc - pc_start));
6471 2c0262af bellard
            s->is_jmp = 3;
6472 2c0262af bellard
        }
6473 2c0262af bellard
        break;
6474 2c0262af bellard
    case 0x100:
6475 61382a50 bellard
        modrm = ldub_code(s->pc++);
6476 2c0262af bellard
        mod = (modrm >> 6) & 3;
6477 2c0262af bellard
        op = (modrm >> 3) & 7;
6478 2c0262af bellard
        switch(op) {
6479 2c0262af bellard
        case 0: /* sldt */
6480 f115e911 bellard
            if (!s->pe || s->vm86)
6481 f115e911 bellard
                goto illegal_op;
6482 872929aa bellard
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
6483 651ba608 bellard
            tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
6484 2c0262af bellard
            ot = OT_WORD;
6485 2c0262af bellard
            if (mod == 3)
6486 2c0262af bellard
                ot += s->dflag;
6487 2c0262af bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
6488 2c0262af bellard
            break;
6489 2c0262af bellard
        case 2: /* lldt */
6490 f115e911 bellard
            if (!s->pe || s->vm86)
6491 f115e911 bellard
                goto illegal_op;
6492 2c0262af bellard
            if (s->cpl != 0) {
6493 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6494 2c0262af bellard
            } else {
6495 872929aa bellard
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
6496 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6497 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
6498 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6499 b6abf97d bellard
                tcg_gen_helper_0_1(helper_lldt, cpu_tmp2_i32);
6500 2c0262af bellard
            }
6501 2c0262af bellard
            break;
6502 2c0262af bellard
        case 1: /* str */
6503 f115e911 bellard
            if (!s->pe || s->vm86)
6504 f115e911 bellard
                goto illegal_op;
6505 872929aa bellard
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
6506 651ba608 bellard
            tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
6507 2c0262af bellard
            ot = OT_WORD;
6508 2c0262af bellard
            if (mod == 3)
6509 2c0262af bellard
                ot += s->dflag;
6510 2c0262af bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
6511 2c0262af bellard
            break;
6512 2c0262af bellard
        case 3: /* ltr */
6513 f115e911 bellard
            if (!s->pe || s->vm86)
6514 f115e911 bellard
                goto illegal_op;
6515 2c0262af bellard
            if (s->cpl != 0) {
6516 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6517 2c0262af bellard
            } else {
6518 872929aa bellard
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
6519 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6520 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
6521 b6abf97d bellard
                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6522 b6abf97d bellard
                tcg_gen_helper_0_1(helper_ltr, cpu_tmp2_i32);
6523 2c0262af bellard
            }
6524 2c0262af bellard
            break;
6525 2c0262af bellard
        case 4: /* verr */
6526 2c0262af bellard
        case 5: /* verw */
6527 f115e911 bellard
            if (!s->pe || s->vm86)
6528 f115e911 bellard
                goto illegal_op;
6529 f115e911 bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6530 f115e911 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6531 f115e911 bellard
                gen_op_set_cc_op(s->cc_op);
6532 f115e911 bellard
            if (op == 4)
6533 cec6843e bellard
                tcg_gen_helper_0_1(helper_verr, cpu_T[0]);
6534 f115e911 bellard
            else
6535 cec6843e bellard
                tcg_gen_helper_0_1(helper_verw, cpu_T[0]);
6536 f115e911 bellard
            s->cc_op = CC_OP_EFLAGS;
6537 f115e911 bellard
            break;
6538 2c0262af bellard
        default:
6539 2c0262af bellard
            goto illegal_op;
6540 2c0262af bellard
        }
6541 2c0262af bellard
        break;
6542 2c0262af bellard
    case 0x101:
6543 61382a50 bellard
        modrm = ldub_code(s->pc++);
6544 2c0262af bellard
        mod = (modrm >> 6) & 3;
6545 2c0262af bellard
        op = (modrm >> 3) & 7;
6546 3d7374c5 bellard
        rm = modrm & 7;
6547 2c0262af bellard
        switch(op) {
6548 2c0262af bellard
        case 0: /* sgdt */
6549 2c0262af bellard
            if (mod == 3)
6550 2c0262af bellard
                goto illegal_op;
6551 872929aa bellard
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
6552 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6553 651ba608 bellard
            tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
6554 57fec1fe bellard
            gen_op_st_T0_A0(OT_WORD + s->mem_index);
6555 aba9d61e bellard
            gen_add_A0_im(s, 2);
6556 651ba608 bellard
            tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
6557 2c0262af bellard
            if (!s->dflag)
6558 2c0262af bellard
                gen_op_andl_T0_im(0xffffff);
6559 57fec1fe bellard
            gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
6560 2c0262af bellard
            break;
6561 3d7374c5 bellard
        case 1:
6562 3d7374c5 bellard
            if (mod == 3) {
6563 3d7374c5 bellard
                switch (rm) {
6564 3d7374c5 bellard
                case 0: /* monitor */
6565 3d7374c5 bellard
                    if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
6566 3d7374c5 bellard
                        s->cpl != 0)
6567 3d7374c5 bellard
                        goto illegal_op;
6568 94451178 bellard
                    if (s->cc_op != CC_OP_DYNAMIC)
6569 94451178 bellard
                        gen_op_set_cc_op(s->cc_op);
6570 3d7374c5 bellard
                    gen_jmp_im(pc_start - s->cs_base);
6571 3d7374c5 bellard
#ifdef TARGET_X86_64
6572 3d7374c5 bellard
                    if (s->aflag == 2) {
6573 bbf662ee bellard
                        gen_op_movq_A0_reg(R_EAX);
6574 5fafdf24 ths
                    } else
6575 3d7374c5 bellard
#endif
6576 3d7374c5 bellard
                    {
6577 bbf662ee bellard
                        gen_op_movl_A0_reg(R_EAX);
6578 3d7374c5 bellard
                        if (s->aflag == 0)
6579 3d7374c5 bellard
                            gen_op_andl_A0_ffff();
6580 3d7374c5 bellard
                    }
6581 3d7374c5 bellard
                    gen_add_A0_ds_seg(s);
6582 b5b38f61 bellard
                    tcg_gen_helper_0_1(helper_monitor, cpu_A0);
6583 3d7374c5 bellard
                    break;
6584 3d7374c5 bellard
                case 1: /* mwait */
6585 3d7374c5 bellard
                    if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
6586 3d7374c5 bellard
                        s->cpl != 0)
6587 3d7374c5 bellard
                        goto illegal_op;
6588 3d7374c5 bellard
                    if (s->cc_op != CC_OP_DYNAMIC) {
6589 3d7374c5 bellard
                        gen_op_set_cc_op(s->cc_op);
6590 3d7374c5 bellard
                        s->cc_op = CC_OP_DYNAMIC;
6591 3d7374c5 bellard
                    }
6592 94451178 bellard
                    gen_jmp_im(pc_start - s->cs_base);
6593 94451178 bellard
                    tcg_gen_helper_0_1(helper_mwait, tcg_const_i32(s->pc - pc_start));
6594 3d7374c5 bellard
                    gen_eob(s);
6595 3d7374c5 bellard
                    break;
6596 3d7374c5 bellard
                default:
6597 3d7374c5 bellard
                    goto illegal_op;
6598 3d7374c5 bellard
                }
6599 3d7374c5 bellard
            } else { /* sidt */
6600 872929aa bellard
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
6601 3d7374c5 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6602 651ba608 bellard
                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
6603 57fec1fe bellard
                gen_op_st_T0_A0(OT_WORD + s->mem_index);
6604 3d7374c5 bellard
                gen_add_A0_im(s, 2);
6605 651ba608 bellard
                tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
6606 3d7374c5 bellard
                if (!s->dflag)
6607 3d7374c5 bellard
                    gen_op_andl_T0_im(0xffffff);
6608 57fec1fe bellard
                gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
6609 3d7374c5 bellard
            }
6610 3d7374c5 bellard
            break;
6611 2c0262af bellard
        case 2: /* lgdt */
6612 2c0262af bellard
        case 3: /* lidt */
6613 0573fbfc ths
            if (mod == 3) {
6614 872929aa bellard
                if (s->cc_op != CC_OP_DYNAMIC)
6615 872929aa bellard
                    gen_op_set_cc_op(s->cc_op);
6616 872929aa bellard
                gen_jmp_im(pc_start - s->cs_base);
6617 0573fbfc ths
                switch(rm) {
6618 0573fbfc ths
                case 0: /* VMRUN */
6619 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK) || !s->pe)
6620 872929aa bellard
                        goto illegal_op;
6621 872929aa bellard
                    if (s->cpl != 0) {
6622 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6623 0573fbfc ths
                        break;
6624 872929aa bellard
                    } else {
6625 db620f46 bellard
                        tcg_gen_helper_0_2(helper_vmrun, 
6626 db620f46 bellard
                                           tcg_const_i32(s->aflag),
6627 db620f46 bellard
                                           tcg_const_i32(s->pc - pc_start));
6628 db620f46 bellard
                        tcg_gen_exit_tb(0);
6629 db620f46 bellard
                        s->is_jmp = 3;
6630 872929aa bellard
                    }
6631 0573fbfc ths
                    break;
6632 0573fbfc ths
                case 1: /* VMMCALL */
6633 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK))
6634 872929aa bellard
                        goto illegal_op;
6635 b5b38f61 bellard
                    tcg_gen_helper_0_0(helper_vmmcall);
6636 0573fbfc ths
                    break;
6637 0573fbfc ths
                case 2: /* VMLOAD */
6638 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK) || !s->pe)
6639 872929aa bellard
                        goto illegal_op;
6640 872929aa bellard
                    if (s->cpl != 0) {
6641 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6642 872929aa bellard
                        break;
6643 872929aa bellard
                    } else {
6644 914178d3 bellard
                        tcg_gen_helper_0_1(helper_vmload,
6645 914178d3 bellard
                                           tcg_const_i32(s->aflag));
6646 872929aa bellard
                    }
6647 0573fbfc ths
                    break;
6648 0573fbfc ths
                case 3: /* VMSAVE */
6649 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK) || !s->pe)
6650 872929aa bellard
                        goto illegal_op;
6651 872929aa bellard
                    if (s->cpl != 0) {
6652 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6653 872929aa bellard
                        break;
6654 872929aa bellard
                    } else {
6655 914178d3 bellard
                        tcg_gen_helper_0_1(helper_vmsave,
6656 914178d3 bellard
                                           tcg_const_i32(s->aflag));
6657 872929aa bellard
                    }
6658 0573fbfc ths
                    break;
6659 0573fbfc ths
                case 4: /* STGI */
6660 872929aa bellard
                    if ((!(s->flags & HF_SVME_MASK) &&
6661 872929aa bellard
                         !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 
6662 872929aa bellard
                        !s->pe)
6663 872929aa bellard
                        goto illegal_op;
6664 872929aa bellard
                    if (s->cpl != 0) {
6665 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6666 872929aa bellard
                        break;
6667 872929aa bellard
                    } else {
6668 872929aa bellard
                        tcg_gen_helper_0_0(helper_stgi);
6669 872929aa bellard
                    }
6670 0573fbfc ths
                    break;
6671 0573fbfc ths
                case 5: /* CLGI */
6672 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK) || !s->pe)
6673 872929aa bellard
                        goto illegal_op;
6674 872929aa bellard
                    if (s->cpl != 0) {
6675 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6676 872929aa bellard
                        break;
6677 872929aa bellard
                    } else {
6678 872929aa bellard
                        tcg_gen_helper_0_0(helper_clgi);
6679 872929aa bellard
                    }
6680 0573fbfc ths
                    break;
6681 0573fbfc ths
                case 6: /* SKINIT */
6682 872929aa bellard
                    if ((!(s->flags & HF_SVME_MASK) && 
6683 872929aa bellard
                         !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 
6684 872929aa bellard
                        !s->pe)
6685 872929aa bellard
                        goto illegal_op;
6686 b5b38f61 bellard
                    tcg_gen_helper_0_0(helper_skinit);
6687 0573fbfc ths
                    break;
6688 0573fbfc ths
                case 7: /* INVLPGA */
6689 872929aa bellard
                    if (!(s->flags & HF_SVME_MASK) || !s->pe)
6690 872929aa bellard
                        goto illegal_op;
6691 872929aa bellard
                    if (s->cpl != 0) {
6692 872929aa bellard
                        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6693 872929aa bellard
                        break;
6694 872929aa bellard
                    } else {
6695 914178d3 bellard
                        tcg_gen_helper_0_1(helper_invlpga,
6696 914178d3 bellard
                                           tcg_const_i32(s->aflag));
6697 872929aa bellard
                    }
6698 0573fbfc ths
                    break;
6699 0573fbfc ths
                default:
6700 0573fbfc ths
                    goto illegal_op;
6701 0573fbfc ths
                }
6702 0573fbfc ths
            } else if (s->cpl != 0) {
6703 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6704 2c0262af bellard
            } else {
6705 872929aa bellard
                gen_svm_check_intercept(s, pc_start,
6706 872929aa bellard
                                        op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
6707 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6708 57fec1fe bellard
                gen_op_ld_T1_A0(OT_WORD + s->mem_index);
6709 aba9d61e bellard
                gen_add_A0_im(s, 2);
6710 57fec1fe bellard
                gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
6711 2c0262af bellard
                if (!s->dflag)
6712 2c0262af bellard
                    gen_op_andl_T0_im(0xffffff);
6713 2c0262af bellard
                if (op == 2) {
6714 651ba608 bellard
                    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
6715 651ba608 bellard
                    tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
6716 2c0262af bellard
                } else {
6717 651ba608 bellard
                    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
6718 651ba608 bellard
                    tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
6719 2c0262af bellard
                }
6720 2c0262af bellard
            }
6721 2c0262af bellard
            break;
6722 2c0262af bellard
        case 4: /* smsw */
6723 872929aa bellard
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
6724 651ba608 bellard
            tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
6725 2c0262af bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
6726 2c0262af bellard
            break;
6727 2c0262af bellard
        case 6: /* lmsw */
6728 2c0262af bellard
            if (s->cpl != 0) {
6729 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6730 2c0262af bellard
            } else {
6731 872929aa bellard
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
6732 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6733 b8b6a50b bellard
                tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]);
6734 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
6735 d71b9a8b bellard
                gen_eob(s);
6736 2c0262af bellard
            }
6737 2c0262af bellard
            break;
6738 2c0262af bellard
        case 7: /* invlpg */
6739 2c0262af bellard
            if (s->cpl != 0) {
6740 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6741 2c0262af bellard
            } else {
6742 14ce26e7 bellard
                if (mod == 3) {
6743 14ce26e7 bellard
#ifdef TARGET_X86_64
6744 3d7374c5 bellard
                    if (CODE64(s) && rm == 0) {
6745 14ce26e7 bellard
                        /* swapgs */
6746 651ba608 bellard
                        tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,segs[R_GS].base));
6747 651ba608 bellard
                        tcg_gen_ld_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,kernelgsbase));
6748 651ba608 bellard
                        tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,segs[R_GS].base));
6749 651ba608 bellard
                        tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,kernelgsbase));
6750 5fafdf24 ths
                    } else
6751 14ce26e7 bellard
#endif
6752 14ce26e7 bellard
                    {
6753 14ce26e7 bellard
                        goto illegal_op;
6754 14ce26e7 bellard
                    }
6755 14ce26e7 bellard
                } else {
6756 9575cb94 bellard
                    if (s->cc_op != CC_OP_DYNAMIC)
6757 9575cb94 bellard
                        gen_op_set_cc_op(s->cc_op);
6758 9575cb94 bellard
                    gen_jmp_im(pc_start - s->cs_base);
6759 14ce26e7 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6760 b5b38f61 bellard
                    tcg_gen_helper_0_1(helper_invlpg, cpu_A0);
6761 14ce26e7 bellard
                    gen_jmp_im(s->pc - s->cs_base);
6762 14ce26e7 bellard
                    gen_eob(s);
6763 14ce26e7 bellard
                }
6764 2c0262af bellard
            }
6765 2c0262af bellard
            break;
6766 2c0262af bellard
        default:
6767 2c0262af bellard
            goto illegal_op;
6768 2c0262af bellard
        }
6769 2c0262af bellard
        break;
6770 3415a4dd bellard
    case 0x108: /* invd */
6771 3415a4dd bellard
    case 0x109: /* wbinvd */
6772 3415a4dd bellard
        if (s->cpl != 0) {
6773 3415a4dd bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6774 3415a4dd bellard
        } else {
6775 872929aa bellard
            gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
6776 3415a4dd bellard
            /* nothing to do */
6777 3415a4dd bellard
        }
6778 3415a4dd bellard
        break;
6779 14ce26e7 bellard
    case 0x63: /* arpl or movslS (x86_64) */
6780 14ce26e7 bellard
#ifdef TARGET_X86_64
6781 14ce26e7 bellard
        if (CODE64(s)) {
6782 14ce26e7 bellard
            int d_ot;
6783 14ce26e7 bellard
            /* d_ot is the size of destination */
6784 14ce26e7 bellard
            d_ot = dflag + OT_WORD;
6785 14ce26e7 bellard
6786 14ce26e7 bellard
            modrm = ldub_code(s->pc++);
6787 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6788 14ce26e7 bellard
            mod = (modrm >> 6) & 3;
6789 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6790 3b46e624 ths
6791 14ce26e7 bellard
            if (mod == 3) {
6792 57fec1fe bellard
                gen_op_mov_TN_reg(OT_LONG, 0, rm);
6793 14ce26e7 bellard
                /* sign extend */
6794 14ce26e7 bellard
                if (d_ot == OT_QUAD)
6795 e108dd01 bellard
                    tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
6796 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
6797 14ce26e7 bellard
            } else {
6798 14ce26e7 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6799 14ce26e7 bellard
                if (d_ot == OT_QUAD) {
6800 57fec1fe bellard
                    gen_op_lds_T0_A0(OT_LONG + s->mem_index);
6801 14ce26e7 bellard
                } else {
6802 57fec1fe bellard
                    gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6803 14ce26e7 bellard
                }
6804 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
6805 14ce26e7 bellard
            }
6806 5fafdf24 ths
        } else
6807 14ce26e7 bellard
#endif
6808 14ce26e7 bellard
        {
6809 3bd7da9e bellard
            int label1;
6810 1e4840bf bellard
            TCGv t0, t1, t2;
6811 1e4840bf bellard
6812 14ce26e7 bellard
            if (!s->pe || s->vm86)
6813 14ce26e7 bellard
                goto illegal_op;
6814 1e4840bf bellard
            t0 = tcg_temp_local_new(TCG_TYPE_TL);
6815 1e4840bf bellard
            t1 = tcg_temp_local_new(TCG_TYPE_TL);
6816 1e4840bf bellard
            t2 = tcg_temp_local_new(TCG_TYPE_TL);
6817 3bd7da9e bellard
            ot = OT_WORD;
6818 14ce26e7 bellard
            modrm = ldub_code(s->pc++);
6819 14ce26e7 bellard
            reg = (modrm >> 3) & 7;
6820 14ce26e7 bellard
            mod = (modrm >> 6) & 3;
6821 14ce26e7 bellard
            rm = modrm & 7;
6822 14ce26e7 bellard
            if (mod != 3) {
6823 14ce26e7 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6824 1e4840bf bellard
                gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
6825 14ce26e7 bellard
            } else {
6826 1e4840bf bellard
                gen_op_mov_v_reg(ot, t0, rm);
6827 14ce26e7 bellard
            }
6828 1e4840bf bellard
            gen_op_mov_v_reg(ot, t1, reg);
6829 1e4840bf bellard
            tcg_gen_andi_tl(cpu_tmp0, t0, 3);
6830 1e4840bf bellard
            tcg_gen_andi_tl(t1, t1, 3);
6831 1e4840bf bellard
            tcg_gen_movi_tl(t2, 0);
6832 3bd7da9e bellard
            label1 = gen_new_label();
6833 1e4840bf bellard
            tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
6834 1e4840bf bellard
            tcg_gen_andi_tl(t0, t0, ~3);
6835 1e4840bf bellard
            tcg_gen_or_tl(t0, t0, t1);
6836 1e4840bf bellard
            tcg_gen_movi_tl(t2, CC_Z);
6837 3bd7da9e bellard
            gen_set_label(label1);
6838 14ce26e7 bellard
            if (mod != 3) {
6839 1e4840bf bellard
                gen_op_st_v(ot + s->mem_index, t0, cpu_A0);
6840 14ce26e7 bellard
            } else {
6841 1e4840bf bellard
                gen_op_mov_reg_v(ot, rm, t0);
6842 14ce26e7 bellard
            }
6843 3bd7da9e bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6844 3bd7da9e bellard
                gen_op_set_cc_op(s->cc_op);
6845 3bd7da9e bellard
            gen_compute_eflags(cpu_cc_src);
6846 3bd7da9e bellard
            tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
6847 1e4840bf bellard
            tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
6848 3bd7da9e bellard
            s->cc_op = CC_OP_EFLAGS;
6849 1e4840bf bellard
            tcg_temp_free(t0);
6850 1e4840bf bellard
            tcg_temp_free(t1);
6851 1e4840bf bellard
            tcg_temp_free(t2);
6852 f115e911 bellard
        }
6853 f115e911 bellard
        break;
6854 2c0262af bellard
    case 0x102: /* lar */
6855 2c0262af bellard
    case 0x103: /* lsl */
6856 cec6843e bellard
        {
6857 cec6843e bellard
            int label1;
6858 1e4840bf bellard
            TCGv t0;
6859 cec6843e bellard
            if (!s->pe || s->vm86)
6860 cec6843e bellard
                goto illegal_op;
6861 cec6843e bellard
            ot = dflag ? OT_LONG : OT_WORD;
6862 cec6843e bellard
            modrm = ldub_code(s->pc++);
6863 cec6843e bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6864 cec6843e bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6865 1e4840bf bellard
            t0 = tcg_temp_local_new(TCG_TYPE_TL);
6866 cec6843e bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6867 cec6843e bellard
                gen_op_set_cc_op(s->cc_op);
6868 cec6843e bellard
            if (b == 0x102)
6869 1e4840bf bellard
                tcg_gen_helper_1_1(helper_lar, t0, cpu_T[0]);
6870 cec6843e bellard
            else
6871 1e4840bf bellard
                tcg_gen_helper_1_1(helper_lsl, t0, cpu_T[0]);
6872 cec6843e bellard
            tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
6873 cec6843e bellard
            label1 = gen_new_label();
6874 cb63669a pbrook
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
6875 1e4840bf bellard
            gen_op_mov_reg_v(ot, reg, t0);
6876 cec6843e bellard
            gen_set_label(label1);
6877 cec6843e bellard
            s->cc_op = CC_OP_EFLAGS;
6878 1e4840bf bellard
            tcg_temp_free(t0);
6879 cec6843e bellard
        }
6880 2c0262af bellard
        break;
6881 2c0262af bellard
    case 0x118:
6882 61382a50 bellard
        modrm = ldub_code(s->pc++);
6883 2c0262af bellard
        mod = (modrm >> 6) & 3;
6884 2c0262af bellard
        op = (modrm >> 3) & 7;
6885 2c0262af bellard
        switch(op) {
6886 2c0262af bellard
        case 0: /* prefetchnta */
6887 2c0262af bellard
        case 1: /* prefetchnt0 */
6888 2c0262af bellard
        case 2: /* prefetchnt0 */
6889 2c0262af bellard
        case 3: /* prefetchnt0 */
6890 2c0262af bellard
            if (mod == 3)
6891 2c0262af bellard
                goto illegal_op;
6892 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6893 2c0262af bellard
            /* nothing more to do */
6894 2c0262af bellard
            break;
6895 e17a36ce bellard
        default: /* nop (multi byte) */
6896 e17a36ce bellard
            gen_nop_modrm(s, modrm);
6897 e17a36ce bellard
            break;
6898 2c0262af bellard
        }
6899 2c0262af bellard
        break;
6900 e17a36ce bellard
    case 0x119 ... 0x11f: /* nop (multi byte) */
6901 e17a36ce bellard
        modrm = ldub_code(s->pc++);
6902 e17a36ce bellard
        gen_nop_modrm(s, modrm);
6903 e17a36ce bellard
        break;
6904 2c0262af bellard
    case 0x120: /* mov reg, crN */
6905 2c0262af bellard
    case 0x122: /* mov crN, reg */
6906 2c0262af bellard
        if (s->cpl != 0) {
6907 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6908 2c0262af bellard
        } else {
6909 61382a50 bellard
            modrm = ldub_code(s->pc++);
6910 2c0262af bellard
            if ((modrm & 0xc0) != 0xc0)
6911 2c0262af bellard
                goto illegal_op;
6912 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6913 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6914 14ce26e7 bellard
            if (CODE64(s))
6915 14ce26e7 bellard
                ot = OT_QUAD;
6916 14ce26e7 bellard
            else
6917 14ce26e7 bellard
                ot = OT_LONG;
6918 2c0262af bellard
            switch(reg) {
6919 2c0262af bellard
            case 0:
6920 2c0262af bellard
            case 2:
6921 2c0262af bellard
            case 3:
6922 2c0262af bellard
            case 4:
6923 9230e66e bellard
            case 8:
6924 872929aa bellard
                if (s->cc_op != CC_OP_DYNAMIC)
6925 872929aa bellard
                    gen_op_set_cc_op(s->cc_op);
6926 872929aa bellard
                gen_jmp_im(pc_start - s->cs_base);
6927 2c0262af bellard
                if (b & 2) {
6928 57fec1fe bellard
                    gen_op_mov_TN_reg(ot, 0, rm);
6929 872929aa bellard
                    tcg_gen_helper_0_2(helper_write_crN, 
6930 b8b6a50b bellard
                                       tcg_const_i32(reg), cpu_T[0]);
6931 14ce26e7 bellard
                    gen_jmp_im(s->pc - s->cs_base);
6932 2c0262af bellard
                    gen_eob(s);
6933 2c0262af bellard
                } else {
6934 872929aa bellard
                    tcg_gen_helper_1_1(helper_read_crN, 
6935 872929aa bellard
                                       cpu_T[0], tcg_const_i32(reg));
6936 57fec1fe bellard
                    gen_op_mov_reg_T0(ot, rm);
6937 2c0262af bellard
                }
6938 2c0262af bellard
                break;
6939 2c0262af bellard
            default:
6940 2c0262af bellard
                goto illegal_op;
6941 2c0262af bellard
            }
6942 2c0262af bellard
        }
6943 2c0262af bellard
        break;
6944 2c0262af bellard
    case 0x121: /* mov reg, drN */
6945 2c0262af bellard
    case 0x123: /* mov drN, reg */
6946 2c0262af bellard
        if (s->cpl != 0) {
6947 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6948 2c0262af bellard
        } else {
6949 61382a50 bellard
            modrm = ldub_code(s->pc++);
6950 2c0262af bellard
            if ((modrm & 0xc0) != 0xc0)
6951 2c0262af bellard
                goto illegal_op;
6952 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6953 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6954 14ce26e7 bellard
            if (CODE64(s))
6955 14ce26e7 bellard
                ot = OT_QUAD;
6956 14ce26e7 bellard
            else
6957 14ce26e7 bellard
                ot = OT_LONG;
6958 2c0262af bellard
            /* XXX: do it dynamically with CR4.DE bit */
6959 14ce26e7 bellard
            if (reg == 4 || reg == 5 || reg >= 8)
6960 2c0262af bellard
                goto illegal_op;
6961 2c0262af bellard
            if (b & 2) {
6962 0573fbfc ths
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
6963 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, rm);
6964 b8b6a50b bellard
                tcg_gen_helper_0_2(helper_movl_drN_T0,
6965 b8b6a50b bellard
                                   tcg_const_i32(reg), cpu_T[0]);
6966 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
6967 2c0262af bellard
                gen_eob(s);
6968 2c0262af bellard
            } else {
6969 0573fbfc ths
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
6970 651ba608 bellard
                tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
6971 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
6972 2c0262af bellard
            }
6973 2c0262af bellard
        }
6974 2c0262af bellard
        break;
6975 2c0262af bellard
    case 0x106: /* clts */
6976 2c0262af bellard
        if (s->cpl != 0) {
6977 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6978 2c0262af bellard
        } else {
6979 0573fbfc ths
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
6980 b8b6a50b bellard
            tcg_gen_helper_0_0(helper_clts);
6981 7eee2a50 bellard
            /* abort block because static cpu state changed */
6982 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
6983 7eee2a50 bellard
            gen_eob(s);
6984 2c0262af bellard
        }
6985 2c0262af bellard
        break;
6986 a35f3ec7 aurel32
    /* MMX/3DNow!/SSE/SSE2/SSE3 support */
6987 664e0f19 bellard
    case 0x1c3: /* MOVNTI reg, mem */
6988 664e0f19 bellard
        if (!(s->cpuid_features & CPUID_SSE2))
6989 14ce26e7 bellard
            goto illegal_op;
6990 664e0f19 bellard
        ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6991 664e0f19 bellard
        modrm = ldub_code(s->pc++);
6992 664e0f19 bellard
        mod = (modrm >> 6) & 3;
6993 664e0f19 bellard
        if (mod == 3)
6994 664e0f19 bellard
            goto illegal_op;
6995 664e0f19 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
6996 664e0f19 bellard
        /* generate a generic store */
6997 664e0f19 bellard
        gen_ldst_modrm(s, modrm, ot, reg, 1);
6998 14ce26e7 bellard
        break;
6999 664e0f19 bellard
    case 0x1ae:
7000 664e0f19 bellard
        modrm = ldub_code(s->pc++);
7001 664e0f19 bellard
        mod = (modrm >> 6) & 3;
7002 664e0f19 bellard
        op = (modrm >> 3) & 7;
7003 664e0f19 bellard
        switch(op) {
7004 664e0f19 bellard
        case 0: /* fxsave */
7005 5fafdf24 ths
            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7006 0fd14b72 bellard
                (s->flags & HF_EM_MASK))
7007 14ce26e7 bellard
                goto illegal_op;
7008 0fd14b72 bellard
            if (s->flags & HF_TS_MASK) {
7009 0fd14b72 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7010 0fd14b72 bellard
                break;
7011 0fd14b72 bellard
            }
7012 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
7013 19e6c4b8 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
7014 19e6c4b8 bellard
                gen_op_set_cc_op(s->cc_op);
7015 19e6c4b8 bellard
            gen_jmp_im(pc_start - s->cs_base);
7016 19e6c4b8 bellard
            tcg_gen_helper_0_2(helper_fxsave, 
7017 19e6c4b8 bellard
                               cpu_A0, tcg_const_i32((s->dflag == 2)));
7018 664e0f19 bellard
            break;
7019 664e0f19 bellard
        case 1: /* fxrstor */
7020 5fafdf24 ths
            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7021 0fd14b72 bellard
                (s->flags & HF_EM_MASK))
7022 14ce26e7 bellard
                goto illegal_op;
7023 0fd14b72 bellard
            if (s->flags & HF_TS_MASK) {
7024 0fd14b72 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7025 0fd14b72 bellard
                break;
7026 0fd14b72 bellard
            }
7027 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
7028 19e6c4b8 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
7029 19e6c4b8 bellard
                gen_op_set_cc_op(s->cc_op);
7030 19e6c4b8 bellard
            gen_jmp_im(pc_start - s->cs_base);
7031 19e6c4b8 bellard
            tcg_gen_helper_0_2(helper_fxrstor,
7032 19e6c4b8 bellard
                               cpu_A0, tcg_const_i32((s->dflag == 2)));
7033 664e0f19 bellard
            break;
7034 664e0f19 bellard
        case 2: /* ldmxcsr */
7035 664e0f19 bellard
        case 3: /* stmxcsr */
7036 664e0f19 bellard
            if (s->flags & HF_TS_MASK) {
7037 664e0f19 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7038 664e0f19 bellard
                break;
7039 14ce26e7 bellard
            }
7040 664e0f19 bellard
            if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7041 664e0f19 bellard
                mod == 3)
7042 14ce26e7 bellard
                goto illegal_op;
7043 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
7044 664e0f19 bellard
            if (op == 2) {
7045 57fec1fe bellard
                gen_op_ld_T0_A0(OT_LONG + s->mem_index);
7046 651ba608 bellard
                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7047 14ce26e7 bellard
            } else {
7048 651ba608 bellard
                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7049 57fec1fe bellard
                gen_op_st_T0_A0(OT_LONG + s->mem_index);
7050 14ce26e7 bellard
            }
7051 664e0f19 bellard
            break;
7052 664e0f19 bellard
        case 5: /* lfence */
7053 664e0f19 bellard
        case 6: /* mfence */
7054 664e0f19 bellard
            if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
7055 664e0f19 bellard
                goto illegal_op;
7056 664e0f19 bellard
            break;
7057 8f091a59 bellard
        case 7: /* sfence / clflush */
7058 8f091a59 bellard
            if ((modrm & 0xc7) == 0xc0) {
7059 8f091a59 bellard
                /* sfence */
7060 a35f3ec7 aurel32
                /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7061 8f091a59 bellard
                if (!(s->cpuid_features & CPUID_SSE))
7062 8f091a59 bellard
                    goto illegal_op;
7063 8f091a59 bellard
            } else {
7064 8f091a59 bellard
                /* clflush */
7065 8f091a59 bellard
                if (!(s->cpuid_features & CPUID_CLFLUSH))
7066 8f091a59 bellard
                    goto illegal_op;
7067 8f091a59 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
7068 8f091a59 bellard
            }
7069 8f091a59 bellard
            break;
7070 664e0f19 bellard
        default:
7071 14ce26e7 bellard
            goto illegal_op;
7072 14ce26e7 bellard
        }
7073 14ce26e7 bellard
        break;
7074 a35f3ec7 aurel32
    case 0x10d: /* 3DNow! prefetch(w) */
7075 8f091a59 bellard
        modrm = ldub_code(s->pc++);
7076 a35f3ec7 aurel32
        mod = (modrm >> 6) & 3;
7077 a35f3ec7 aurel32
        if (mod == 3)
7078 a35f3ec7 aurel32
            goto illegal_op;
7079 8f091a59 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
7080 8f091a59 bellard
        /* ignore for now */
7081 8f091a59 bellard
        break;
7082 3b21e03e bellard
    case 0x1aa: /* rsm */
7083 872929aa bellard
        gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7084 3b21e03e bellard
        if (!(s->flags & HF_SMM_MASK))
7085 3b21e03e bellard
            goto illegal_op;
7086 3b21e03e bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
7087 3b21e03e bellard
            gen_op_set_cc_op(s->cc_op);
7088 3b21e03e bellard
            s->cc_op = CC_OP_DYNAMIC;
7089 3b21e03e bellard
        }
7090 3b21e03e bellard
        gen_jmp_im(s->pc - s->cs_base);
7091 b5b38f61 bellard
        tcg_gen_helper_0_0(helper_rsm);
7092 3b21e03e bellard
        gen_eob(s);
7093 3b21e03e bellard
        break;
7094 a35f3ec7 aurel32
    case 0x10e ... 0x10f:
7095 a35f3ec7 aurel32
        /* 3DNow! instructions, ignore prefixes */
7096 a35f3ec7 aurel32
        s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7097 664e0f19 bellard
    case 0x110 ... 0x117:
7098 664e0f19 bellard
    case 0x128 ... 0x12f:
7099 664e0f19 bellard
    case 0x150 ... 0x177:
7100 664e0f19 bellard
    case 0x17c ... 0x17f:
7101 664e0f19 bellard
    case 0x1c2:
7102 664e0f19 bellard
    case 0x1c4 ... 0x1c6:
7103 664e0f19 bellard
    case 0x1d0 ... 0x1fe:
7104 664e0f19 bellard
        gen_sse(s, b, pc_start, rex_r);
7105 664e0f19 bellard
        break;
7106 2c0262af bellard
    default:
7107 2c0262af bellard
        goto illegal_op;
7108 2c0262af bellard
    }
7109 2c0262af bellard
    /* lock generation */
7110 2c0262af bellard
    if (s->prefix & PREFIX_LOCK)
7111 b8b6a50b bellard
        tcg_gen_helper_0_0(helper_unlock);
7112 2c0262af bellard
    return s->pc;
7113 2c0262af bellard
 illegal_op:
7114 ab1f142b bellard
    if (s->prefix & PREFIX_LOCK)
7115 b8b6a50b bellard
        tcg_gen_helper_0_0(helper_unlock);
7116 2c0262af bellard
    /* XXX: ensure that no lock was generated */
7117 2c0262af bellard
    gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7118 2c0262af bellard
    return s->pc;
7119 2c0262af bellard
}
7120 2c0262af bellard
7121 2c0262af bellard
void optimize_flags_init(void)
7122 2c0262af bellard
{
7123 b6abf97d bellard
#if TCG_TARGET_REG_BITS == 32
7124 b6abf97d bellard
    assert(sizeof(CCTable) == (1 << 3));
7125 b6abf97d bellard
#else
7126 b6abf97d bellard
    assert(sizeof(CCTable) == (1 << 4));
7127 b6abf97d bellard
#endif
7128 57fec1fe bellard
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
7129 b6abf97d bellard
    cpu_cc_op = tcg_global_mem_new(TCG_TYPE_I32,
7130 b6abf97d bellard
                                   TCG_AREG0, offsetof(CPUState, cc_op), "cc_op");
7131 b6abf97d bellard
    cpu_cc_src = tcg_global_mem_new(TCG_TYPE_TL,
7132 b6abf97d bellard
                                    TCG_AREG0, offsetof(CPUState, cc_src), "cc_src");
7133 b6abf97d bellard
    cpu_cc_dst = tcg_global_mem_new(TCG_TYPE_TL,
7134 b6abf97d bellard
                                    TCG_AREG0, offsetof(CPUState, cc_dst), "cc_dst");
7135 1e4840bf bellard
    cpu_cc_tmp = tcg_global_mem_new(TCG_TYPE_TL,
7136 1e4840bf bellard
                                    TCG_AREG0, offsetof(CPUState, cc_tmp), "cc_tmp");
7137 437a88a5 bellard
7138 437a88a5 bellard
    /* register helpers */
7139 437a88a5 bellard
7140 437a88a5 bellard
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
7141 437a88a5 bellard
#include "helper.h"
7142 2c0262af bellard
}
7143 2c0262af bellard
7144 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7145 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
7146 2c0262af bellard
   information for each intermediate instruction. */
7147 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env,
7148 5fafdf24 ths
                                                 TranslationBlock *tb,
7149 2c0262af bellard
                                                 int search_pc)
7150 2c0262af bellard
{
7151 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
7152 14ce26e7 bellard
    target_ulong pc_ptr;
7153 2c0262af bellard
    uint16_t *gen_opc_end;
7154 c068688b j_mayer
    int j, lj, cflags;
7155 c068688b j_mayer
    uint64_t flags;
7156 14ce26e7 bellard
    target_ulong pc_start;
7157 14ce26e7 bellard
    target_ulong cs_base;
7158 2e70f6ef pbrook
    int num_insns;
7159 2e70f6ef pbrook
    int max_insns;
7160 3b46e624 ths
7161 2c0262af bellard
    /* generate intermediate code */
7162 14ce26e7 bellard
    pc_start = tb->pc;
7163 14ce26e7 bellard
    cs_base = tb->cs_base;
7164 2c0262af bellard
    flags = tb->flags;
7165 d720b93d bellard
    cflags = tb->cflags;
7166 3a1d9b8b bellard
7167 4f31916f bellard
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
7168 2c0262af bellard
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7169 2c0262af bellard
    dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7170 2c0262af bellard
    dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7171 2c0262af bellard
    dc->f_st = 0;
7172 2c0262af bellard
    dc->vm86 = (flags >> VM_SHIFT) & 1;
7173 2c0262af bellard
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7174 2c0262af bellard
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
7175 2c0262af bellard
    dc->tf = (flags >> TF_SHIFT) & 1;
7176 34865134 bellard
    dc->singlestep_enabled = env->singlestep_enabled;
7177 2c0262af bellard
    dc->cc_op = CC_OP_DYNAMIC;
7178 2c0262af bellard
    dc->cs_base = cs_base;
7179 2c0262af bellard
    dc->tb = tb;
7180 2c0262af bellard
    dc->popl_esp_hack = 0;
7181 2c0262af bellard
    /* select memory access functions */
7182 2c0262af bellard
    dc->mem_index = 0;
7183 2c0262af bellard
    if (flags & HF_SOFTMMU_MASK) {
7184 2c0262af bellard
        if (dc->cpl == 3)
7185 14ce26e7 bellard
            dc->mem_index = 2 * 4;
7186 2c0262af bellard
        else
7187 14ce26e7 bellard
            dc->mem_index = 1 * 4;
7188 2c0262af bellard
    }
7189 14ce26e7 bellard
    dc->cpuid_features = env->cpuid_features;
7190 3d7374c5 bellard
    dc->cpuid_ext_features = env->cpuid_ext_features;
7191 e771edab aurel32
    dc->cpuid_ext2_features = env->cpuid_ext2_features;
7192 12e26b75 bellard
    dc->cpuid_ext3_features = env->cpuid_ext3_features;
7193 14ce26e7 bellard
#ifdef TARGET_X86_64
7194 14ce26e7 bellard
    dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7195 14ce26e7 bellard
    dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7196 14ce26e7 bellard
#endif
7197 7eee2a50 bellard
    dc->flags = flags;
7198 a2cc3b24 bellard
    dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
7199 a2cc3b24 bellard
                    (flags & HF_INHIBIT_IRQ_MASK)
7200 415fa2ea bellard
#ifndef CONFIG_SOFTMMU
7201 2c0262af bellard
                    || (flags & HF_SOFTMMU_MASK)
7202 2c0262af bellard
#endif
7203 2c0262af bellard
                    );
7204 4f31916f bellard
#if 0
7205 4f31916f bellard
    /* check addseg logic */
7206 dc196a57 bellard
    if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7207 4f31916f bellard
        printf("ERROR addseg\n");
7208 4f31916f bellard
#endif
7209 4f31916f bellard
7210 1e4840bf bellard
    cpu_T[0] = tcg_temp_new(TCG_TYPE_TL);
7211 1e4840bf bellard
    cpu_T[1] = tcg_temp_new(TCG_TYPE_TL);
7212 1e4840bf bellard
    cpu_A0 = tcg_temp_new(TCG_TYPE_TL);
7213 1e4840bf bellard
    cpu_T3 = tcg_temp_new(TCG_TYPE_TL);
7214 1e4840bf bellard
7215 57fec1fe bellard
    cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);
7216 b6abf97d bellard
    cpu_tmp1_i64 = tcg_temp_new(TCG_TYPE_I64);
7217 b6abf97d bellard
    cpu_tmp2_i32 = tcg_temp_new(TCG_TYPE_I32);
7218 b6abf97d bellard
    cpu_tmp3_i32 = tcg_temp_new(TCG_TYPE_I32);
7219 b6abf97d bellard
    cpu_tmp4 = tcg_temp_new(TCG_TYPE_TL);
7220 b6abf97d bellard
    cpu_tmp5 = tcg_temp_new(TCG_TYPE_TL);
7221 b6abf97d bellard
    cpu_tmp6 = tcg_temp_new(TCG_TYPE_TL);
7222 5af45186 bellard
    cpu_ptr0 = tcg_temp_new(TCG_TYPE_PTR);
7223 5af45186 bellard
    cpu_ptr1 = tcg_temp_new(TCG_TYPE_PTR);
7224 57fec1fe bellard
7225 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7226 2c0262af bellard
7227 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
7228 2c0262af bellard
    pc_ptr = pc_start;
7229 2c0262af bellard
    lj = -1;
7230 2e70f6ef pbrook
    num_insns = 0;
7231 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
7232 2e70f6ef pbrook
    if (max_insns == 0)
7233 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
7234 2c0262af bellard
7235 2e70f6ef pbrook
    gen_icount_start();
7236 2c0262af bellard
    for(;;) {
7237 2c0262af bellard
        if (env->nb_breakpoints > 0) {
7238 2c0262af bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
7239 14ce26e7 bellard
                if (env->breakpoints[j] == pc_ptr) {
7240 2c0262af bellard
                    gen_debug(dc, pc_ptr - dc->cs_base);
7241 2c0262af bellard
                    break;
7242 2c0262af bellard
                }
7243 2c0262af bellard
            }
7244 2c0262af bellard
        }
7245 2c0262af bellard
        if (search_pc) {
7246 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
7247 2c0262af bellard
            if (lj < j) {
7248 2c0262af bellard
                lj++;
7249 2c0262af bellard
                while (lj < j)
7250 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
7251 2c0262af bellard
            }
7252 14ce26e7 bellard
            gen_opc_pc[lj] = pc_ptr;
7253 2c0262af bellard
            gen_opc_cc_op[lj] = dc->cc_op;
7254 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
7255 2e70f6ef pbrook
            gen_opc_icount[lj] = num_insns;
7256 2c0262af bellard
        }
7257 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7258 2e70f6ef pbrook
            gen_io_start();
7259 2e70f6ef pbrook
7260 2c0262af bellard
        pc_ptr = disas_insn(dc, pc_ptr);
7261 2e70f6ef pbrook
        num_insns++;
7262 2c0262af bellard
        /* stop translation if indicated */
7263 2c0262af bellard
        if (dc->is_jmp)
7264 2c0262af bellard
            break;
7265 2c0262af bellard
        /* if single step mode, we generate only one instruction and
7266 2c0262af bellard
           generate an exception */
7267 a2cc3b24 bellard
        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
7268 a2cc3b24 bellard
           the flag and abort the translation to give the irqs a
7269 a2cc3b24 bellard
           change to be happen */
7270 5fafdf24 ths
        if (dc->tf || dc->singlestep_enabled ||
7271 2e70f6ef pbrook
            (flags & HF_INHIBIT_IRQ_MASK)) {
7272 14ce26e7 bellard
            gen_jmp_im(pc_ptr - dc->cs_base);
7273 2c0262af bellard
            gen_eob(dc);
7274 2c0262af bellard
            break;
7275 2c0262af bellard
        }
7276 2c0262af bellard
        /* if too long translation, stop generation too */
7277 2c0262af bellard
        if (gen_opc_ptr >= gen_opc_end ||
7278 2e70f6ef pbrook
            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
7279 2e70f6ef pbrook
            num_insns >= max_insns) {
7280 14ce26e7 bellard
            gen_jmp_im(pc_ptr - dc->cs_base);
7281 2c0262af bellard
            gen_eob(dc);
7282 2c0262af bellard
            break;
7283 2c0262af bellard
        }
7284 2c0262af bellard
    }
7285 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO)
7286 2e70f6ef pbrook
        gen_io_end();
7287 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
7288 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
7289 2c0262af bellard
    /* we don't forget to fill the last values */
7290 2c0262af bellard
    if (search_pc) {
7291 2c0262af bellard
        j = gen_opc_ptr - gen_opc_buf;
7292 2c0262af bellard
        lj++;
7293 2c0262af bellard
        while (lj <= j)
7294 2c0262af bellard
            gen_opc_instr_start[lj++] = 0;
7295 2c0262af bellard
    }
7296 3b46e624 ths
7297 2c0262af bellard
#ifdef DEBUG_DISAS
7298 658c8bda bellard
    if (loglevel & CPU_LOG_TB_CPU) {
7299 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
7300 658c8bda bellard
    }
7301 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7302 14ce26e7 bellard
        int disas_flags;
7303 2c0262af bellard
        fprintf(logfile, "----------------\n");
7304 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7305 14ce26e7 bellard
#ifdef TARGET_X86_64
7306 14ce26e7 bellard
        if (dc->code64)
7307 14ce26e7 bellard
            disas_flags = 2;
7308 14ce26e7 bellard
        else
7309 14ce26e7 bellard
#endif
7310 14ce26e7 bellard
            disas_flags = !dc->code32;
7311 14ce26e7 bellard
        target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
7312 2c0262af bellard
        fprintf(logfile, "\n");
7313 2c0262af bellard
    }
7314 2c0262af bellard
#endif
7315 2c0262af bellard
7316 2e70f6ef pbrook
    if (!search_pc) {
7317 2c0262af bellard
        tb->size = pc_ptr - pc_start;
7318 2e70f6ef pbrook
        tb->icount = num_insns;
7319 2e70f6ef pbrook
    }
7320 2c0262af bellard
    return 0;
7321 2c0262af bellard
}
7322 2c0262af bellard
7323 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
7324 2c0262af bellard
{
7325 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
7326 2c0262af bellard
}
7327 2c0262af bellard
7328 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
7329 2c0262af bellard
{
7330 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
7331 2c0262af bellard
}
7332 2c0262af bellard
7333 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
7334 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
7335 d2856f1a aurel32
{
7336 d2856f1a aurel32
    int cc_op;
7337 d2856f1a aurel32
#ifdef DEBUG_DISAS
7338 d2856f1a aurel32
    if (loglevel & CPU_LOG_TB_OP) {
7339 d2856f1a aurel32
        int i;
7340 d2856f1a aurel32
        fprintf(logfile, "RESTORE:\n");
7341 d2856f1a aurel32
        for(i = 0;i <= pc_pos; i++) {
7342 d2856f1a aurel32
            if (gen_opc_instr_start[i]) {
7343 d2856f1a aurel32
                fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
7344 d2856f1a aurel32
            }
7345 d2856f1a aurel32
        }
7346 d2856f1a aurel32
        fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
7347 d2856f1a aurel32
                searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
7348 d2856f1a aurel32
                (uint32_t)tb->cs_base);
7349 d2856f1a aurel32
    }
7350 d2856f1a aurel32
#endif
7351 d2856f1a aurel32
    env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
7352 d2856f1a aurel32
    cc_op = gen_opc_cc_op[pc_pos];
7353 d2856f1a aurel32
    if (cc_op != CC_OP_DYNAMIC)
7354 d2856f1a aurel32
        env->cc_op = cc_op;
7355 d2856f1a aurel32
}