Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 8686c490

History | View | Annotate | Download (208.5 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 ac56dd48 pbrook
static TCGv cpu_env, cpu_T[2], cpu_A0;
62 57fec1fe bellard
/* local register indexes (only used inside old micro ops) */
63 8686c490 bellard
static TCGv cpu_tmp0, cpu_tmp1;
64 57fec1fe bellard
65 57fec1fe bellard
#ifdef TARGET_X86_64
66 57fec1fe bellard
static int x86_64_hregs;
67 ae063a68 bellard
#endif
68 ae063a68 bellard
69 2c0262af bellard
typedef struct DisasContext {
70 2c0262af bellard
    /* current insn context */
71 2c0262af bellard
    int override; /* -1 if no override */
72 2c0262af bellard
    int prefix;
73 2c0262af bellard
    int aflag, dflag;
74 14ce26e7 bellard
    target_ulong pc; /* pc = eip + cs_base */
75 2c0262af bellard
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
76 2c0262af bellard
                   static state change (stop translation) */
77 2c0262af bellard
    /* current block context */
78 14ce26e7 bellard
    target_ulong cs_base; /* base of CS segment */
79 2c0262af bellard
    int pe;     /* protected mode */
80 2c0262af bellard
    int code32; /* 32 bit code segment */
81 14ce26e7 bellard
#ifdef TARGET_X86_64
82 14ce26e7 bellard
    int lma;    /* long mode active */
83 14ce26e7 bellard
    int code64; /* 64 bit code segment */
84 14ce26e7 bellard
    int rex_x, rex_b;
85 14ce26e7 bellard
#endif
86 2c0262af bellard
    int ss32;   /* 32 bit stack segment */
87 2c0262af bellard
    int cc_op;  /* current CC operation */
88 2c0262af bellard
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
89 2c0262af bellard
    int f_st;   /* currently unused */
90 2c0262af bellard
    int vm86;   /* vm86 mode */
91 2c0262af bellard
    int cpl;
92 2c0262af bellard
    int iopl;
93 2c0262af bellard
    int tf;     /* TF cpu flag */
94 34865134 bellard
    int singlestep_enabled; /* "hardware" single step enabled */
95 2c0262af bellard
    int jmp_opt; /* use direct block chaining for direct jumps */
96 2c0262af bellard
    int mem_index; /* select memory access functions */
97 c068688b j_mayer
    uint64_t flags; /* all execution flags */
98 2c0262af bellard
    struct TranslationBlock *tb;
99 2c0262af bellard
    int popl_esp_hack; /* for correct popl with esp base handling */
100 14ce26e7 bellard
    int rip_offset; /* only used in x86_64, but left for simplicity */
101 14ce26e7 bellard
    int cpuid_features;
102 3d7374c5 bellard
    int cpuid_ext_features;
103 e771edab aurel32
    int cpuid_ext2_features;
104 2c0262af bellard
} DisasContext;
105 2c0262af bellard
106 2c0262af bellard
static void gen_eob(DisasContext *s);
107 14ce26e7 bellard
static void gen_jmp(DisasContext *s, target_ulong eip);
108 14ce26e7 bellard
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
109 2c0262af bellard
110 2c0262af bellard
/* i386 arith/logic operations */
111 2c0262af bellard
enum {
112 5fafdf24 ths
    OP_ADDL,
113 5fafdf24 ths
    OP_ORL,
114 5fafdf24 ths
    OP_ADCL,
115 2c0262af bellard
    OP_SBBL,
116 5fafdf24 ths
    OP_ANDL,
117 5fafdf24 ths
    OP_SUBL,
118 5fafdf24 ths
    OP_XORL,
119 2c0262af bellard
    OP_CMPL,
120 2c0262af bellard
};
121 2c0262af bellard
122 2c0262af bellard
/* i386 shift ops */
123 2c0262af bellard
enum {
124 5fafdf24 ths
    OP_ROL,
125 5fafdf24 ths
    OP_ROR,
126 5fafdf24 ths
    OP_RCL,
127 5fafdf24 ths
    OP_RCR,
128 5fafdf24 ths
    OP_SHL,
129 5fafdf24 ths
    OP_SHR,
130 2c0262af bellard
    OP_SHL1, /* undocumented */
131 2c0262af bellard
    OP_SAR = 7,
132 2c0262af bellard
};
133 2c0262af bellard
134 2c0262af bellard
/* operand size */
135 2c0262af bellard
enum {
136 2c0262af bellard
    OT_BYTE = 0,
137 2c0262af bellard
    OT_WORD,
138 5fafdf24 ths
    OT_LONG,
139 2c0262af bellard
    OT_QUAD,
140 2c0262af bellard
};
141 2c0262af bellard
142 2c0262af bellard
enum {
143 2c0262af bellard
    /* I386 int registers */
144 2c0262af bellard
    OR_EAX,   /* MUST be even numbered */
145 2c0262af bellard
    OR_ECX,
146 2c0262af bellard
    OR_EDX,
147 2c0262af bellard
    OR_EBX,
148 2c0262af bellard
    OR_ESP,
149 2c0262af bellard
    OR_EBP,
150 2c0262af bellard
    OR_ESI,
151 2c0262af bellard
    OR_EDI,
152 14ce26e7 bellard
153 14ce26e7 bellard
    OR_TMP0 = 16,    /* temporary operand register */
154 2c0262af bellard
    OR_TMP1,
155 2c0262af bellard
    OR_A0, /* temporary register used when doing address evaluation */
156 2c0262af bellard
};
157 2c0262af bellard
158 57fec1fe bellard
static inline void gen_op_movl_T0_0(void)
159 57fec1fe bellard
{
160 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[0], 0);
161 57fec1fe bellard
}
162 57fec1fe bellard
163 57fec1fe bellard
static inline void gen_op_movl_T0_im(int32_t val)
164 57fec1fe bellard
{
165 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[0], val);
166 57fec1fe bellard
}
167 57fec1fe bellard
168 57fec1fe bellard
static inline void gen_op_movl_T0_imu(uint32_t val)
169 57fec1fe bellard
{
170 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[0], val);
171 57fec1fe bellard
}
172 57fec1fe bellard
173 57fec1fe bellard
static inline void gen_op_movl_T1_im(int32_t val)
174 57fec1fe bellard
{
175 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[1], val);
176 57fec1fe bellard
}
177 57fec1fe bellard
178 57fec1fe bellard
static inline void gen_op_movl_T1_imu(uint32_t val)
179 57fec1fe bellard
{
180 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[1], val);
181 57fec1fe bellard
}
182 57fec1fe bellard
183 57fec1fe bellard
static inline void gen_op_movl_A0_im(uint32_t val)
184 57fec1fe bellard
{
185 57fec1fe bellard
    tcg_gen_movi_tl(cpu_A0, val);
186 57fec1fe bellard
}
187 57fec1fe bellard
188 57fec1fe bellard
#ifdef TARGET_X86_64
189 57fec1fe bellard
static inline void gen_op_movq_A0_im(int64_t val)
190 57fec1fe bellard
{
191 57fec1fe bellard
    tcg_gen_movi_tl(cpu_A0, val);
192 57fec1fe bellard
}
193 57fec1fe bellard
#endif
194 57fec1fe bellard
195 57fec1fe bellard
static inline void gen_movtl_T0_im(target_ulong val)
196 57fec1fe bellard
{
197 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[0], val);
198 57fec1fe bellard
}
199 57fec1fe bellard
200 57fec1fe bellard
static inline void gen_movtl_T1_im(target_ulong val)
201 57fec1fe bellard
{
202 57fec1fe bellard
    tcg_gen_movi_tl(cpu_T[1], val);
203 57fec1fe bellard
}
204 57fec1fe bellard
205 57fec1fe bellard
static inline void gen_op_andl_T0_ffff(void)
206 57fec1fe bellard
{
207 57fec1fe bellard
    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
208 57fec1fe bellard
}
209 57fec1fe bellard
210 57fec1fe bellard
static inline void gen_op_andl_T0_im(uint32_t val)
211 57fec1fe bellard
{
212 57fec1fe bellard
    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
213 57fec1fe bellard
}
214 57fec1fe bellard
215 57fec1fe bellard
static inline void gen_op_movl_T0_T1(void)
216 57fec1fe bellard
{
217 57fec1fe bellard
    tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
218 57fec1fe bellard
}
219 57fec1fe bellard
220 57fec1fe bellard
static inline void gen_op_andl_A0_ffff(void)
221 57fec1fe bellard
{
222 57fec1fe bellard
    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
223 57fec1fe bellard
}
224 57fec1fe bellard
225 14ce26e7 bellard
#ifdef TARGET_X86_64
226 14ce26e7 bellard
227 14ce26e7 bellard
#define NB_OP_SIZES 4
228 14ce26e7 bellard
229 14ce26e7 bellard
#define DEF_REGS(prefix, suffix) \
230 14ce26e7 bellard
  prefix ## EAX ## suffix,\
231 14ce26e7 bellard
  prefix ## ECX ## suffix,\
232 14ce26e7 bellard
  prefix ## EDX ## suffix,\
233 14ce26e7 bellard
  prefix ## EBX ## suffix,\
234 14ce26e7 bellard
  prefix ## ESP ## suffix,\
235 14ce26e7 bellard
  prefix ## EBP ## suffix,\
236 14ce26e7 bellard
  prefix ## ESI ## suffix,\
237 14ce26e7 bellard
  prefix ## EDI ## suffix,\
238 14ce26e7 bellard
  prefix ## R8 ## suffix,\
239 14ce26e7 bellard
  prefix ## R9 ## suffix,\
240 14ce26e7 bellard
  prefix ## R10 ## suffix,\
241 14ce26e7 bellard
  prefix ## R11 ## suffix,\
242 14ce26e7 bellard
  prefix ## R12 ## suffix,\
243 14ce26e7 bellard
  prefix ## R13 ## suffix,\
244 14ce26e7 bellard
  prefix ## R14 ## suffix,\
245 14ce26e7 bellard
  prefix ## R15 ## suffix,
246 14ce26e7 bellard
247 14ce26e7 bellard
#else /* !TARGET_X86_64 */
248 14ce26e7 bellard
249 14ce26e7 bellard
#define NB_OP_SIZES 3
250 14ce26e7 bellard
251 14ce26e7 bellard
#define DEF_REGS(prefix, suffix) \
252 14ce26e7 bellard
  prefix ## EAX ## suffix,\
253 14ce26e7 bellard
  prefix ## ECX ## suffix,\
254 14ce26e7 bellard
  prefix ## EDX ## suffix,\
255 14ce26e7 bellard
  prefix ## EBX ## suffix,\
256 14ce26e7 bellard
  prefix ## ESP ## suffix,\
257 14ce26e7 bellard
  prefix ## EBP ## suffix,\
258 14ce26e7 bellard
  prefix ## ESI ## suffix,\
259 14ce26e7 bellard
  prefix ## EDI ## suffix,
260 14ce26e7 bellard
261 14ce26e7 bellard
#endif /* !TARGET_X86_64 */
262 14ce26e7 bellard
263 57fec1fe bellard
#if defined(WORDS_BIGENDIAN)
264 57fec1fe bellard
#define REG_B_OFFSET (sizeof(target_ulong) - 1)
265 57fec1fe bellard
#define REG_H_OFFSET (sizeof(target_ulong) - 2)
266 57fec1fe bellard
#define REG_W_OFFSET (sizeof(target_ulong) - 2)
267 57fec1fe bellard
#define REG_L_OFFSET (sizeof(target_ulong) - 4)
268 57fec1fe bellard
#define REG_LH_OFFSET (sizeof(target_ulong) - 8)
269 14ce26e7 bellard
#else
270 57fec1fe bellard
#define REG_B_OFFSET 0
271 57fec1fe bellard
#define REG_H_OFFSET 1
272 57fec1fe bellard
#define REG_W_OFFSET 0
273 57fec1fe bellard
#define REG_L_OFFSET 0
274 57fec1fe bellard
#define REG_LH_OFFSET 4
275 14ce26e7 bellard
#endif
276 57fec1fe bellard
277 57fec1fe bellard
static inline void gen_op_mov_reg_TN(int ot, int t_index, int reg)
278 57fec1fe bellard
{
279 57fec1fe bellard
    switch(ot) {
280 57fec1fe bellard
    case OT_BYTE:
281 57fec1fe bellard
        if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
282 57fec1fe bellard
            tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET);
283 57fec1fe bellard
        } else {
284 57fec1fe bellard
            tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);
285 57fec1fe bellard
        }
286 57fec1fe bellard
        break;
287 57fec1fe bellard
    case OT_WORD:
288 57fec1fe bellard
        tcg_gen_st16_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
289 57fec1fe bellard
        break;
290 14ce26e7 bellard
#ifdef TARGET_X86_64
291 57fec1fe bellard
    case OT_LONG:
292 57fec1fe bellard
        tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
293 57fec1fe bellard
        /* high part of register set to zero */
294 57fec1fe bellard
        tcg_gen_movi_tl(cpu_tmp0, 0);
295 57fec1fe bellard
        tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
296 57fec1fe bellard
        break;
297 57fec1fe bellard
    default:
298 57fec1fe bellard
    case OT_QUAD:
299 57fec1fe bellard
        tcg_gen_st_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]));
300 57fec1fe bellard
        break;
301 57fec1fe bellard
#else
302 57fec1fe bellard
    default:
303 57fec1fe bellard
    case OT_LONG:
304 57fec1fe bellard
        tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
305 57fec1fe bellard
        break;
306 14ce26e7 bellard
#endif
307 57fec1fe bellard
    }
308 57fec1fe bellard
}
309 2c0262af bellard
310 57fec1fe bellard
static inline void gen_op_mov_reg_T0(int ot, int reg)
311 57fec1fe bellard
{
312 57fec1fe bellard
    gen_op_mov_reg_TN(ot, 0, reg);
313 57fec1fe bellard
}
314 57fec1fe bellard
315 57fec1fe bellard
static inline void gen_op_mov_reg_T1(int ot, int reg)
316 57fec1fe bellard
{
317 57fec1fe bellard
    gen_op_mov_reg_TN(ot, 1, reg);
318 57fec1fe bellard
}
319 57fec1fe bellard
320 57fec1fe bellard
static inline void gen_op_mov_reg_A0(int size, int reg)
321 57fec1fe bellard
{
322 57fec1fe bellard
    switch(size) {
323 57fec1fe bellard
    case 0:
324 57fec1fe bellard
        tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
325 57fec1fe bellard
        break;
326 14ce26e7 bellard
#ifdef TARGET_X86_64
327 57fec1fe bellard
    case 1:
328 57fec1fe bellard
        tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
329 57fec1fe bellard
        /* high part of register set to zero */
330 57fec1fe bellard
        tcg_gen_movi_tl(cpu_tmp0, 0);
331 57fec1fe bellard
        tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);
332 57fec1fe bellard
        break;
333 57fec1fe bellard
    default:
334 57fec1fe bellard
    case 2:
335 57fec1fe bellard
        tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));
336 57fec1fe bellard
        break;
337 14ce26e7 bellard
#else
338 57fec1fe bellard
    default:
339 57fec1fe bellard
    case 1:
340 57fec1fe bellard
        tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
341 57fec1fe bellard
        break;
342 14ce26e7 bellard
#endif
343 57fec1fe bellard
    }
344 57fec1fe bellard
}
345 57fec1fe bellard
346 57fec1fe bellard
static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
347 57fec1fe bellard
{
348 57fec1fe bellard
    switch(ot) {
349 57fec1fe bellard
    case OT_BYTE:
350 57fec1fe bellard
        if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
351 57fec1fe bellard
            goto std_case;
352 57fec1fe bellard
        } else {
353 57fec1fe bellard
            tcg_gen_ld8u_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);
354 57fec1fe bellard
        }
355 57fec1fe bellard
        break;
356 57fec1fe bellard
    default:
357 57fec1fe bellard
    std_case:
358 57fec1fe bellard
        tcg_gen_ld_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]));
359 57fec1fe bellard
        break;
360 57fec1fe bellard
    }
361 57fec1fe bellard
}
362 57fec1fe bellard
363 57fec1fe bellard
static inline void gen_op_movl_A0_reg(int reg)
364 57fec1fe bellard
{
365 57fec1fe bellard
    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);
366 57fec1fe bellard
}
367 57fec1fe bellard
368 57fec1fe bellard
static inline void gen_op_addl_A0_im(int32_t val)
369 57fec1fe bellard
{
370 57fec1fe bellard
    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
371 14ce26e7 bellard
#ifdef TARGET_X86_64
372 57fec1fe bellard
    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
373 14ce26e7 bellard
#endif
374 57fec1fe bellard
}
375 2c0262af bellard
376 14ce26e7 bellard
#ifdef TARGET_X86_64
377 57fec1fe bellard
static inline void gen_op_addq_A0_im(int64_t val)
378 57fec1fe bellard
{
379 57fec1fe bellard
    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
380 57fec1fe bellard
}
381 14ce26e7 bellard
#endif
382 57fec1fe bellard
    
383 57fec1fe bellard
static void gen_add_A0_im(DisasContext *s, int val)
384 57fec1fe bellard
{
385 57fec1fe bellard
#ifdef TARGET_X86_64
386 57fec1fe bellard
    if (CODE64(s))
387 57fec1fe bellard
        gen_op_addq_A0_im(val);
388 57fec1fe bellard
    else
389 57fec1fe bellard
#endif
390 57fec1fe bellard
        gen_op_addl_A0_im(val);
391 57fec1fe bellard
}
392 2c0262af bellard
393 57fec1fe bellard
static inline void gen_op_addl_T0_T1(void)
394 2c0262af bellard
{
395 57fec1fe bellard
    tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
396 57fec1fe bellard
}
397 57fec1fe bellard
398 57fec1fe bellard
static inline void gen_op_jmp_T0(void)
399 57fec1fe bellard
{
400 57fec1fe bellard
    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));
401 57fec1fe bellard
}
402 57fec1fe bellard
403 57fec1fe bellard
static inline void gen_op_addw_ESP_im(int32_t val)
404 57fec1fe bellard
{
405 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
406 57fec1fe bellard
    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
407 57fec1fe bellard
    tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]) + REG_W_OFFSET);
408 57fec1fe bellard
}
409 57fec1fe bellard
410 57fec1fe bellard
static inline void gen_op_addl_ESP_im(int32_t val)
411 57fec1fe bellard
{
412 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
413 57fec1fe bellard
    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
414 14ce26e7 bellard
#ifdef TARGET_X86_64
415 57fec1fe bellard
    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
416 14ce26e7 bellard
#endif
417 57fec1fe bellard
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
418 57fec1fe bellard
}
419 57fec1fe bellard
420 14ce26e7 bellard
#ifdef TARGET_X86_64
421 57fec1fe bellard
static inline void gen_op_addq_ESP_im(int32_t val)
422 57fec1fe bellard
{
423 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
424 57fec1fe bellard
    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
425 57fec1fe bellard
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
426 57fec1fe bellard
}
427 14ce26e7 bellard
#endif
428 57fec1fe bellard
429 57fec1fe bellard
static inline void gen_op_set_cc_op(int32_t val)
430 57fec1fe bellard
{
431 57fec1fe bellard
    tcg_gen_movi_tl(cpu_tmp0, val);
432 57fec1fe bellard
    tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, cc_op));
433 57fec1fe bellard
}
434 57fec1fe bellard
435 57fec1fe bellard
static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
436 57fec1fe bellard
{
437 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
438 57fec1fe bellard
    if (shift != 0) 
439 57fec1fe bellard
        tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
440 57fec1fe bellard
    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
441 14ce26e7 bellard
#ifdef TARGET_X86_64
442 57fec1fe bellard
    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
443 14ce26e7 bellard
#endif
444 57fec1fe bellard
}
445 2c0262af bellard
446 57fec1fe bellard
static inline void gen_op_movl_A0_seg(int reg)
447 57fec1fe bellard
{
448 57fec1fe bellard
    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET);
449 57fec1fe bellard
}
450 2c0262af bellard
451 57fec1fe bellard
static inline void gen_op_addl_A0_seg(int reg)
452 57fec1fe bellard
{
453 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
454 57fec1fe bellard
    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
455 57fec1fe bellard
#ifdef TARGET_X86_64
456 57fec1fe bellard
    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
457 57fec1fe bellard
#endif
458 57fec1fe bellard
}
459 2c0262af bellard
460 14ce26e7 bellard
#ifdef TARGET_X86_64
461 57fec1fe bellard
static inline void gen_op_movq_A0_seg(int reg)
462 57fec1fe bellard
{
463 57fec1fe bellard
    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base));
464 57fec1fe bellard
}
465 14ce26e7 bellard
466 57fec1fe bellard
static inline void gen_op_addq_A0_seg(int reg)
467 57fec1fe bellard
{
468 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
469 57fec1fe bellard
    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
470 57fec1fe bellard
}
471 57fec1fe bellard
472 57fec1fe bellard
static inline void gen_op_movq_A0_reg(int reg)
473 57fec1fe bellard
{
474 57fec1fe bellard
    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));
475 57fec1fe bellard
}
476 57fec1fe bellard
477 57fec1fe bellard
static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
478 57fec1fe bellard
{
479 57fec1fe bellard
    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
480 57fec1fe bellard
    if (shift != 0) 
481 57fec1fe bellard
        tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
482 57fec1fe bellard
    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
483 57fec1fe bellard
}
484 14ce26e7 bellard
#endif
485 14ce26e7 bellard
486 14ce26e7 bellard
static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
487 14ce26e7 bellard
    [0] = {
488 14ce26e7 bellard
        DEF_REGS(gen_op_cmovw_, _T1_T0)
489 14ce26e7 bellard
    },
490 14ce26e7 bellard
    [1] = {
491 14ce26e7 bellard
        DEF_REGS(gen_op_cmovl_, _T1_T0)
492 14ce26e7 bellard
    },
493 14ce26e7 bellard
#ifdef TARGET_X86_64
494 14ce26e7 bellard
    [2] = {
495 14ce26e7 bellard
        DEF_REGS(gen_op_cmovq_, _T1_T0)
496 14ce26e7 bellard
    },
497 14ce26e7 bellard
#endif
498 14ce26e7 bellard
};
499 2c0262af bellard
500 4f31916f bellard
#define DEF_ARITHC(SUFFIX)\
501 4f31916f bellard
    {\
502 4f31916f bellard
        gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
503 4f31916f bellard
        gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
504 4f31916f bellard
    },\
505 4f31916f bellard
    {\
506 4f31916f bellard
        gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
507 4f31916f bellard
        gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
508 4f31916f bellard
    },\
509 4f31916f bellard
    {\
510 4f31916f bellard
        gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
511 4f31916f bellard
        gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
512 14ce26e7 bellard
    },\
513 14ce26e7 bellard
    {\
514 14ce26e7 bellard
        X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
515 14ce26e7 bellard
        X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
516 2c0262af bellard
    },
517 4f31916f bellard
518 14ce26e7 bellard
static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
519 4bb2fcc7 bellard
    DEF_ARITHC( )
520 2c0262af bellard
};
521 2c0262af bellard
522 14ce26e7 bellard
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
523 4f31916f bellard
    DEF_ARITHC(_raw)
524 4f31916f bellard
#ifndef CONFIG_USER_ONLY
525 4f31916f bellard
    DEF_ARITHC(_kernel)
526 4f31916f bellard
    DEF_ARITHC(_user)
527 4f31916f bellard
#endif
528 2c0262af bellard
};
529 2c0262af bellard
530 2c0262af bellard
static const int cc_op_arithb[8] = {
531 2c0262af bellard
    CC_OP_ADDB,
532 2c0262af bellard
    CC_OP_LOGICB,
533 2c0262af bellard
    CC_OP_ADDB,
534 2c0262af bellard
    CC_OP_SUBB,
535 2c0262af bellard
    CC_OP_LOGICB,
536 2c0262af bellard
    CC_OP_SUBB,
537 2c0262af bellard
    CC_OP_LOGICB,
538 2c0262af bellard
    CC_OP_SUBB,
539 2c0262af bellard
};
540 2c0262af bellard
541 4f31916f bellard
#define DEF_CMPXCHG(SUFFIX)\
542 4f31916f bellard
    gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
543 4f31916f bellard
    gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
544 14ce26e7 bellard
    gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
545 14ce26e7 bellard
    X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
546 4f31916f bellard
547 14ce26e7 bellard
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
548 4bb2fcc7 bellard
    DEF_CMPXCHG( )
549 2c0262af bellard
};
550 2c0262af bellard
551 14ce26e7 bellard
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
552 4f31916f bellard
    DEF_CMPXCHG(_raw)
553 4f31916f bellard
#ifndef CONFIG_USER_ONLY
554 4f31916f bellard
    DEF_CMPXCHG(_kernel)
555 4f31916f bellard
    DEF_CMPXCHG(_user)
556 4f31916f bellard
#endif
557 2c0262af bellard
};
558 2c0262af bellard
559 4f31916f bellard
#define DEF_SHIFT(SUFFIX)\
560 4f31916f bellard
    {\
561 4f31916f bellard
        gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
562 4f31916f bellard
        gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
563 4f31916f bellard
        gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
564 4f31916f bellard
        gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
565 4f31916f bellard
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
566 4f31916f bellard
        gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
567 4f31916f bellard
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
568 4f31916f bellard
        gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
569 4f31916f bellard
    },\
570 4f31916f bellard
    {\
571 4f31916f bellard
        gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
572 4f31916f bellard
        gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
573 4f31916f bellard
        gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
574 4f31916f bellard
        gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
575 4f31916f bellard
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
576 4f31916f bellard
        gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
577 4f31916f bellard
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
578 4f31916f bellard
        gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
579 4f31916f bellard
    },\
580 4f31916f bellard
    {\
581 4f31916f bellard
        gen_op_roll ## SUFFIX ## _T0_T1_cc,\
582 4f31916f bellard
        gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
583 4f31916f bellard
        gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
584 4f31916f bellard
        gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
585 4f31916f bellard
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
586 4f31916f bellard
        gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
587 4f31916f bellard
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
588 4f31916f bellard
        gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
589 14ce26e7 bellard
    },\
590 14ce26e7 bellard
    {\
591 14ce26e7 bellard
        X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
592 14ce26e7 bellard
        X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
593 14ce26e7 bellard
        X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
594 14ce26e7 bellard
        X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
595 14ce26e7 bellard
        X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
596 14ce26e7 bellard
        X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
597 14ce26e7 bellard
        X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
598 14ce26e7 bellard
        X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
599 2c0262af bellard
    },
600 4f31916f bellard
601 14ce26e7 bellard
static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
602 4bb2fcc7 bellard
    DEF_SHIFT( )
603 2c0262af bellard
};
604 2c0262af bellard
605 14ce26e7 bellard
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
606 4f31916f bellard
    DEF_SHIFT(_raw)
607 4f31916f bellard
#ifndef CONFIG_USER_ONLY
608 4f31916f bellard
    DEF_SHIFT(_kernel)
609 4f31916f bellard
    DEF_SHIFT(_user)
610 4f31916f bellard
#endif
611 2c0262af bellard
};
612 2c0262af bellard
613 4f31916f bellard
#define DEF_SHIFTD(SUFFIX, op)\
614 4f31916f bellard
    {\
615 4f31916f bellard
        NULL,\
616 4f31916f bellard
        NULL,\
617 4f31916f bellard
    },\
618 4f31916f bellard
    {\
619 4f31916f bellard
        gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
620 4f31916f bellard
        gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
621 31313213 bellard
     },\
622 4f31916f bellard
    {\
623 4f31916f bellard
        gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
624 4f31916f bellard
        gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
625 14ce26e7 bellard
    },\
626 14ce26e7 bellard
    {\
627 31313213 bellard
X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
628 31313213 bellard
           gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
629 2c0262af bellard
    },
630 4f31916f bellard
631 14ce26e7 bellard
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
632 4f31916f bellard
    DEF_SHIFTD(, im)
633 2c0262af bellard
};
634 2c0262af bellard
635 14ce26e7 bellard
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
636 4f31916f bellard
    DEF_SHIFTD(, ECX)
637 2c0262af bellard
};
638 2c0262af bellard
639 14ce26e7 bellard
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
640 4f31916f bellard
    DEF_SHIFTD(_raw, im)
641 4f31916f bellard
#ifndef CONFIG_USER_ONLY
642 4f31916f bellard
    DEF_SHIFTD(_kernel, im)
643 4f31916f bellard
    DEF_SHIFTD(_user, im)
644 4f31916f bellard
#endif
645 2c0262af bellard
};
646 2c0262af bellard
647 14ce26e7 bellard
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
648 4f31916f bellard
    DEF_SHIFTD(_raw, ECX)
649 4f31916f bellard
#ifndef CONFIG_USER_ONLY
650 4f31916f bellard
    DEF_SHIFTD(_kernel, ECX)
651 4f31916f bellard
    DEF_SHIFTD(_user, ECX)
652 4f31916f bellard
#endif
653 2c0262af bellard
};
654 2c0262af bellard
655 14ce26e7 bellard
static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
656 2c0262af bellard
    [0] = {
657 2c0262af bellard
        gen_op_btw_T0_T1_cc,
658 2c0262af bellard
        gen_op_btsw_T0_T1_cc,
659 2c0262af bellard
        gen_op_btrw_T0_T1_cc,
660 2c0262af bellard
        gen_op_btcw_T0_T1_cc,
661 2c0262af bellard
    },
662 2c0262af bellard
    [1] = {
663 2c0262af bellard
        gen_op_btl_T0_T1_cc,
664 2c0262af bellard
        gen_op_btsl_T0_T1_cc,
665 2c0262af bellard
        gen_op_btrl_T0_T1_cc,
666 2c0262af bellard
        gen_op_btcl_T0_T1_cc,
667 2c0262af bellard
    },
668 14ce26e7 bellard
#ifdef TARGET_X86_64
669 14ce26e7 bellard
    [2] = {
670 14ce26e7 bellard
        gen_op_btq_T0_T1_cc,
671 14ce26e7 bellard
        gen_op_btsq_T0_T1_cc,
672 14ce26e7 bellard
        gen_op_btrq_T0_T1_cc,
673 14ce26e7 bellard
        gen_op_btcq_T0_T1_cc,
674 14ce26e7 bellard
    },
675 14ce26e7 bellard
#endif
676 14ce26e7 bellard
};
677 14ce26e7 bellard
678 14ce26e7 bellard
static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
679 14ce26e7 bellard
    gen_op_add_bitw_A0_T1,
680 14ce26e7 bellard
    gen_op_add_bitl_A0_T1,
681 14ce26e7 bellard
    X86_64_ONLY(gen_op_add_bitq_A0_T1),
682 2c0262af bellard
};
683 2c0262af bellard
684 14ce26e7 bellard
static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
685 2c0262af bellard
    [0] = {
686 2c0262af bellard
        gen_op_bsfw_T0_cc,
687 2c0262af bellard
        gen_op_bsrw_T0_cc,
688 2c0262af bellard
    },
689 2c0262af bellard
    [1] = {
690 2c0262af bellard
        gen_op_bsfl_T0_cc,
691 2c0262af bellard
        gen_op_bsrl_T0_cc,
692 2c0262af bellard
    },
693 14ce26e7 bellard
#ifdef TARGET_X86_64
694 14ce26e7 bellard
    [2] = {
695 14ce26e7 bellard
        gen_op_bsfq_T0_cc,
696 14ce26e7 bellard
        gen_op_bsrq_T0_cc,
697 14ce26e7 bellard
    },
698 14ce26e7 bellard
#endif
699 2c0262af bellard
};
700 2c0262af bellard
701 57fec1fe bellard
static inline void gen_op_lds_T0_A0(int idx)
702 57fec1fe bellard
{
703 57fec1fe bellard
    int mem_index = (idx >> 2) - 1;
704 57fec1fe bellard
    switch(idx & 3) {
705 57fec1fe bellard
    case 0:
706 57fec1fe bellard
        tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
707 57fec1fe bellard
        break;
708 57fec1fe bellard
    case 1:
709 57fec1fe bellard
        tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
710 57fec1fe bellard
        break;
711 57fec1fe bellard
    default:
712 57fec1fe bellard
    case 2:
713 57fec1fe bellard
        tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
714 57fec1fe bellard
        break;
715 57fec1fe bellard
    }
716 57fec1fe bellard
}
717 2c0262af bellard
718 2c0262af bellard
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
719 57fec1fe bellard
static inline void gen_op_ld_T0_A0(int idx)
720 57fec1fe bellard
{
721 57fec1fe bellard
    int mem_index = (idx >> 2) - 1;
722 57fec1fe bellard
    switch(idx & 3) {
723 57fec1fe bellard
    case 0:
724 57fec1fe bellard
        tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, mem_index);
725 57fec1fe bellard
        break;
726 57fec1fe bellard
    case 1:
727 57fec1fe bellard
        tcg_gen_qemu_ld16u(cpu_T[0], cpu_A0, mem_index);
728 57fec1fe bellard
        break;
729 57fec1fe bellard
    case 2:
730 57fec1fe bellard
        tcg_gen_qemu_ld32u(cpu_T[0], cpu_A0, mem_index);
731 57fec1fe bellard
        break;
732 57fec1fe bellard
    default:
733 57fec1fe bellard
    case 3:
734 57fec1fe bellard
        tcg_gen_qemu_ld64(cpu_T[0], cpu_A0, mem_index);
735 57fec1fe bellard
        break;
736 57fec1fe bellard
    }
737 57fec1fe bellard
}
738 2c0262af bellard
739 57fec1fe bellard
static inline void gen_op_ldu_T0_A0(int idx)
740 57fec1fe bellard
{
741 57fec1fe bellard
    gen_op_ld_T0_A0(idx);
742 57fec1fe bellard
}
743 2c0262af bellard
744 57fec1fe bellard
static inline void gen_op_ld_T1_A0(int idx)
745 57fec1fe bellard
{
746 57fec1fe bellard
    int mem_index = (idx >> 2) - 1;
747 57fec1fe bellard
    switch(idx & 3) {
748 57fec1fe bellard
    case 0:
749 57fec1fe bellard
        tcg_gen_qemu_ld8u(cpu_T[1], cpu_A0, mem_index);
750 57fec1fe bellard
        break;
751 57fec1fe bellard
    case 1:
752 57fec1fe bellard
        tcg_gen_qemu_ld16u(cpu_T[1], cpu_A0, mem_index);
753 57fec1fe bellard
        break;
754 57fec1fe bellard
    case 2:
755 57fec1fe bellard
        tcg_gen_qemu_ld32u(cpu_T[1], cpu_A0, mem_index);
756 57fec1fe bellard
        break;
757 57fec1fe bellard
    default:
758 57fec1fe bellard
    case 3:
759 57fec1fe bellard
        tcg_gen_qemu_ld64(cpu_T[1], cpu_A0, mem_index);
760 57fec1fe bellard
        break;
761 57fec1fe bellard
    }
762 57fec1fe bellard
}
763 4f31916f bellard
764 57fec1fe bellard
static inline void gen_op_st_T0_A0(int idx)
765 57fec1fe bellard
{
766 57fec1fe bellard
    int mem_index = (idx >> 2) - 1;
767 57fec1fe bellard
    switch(idx & 3) {
768 57fec1fe bellard
    case 0:
769 57fec1fe bellard
        tcg_gen_qemu_st8(cpu_T[0], cpu_A0, mem_index);
770 57fec1fe bellard
        break;
771 57fec1fe bellard
    case 1:
772 57fec1fe bellard
        tcg_gen_qemu_st16(cpu_T[0], cpu_A0, mem_index);
773 57fec1fe bellard
        break;
774 57fec1fe bellard
    case 2:
775 57fec1fe bellard
        tcg_gen_qemu_st32(cpu_T[0], cpu_A0, mem_index);
776 57fec1fe bellard
        break;
777 57fec1fe bellard
    default:
778 57fec1fe bellard
    case 3:
779 57fec1fe bellard
        tcg_gen_qemu_st64(cpu_T[0], cpu_A0, mem_index);
780 57fec1fe bellard
        break;
781 57fec1fe bellard
    }
782 57fec1fe bellard
}
783 4f31916f bellard
784 57fec1fe bellard
static inline void gen_op_st_T1_A0(int idx)
785 57fec1fe bellard
{
786 57fec1fe bellard
    int mem_index = (idx >> 2) - 1;
787 57fec1fe bellard
    switch(idx & 3) {
788 57fec1fe bellard
    case 0:
789 57fec1fe bellard
        tcg_gen_qemu_st8(cpu_T[1], cpu_A0, mem_index);
790 57fec1fe bellard
        break;
791 57fec1fe bellard
    case 1:
792 57fec1fe bellard
        tcg_gen_qemu_st16(cpu_T[1], cpu_A0, mem_index);
793 57fec1fe bellard
        break;
794 57fec1fe bellard
    case 2:
795 57fec1fe bellard
        tcg_gen_qemu_st32(cpu_T[1], cpu_A0, mem_index);
796 57fec1fe bellard
        break;
797 57fec1fe bellard
    default:
798 57fec1fe bellard
    case 3:
799 57fec1fe bellard
        tcg_gen_qemu_st64(cpu_T[1], cpu_A0, mem_index);
800 57fec1fe bellard
        break;
801 57fec1fe bellard
    }
802 57fec1fe bellard
}
803 4f31916f bellard
804 14ce26e7 bellard
static inline void gen_jmp_im(target_ulong pc)
805 14ce26e7 bellard
{
806 57fec1fe bellard
    tcg_gen_movi_tl(cpu_tmp0, pc);
807 57fec1fe bellard
    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip));
808 14ce26e7 bellard
}
809 14ce26e7 bellard
810 2c0262af bellard
static inline void gen_string_movl_A0_ESI(DisasContext *s)
811 2c0262af bellard
{
812 2c0262af bellard
    int override;
813 2c0262af bellard
814 2c0262af bellard
    override = s->override;
815 14ce26e7 bellard
#ifdef TARGET_X86_64
816 14ce26e7 bellard
    if (s->aflag == 2) {
817 14ce26e7 bellard
        if (override >= 0) {
818 57fec1fe bellard
            gen_op_movq_A0_seg(override);
819 57fec1fe bellard
            gen_op_addq_A0_reg_sN(0, R_ESI);
820 14ce26e7 bellard
        } else {
821 57fec1fe bellard
            gen_op_movq_A0_reg(R_ESI);
822 14ce26e7 bellard
        }
823 14ce26e7 bellard
    } else
824 14ce26e7 bellard
#endif
825 2c0262af bellard
    if (s->aflag) {
826 2c0262af bellard
        /* 32 bit address */
827 2c0262af bellard
        if (s->addseg && override < 0)
828 2c0262af bellard
            override = R_DS;
829 2c0262af bellard
        if (override >= 0) {
830 57fec1fe bellard
            gen_op_movl_A0_seg(override);
831 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_ESI);
832 2c0262af bellard
        } else {
833 57fec1fe bellard
            gen_op_movl_A0_reg(R_ESI);
834 2c0262af bellard
        }
835 2c0262af bellard
    } else {
836 2c0262af bellard
        /* 16 address, always override */
837 2c0262af bellard
        if (override < 0)
838 2c0262af bellard
            override = R_DS;
839 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESI);
840 2c0262af bellard
        gen_op_andl_A0_ffff();
841 57fec1fe bellard
        gen_op_addl_A0_seg(override);
842 2c0262af bellard
    }
843 2c0262af bellard
}
844 2c0262af bellard
845 2c0262af bellard
static inline void gen_string_movl_A0_EDI(DisasContext *s)
846 2c0262af bellard
{
847 14ce26e7 bellard
#ifdef TARGET_X86_64
848 14ce26e7 bellard
    if (s->aflag == 2) {
849 57fec1fe bellard
        gen_op_movq_A0_reg(R_EDI);
850 14ce26e7 bellard
    } else
851 14ce26e7 bellard
#endif
852 2c0262af bellard
    if (s->aflag) {
853 2c0262af bellard
        if (s->addseg) {
854 57fec1fe bellard
            gen_op_movl_A0_seg(R_ES);
855 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_EDI);
856 2c0262af bellard
        } else {
857 57fec1fe bellard
            gen_op_movl_A0_reg(R_EDI);
858 2c0262af bellard
        }
859 2c0262af bellard
    } else {
860 57fec1fe bellard
        gen_op_movl_A0_reg(R_EDI);
861 2c0262af bellard
        gen_op_andl_A0_ffff();
862 57fec1fe bellard
        gen_op_addl_A0_seg(R_ES);
863 2c0262af bellard
    }
864 2c0262af bellard
}
865 2c0262af bellard
866 14ce26e7 bellard
static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
867 2c0262af bellard
    gen_op_movl_T0_Dshiftb,
868 2c0262af bellard
    gen_op_movl_T0_Dshiftw,
869 2c0262af bellard
    gen_op_movl_T0_Dshiftl,
870 14ce26e7 bellard
    X86_64_ONLY(gen_op_movl_T0_Dshiftq),
871 2c0262af bellard
};
872 2c0262af bellard
873 14ce26e7 bellard
static GenOpFunc1 *gen_op_jnz_ecx[3] = {
874 14ce26e7 bellard
    gen_op_jnz_ecxw,
875 14ce26e7 bellard
    gen_op_jnz_ecxl,
876 14ce26e7 bellard
    X86_64_ONLY(gen_op_jnz_ecxq),
877 2c0262af bellard
};
878 3b46e624 ths
879 14ce26e7 bellard
static GenOpFunc1 *gen_op_jz_ecx[3] = {
880 14ce26e7 bellard
    gen_op_jz_ecxw,
881 14ce26e7 bellard
    gen_op_jz_ecxl,
882 14ce26e7 bellard
    X86_64_ONLY(gen_op_jz_ecxq),
883 2c0262af bellard
};
884 2c0262af bellard
885 14ce26e7 bellard
static GenOpFunc *gen_op_dec_ECX[3] = {
886 2c0262af bellard
    gen_op_decw_ECX,
887 2c0262af bellard
    gen_op_decl_ECX,
888 14ce26e7 bellard
    X86_64_ONLY(gen_op_decq_ECX),
889 2c0262af bellard
};
890 2c0262af bellard
891 14ce26e7 bellard
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
892 2c0262af bellard
    {
893 14ce26e7 bellard
        gen_op_jnz_subb,
894 14ce26e7 bellard
        gen_op_jnz_subw,
895 14ce26e7 bellard
        gen_op_jnz_subl,
896 14ce26e7 bellard
        X86_64_ONLY(gen_op_jnz_subq),
897 2c0262af bellard
    },
898 2c0262af bellard
    {
899 14ce26e7 bellard
        gen_op_jz_subb,
900 14ce26e7 bellard
        gen_op_jz_subw,
901 14ce26e7 bellard
        gen_op_jz_subl,
902 14ce26e7 bellard
        X86_64_ONLY(gen_op_jz_subq),
903 2c0262af bellard
    },
904 2c0262af bellard
};
905 2c0262af bellard
906 2c0262af bellard
static GenOpFunc *gen_op_in_DX_T0[3] = {
907 2c0262af bellard
    gen_op_inb_DX_T0,
908 2c0262af bellard
    gen_op_inw_DX_T0,
909 2c0262af bellard
    gen_op_inl_DX_T0,
910 2c0262af bellard
};
911 2c0262af bellard
912 2c0262af bellard
static GenOpFunc *gen_op_out_DX_T0[3] = {
913 2c0262af bellard
    gen_op_outb_DX_T0,
914 2c0262af bellard
    gen_op_outw_DX_T0,
915 2c0262af bellard
    gen_op_outl_DX_T0,
916 2c0262af bellard
};
917 2c0262af bellard
918 f115e911 bellard
static GenOpFunc *gen_op_in[3] = {
919 f115e911 bellard
    gen_op_inb_T0_T1,
920 f115e911 bellard
    gen_op_inw_T0_T1,
921 f115e911 bellard
    gen_op_inl_T0_T1,
922 f115e911 bellard
};
923 f115e911 bellard
924 f115e911 bellard
static GenOpFunc *gen_op_out[3] = {
925 f115e911 bellard
    gen_op_outb_T0_T1,
926 f115e911 bellard
    gen_op_outw_T0_T1,
927 f115e911 bellard
    gen_op_outl_T0_T1,
928 f115e911 bellard
};
929 f115e911 bellard
930 f115e911 bellard
static GenOpFunc *gen_check_io_T0[3] = {
931 f115e911 bellard
    gen_op_check_iob_T0,
932 f115e911 bellard
    gen_op_check_iow_T0,
933 f115e911 bellard
    gen_op_check_iol_T0,
934 f115e911 bellard
};
935 f115e911 bellard
936 f115e911 bellard
static GenOpFunc *gen_check_io_DX[3] = {
937 f115e911 bellard
    gen_op_check_iob_DX,
938 f115e911 bellard
    gen_op_check_iow_DX,
939 f115e911 bellard
    gen_op_check_iol_DX,
940 f115e911 bellard
};
941 f115e911 bellard
942 14ce26e7 bellard
static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
943 f115e911 bellard
{
944 f115e911 bellard
    if (s->pe && (s->cpl > s->iopl || s->vm86)) {
945 f115e911 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
946 f115e911 bellard
            gen_op_set_cc_op(s->cc_op);
947 14ce26e7 bellard
        gen_jmp_im(cur_eip);
948 f115e911 bellard
        if (use_dx)
949 f115e911 bellard
            gen_check_io_DX[ot]();
950 f115e911 bellard
        else
951 f115e911 bellard
            gen_check_io_T0[ot]();
952 f115e911 bellard
    }
953 f115e911 bellard
}
954 f115e911 bellard
955 2c0262af bellard
static inline void gen_movs(DisasContext *s, int ot)
956 2c0262af bellard
{
957 2c0262af bellard
    gen_string_movl_A0_ESI(s);
958 57fec1fe bellard
    gen_op_ld_T0_A0(ot + s->mem_index);
959 2c0262af bellard
    gen_string_movl_A0_EDI(s);
960 57fec1fe bellard
    gen_op_st_T0_A0(ot + s->mem_index);
961 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
962 14ce26e7 bellard
#ifdef TARGET_X86_64
963 14ce26e7 bellard
    if (s->aflag == 2) {
964 14ce26e7 bellard
        gen_op_addq_ESI_T0();
965 14ce26e7 bellard
        gen_op_addq_EDI_T0();
966 5fafdf24 ths
    } else
967 14ce26e7 bellard
#endif
968 2c0262af bellard
    if (s->aflag) {
969 2c0262af bellard
        gen_op_addl_ESI_T0();
970 2c0262af bellard
        gen_op_addl_EDI_T0();
971 2c0262af bellard
    } else {
972 2c0262af bellard
        gen_op_addw_ESI_T0();
973 2c0262af bellard
        gen_op_addw_EDI_T0();
974 2c0262af bellard
    }
975 2c0262af bellard
}
976 2c0262af bellard
977 2c0262af bellard
static inline void gen_update_cc_op(DisasContext *s)
978 2c0262af bellard
{
979 2c0262af bellard
    if (s->cc_op != CC_OP_DYNAMIC) {
980 2c0262af bellard
        gen_op_set_cc_op(s->cc_op);
981 2c0262af bellard
        s->cc_op = CC_OP_DYNAMIC;
982 2c0262af bellard
    }
983 2c0262af bellard
}
984 2c0262af bellard
985 14ce26e7 bellard
/* XXX: does not work with gdbstub "ice" single step - not a
986 14ce26e7 bellard
   serious problem */
987 14ce26e7 bellard
static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
988 2c0262af bellard
{
989 14ce26e7 bellard
    int l1, l2;
990 14ce26e7 bellard
991 14ce26e7 bellard
    l1 = gen_new_label();
992 14ce26e7 bellard
    l2 = gen_new_label();
993 14ce26e7 bellard
    gen_op_jnz_ecx[s->aflag](l1);
994 14ce26e7 bellard
    gen_set_label(l2);
995 14ce26e7 bellard
    gen_jmp_tb(s, next_eip, 1);
996 14ce26e7 bellard
    gen_set_label(l1);
997 14ce26e7 bellard
    return l2;
998 2c0262af bellard
}
999 2c0262af bellard
1000 2c0262af bellard
static inline void gen_stos(DisasContext *s, int ot)
1001 2c0262af bellard
{
1002 57fec1fe bellard
    gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1003 2c0262af bellard
    gen_string_movl_A0_EDI(s);
1004 57fec1fe bellard
    gen_op_st_T0_A0(ot + s->mem_index);
1005 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1006 14ce26e7 bellard
#ifdef TARGET_X86_64
1007 14ce26e7 bellard
    if (s->aflag == 2) {
1008 14ce26e7 bellard
        gen_op_addq_EDI_T0();
1009 5fafdf24 ths
    } else
1010 14ce26e7 bellard
#endif
1011 2c0262af bellard
    if (s->aflag) {
1012 2c0262af bellard
        gen_op_addl_EDI_T0();
1013 2c0262af bellard
    } else {
1014 2c0262af bellard
        gen_op_addw_EDI_T0();
1015 2c0262af bellard
    }
1016 2c0262af bellard
}
1017 2c0262af bellard
1018 2c0262af bellard
static inline void gen_lods(DisasContext *s, int ot)
1019 2c0262af bellard
{
1020 2c0262af bellard
    gen_string_movl_A0_ESI(s);
1021 57fec1fe bellard
    gen_op_ld_T0_A0(ot + s->mem_index);
1022 57fec1fe bellard
    gen_op_mov_reg_T0(ot, R_EAX);
1023 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1024 14ce26e7 bellard
#ifdef TARGET_X86_64
1025 14ce26e7 bellard
    if (s->aflag == 2) {
1026 14ce26e7 bellard
        gen_op_addq_ESI_T0();
1027 5fafdf24 ths
    } else
1028 14ce26e7 bellard
#endif
1029 2c0262af bellard
    if (s->aflag) {
1030 2c0262af bellard
        gen_op_addl_ESI_T0();
1031 2c0262af bellard
    } else {
1032 2c0262af bellard
        gen_op_addw_ESI_T0();
1033 2c0262af bellard
    }
1034 2c0262af bellard
}
1035 2c0262af bellard
1036 2c0262af bellard
static inline void gen_scas(DisasContext *s, int ot)
1037 2c0262af bellard
{
1038 57fec1fe bellard
    gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1039 2c0262af bellard
    gen_string_movl_A0_EDI(s);
1040 57fec1fe bellard
    gen_op_ld_T1_A0(ot + s->mem_index);
1041 2c0262af bellard
    gen_op_cmpl_T0_T1_cc();
1042 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1043 14ce26e7 bellard
#ifdef TARGET_X86_64
1044 14ce26e7 bellard
    if (s->aflag == 2) {
1045 14ce26e7 bellard
        gen_op_addq_EDI_T0();
1046 5fafdf24 ths
    } else
1047 14ce26e7 bellard
#endif
1048 2c0262af bellard
    if (s->aflag) {
1049 2c0262af bellard
        gen_op_addl_EDI_T0();
1050 2c0262af bellard
    } else {
1051 2c0262af bellard
        gen_op_addw_EDI_T0();
1052 2c0262af bellard
    }
1053 2c0262af bellard
}
1054 2c0262af bellard
1055 2c0262af bellard
static inline void gen_cmps(DisasContext *s, int ot)
1056 2c0262af bellard
{
1057 2c0262af bellard
    gen_string_movl_A0_ESI(s);
1058 57fec1fe bellard
    gen_op_ld_T0_A0(ot + s->mem_index);
1059 2c0262af bellard
    gen_string_movl_A0_EDI(s);
1060 57fec1fe bellard
    gen_op_ld_T1_A0(ot + s->mem_index);
1061 2c0262af bellard
    gen_op_cmpl_T0_T1_cc();
1062 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1063 14ce26e7 bellard
#ifdef TARGET_X86_64
1064 14ce26e7 bellard
    if (s->aflag == 2) {
1065 14ce26e7 bellard
        gen_op_addq_ESI_T0();
1066 14ce26e7 bellard
        gen_op_addq_EDI_T0();
1067 5fafdf24 ths
    } else
1068 14ce26e7 bellard
#endif
1069 2c0262af bellard
    if (s->aflag) {
1070 2c0262af bellard
        gen_op_addl_ESI_T0();
1071 2c0262af bellard
        gen_op_addl_EDI_T0();
1072 2c0262af bellard
    } else {
1073 2c0262af bellard
        gen_op_addw_ESI_T0();
1074 2c0262af bellard
        gen_op_addw_EDI_T0();
1075 2c0262af bellard
    }
1076 2c0262af bellard
}
1077 2c0262af bellard
1078 2c0262af bellard
static inline void gen_ins(DisasContext *s, int ot)
1079 2c0262af bellard
{
1080 2c0262af bellard
    gen_string_movl_A0_EDI(s);
1081 9772c73b bellard
    gen_op_movl_T0_0();
1082 57fec1fe bellard
    gen_op_st_T0_A0(ot + s->mem_index);
1083 9772c73b bellard
    gen_op_in_DX_T0[ot]();
1084 57fec1fe bellard
    gen_op_st_T0_A0(ot + s->mem_index);
1085 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1086 14ce26e7 bellard
#ifdef TARGET_X86_64
1087 14ce26e7 bellard
    if (s->aflag == 2) {
1088 14ce26e7 bellard
        gen_op_addq_EDI_T0();
1089 5fafdf24 ths
    } else
1090 14ce26e7 bellard
#endif
1091 2c0262af bellard
    if (s->aflag) {
1092 2c0262af bellard
        gen_op_addl_EDI_T0();
1093 2c0262af bellard
    } else {
1094 2c0262af bellard
        gen_op_addw_EDI_T0();
1095 2c0262af bellard
    }
1096 2c0262af bellard
}
1097 2c0262af bellard
1098 2c0262af bellard
static inline void gen_outs(DisasContext *s, int ot)
1099 2c0262af bellard
{
1100 2c0262af bellard
    gen_string_movl_A0_ESI(s);
1101 57fec1fe bellard
    gen_op_ld_T0_A0(ot + s->mem_index);
1102 2c0262af bellard
    gen_op_out_DX_T0[ot]();
1103 2c0262af bellard
    gen_op_movl_T0_Dshift[ot]();
1104 14ce26e7 bellard
#ifdef TARGET_X86_64
1105 14ce26e7 bellard
    if (s->aflag == 2) {
1106 14ce26e7 bellard
        gen_op_addq_ESI_T0();
1107 5fafdf24 ths
    } else
1108 14ce26e7 bellard
#endif
1109 2c0262af bellard
    if (s->aflag) {
1110 2c0262af bellard
        gen_op_addl_ESI_T0();
1111 2c0262af bellard
    } else {
1112 2c0262af bellard
        gen_op_addw_ESI_T0();
1113 2c0262af bellard
    }
1114 2c0262af bellard
}
1115 2c0262af bellard
1116 2c0262af bellard
/* same method as Valgrind : we generate jumps to current or next
1117 2c0262af bellard
   instruction */
1118 2c0262af bellard
#define GEN_REPZ(op)                                                          \
1119 2c0262af bellard
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1120 14ce26e7 bellard
                                 target_ulong cur_eip, target_ulong next_eip) \
1121 2c0262af bellard
{                                                                             \
1122 14ce26e7 bellard
    int l2;\
1123 2c0262af bellard
    gen_update_cc_op(s);                                                      \
1124 14ce26e7 bellard
    l2 = gen_jz_ecx_string(s, next_eip);                                      \
1125 2c0262af bellard
    gen_ ## op(s, ot);                                                        \
1126 2c0262af bellard
    gen_op_dec_ECX[s->aflag]();                                               \
1127 2c0262af bellard
    /* a loop would cause two single step exceptions if ECX = 1               \
1128 2c0262af bellard
       before rep string_insn */                                              \
1129 2c0262af bellard
    if (!s->jmp_opt)                                                          \
1130 14ce26e7 bellard
        gen_op_jz_ecx[s->aflag](l2);                                          \
1131 2c0262af bellard
    gen_jmp(s, cur_eip);                                                      \
1132 2c0262af bellard
}
1133 2c0262af bellard
1134 2c0262af bellard
#define GEN_REPZ2(op)                                                         \
1135 2c0262af bellard
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1136 14ce26e7 bellard
                                   target_ulong cur_eip,                      \
1137 14ce26e7 bellard
                                   target_ulong next_eip,                     \
1138 2c0262af bellard
                                   int nz)                                    \
1139 2c0262af bellard
{                                                                             \
1140 14ce26e7 bellard
    int l2;\
1141 2c0262af bellard
    gen_update_cc_op(s);                                                      \
1142 14ce26e7 bellard
    l2 = gen_jz_ecx_string(s, next_eip);                                      \
1143 2c0262af bellard
    gen_ ## op(s, ot);                                                        \
1144 2c0262af bellard
    gen_op_dec_ECX[s->aflag]();                                               \
1145 2c0262af bellard
    gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
1146 14ce26e7 bellard
    gen_op_string_jnz_sub[nz][ot](l2);\
1147 2c0262af bellard
    if (!s->jmp_opt)                                                          \
1148 14ce26e7 bellard
        gen_op_jz_ecx[s->aflag](l2);                                          \
1149 2c0262af bellard
    gen_jmp(s, cur_eip);                                                      \
1150 2c0262af bellard
}
1151 2c0262af bellard
1152 2c0262af bellard
GEN_REPZ(movs)
1153 2c0262af bellard
GEN_REPZ(stos)
1154 2c0262af bellard
GEN_REPZ(lods)
1155 2c0262af bellard
GEN_REPZ(ins)
1156 2c0262af bellard
GEN_REPZ(outs)
1157 2c0262af bellard
GEN_REPZ2(scas)
1158 2c0262af bellard
GEN_REPZ2(cmps)
1159 2c0262af bellard
1160 2c0262af bellard
enum {
1161 2c0262af bellard
    JCC_O,
1162 2c0262af bellard
    JCC_B,
1163 2c0262af bellard
    JCC_Z,
1164 2c0262af bellard
    JCC_BE,
1165 2c0262af bellard
    JCC_S,
1166 2c0262af bellard
    JCC_P,
1167 2c0262af bellard
    JCC_L,
1168 2c0262af bellard
    JCC_LE,
1169 2c0262af bellard
};
1170 2c0262af bellard
1171 14ce26e7 bellard
static GenOpFunc1 *gen_jcc_sub[4][8] = {
1172 2c0262af bellard
    [OT_BYTE] = {
1173 2c0262af bellard
        NULL,
1174 2c0262af bellard
        gen_op_jb_subb,
1175 2c0262af bellard
        gen_op_jz_subb,
1176 2c0262af bellard
        gen_op_jbe_subb,
1177 2c0262af bellard
        gen_op_js_subb,
1178 2c0262af bellard
        NULL,
1179 2c0262af bellard
        gen_op_jl_subb,
1180 2c0262af bellard
        gen_op_jle_subb,
1181 2c0262af bellard
    },
1182 2c0262af bellard
    [OT_WORD] = {
1183 2c0262af bellard
        NULL,
1184 2c0262af bellard
        gen_op_jb_subw,
1185 2c0262af bellard
        gen_op_jz_subw,
1186 2c0262af bellard
        gen_op_jbe_subw,
1187 2c0262af bellard
        gen_op_js_subw,
1188 2c0262af bellard
        NULL,
1189 2c0262af bellard
        gen_op_jl_subw,
1190 2c0262af bellard
        gen_op_jle_subw,
1191 2c0262af bellard
    },
1192 2c0262af bellard
    [OT_LONG] = {
1193 2c0262af bellard
        NULL,
1194 2c0262af bellard
        gen_op_jb_subl,
1195 2c0262af bellard
        gen_op_jz_subl,
1196 2c0262af bellard
        gen_op_jbe_subl,
1197 2c0262af bellard
        gen_op_js_subl,
1198 2c0262af bellard
        NULL,
1199 2c0262af bellard
        gen_op_jl_subl,
1200 2c0262af bellard
        gen_op_jle_subl,
1201 2c0262af bellard
    },
1202 14ce26e7 bellard
#ifdef TARGET_X86_64
1203 14ce26e7 bellard
    [OT_QUAD] = {
1204 14ce26e7 bellard
        NULL,
1205 14ce26e7 bellard
        BUGGY_64(gen_op_jb_subq),
1206 14ce26e7 bellard
        gen_op_jz_subq,
1207 14ce26e7 bellard
        BUGGY_64(gen_op_jbe_subq),
1208 14ce26e7 bellard
        gen_op_js_subq,
1209 14ce26e7 bellard
        NULL,
1210 14ce26e7 bellard
        BUGGY_64(gen_op_jl_subq),
1211 14ce26e7 bellard
        BUGGY_64(gen_op_jle_subq),
1212 14ce26e7 bellard
    },
1213 14ce26e7 bellard
#endif
1214 2c0262af bellard
};
1215 14ce26e7 bellard
static GenOpFunc1 *gen_op_loop[3][4] = {
1216 2c0262af bellard
    [0] = {
1217 2c0262af bellard
        gen_op_loopnzw,
1218 2c0262af bellard
        gen_op_loopzw,
1219 14ce26e7 bellard
        gen_op_jnz_ecxw,
1220 2c0262af bellard
    },
1221 2c0262af bellard
    [1] = {
1222 2c0262af bellard
        gen_op_loopnzl,
1223 2c0262af bellard
        gen_op_loopzl,
1224 14ce26e7 bellard
        gen_op_jnz_ecxl,
1225 14ce26e7 bellard
    },
1226 14ce26e7 bellard
#ifdef TARGET_X86_64
1227 14ce26e7 bellard
    [2] = {
1228 14ce26e7 bellard
        gen_op_loopnzq,
1229 14ce26e7 bellard
        gen_op_loopzq,
1230 14ce26e7 bellard
        gen_op_jnz_ecxq,
1231 2c0262af bellard
    },
1232 14ce26e7 bellard
#endif
1233 2c0262af bellard
};
1234 2c0262af bellard
1235 2c0262af bellard
static GenOpFunc *gen_setcc_slow[8] = {
1236 2c0262af bellard
    gen_op_seto_T0_cc,
1237 2c0262af bellard
    gen_op_setb_T0_cc,
1238 2c0262af bellard
    gen_op_setz_T0_cc,
1239 2c0262af bellard
    gen_op_setbe_T0_cc,
1240 2c0262af bellard
    gen_op_sets_T0_cc,
1241 2c0262af bellard
    gen_op_setp_T0_cc,
1242 2c0262af bellard
    gen_op_setl_T0_cc,
1243 2c0262af bellard
    gen_op_setle_T0_cc,
1244 2c0262af bellard
};
1245 2c0262af bellard
1246 14ce26e7 bellard
static GenOpFunc *gen_setcc_sub[4][8] = {
1247 2c0262af bellard
    [OT_BYTE] = {
1248 2c0262af bellard
        NULL,
1249 2c0262af bellard
        gen_op_setb_T0_subb,
1250 2c0262af bellard
        gen_op_setz_T0_subb,
1251 2c0262af bellard
        gen_op_setbe_T0_subb,
1252 2c0262af bellard
        gen_op_sets_T0_subb,
1253 2c0262af bellard
        NULL,
1254 2c0262af bellard
        gen_op_setl_T0_subb,
1255 2c0262af bellard
        gen_op_setle_T0_subb,
1256 2c0262af bellard
    },
1257 2c0262af bellard
    [OT_WORD] = {
1258 2c0262af bellard
        NULL,
1259 2c0262af bellard
        gen_op_setb_T0_subw,
1260 2c0262af bellard
        gen_op_setz_T0_subw,
1261 2c0262af bellard
        gen_op_setbe_T0_subw,
1262 2c0262af bellard
        gen_op_sets_T0_subw,
1263 2c0262af bellard
        NULL,
1264 2c0262af bellard
        gen_op_setl_T0_subw,
1265 2c0262af bellard
        gen_op_setle_T0_subw,
1266 2c0262af bellard
    },
1267 2c0262af bellard
    [OT_LONG] = {
1268 2c0262af bellard
        NULL,
1269 2c0262af bellard
        gen_op_setb_T0_subl,
1270 2c0262af bellard
        gen_op_setz_T0_subl,
1271 2c0262af bellard
        gen_op_setbe_T0_subl,
1272 2c0262af bellard
        gen_op_sets_T0_subl,
1273 2c0262af bellard
        NULL,
1274 2c0262af bellard
        gen_op_setl_T0_subl,
1275 2c0262af bellard
        gen_op_setle_T0_subl,
1276 2c0262af bellard
    },
1277 14ce26e7 bellard
#ifdef TARGET_X86_64
1278 14ce26e7 bellard
    [OT_QUAD] = {
1279 14ce26e7 bellard
        NULL,
1280 14ce26e7 bellard
        gen_op_setb_T0_subq,
1281 14ce26e7 bellard
        gen_op_setz_T0_subq,
1282 14ce26e7 bellard
        gen_op_setbe_T0_subq,
1283 14ce26e7 bellard
        gen_op_sets_T0_subq,
1284 14ce26e7 bellard
        NULL,
1285 14ce26e7 bellard
        gen_op_setl_T0_subq,
1286 14ce26e7 bellard
        gen_op_setle_T0_subq,
1287 14ce26e7 bellard
    },
1288 14ce26e7 bellard
#endif
1289 2c0262af bellard
};
1290 2c0262af bellard
1291 2c0262af bellard
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1292 2c0262af bellard
    gen_op_fadd_ST0_FT0,
1293 2c0262af bellard
    gen_op_fmul_ST0_FT0,
1294 2c0262af bellard
    gen_op_fcom_ST0_FT0,
1295 2c0262af bellard
    gen_op_fcom_ST0_FT0,
1296 2c0262af bellard
    gen_op_fsub_ST0_FT0,
1297 2c0262af bellard
    gen_op_fsubr_ST0_FT0,
1298 2c0262af bellard
    gen_op_fdiv_ST0_FT0,
1299 2c0262af bellard
    gen_op_fdivr_ST0_FT0,
1300 2c0262af bellard
};
1301 2c0262af bellard
1302 2c0262af bellard
/* NOTE the exception in "r" op ordering */
1303 2c0262af bellard
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1304 2c0262af bellard
    gen_op_fadd_STN_ST0,
1305 2c0262af bellard
    gen_op_fmul_STN_ST0,
1306 2c0262af bellard
    NULL,
1307 2c0262af bellard
    NULL,
1308 2c0262af bellard
    gen_op_fsubr_STN_ST0,
1309 2c0262af bellard
    gen_op_fsub_STN_ST0,
1310 2c0262af bellard
    gen_op_fdivr_STN_ST0,
1311 2c0262af bellard
    gen_op_fdiv_STN_ST0,
1312 2c0262af bellard
};
1313 2c0262af bellard
1314 2c0262af bellard
/* if d == OR_TMP0, it means memory operand (address in A0) */
1315 2c0262af bellard
static void gen_op(DisasContext *s1, int op, int ot, int d)
1316 2c0262af bellard
{
1317 2c0262af bellard
    GenOpFunc *gen_update_cc;
1318 3b46e624 ths
1319 2c0262af bellard
    if (d != OR_TMP0) {
1320 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, d);
1321 2c0262af bellard
    } else {
1322 57fec1fe bellard
        gen_op_ld_T0_A0(ot + s1->mem_index);
1323 2c0262af bellard
    }
1324 2c0262af bellard
    switch(op) {
1325 2c0262af bellard
    case OP_ADCL:
1326 2c0262af bellard
    case OP_SBBL:
1327 2c0262af bellard
        if (s1->cc_op != CC_OP_DYNAMIC)
1328 2c0262af bellard
            gen_op_set_cc_op(s1->cc_op);
1329 2c0262af bellard
        if (d != OR_TMP0) {
1330 2c0262af bellard
            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1331 57fec1fe bellard
            gen_op_mov_reg_T0(ot, d);
1332 2c0262af bellard
        } else {
1333 4f31916f bellard
            gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1334 2c0262af bellard
        }
1335 2c0262af bellard
        s1->cc_op = CC_OP_DYNAMIC;
1336 2c0262af bellard
        goto the_end;
1337 2c0262af bellard
    case OP_ADDL:
1338 2c0262af bellard
        gen_op_addl_T0_T1();
1339 2c0262af bellard
        s1->cc_op = CC_OP_ADDB + ot;
1340 2c0262af bellard
        gen_update_cc = gen_op_update2_cc;
1341 2c0262af bellard
        break;
1342 2c0262af bellard
    case OP_SUBL:
1343 57fec1fe bellard
        tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1344 2c0262af bellard
        s1->cc_op = CC_OP_SUBB + ot;
1345 2c0262af bellard
        gen_update_cc = gen_op_update2_cc;
1346 2c0262af bellard
        break;
1347 2c0262af bellard
    default:
1348 2c0262af bellard
    case OP_ANDL:
1349 57fec1fe bellard
        tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1350 57fec1fe bellard
        s1->cc_op = CC_OP_LOGICB + ot;
1351 57fec1fe bellard
        gen_update_cc = gen_op_update1_cc;
1352 57fec1fe bellard
        break;
1353 2c0262af bellard
    case OP_ORL:
1354 57fec1fe bellard
        tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1355 57fec1fe bellard
        s1->cc_op = CC_OP_LOGICB + ot;
1356 57fec1fe bellard
        gen_update_cc = gen_op_update1_cc;
1357 57fec1fe bellard
        break;
1358 2c0262af bellard
    case OP_XORL:
1359 57fec1fe bellard
        tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1360 2c0262af bellard
        s1->cc_op = CC_OP_LOGICB + ot;
1361 2c0262af bellard
        gen_update_cc = gen_op_update1_cc;
1362 2c0262af bellard
        break;
1363 2c0262af bellard
    case OP_CMPL:
1364 2c0262af bellard
        gen_op_cmpl_T0_T1_cc();
1365 2c0262af bellard
        s1->cc_op = CC_OP_SUBB + ot;
1366 2c0262af bellard
        gen_update_cc = NULL;
1367 2c0262af bellard
        break;
1368 2c0262af bellard
    }
1369 2c0262af bellard
    if (op != OP_CMPL) {
1370 2c0262af bellard
        if (d != OR_TMP0)
1371 57fec1fe bellard
            gen_op_mov_reg_T0(ot, d);
1372 2c0262af bellard
        else
1373 57fec1fe bellard
            gen_op_st_T0_A0(ot + s1->mem_index);
1374 2c0262af bellard
    }
1375 2c0262af bellard
    /* the flags update must happen after the memory write (precise
1376 2c0262af bellard
       exception support) */
1377 2c0262af bellard
    if (gen_update_cc)
1378 2c0262af bellard
        gen_update_cc();
1379 2c0262af bellard
 the_end: ;
1380 2c0262af bellard
}
1381 2c0262af bellard
1382 2c0262af bellard
/* if d == OR_TMP0, it means memory operand (address in A0) */
1383 2c0262af bellard
static void gen_inc(DisasContext *s1, int ot, int d, int c)
1384 2c0262af bellard
{
1385 2c0262af bellard
    if (d != OR_TMP0)
1386 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, d);
1387 2c0262af bellard
    else
1388 57fec1fe bellard
        gen_op_ld_T0_A0(ot + s1->mem_index);
1389 2c0262af bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
1390 2c0262af bellard
        gen_op_set_cc_op(s1->cc_op);
1391 2c0262af bellard
    if (c > 0) {
1392 2c0262af bellard
        gen_op_incl_T0();
1393 2c0262af bellard
        s1->cc_op = CC_OP_INCB + ot;
1394 2c0262af bellard
    } else {
1395 2c0262af bellard
        gen_op_decl_T0();
1396 2c0262af bellard
        s1->cc_op = CC_OP_DECB + ot;
1397 2c0262af bellard
    }
1398 2c0262af bellard
    if (d != OR_TMP0)
1399 57fec1fe bellard
        gen_op_mov_reg_T0(ot, d);
1400 2c0262af bellard
    else
1401 57fec1fe bellard
        gen_op_st_T0_A0(ot + s1->mem_index);
1402 2c0262af bellard
    gen_op_update_inc_cc();
1403 2c0262af bellard
}
1404 2c0262af bellard
1405 2c0262af bellard
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1406 2c0262af bellard
{
1407 2c0262af bellard
    if (d != OR_TMP0)
1408 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, d);
1409 2c0262af bellard
    else
1410 57fec1fe bellard
        gen_op_ld_T0_A0(ot + s1->mem_index);
1411 2c0262af bellard
    if (s != OR_TMP1)
1412 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, s);
1413 2c0262af bellard
    /* for zero counts, flags are not updated, so must do it dynamically */
1414 2c0262af bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
1415 2c0262af bellard
        gen_op_set_cc_op(s1->cc_op);
1416 3b46e624 ths
1417 2c0262af bellard
    if (d != OR_TMP0)
1418 2c0262af bellard
        gen_op_shift_T0_T1_cc[ot][op]();
1419 2c0262af bellard
    else
1420 4f31916f bellard
        gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1421 2c0262af bellard
    if (d != OR_TMP0)
1422 57fec1fe bellard
        gen_op_mov_reg_T0(ot, d);
1423 2c0262af bellard
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1424 2c0262af bellard
}
1425 2c0262af bellard
1426 2c0262af bellard
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1427 2c0262af bellard
{
1428 2c0262af bellard
    /* currently not optimized */
1429 2c0262af bellard
    gen_op_movl_T1_im(c);
1430 2c0262af bellard
    gen_shift(s1, op, ot, d, OR_TMP1);
1431 2c0262af bellard
}
1432 2c0262af bellard
1433 2c0262af bellard
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1434 2c0262af bellard
{
1435 14ce26e7 bellard
    target_long disp;
1436 2c0262af bellard
    int havesib;
1437 14ce26e7 bellard
    int base;
1438 2c0262af bellard
    int index;
1439 2c0262af bellard
    int scale;
1440 2c0262af bellard
    int opreg;
1441 2c0262af bellard
    int mod, rm, code, override, must_add_seg;
1442 2c0262af bellard
1443 2c0262af bellard
    override = s->override;
1444 2c0262af bellard
    must_add_seg = s->addseg;
1445 2c0262af bellard
    if (override >= 0)
1446 2c0262af bellard
        must_add_seg = 1;
1447 2c0262af bellard
    mod = (modrm >> 6) & 3;
1448 2c0262af bellard
    rm = modrm & 7;
1449 2c0262af bellard
1450 2c0262af bellard
    if (s->aflag) {
1451 2c0262af bellard
1452 2c0262af bellard
        havesib = 0;
1453 2c0262af bellard
        base = rm;
1454 2c0262af bellard
        index = 0;
1455 2c0262af bellard
        scale = 0;
1456 3b46e624 ths
1457 2c0262af bellard
        if (base == 4) {
1458 2c0262af bellard
            havesib = 1;
1459 61382a50 bellard
            code = ldub_code(s->pc++);
1460 2c0262af bellard
            scale = (code >> 6) & 3;
1461 14ce26e7 bellard
            index = ((code >> 3) & 7) | REX_X(s);
1462 14ce26e7 bellard
            base = (code & 7);
1463 2c0262af bellard
        }
1464 14ce26e7 bellard
        base |= REX_B(s);
1465 2c0262af bellard
1466 2c0262af bellard
        switch (mod) {
1467 2c0262af bellard
        case 0:
1468 14ce26e7 bellard
            if ((base & 7) == 5) {
1469 2c0262af bellard
                base = -1;
1470 14ce26e7 bellard
                disp = (int32_t)ldl_code(s->pc);
1471 2c0262af bellard
                s->pc += 4;
1472 14ce26e7 bellard
                if (CODE64(s) && !havesib) {
1473 14ce26e7 bellard
                    disp += s->pc + s->rip_offset;
1474 14ce26e7 bellard
                }
1475 2c0262af bellard
            } else {
1476 2c0262af bellard
                disp = 0;
1477 2c0262af bellard
            }
1478 2c0262af bellard
            break;
1479 2c0262af bellard
        case 1:
1480 61382a50 bellard
            disp = (int8_t)ldub_code(s->pc++);
1481 2c0262af bellard
            break;
1482 2c0262af bellard
        default:
1483 2c0262af bellard
        case 2:
1484 61382a50 bellard
            disp = ldl_code(s->pc);
1485 2c0262af bellard
            s->pc += 4;
1486 2c0262af bellard
            break;
1487 2c0262af bellard
        }
1488 3b46e624 ths
1489 2c0262af bellard
        if (base >= 0) {
1490 2c0262af bellard
            /* for correct popl handling with esp */
1491 2c0262af bellard
            if (base == 4 && s->popl_esp_hack)
1492 2c0262af bellard
                disp += s->popl_esp_hack;
1493 14ce26e7 bellard
#ifdef TARGET_X86_64
1494 14ce26e7 bellard
            if (s->aflag == 2) {
1495 57fec1fe bellard
                gen_op_movq_A0_reg(base);
1496 14ce26e7 bellard
                if (disp != 0) {
1497 57fec1fe bellard
                    gen_op_addq_A0_im(disp);
1498 14ce26e7 bellard
                }
1499 5fafdf24 ths
            } else
1500 14ce26e7 bellard
#endif
1501 14ce26e7 bellard
            {
1502 57fec1fe bellard
                gen_op_movl_A0_reg(base);
1503 14ce26e7 bellard
                if (disp != 0)
1504 14ce26e7 bellard
                    gen_op_addl_A0_im(disp);
1505 14ce26e7 bellard
            }
1506 2c0262af bellard
        } else {
1507 14ce26e7 bellard
#ifdef TARGET_X86_64
1508 14ce26e7 bellard
            if (s->aflag == 2) {
1509 57fec1fe bellard
                gen_op_movq_A0_im(disp);
1510 5fafdf24 ths
            } else
1511 14ce26e7 bellard
#endif
1512 14ce26e7 bellard
            {
1513 14ce26e7 bellard
                gen_op_movl_A0_im(disp);
1514 14ce26e7 bellard
            }
1515 2c0262af bellard
        }
1516 2c0262af bellard
        /* XXX: index == 4 is always invalid */
1517 2c0262af bellard
        if (havesib && (index != 4 || scale != 0)) {
1518 14ce26e7 bellard
#ifdef TARGET_X86_64
1519 14ce26e7 bellard
            if (s->aflag == 2) {
1520 57fec1fe bellard
                gen_op_addq_A0_reg_sN(scale, index);
1521 5fafdf24 ths
            } else
1522 14ce26e7 bellard
#endif
1523 14ce26e7 bellard
            {
1524 57fec1fe bellard
                gen_op_addl_A0_reg_sN(scale, index);
1525 14ce26e7 bellard
            }
1526 2c0262af bellard
        }
1527 2c0262af bellard
        if (must_add_seg) {
1528 2c0262af bellard
            if (override < 0) {
1529 2c0262af bellard
                if (base == R_EBP || base == R_ESP)
1530 2c0262af bellard
                    override = R_SS;
1531 2c0262af bellard
                else
1532 2c0262af bellard
                    override = R_DS;
1533 2c0262af bellard
            }
1534 14ce26e7 bellard
#ifdef TARGET_X86_64
1535 14ce26e7 bellard
            if (s->aflag == 2) {
1536 57fec1fe bellard
                gen_op_addq_A0_seg(override);
1537 5fafdf24 ths
            } else
1538 14ce26e7 bellard
#endif
1539 14ce26e7 bellard
            {
1540 57fec1fe bellard
                gen_op_addl_A0_seg(override);
1541 14ce26e7 bellard
            }
1542 2c0262af bellard
        }
1543 2c0262af bellard
    } else {
1544 2c0262af bellard
        switch (mod) {
1545 2c0262af bellard
        case 0:
1546 2c0262af bellard
            if (rm == 6) {
1547 61382a50 bellard
                disp = lduw_code(s->pc);
1548 2c0262af bellard
                s->pc += 2;
1549 2c0262af bellard
                gen_op_movl_A0_im(disp);
1550 2c0262af bellard
                rm = 0; /* avoid SS override */
1551 2c0262af bellard
                goto no_rm;
1552 2c0262af bellard
            } else {
1553 2c0262af bellard
                disp = 0;
1554 2c0262af bellard
            }
1555 2c0262af bellard
            break;
1556 2c0262af bellard
        case 1:
1557 61382a50 bellard
            disp = (int8_t)ldub_code(s->pc++);
1558 2c0262af bellard
            break;
1559 2c0262af bellard
        default:
1560 2c0262af bellard
        case 2:
1561 61382a50 bellard
            disp = lduw_code(s->pc);
1562 2c0262af bellard
            s->pc += 2;
1563 2c0262af bellard
            break;
1564 2c0262af bellard
        }
1565 2c0262af bellard
        switch(rm) {
1566 2c0262af bellard
        case 0:
1567 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBX);
1568 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_ESI);
1569 2c0262af bellard
            break;
1570 2c0262af bellard
        case 1:
1571 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBX);
1572 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_EDI);
1573 2c0262af bellard
            break;
1574 2c0262af bellard
        case 2:
1575 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBP);
1576 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_ESI);
1577 2c0262af bellard
            break;
1578 2c0262af bellard
        case 3:
1579 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBP);
1580 57fec1fe bellard
            gen_op_addl_A0_reg_sN(0, R_EDI);
1581 2c0262af bellard
            break;
1582 2c0262af bellard
        case 4:
1583 57fec1fe bellard
            gen_op_movl_A0_reg(R_ESI);
1584 2c0262af bellard
            break;
1585 2c0262af bellard
        case 5:
1586 57fec1fe bellard
            gen_op_movl_A0_reg(R_EDI);
1587 2c0262af bellard
            break;
1588 2c0262af bellard
        case 6:
1589 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBP);
1590 2c0262af bellard
            break;
1591 2c0262af bellard
        default:
1592 2c0262af bellard
        case 7:
1593 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBX);
1594 2c0262af bellard
            break;
1595 2c0262af bellard
        }
1596 2c0262af bellard
        if (disp != 0)
1597 2c0262af bellard
            gen_op_addl_A0_im(disp);
1598 2c0262af bellard
        gen_op_andl_A0_ffff();
1599 2c0262af bellard
    no_rm:
1600 2c0262af bellard
        if (must_add_seg) {
1601 2c0262af bellard
            if (override < 0) {
1602 2c0262af bellard
                if (rm == 2 || rm == 3 || rm == 6)
1603 2c0262af bellard
                    override = R_SS;
1604 2c0262af bellard
                else
1605 2c0262af bellard
                    override = R_DS;
1606 2c0262af bellard
            }
1607 57fec1fe bellard
            gen_op_addl_A0_seg(override);
1608 2c0262af bellard
        }
1609 2c0262af bellard
    }
1610 2c0262af bellard
1611 2c0262af bellard
    opreg = OR_A0;
1612 2c0262af bellard
    disp = 0;
1613 2c0262af bellard
    *reg_ptr = opreg;
1614 2c0262af bellard
    *offset_ptr = disp;
1615 2c0262af bellard
}
1616 2c0262af bellard
1617 e17a36ce bellard
static void gen_nop_modrm(DisasContext *s, int modrm)
1618 e17a36ce bellard
{
1619 e17a36ce bellard
    int mod, rm, base, code;
1620 e17a36ce bellard
1621 e17a36ce bellard
    mod = (modrm >> 6) & 3;
1622 e17a36ce bellard
    if (mod == 3)
1623 e17a36ce bellard
        return;
1624 e17a36ce bellard
    rm = modrm & 7;
1625 e17a36ce bellard
1626 e17a36ce bellard
    if (s->aflag) {
1627 e17a36ce bellard
1628 e17a36ce bellard
        base = rm;
1629 3b46e624 ths
1630 e17a36ce bellard
        if (base == 4) {
1631 e17a36ce bellard
            code = ldub_code(s->pc++);
1632 e17a36ce bellard
            base = (code & 7);
1633 e17a36ce bellard
        }
1634 3b46e624 ths
1635 e17a36ce bellard
        switch (mod) {
1636 e17a36ce bellard
        case 0:
1637 e17a36ce bellard
            if (base == 5) {
1638 e17a36ce bellard
                s->pc += 4;
1639 e17a36ce bellard
            }
1640 e17a36ce bellard
            break;
1641 e17a36ce bellard
        case 1:
1642 e17a36ce bellard
            s->pc++;
1643 e17a36ce bellard
            break;
1644 e17a36ce bellard
        default:
1645 e17a36ce bellard
        case 2:
1646 e17a36ce bellard
            s->pc += 4;
1647 e17a36ce bellard
            break;
1648 e17a36ce bellard
        }
1649 e17a36ce bellard
    } else {
1650 e17a36ce bellard
        switch (mod) {
1651 e17a36ce bellard
        case 0:
1652 e17a36ce bellard
            if (rm == 6) {
1653 e17a36ce bellard
                s->pc += 2;
1654 e17a36ce bellard
            }
1655 e17a36ce bellard
            break;
1656 e17a36ce bellard
        case 1:
1657 e17a36ce bellard
            s->pc++;
1658 e17a36ce bellard
            break;
1659 e17a36ce bellard
        default:
1660 e17a36ce bellard
        case 2:
1661 e17a36ce bellard
            s->pc += 2;
1662 e17a36ce bellard
            break;
1663 e17a36ce bellard
        }
1664 e17a36ce bellard
    }
1665 e17a36ce bellard
}
1666 e17a36ce bellard
1667 664e0f19 bellard
/* used for LEA and MOV AX, mem */
1668 664e0f19 bellard
static void gen_add_A0_ds_seg(DisasContext *s)
1669 664e0f19 bellard
{
1670 664e0f19 bellard
    int override, must_add_seg;
1671 664e0f19 bellard
    must_add_seg = s->addseg;
1672 664e0f19 bellard
    override = R_DS;
1673 664e0f19 bellard
    if (s->override >= 0) {
1674 664e0f19 bellard
        override = s->override;
1675 664e0f19 bellard
        must_add_seg = 1;
1676 664e0f19 bellard
    } else {
1677 664e0f19 bellard
        override = R_DS;
1678 664e0f19 bellard
    }
1679 664e0f19 bellard
    if (must_add_seg) {
1680 8f091a59 bellard
#ifdef TARGET_X86_64
1681 8f091a59 bellard
        if (CODE64(s)) {
1682 57fec1fe bellard
            gen_op_addq_A0_seg(override);
1683 5fafdf24 ths
        } else
1684 8f091a59 bellard
#endif
1685 8f091a59 bellard
        {
1686 57fec1fe bellard
            gen_op_addl_A0_seg(override);
1687 8f091a59 bellard
        }
1688 664e0f19 bellard
    }
1689 664e0f19 bellard
}
1690 664e0f19 bellard
1691 2c0262af bellard
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1692 2c0262af bellard
   OR_TMP0 */
1693 2c0262af bellard
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1694 2c0262af bellard
{
1695 2c0262af bellard
    int mod, rm, opreg, disp;
1696 2c0262af bellard
1697 2c0262af bellard
    mod = (modrm >> 6) & 3;
1698 14ce26e7 bellard
    rm = (modrm & 7) | REX_B(s);
1699 2c0262af bellard
    if (mod == 3) {
1700 2c0262af bellard
        if (is_store) {
1701 2c0262af bellard
            if (reg != OR_TMP0)
1702 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, reg);
1703 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
1704 2c0262af bellard
        } else {
1705 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
1706 2c0262af bellard
            if (reg != OR_TMP0)
1707 57fec1fe bellard
                gen_op_mov_reg_T0(ot, reg);
1708 2c0262af bellard
        }
1709 2c0262af bellard
    } else {
1710 2c0262af bellard
        gen_lea_modrm(s, modrm, &opreg, &disp);
1711 2c0262af bellard
        if (is_store) {
1712 2c0262af bellard
            if (reg != OR_TMP0)
1713 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, reg);
1714 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
1715 2c0262af bellard
        } else {
1716 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
1717 2c0262af bellard
            if (reg != OR_TMP0)
1718 57fec1fe bellard
                gen_op_mov_reg_T0(ot, reg);
1719 2c0262af bellard
        }
1720 2c0262af bellard
    }
1721 2c0262af bellard
}
1722 2c0262af bellard
1723 2c0262af bellard
static inline uint32_t insn_get(DisasContext *s, int ot)
1724 2c0262af bellard
{
1725 2c0262af bellard
    uint32_t ret;
1726 2c0262af bellard
1727 2c0262af bellard
    switch(ot) {
1728 2c0262af bellard
    case OT_BYTE:
1729 61382a50 bellard
        ret = ldub_code(s->pc);
1730 2c0262af bellard
        s->pc++;
1731 2c0262af bellard
        break;
1732 2c0262af bellard
    case OT_WORD:
1733 61382a50 bellard
        ret = lduw_code(s->pc);
1734 2c0262af bellard
        s->pc += 2;
1735 2c0262af bellard
        break;
1736 2c0262af bellard
    default:
1737 2c0262af bellard
    case OT_LONG:
1738 61382a50 bellard
        ret = ldl_code(s->pc);
1739 2c0262af bellard
        s->pc += 4;
1740 2c0262af bellard
        break;
1741 2c0262af bellard
    }
1742 2c0262af bellard
    return ret;
1743 2c0262af bellard
}
1744 2c0262af bellard
1745 14ce26e7 bellard
static inline int insn_const_size(unsigned int ot)
1746 14ce26e7 bellard
{
1747 14ce26e7 bellard
    if (ot <= OT_LONG)
1748 14ce26e7 bellard
        return 1 << ot;
1749 14ce26e7 bellard
    else
1750 14ce26e7 bellard
        return 4;
1751 14ce26e7 bellard
}
1752 14ce26e7 bellard
1753 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1754 6e256c93 bellard
{
1755 6e256c93 bellard
    TranslationBlock *tb;
1756 6e256c93 bellard
    target_ulong pc;
1757 6e256c93 bellard
1758 6e256c93 bellard
    pc = s->cs_base + eip;
1759 6e256c93 bellard
    tb = s->tb;
1760 6e256c93 bellard
    /* NOTE: we handle the case where the TB spans two pages here */
1761 6e256c93 bellard
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1762 6e256c93 bellard
        (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))  {
1763 6e256c93 bellard
        /* jump to same page: we can use a direct jump */
1764 57fec1fe bellard
        tcg_gen_goto_tb(tb_num);
1765 6e256c93 bellard
        gen_jmp_im(eip);
1766 57fec1fe bellard
        tcg_gen_exit_tb((long)tb + tb_num);
1767 6e256c93 bellard
    } else {
1768 6e256c93 bellard
        /* jump to another page: currently not optimized */
1769 6e256c93 bellard
        gen_jmp_im(eip);
1770 6e256c93 bellard
        gen_eob(s);
1771 6e256c93 bellard
    }
1772 6e256c93 bellard
}
1773 6e256c93 bellard
1774 5fafdf24 ths
static inline void gen_jcc(DisasContext *s, int b,
1775 14ce26e7 bellard
                           target_ulong val, target_ulong next_eip)
1776 2c0262af bellard
{
1777 2c0262af bellard
    TranslationBlock *tb;
1778 2c0262af bellard
    int inv, jcc_op;
1779 14ce26e7 bellard
    GenOpFunc1 *func;
1780 14ce26e7 bellard
    target_ulong tmp;
1781 14ce26e7 bellard
    int l1, l2;
1782 2c0262af bellard
1783 2c0262af bellard
    inv = b & 1;
1784 2c0262af bellard
    jcc_op = (b >> 1) & 7;
1785 3b46e624 ths
1786 2c0262af bellard
    if (s->jmp_opt) {
1787 2c0262af bellard
        switch(s->cc_op) {
1788 2c0262af bellard
            /* we optimize the cmp/jcc case */
1789 2c0262af bellard
        case CC_OP_SUBB:
1790 2c0262af bellard
        case CC_OP_SUBW:
1791 2c0262af bellard
        case CC_OP_SUBL:
1792 14ce26e7 bellard
        case CC_OP_SUBQ:
1793 2c0262af bellard
            func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1794 2c0262af bellard
            break;
1795 3b46e624 ths
1796 2c0262af bellard
            /* some jumps are easy to compute */
1797 2c0262af bellard
        case CC_OP_ADDB:
1798 2c0262af bellard
        case CC_OP_ADDW:
1799 2c0262af bellard
        case CC_OP_ADDL:
1800 14ce26e7 bellard
        case CC_OP_ADDQ:
1801 14ce26e7 bellard
1802 2c0262af bellard
        case CC_OP_ADCB:
1803 2c0262af bellard
        case CC_OP_ADCW:
1804 2c0262af bellard
        case CC_OP_ADCL:
1805 14ce26e7 bellard
        case CC_OP_ADCQ:
1806 14ce26e7 bellard
1807 2c0262af bellard
        case CC_OP_SBBB:
1808 2c0262af bellard
        case CC_OP_SBBW:
1809 2c0262af bellard
        case CC_OP_SBBL:
1810 14ce26e7 bellard
        case CC_OP_SBBQ:
1811 14ce26e7 bellard
1812 2c0262af bellard
        case CC_OP_LOGICB:
1813 2c0262af bellard
        case CC_OP_LOGICW:
1814 2c0262af bellard
        case CC_OP_LOGICL:
1815 14ce26e7 bellard
        case CC_OP_LOGICQ:
1816 14ce26e7 bellard
1817 2c0262af bellard
        case CC_OP_INCB:
1818 2c0262af bellard
        case CC_OP_INCW:
1819 2c0262af bellard
        case CC_OP_INCL:
1820 14ce26e7 bellard
        case CC_OP_INCQ:
1821 14ce26e7 bellard
1822 2c0262af bellard
        case CC_OP_DECB:
1823 2c0262af bellard
        case CC_OP_DECW:
1824 2c0262af bellard
        case CC_OP_DECL:
1825 14ce26e7 bellard
        case CC_OP_DECQ:
1826 14ce26e7 bellard
1827 2c0262af bellard
        case CC_OP_SHLB:
1828 2c0262af bellard
        case CC_OP_SHLW:
1829 2c0262af bellard
        case CC_OP_SHLL:
1830 14ce26e7 bellard
        case CC_OP_SHLQ:
1831 14ce26e7 bellard
1832 2c0262af bellard
        case CC_OP_SARB:
1833 2c0262af bellard
        case CC_OP_SARW:
1834 2c0262af bellard
        case CC_OP_SARL:
1835 14ce26e7 bellard
        case CC_OP_SARQ:
1836 2c0262af bellard
            switch(jcc_op) {
1837 2c0262af bellard
            case JCC_Z:
1838 14ce26e7 bellard
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1839 2c0262af bellard
                break;
1840 2c0262af bellard
            case JCC_S:
1841 14ce26e7 bellard
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1842 2c0262af bellard
                break;
1843 2c0262af bellard
            default:
1844 2c0262af bellard
                func = NULL;
1845 2c0262af bellard
                break;
1846 2c0262af bellard
            }
1847 2c0262af bellard
            break;
1848 2c0262af bellard
        default:
1849 2c0262af bellard
            func = NULL;
1850 2c0262af bellard
            break;
1851 2c0262af bellard
        }
1852 2c0262af bellard
1853 6e256c93 bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
1854 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
1855 6e256c93 bellard
            s->cc_op = CC_OP_DYNAMIC;
1856 6e256c93 bellard
        }
1857 2c0262af bellard
1858 2c0262af bellard
        if (!func) {
1859 2c0262af bellard
            gen_setcc_slow[jcc_op]();
1860 14ce26e7 bellard
            func = gen_op_jnz_T0_label;
1861 2c0262af bellard
        }
1862 3b46e624 ths
1863 14ce26e7 bellard
        if (inv) {
1864 14ce26e7 bellard
            tmp = val;
1865 14ce26e7 bellard
            val = next_eip;
1866 14ce26e7 bellard
            next_eip = tmp;
1867 2c0262af bellard
        }
1868 14ce26e7 bellard
        tb = s->tb;
1869 14ce26e7 bellard
1870 14ce26e7 bellard
        l1 = gen_new_label();
1871 14ce26e7 bellard
        func(l1);
1872 14ce26e7 bellard
1873 6e256c93 bellard
        gen_goto_tb(s, 0, next_eip);
1874 14ce26e7 bellard
1875 14ce26e7 bellard
        gen_set_label(l1);
1876 6e256c93 bellard
        gen_goto_tb(s, 1, val);
1877 14ce26e7 bellard
1878 2c0262af bellard
        s->is_jmp = 3;
1879 2c0262af bellard
    } else {
1880 14ce26e7 bellard
1881 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
1882 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
1883 2c0262af bellard
            s->cc_op = CC_OP_DYNAMIC;
1884 2c0262af bellard
        }
1885 2c0262af bellard
        gen_setcc_slow[jcc_op]();
1886 14ce26e7 bellard
        if (inv) {
1887 14ce26e7 bellard
            tmp = val;
1888 14ce26e7 bellard
            val = next_eip;
1889 14ce26e7 bellard
            next_eip = tmp;
1890 2c0262af bellard
        }
1891 14ce26e7 bellard
        l1 = gen_new_label();
1892 14ce26e7 bellard
        l2 = gen_new_label();
1893 14ce26e7 bellard
        gen_op_jnz_T0_label(l1);
1894 14ce26e7 bellard
        gen_jmp_im(next_eip);
1895 14ce26e7 bellard
        gen_op_jmp_label(l2);
1896 14ce26e7 bellard
        gen_set_label(l1);
1897 14ce26e7 bellard
        gen_jmp_im(val);
1898 14ce26e7 bellard
        gen_set_label(l2);
1899 2c0262af bellard
        gen_eob(s);
1900 2c0262af bellard
    }
1901 2c0262af bellard
}
1902 2c0262af bellard
1903 2c0262af bellard
static void gen_setcc(DisasContext *s, int b)
1904 2c0262af bellard
{
1905 2c0262af bellard
    int inv, jcc_op;
1906 2c0262af bellard
    GenOpFunc *func;
1907 2c0262af bellard
1908 2c0262af bellard
    inv = b & 1;
1909 2c0262af bellard
    jcc_op = (b >> 1) & 7;
1910 2c0262af bellard
    switch(s->cc_op) {
1911 2c0262af bellard
        /* we optimize the cmp/jcc case */
1912 2c0262af bellard
    case CC_OP_SUBB:
1913 2c0262af bellard
    case CC_OP_SUBW:
1914 2c0262af bellard
    case CC_OP_SUBL:
1915 14ce26e7 bellard
    case CC_OP_SUBQ:
1916 2c0262af bellard
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1917 2c0262af bellard
        if (!func)
1918 2c0262af bellard
            goto slow_jcc;
1919 2c0262af bellard
        break;
1920 3b46e624 ths
1921 2c0262af bellard
        /* some jumps are easy to compute */
1922 2c0262af bellard
    case CC_OP_ADDB:
1923 2c0262af bellard
    case CC_OP_ADDW:
1924 2c0262af bellard
    case CC_OP_ADDL:
1925 14ce26e7 bellard
    case CC_OP_ADDQ:
1926 14ce26e7 bellard
1927 2c0262af bellard
    case CC_OP_LOGICB:
1928 2c0262af bellard
    case CC_OP_LOGICW:
1929 2c0262af bellard
    case CC_OP_LOGICL:
1930 14ce26e7 bellard
    case CC_OP_LOGICQ:
1931 14ce26e7 bellard
1932 2c0262af bellard
    case CC_OP_INCB:
1933 2c0262af bellard
    case CC_OP_INCW:
1934 2c0262af bellard
    case CC_OP_INCL:
1935 14ce26e7 bellard
    case CC_OP_INCQ:
1936 14ce26e7 bellard
1937 2c0262af bellard
    case CC_OP_DECB:
1938 2c0262af bellard
    case CC_OP_DECW:
1939 2c0262af bellard
    case CC_OP_DECL:
1940 14ce26e7 bellard
    case CC_OP_DECQ:
1941 14ce26e7 bellard
1942 2c0262af bellard
    case CC_OP_SHLB:
1943 2c0262af bellard
    case CC_OP_SHLW:
1944 2c0262af bellard
    case CC_OP_SHLL:
1945 14ce26e7 bellard
    case CC_OP_SHLQ:
1946 2c0262af bellard
        switch(jcc_op) {
1947 2c0262af bellard
        case JCC_Z:
1948 14ce26e7 bellard
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1949 2c0262af bellard
            break;
1950 2c0262af bellard
        case JCC_S:
1951 14ce26e7 bellard
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1952 2c0262af bellard
            break;
1953 2c0262af bellard
        default:
1954 2c0262af bellard
            goto slow_jcc;
1955 2c0262af bellard
        }
1956 2c0262af bellard
        break;
1957 2c0262af bellard
    default:
1958 2c0262af bellard
    slow_jcc:
1959 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1960 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
1961 2c0262af bellard
        func = gen_setcc_slow[jcc_op];
1962 2c0262af bellard
        break;
1963 2c0262af bellard
    }
1964 2c0262af bellard
    func();
1965 2c0262af bellard
    if (inv) {
1966 2c0262af bellard
        gen_op_xor_T0_1();
1967 2c0262af bellard
    }
1968 2c0262af bellard
}
1969 2c0262af bellard
1970 2c0262af bellard
/* move T0 to seg_reg and compute if the CPU state may change. Never
1971 2c0262af bellard
   call this function with seg_reg == R_CS */
1972 14ce26e7 bellard
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1973 2c0262af bellard
{
1974 3415a4dd bellard
    if (s->pe && !s->vm86) {
1975 3415a4dd bellard
        /* XXX: optimize by finding processor state dynamically */
1976 3415a4dd bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1977 3415a4dd bellard
            gen_op_set_cc_op(s->cc_op);
1978 14ce26e7 bellard
        gen_jmp_im(cur_eip);
1979 3415a4dd bellard
        gen_op_movl_seg_T0(seg_reg);
1980 dc196a57 bellard
        /* abort translation because the addseg value may change or
1981 dc196a57 bellard
           because ss32 may change. For R_SS, translation must always
1982 dc196a57 bellard
           stop as a special handling must be done to disable hardware
1983 dc196a57 bellard
           interrupts for the next instruction */
1984 dc196a57 bellard
        if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1985 dc196a57 bellard
            s->is_jmp = 3;
1986 3415a4dd bellard
    } else {
1987 2c0262af bellard
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1988 dc196a57 bellard
        if (seg_reg == R_SS)
1989 dc196a57 bellard
            s->is_jmp = 3;
1990 3415a4dd bellard
    }
1991 2c0262af bellard
}
1992 2c0262af bellard
1993 57fec1fe bellard
#define SVM_movq_T1_im(x) gen_movtl_T1_im(x)
1994 0573fbfc ths
1995 0573fbfc ths
static inline int
1996 0573fbfc ths
gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
1997 0573fbfc ths
{
1998 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
1999 0573fbfc ths
    if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
2000 0573fbfc ths
        if (s->cc_op != CC_OP_DYNAMIC)
2001 0573fbfc ths
            gen_op_set_cc_op(s->cc_op);
2002 0573fbfc ths
        SVM_movq_T1_im(s->pc - s->cs_base);
2003 0573fbfc ths
        gen_jmp_im(pc_start - s->cs_base);
2004 0573fbfc ths
        gen_op_geneflags();
2005 0573fbfc ths
        gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
2006 0573fbfc ths
        s->cc_op = CC_OP_DYNAMIC;
2007 0573fbfc ths
        /* FIXME: maybe we could move the io intercept vector to the TB as well
2008 0573fbfc ths
                  so we know if this is an EOB or not ... let's assume it's not
2009 0573fbfc ths
                  for now. */
2010 0573fbfc ths
    }
2011 0573fbfc ths
#endif
2012 0573fbfc ths
    return 0;
2013 0573fbfc ths
}
2014 0573fbfc ths
2015 0573fbfc ths
static inline int svm_is_rep(int prefixes)
2016 0573fbfc ths
{
2017 0573fbfc ths
    return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2018 0573fbfc ths
}
2019 0573fbfc ths
2020 0573fbfc ths
static inline int
2021 0573fbfc ths
gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2022 0573fbfc ths
                              uint64_t type, uint64_t param)
2023 0573fbfc ths
{
2024 0573fbfc ths
    if(!(s->flags & (INTERCEPT_SVM_MASK)))
2025 0573fbfc ths
        /* no SVM activated */
2026 0573fbfc ths
        return 0;
2027 0573fbfc ths
    switch(type) {
2028 0573fbfc ths
        /* CRx and DRx reads/writes */
2029 0573fbfc ths
        case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
2030 0573fbfc ths
            if (s->cc_op != CC_OP_DYNAMIC) {
2031 0573fbfc ths
                gen_op_set_cc_op(s->cc_op);
2032 0573fbfc ths
                s->cc_op = CC_OP_DYNAMIC;
2033 0573fbfc ths
            }
2034 0573fbfc ths
            gen_jmp_im(pc_start - s->cs_base);
2035 0573fbfc ths
            SVM_movq_T1_im(param);
2036 0573fbfc ths
            gen_op_geneflags();
2037 0573fbfc ths
            gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2038 0573fbfc ths
            /* this is a special case as we do not know if the interception occurs
2039 0573fbfc ths
               so we assume there was none */
2040 0573fbfc ths
            return 0;
2041 0573fbfc ths
        case SVM_EXIT_MSR:
2042 0573fbfc ths
            if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
2043 0573fbfc ths
                if (s->cc_op != CC_OP_DYNAMIC) {
2044 0573fbfc ths
                    gen_op_set_cc_op(s->cc_op);
2045 0573fbfc ths
                    s->cc_op = CC_OP_DYNAMIC;
2046 0573fbfc ths
                }
2047 0573fbfc ths
                gen_jmp_im(pc_start - s->cs_base);
2048 0573fbfc ths
                SVM_movq_T1_im(param);
2049 0573fbfc ths
                gen_op_geneflags();
2050 0573fbfc ths
                gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2051 0573fbfc ths
                /* this is a special case as we do not know if the interception occurs
2052 0573fbfc ths
                   so we assume there was none */
2053 0573fbfc ths
                return 0;
2054 0573fbfc ths
            }
2055 0573fbfc ths
            break;
2056 0573fbfc ths
        default:
2057 0573fbfc ths
            if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
2058 0573fbfc ths
                if (s->cc_op != CC_OP_DYNAMIC) {
2059 0573fbfc ths
                    gen_op_set_cc_op(s->cc_op);
2060 0573fbfc ths
                    s->cc_op = CC_OP_EFLAGS;
2061 0573fbfc ths
                }
2062 0573fbfc ths
                gen_jmp_im(pc_start - s->cs_base);
2063 0573fbfc ths
                SVM_movq_T1_im(param);
2064 0573fbfc ths
                gen_op_geneflags();
2065 0573fbfc ths
                gen_op_svm_vmexit(type >> 32, type);
2066 0573fbfc ths
                /* we can optimize this one so TBs don't get longer
2067 0573fbfc ths
                   than up to vmexit */
2068 0573fbfc ths
                gen_eob(s);
2069 0573fbfc ths
                return 1;
2070 0573fbfc ths
            }
2071 0573fbfc ths
    }
2072 0573fbfc ths
    return 0;
2073 0573fbfc ths
}
2074 0573fbfc ths
2075 0573fbfc ths
static inline int
2076 0573fbfc ths
gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2077 0573fbfc ths
{
2078 0573fbfc ths
    return gen_svm_check_intercept_param(s, pc_start, type, 0);
2079 0573fbfc ths
}
2080 0573fbfc ths
2081 4f31916f bellard
static inline void gen_stack_update(DisasContext *s, int addend)
2082 4f31916f bellard
{
2083 14ce26e7 bellard
#ifdef TARGET_X86_64
2084 14ce26e7 bellard
    if (CODE64(s)) {
2085 57fec1fe bellard
        gen_op_addq_ESP_im(addend);
2086 14ce26e7 bellard
    } else
2087 14ce26e7 bellard
#endif
2088 4f31916f bellard
    if (s->ss32) {
2089 57fec1fe bellard
        gen_op_addl_ESP_im(addend);
2090 4f31916f bellard
    } else {
2091 57fec1fe bellard
        gen_op_addw_ESP_im(addend);
2092 4f31916f bellard
    }
2093 4f31916f bellard
}
2094 4f31916f bellard
2095 2c0262af bellard
/* generate a push. It depends on ss32, addseg and dflag */
2096 2c0262af bellard
static void gen_push_T0(DisasContext *s)
2097 2c0262af bellard
{
2098 14ce26e7 bellard
#ifdef TARGET_X86_64
2099 14ce26e7 bellard
    if (CODE64(s)) {
2100 57fec1fe bellard
        gen_op_movq_A0_reg(R_ESP);
2101 8f091a59 bellard
        if (s->dflag) {
2102 57fec1fe bellard
            gen_op_addq_A0_im(-8);
2103 57fec1fe bellard
            gen_op_st_T0_A0(OT_QUAD + s->mem_index);
2104 8f091a59 bellard
        } else {
2105 57fec1fe bellard
            gen_op_addq_A0_im(-2);
2106 57fec1fe bellard
            gen_op_st_T0_A0(OT_WORD + s->mem_index);
2107 8f091a59 bellard
        }
2108 57fec1fe bellard
        gen_op_mov_reg_A0(2, R_ESP);
2109 5fafdf24 ths
    } else
2110 14ce26e7 bellard
#endif
2111 14ce26e7 bellard
    {
2112 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESP);
2113 14ce26e7 bellard
        if (!s->dflag)
2114 57fec1fe bellard
            gen_op_addl_A0_im(-2);
2115 14ce26e7 bellard
        else
2116 57fec1fe bellard
            gen_op_addl_A0_im(-4);
2117 14ce26e7 bellard
        if (s->ss32) {
2118 14ce26e7 bellard
            if (s->addseg) {
2119 14ce26e7 bellard
                gen_op_movl_T1_A0();
2120 57fec1fe bellard
                gen_op_addl_A0_seg(R_SS);
2121 14ce26e7 bellard
            }
2122 14ce26e7 bellard
        } else {
2123 14ce26e7 bellard
            gen_op_andl_A0_ffff();
2124 4f31916f bellard
            gen_op_movl_T1_A0();
2125 57fec1fe bellard
            gen_op_addl_A0_seg(R_SS);
2126 2c0262af bellard
        }
2127 57fec1fe bellard
        gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
2128 14ce26e7 bellard
        if (s->ss32 && !s->addseg)
2129 57fec1fe bellard
            gen_op_mov_reg_A0(1, R_ESP);
2130 14ce26e7 bellard
        else
2131 57fec1fe bellard
            gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
2132 2c0262af bellard
    }
2133 2c0262af bellard
}
2134 2c0262af bellard
2135 4f31916f bellard
/* generate a push. It depends on ss32, addseg and dflag */
2136 4f31916f bellard
/* slower version for T1, only used for call Ev */
2137 4f31916f bellard
static void gen_push_T1(DisasContext *s)
2138 2c0262af bellard
{
2139 14ce26e7 bellard
#ifdef TARGET_X86_64
2140 14ce26e7 bellard
    if (CODE64(s)) {
2141 57fec1fe bellard
        gen_op_movq_A0_reg(R_ESP);
2142 8f091a59 bellard
        if (s->dflag) {
2143 57fec1fe bellard
            gen_op_addq_A0_im(-8);
2144 57fec1fe bellard
            gen_op_st_T1_A0(OT_QUAD + s->mem_index);
2145 8f091a59 bellard
        } else {
2146 57fec1fe bellard
            gen_op_addq_A0_im(-2);
2147 57fec1fe bellard
            gen_op_st_T0_A0(OT_WORD + s->mem_index);
2148 8f091a59 bellard
        }
2149 57fec1fe bellard
        gen_op_mov_reg_A0(2, R_ESP);
2150 5fafdf24 ths
    } else
2151 14ce26e7 bellard
#endif
2152 14ce26e7 bellard
    {
2153 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESP);
2154 14ce26e7 bellard
        if (!s->dflag)
2155 57fec1fe bellard
            gen_op_addl_A0_im(-2);
2156 14ce26e7 bellard
        else
2157 57fec1fe bellard
            gen_op_addl_A0_im(-4);
2158 14ce26e7 bellard
        if (s->ss32) {
2159 14ce26e7 bellard
            if (s->addseg) {
2160 57fec1fe bellard
                gen_op_addl_A0_seg(R_SS);
2161 14ce26e7 bellard
            }
2162 14ce26e7 bellard
        } else {
2163 14ce26e7 bellard
            gen_op_andl_A0_ffff();
2164 57fec1fe bellard
            gen_op_addl_A0_seg(R_SS);
2165 2c0262af bellard
        }
2166 57fec1fe bellard
        gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
2167 3b46e624 ths
2168 14ce26e7 bellard
        if (s->ss32 && !s->addseg)
2169 57fec1fe bellard
            gen_op_mov_reg_A0(1, R_ESP);
2170 14ce26e7 bellard
        else
2171 14ce26e7 bellard
            gen_stack_update(s, (-2) << s->dflag);
2172 2c0262af bellard
    }
2173 2c0262af bellard
}
2174 2c0262af bellard
2175 4f31916f bellard
/* two step pop is necessary for precise exceptions */
2176 4f31916f bellard
static void gen_pop_T0(DisasContext *s)
2177 2c0262af bellard
{
2178 14ce26e7 bellard
#ifdef TARGET_X86_64
2179 14ce26e7 bellard
    if (CODE64(s)) {
2180 57fec1fe bellard
        gen_op_movq_A0_reg(R_ESP);
2181 57fec1fe bellard
        gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
2182 5fafdf24 ths
    } else
2183 14ce26e7 bellard
#endif
2184 14ce26e7 bellard
    {
2185 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESP);
2186 14ce26e7 bellard
        if (s->ss32) {
2187 14ce26e7 bellard
            if (s->addseg)
2188 57fec1fe bellard
                gen_op_addl_A0_seg(R_SS);
2189 14ce26e7 bellard
        } else {
2190 14ce26e7 bellard
            gen_op_andl_A0_ffff();
2191 57fec1fe bellard
            gen_op_addl_A0_seg(R_SS);
2192 14ce26e7 bellard
        }
2193 57fec1fe bellard
        gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
2194 2c0262af bellard
    }
2195 2c0262af bellard
}
2196 2c0262af bellard
2197 2c0262af bellard
static void gen_pop_update(DisasContext *s)
2198 2c0262af bellard
{
2199 14ce26e7 bellard
#ifdef TARGET_X86_64
2200 8f091a59 bellard
    if (CODE64(s) && s->dflag) {
2201 14ce26e7 bellard
        gen_stack_update(s, 8);
2202 14ce26e7 bellard
    } else
2203 14ce26e7 bellard
#endif
2204 14ce26e7 bellard
    {
2205 14ce26e7 bellard
        gen_stack_update(s, 2 << s->dflag);
2206 14ce26e7 bellard
    }
2207 2c0262af bellard
}
2208 2c0262af bellard
2209 2c0262af bellard
static void gen_stack_A0(DisasContext *s)
2210 2c0262af bellard
{
2211 57fec1fe bellard
    gen_op_movl_A0_reg(R_ESP);
2212 2c0262af bellard
    if (!s->ss32)
2213 2c0262af bellard
        gen_op_andl_A0_ffff();
2214 2c0262af bellard
    gen_op_movl_T1_A0();
2215 2c0262af bellard
    if (s->addseg)
2216 57fec1fe bellard
        gen_op_addl_A0_seg(R_SS);
2217 2c0262af bellard
}
2218 2c0262af bellard
2219 2c0262af bellard
/* NOTE: wrap around in 16 bit not fully handled */
2220 2c0262af bellard
static void gen_pusha(DisasContext *s)
2221 2c0262af bellard
{
2222 2c0262af bellard
    int i;
2223 57fec1fe bellard
    gen_op_movl_A0_reg(R_ESP);
2224 2c0262af bellard
    gen_op_addl_A0_im(-16 <<  s->dflag);
2225 2c0262af bellard
    if (!s->ss32)
2226 2c0262af bellard
        gen_op_andl_A0_ffff();
2227 2c0262af bellard
    gen_op_movl_T1_A0();
2228 2c0262af bellard
    if (s->addseg)
2229 57fec1fe bellard
        gen_op_addl_A0_seg(R_SS);
2230 2c0262af bellard
    for(i = 0;i < 8; i++) {
2231 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
2232 57fec1fe bellard
        gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
2233 2c0262af bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
2234 2c0262af bellard
    }
2235 57fec1fe bellard
    gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2236 2c0262af bellard
}
2237 2c0262af bellard
2238 2c0262af bellard
/* NOTE: wrap around in 16 bit not fully handled */
2239 2c0262af bellard
static void gen_popa(DisasContext *s)
2240 2c0262af bellard
{
2241 2c0262af bellard
    int i;
2242 57fec1fe bellard
    gen_op_movl_A0_reg(R_ESP);
2243 2c0262af bellard
    if (!s->ss32)
2244 2c0262af bellard
        gen_op_andl_A0_ffff();
2245 2c0262af bellard
    gen_op_movl_T1_A0();
2246 2c0262af bellard
    gen_op_addl_T1_im(16 <<  s->dflag);
2247 2c0262af bellard
    if (s->addseg)
2248 57fec1fe bellard
        gen_op_addl_A0_seg(R_SS);
2249 2c0262af bellard
    for(i = 0;i < 8; i++) {
2250 2c0262af bellard
        /* ESP is not reloaded */
2251 2c0262af bellard
        if (i != 3) {
2252 57fec1fe bellard
            gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
2253 57fec1fe bellard
            gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
2254 2c0262af bellard
        }
2255 2c0262af bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
2256 2c0262af bellard
    }
2257 57fec1fe bellard
    gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2258 2c0262af bellard
}
2259 2c0262af bellard
2260 2c0262af bellard
static void gen_enter(DisasContext *s, int esp_addend, int level)
2261 2c0262af bellard
{
2262 61a8c4ec bellard
    int ot, opsize;
2263 2c0262af bellard
2264 2c0262af bellard
    level &= 0x1f;
2265 8f091a59 bellard
#ifdef TARGET_X86_64
2266 8f091a59 bellard
    if (CODE64(s)) {
2267 8f091a59 bellard
        ot = s->dflag ? OT_QUAD : OT_WORD;
2268 8f091a59 bellard
        opsize = 1 << ot;
2269 3b46e624 ths
2270 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESP);
2271 8f091a59 bellard
        gen_op_addq_A0_im(-opsize);
2272 8f091a59 bellard
        gen_op_movl_T1_A0();
2273 8f091a59 bellard
2274 8f091a59 bellard
        /* push bp */
2275 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2276 57fec1fe bellard
        gen_op_st_T0_A0(ot + s->mem_index);
2277 8f091a59 bellard
        if (level) {
2278 8f091a59 bellard
            gen_op_enter64_level(level, (ot == OT_QUAD));
2279 8f091a59 bellard
        }
2280 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EBP);
2281 8f091a59 bellard
        gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2282 57fec1fe bellard
        gen_op_mov_reg_T1(OT_QUAD, R_ESP);
2283 5fafdf24 ths
    } else
2284 8f091a59 bellard
#endif
2285 8f091a59 bellard
    {
2286 8f091a59 bellard
        ot = s->dflag + OT_WORD;
2287 8f091a59 bellard
        opsize = 2 << s->dflag;
2288 3b46e624 ths
2289 57fec1fe bellard
        gen_op_movl_A0_reg(R_ESP);
2290 8f091a59 bellard
        gen_op_addl_A0_im(-opsize);
2291 8f091a59 bellard
        if (!s->ss32)
2292 8f091a59 bellard
            gen_op_andl_A0_ffff();
2293 8f091a59 bellard
        gen_op_movl_T1_A0();
2294 8f091a59 bellard
        if (s->addseg)
2295 57fec1fe bellard
            gen_op_addl_A0_seg(R_SS);
2296 8f091a59 bellard
        /* push bp */
2297 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2298 57fec1fe bellard
        gen_op_st_T0_A0(ot + s->mem_index);
2299 8f091a59 bellard
        if (level) {
2300 8f091a59 bellard
            gen_op_enter_level(level, s->dflag);
2301 8f091a59 bellard
        }
2302 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EBP);
2303 8f091a59 bellard
        gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2304 57fec1fe bellard
        gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2305 2c0262af bellard
    }
2306 2c0262af bellard
}
2307 2c0262af bellard
2308 14ce26e7 bellard
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2309 2c0262af bellard
{
2310 2c0262af bellard
    if (s->cc_op != CC_OP_DYNAMIC)
2311 2c0262af bellard
        gen_op_set_cc_op(s->cc_op);
2312 14ce26e7 bellard
    gen_jmp_im(cur_eip);
2313 2c0262af bellard
    gen_op_raise_exception(trapno);
2314 2c0262af bellard
    s->is_jmp = 3;
2315 2c0262af bellard
}
2316 2c0262af bellard
2317 2c0262af bellard
/* an interrupt is different from an exception because of the
2318 7f75ffd3 blueswir1
   privilege checks */
2319 5fafdf24 ths
static void gen_interrupt(DisasContext *s, int intno,
2320 14ce26e7 bellard
                          target_ulong cur_eip, target_ulong next_eip)
2321 2c0262af bellard
{
2322 2c0262af bellard
    if (s->cc_op != CC_OP_DYNAMIC)
2323 2c0262af bellard
        gen_op_set_cc_op(s->cc_op);
2324 14ce26e7 bellard
    gen_jmp_im(cur_eip);
2325 a8ede8ba bellard
    gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2326 2c0262af bellard
    s->is_jmp = 3;
2327 2c0262af bellard
}
2328 2c0262af bellard
2329 14ce26e7 bellard
static void gen_debug(DisasContext *s, target_ulong cur_eip)
2330 2c0262af bellard
{
2331 2c0262af bellard
    if (s->cc_op != CC_OP_DYNAMIC)
2332 2c0262af bellard
        gen_op_set_cc_op(s->cc_op);
2333 14ce26e7 bellard
    gen_jmp_im(cur_eip);
2334 2c0262af bellard
    gen_op_debug();
2335 2c0262af bellard
    s->is_jmp = 3;
2336 2c0262af bellard
}
2337 2c0262af bellard
2338 2c0262af bellard
/* generate a generic end of block. Trace exception is also generated
2339 2c0262af bellard
   if needed */
2340 2c0262af bellard
static void gen_eob(DisasContext *s)
2341 2c0262af bellard
{
2342 2c0262af bellard
    if (s->cc_op != CC_OP_DYNAMIC)
2343 2c0262af bellard
        gen_op_set_cc_op(s->cc_op);
2344 a2cc3b24 bellard
    if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2345 a2cc3b24 bellard
        gen_op_reset_inhibit_irq();
2346 a2cc3b24 bellard
    }
2347 34865134 bellard
    if (s->singlestep_enabled) {
2348 34865134 bellard
        gen_op_debug();
2349 34865134 bellard
    } else if (s->tf) {
2350 88fe8a41 ths
        gen_op_single_step();
2351 2c0262af bellard
    } else {
2352 57fec1fe bellard
        tcg_gen_exit_tb(0);
2353 2c0262af bellard
    }
2354 2c0262af bellard
    s->is_jmp = 3;
2355 2c0262af bellard
}
2356 2c0262af bellard
2357 2c0262af bellard
/* generate a jump to eip. No segment change must happen before as a
2358 2c0262af bellard
   direct call to the next block may occur */
2359 14ce26e7 bellard
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2360 2c0262af bellard
{
2361 2c0262af bellard
    if (s->jmp_opt) {
2362 6e256c93 bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
2363 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
2364 6e256c93 bellard
            s->cc_op = CC_OP_DYNAMIC;
2365 6e256c93 bellard
        }
2366 6e256c93 bellard
        gen_goto_tb(s, tb_num, eip);
2367 2c0262af bellard
        s->is_jmp = 3;
2368 2c0262af bellard
    } else {
2369 14ce26e7 bellard
        gen_jmp_im(eip);
2370 2c0262af bellard
        gen_eob(s);
2371 2c0262af bellard
    }
2372 2c0262af bellard
}
2373 2c0262af bellard
2374 14ce26e7 bellard
static void gen_jmp(DisasContext *s, target_ulong eip)
2375 14ce26e7 bellard
{
2376 14ce26e7 bellard
    gen_jmp_tb(s, eip, 0);
2377 14ce26e7 bellard
}
2378 14ce26e7 bellard
2379 8686c490 bellard
static inline void gen_ldq_env_A0(int idx, int offset)
2380 8686c490 bellard
{
2381 8686c490 bellard
    int mem_index = (idx >> 2) - 1;
2382 8686c490 bellard
    tcg_gen_qemu_ld64(cpu_tmp1, cpu_A0, mem_index);
2383 8686c490 bellard
    tcg_gen_st_i64(cpu_tmp1, cpu_env, offset);
2384 8686c490 bellard
}
2385 664e0f19 bellard
2386 8686c490 bellard
static inline void gen_stq_env_A0(int idx, int offset)
2387 8686c490 bellard
{
2388 8686c490 bellard
    int mem_index = (idx >> 2) - 1;
2389 8686c490 bellard
    tcg_gen_ld_i64(cpu_tmp1, cpu_env, offset);
2390 8686c490 bellard
    tcg_gen_qemu_st64(cpu_tmp1, cpu_A0, mem_index);
2391 8686c490 bellard
}
2392 664e0f19 bellard
2393 8686c490 bellard
static inline void gen_ldo_env_A0(int idx, int offset)
2394 8686c490 bellard
{
2395 8686c490 bellard
    int mem_index = (idx >> 2) - 1;
2396 8686c490 bellard
    tcg_gen_qemu_ld64(cpu_tmp1, cpu_A0, mem_index);
2397 8686c490 bellard
    tcg_gen_st_i64(cpu_tmp1, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2398 8686c490 bellard
    tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2399 8686c490 bellard
    tcg_gen_qemu_ld64(cpu_tmp1, cpu_tmp0, mem_index);
2400 8686c490 bellard
    tcg_gen_st_i64(cpu_tmp1, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2401 8686c490 bellard
}
2402 14ce26e7 bellard
2403 8686c490 bellard
static inline void gen_sto_env_A0(int idx, int offset)
2404 8686c490 bellard
{
2405 8686c490 bellard
    int mem_index = (idx >> 2) - 1;
2406 8686c490 bellard
    tcg_gen_ld_i64(cpu_tmp1, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2407 8686c490 bellard
    tcg_gen_qemu_st64(cpu_tmp1, cpu_A0, mem_index);
2408 8686c490 bellard
    tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2409 8686c490 bellard
    tcg_gen_ld_i64(cpu_tmp1, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2410 8686c490 bellard
    tcg_gen_qemu_st64(cpu_tmp1, cpu_tmp0, mem_index);
2411 8686c490 bellard
}
2412 14ce26e7 bellard
2413 664e0f19 bellard
#define SSE_SPECIAL ((GenOpFunc2 *)1)
2414 a35f3ec7 aurel32
#define SSE_DUMMY ((GenOpFunc2 *)2)
2415 664e0f19 bellard
2416 664e0f19 bellard
#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2417 664e0f19 bellard
#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2418 664e0f19 bellard
                     gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2419 664e0f19 bellard
2420 664e0f19 bellard
static GenOpFunc2 *sse_op_table1[256][4] = {
2421 a35f3ec7 aurel32
    /* 3DNow! extensions */
2422 a35f3ec7 aurel32
    [0x0e] = { SSE_DUMMY }, /* femms */
2423 a35f3ec7 aurel32
    [0x0f] = { SSE_DUMMY }, /* pf... */
2424 664e0f19 bellard
    /* pure SSE operations */
2425 664e0f19 bellard
    [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2426 664e0f19 bellard
    [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2427 465e9838 bellard
    [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2428 664e0f19 bellard
    [0x13] = { SSE_SPECIAL, SSE_SPECIAL },  /* movlps, movlpd */
2429 664e0f19 bellard
    [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2430 664e0f19 bellard
    [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2431 664e0f19 bellard
    [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd, movshdup */
2432 664e0f19 bellard
    [0x17] = { SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd */
2433 664e0f19 bellard
2434 664e0f19 bellard
    [0x28] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2435 664e0f19 bellard
    [0x29] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2436 664e0f19 bellard
    [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2437 664e0f19 bellard
    [0x2b] = { SSE_SPECIAL, SSE_SPECIAL },  /* movntps, movntpd */
2438 664e0f19 bellard
    [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2439 664e0f19 bellard
    [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2440 664e0f19 bellard
    [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2441 664e0f19 bellard
    [0x2f] = { gen_op_comiss, gen_op_comisd },
2442 664e0f19 bellard
    [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2443 664e0f19 bellard
    [0x51] = SSE_FOP(sqrt),
2444 664e0f19 bellard
    [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2445 664e0f19 bellard
    [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2446 664e0f19 bellard
    [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2447 664e0f19 bellard
    [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2448 664e0f19 bellard
    [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2449 664e0f19 bellard
    [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2450 664e0f19 bellard
    [0x58] = SSE_FOP(add),
2451 664e0f19 bellard
    [0x59] = SSE_FOP(mul),
2452 5fafdf24 ths
    [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
2453 664e0f19 bellard
               gen_op_cvtss2sd, gen_op_cvtsd2ss },
2454 664e0f19 bellard
    [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2455 664e0f19 bellard
    [0x5c] = SSE_FOP(sub),
2456 664e0f19 bellard
    [0x5d] = SSE_FOP(min),
2457 664e0f19 bellard
    [0x5e] = SSE_FOP(div),
2458 664e0f19 bellard
    [0x5f] = SSE_FOP(max),
2459 664e0f19 bellard
2460 664e0f19 bellard
    [0xc2] = SSE_FOP(cmpeq),
2461 d52cf7a6 bellard
    [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2462 664e0f19 bellard
2463 664e0f19 bellard
    /* MMX ops and their SSE extensions */
2464 664e0f19 bellard
    [0x60] = MMX_OP2(punpcklbw),
2465 664e0f19 bellard
    [0x61] = MMX_OP2(punpcklwd),
2466 664e0f19 bellard
    [0x62] = MMX_OP2(punpckldq),
2467 664e0f19 bellard
    [0x63] = MMX_OP2(packsswb),
2468 664e0f19 bellard
    [0x64] = MMX_OP2(pcmpgtb),
2469 664e0f19 bellard
    [0x65] = MMX_OP2(pcmpgtw),
2470 664e0f19 bellard
    [0x66] = MMX_OP2(pcmpgtl),
2471 664e0f19 bellard
    [0x67] = MMX_OP2(packuswb),
2472 664e0f19 bellard
    [0x68] = MMX_OP2(punpckhbw),
2473 664e0f19 bellard
    [0x69] = MMX_OP2(punpckhwd),
2474 664e0f19 bellard
    [0x6a] = MMX_OP2(punpckhdq),
2475 664e0f19 bellard
    [0x6b] = MMX_OP2(packssdw),
2476 664e0f19 bellard
    [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2477 664e0f19 bellard
    [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2478 664e0f19 bellard
    [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2479 664e0f19 bellard
    [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2480 5fafdf24 ths
    [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2481 5fafdf24 ths
               (GenOpFunc2 *)gen_op_pshufd_xmm,
2482 5fafdf24 ths
               (GenOpFunc2 *)gen_op_pshufhw_xmm,
2483 664e0f19 bellard
               (GenOpFunc2 *)gen_op_pshuflw_xmm },
2484 664e0f19 bellard
    [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2485 664e0f19 bellard
    [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2486 664e0f19 bellard
    [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2487 664e0f19 bellard
    [0x74] = MMX_OP2(pcmpeqb),
2488 664e0f19 bellard
    [0x75] = MMX_OP2(pcmpeqw),
2489 664e0f19 bellard
    [0x76] = MMX_OP2(pcmpeql),
2490 a35f3ec7 aurel32
    [0x77] = { SSE_DUMMY }, /* emms */
2491 664e0f19 bellard
    [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2492 664e0f19 bellard
    [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2493 664e0f19 bellard
    [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2494 664e0f19 bellard
    [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2495 664e0f19 bellard
    [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2496 664e0f19 bellard
    [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2497 664e0f19 bellard
    [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2498 664e0f19 bellard
    [0xd1] = MMX_OP2(psrlw),
2499 664e0f19 bellard
    [0xd2] = MMX_OP2(psrld),
2500 664e0f19 bellard
    [0xd3] = MMX_OP2(psrlq),
2501 664e0f19 bellard
    [0xd4] = MMX_OP2(paddq),
2502 664e0f19 bellard
    [0xd5] = MMX_OP2(pmullw),
2503 664e0f19 bellard
    [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2504 664e0f19 bellard
    [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2505 664e0f19 bellard
    [0xd8] = MMX_OP2(psubusb),
2506 664e0f19 bellard
    [0xd9] = MMX_OP2(psubusw),
2507 664e0f19 bellard
    [0xda] = MMX_OP2(pminub),
2508 664e0f19 bellard
    [0xdb] = MMX_OP2(pand),
2509 664e0f19 bellard
    [0xdc] = MMX_OP2(paddusb),
2510 664e0f19 bellard
    [0xdd] = MMX_OP2(paddusw),
2511 664e0f19 bellard
    [0xde] = MMX_OP2(pmaxub),
2512 664e0f19 bellard
    [0xdf] = MMX_OP2(pandn),
2513 664e0f19 bellard
    [0xe0] = MMX_OP2(pavgb),
2514 664e0f19 bellard
    [0xe1] = MMX_OP2(psraw),
2515 664e0f19 bellard
    [0xe2] = MMX_OP2(psrad),
2516 664e0f19 bellard
    [0xe3] = MMX_OP2(pavgw),
2517 664e0f19 bellard
    [0xe4] = MMX_OP2(pmulhuw),
2518 664e0f19 bellard
    [0xe5] = MMX_OP2(pmulhw),
2519 664e0f19 bellard
    [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2520 664e0f19 bellard
    [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
2521 664e0f19 bellard
    [0xe8] = MMX_OP2(psubsb),
2522 664e0f19 bellard
    [0xe9] = MMX_OP2(psubsw),
2523 664e0f19 bellard
    [0xea] = MMX_OP2(pminsw),
2524 664e0f19 bellard
    [0xeb] = MMX_OP2(por),
2525 664e0f19 bellard
    [0xec] = MMX_OP2(paddsb),
2526 664e0f19 bellard
    [0xed] = MMX_OP2(paddsw),
2527 664e0f19 bellard
    [0xee] = MMX_OP2(pmaxsw),
2528 664e0f19 bellard
    [0xef] = MMX_OP2(pxor),
2529 465e9838 bellard
    [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2530 664e0f19 bellard
    [0xf1] = MMX_OP2(psllw),
2531 664e0f19 bellard
    [0xf2] = MMX_OP2(pslld),
2532 664e0f19 bellard
    [0xf3] = MMX_OP2(psllq),
2533 664e0f19 bellard
    [0xf4] = MMX_OP2(pmuludq),
2534 664e0f19 bellard
    [0xf5] = MMX_OP2(pmaddwd),
2535 664e0f19 bellard
    [0xf6] = MMX_OP2(psadbw),
2536 664e0f19 bellard
    [0xf7] = MMX_OP2(maskmov),
2537 664e0f19 bellard
    [0xf8] = MMX_OP2(psubb),
2538 664e0f19 bellard
    [0xf9] = MMX_OP2(psubw),
2539 664e0f19 bellard
    [0xfa] = MMX_OP2(psubl),
2540 664e0f19 bellard
    [0xfb] = MMX_OP2(psubq),
2541 664e0f19 bellard
    [0xfc] = MMX_OP2(paddb),
2542 664e0f19 bellard
    [0xfd] = MMX_OP2(paddw),
2543 664e0f19 bellard
    [0xfe] = MMX_OP2(paddl),
2544 664e0f19 bellard
};
2545 664e0f19 bellard
2546 664e0f19 bellard
static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2547 664e0f19 bellard
    [0 + 2] = MMX_OP2(psrlw),
2548 664e0f19 bellard
    [0 + 4] = MMX_OP2(psraw),
2549 664e0f19 bellard
    [0 + 6] = MMX_OP2(psllw),
2550 664e0f19 bellard
    [8 + 2] = MMX_OP2(psrld),
2551 664e0f19 bellard
    [8 + 4] = MMX_OP2(psrad),
2552 664e0f19 bellard
    [8 + 6] = MMX_OP2(pslld),
2553 664e0f19 bellard
    [16 + 2] = MMX_OP2(psrlq),
2554 664e0f19 bellard
    [16 + 3] = { NULL, gen_op_psrldq_xmm },
2555 664e0f19 bellard
    [16 + 6] = MMX_OP2(psllq),
2556 664e0f19 bellard
    [16 + 7] = { NULL, gen_op_pslldq_xmm },
2557 664e0f19 bellard
};
2558 664e0f19 bellard
2559 664e0f19 bellard
static GenOpFunc1 *sse_op_table3[4 * 3] = {
2560 664e0f19 bellard
    gen_op_cvtsi2ss,
2561 664e0f19 bellard
    gen_op_cvtsi2sd,
2562 664e0f19 bellard
    X86_64_ONLY(gen_op_cvtsq2ss),
2563 664e0f19 bellard
    X86_64_ONLY(gen_op_cvtsq2sd),
2564 3b46e624 ths
2565 664e0f19 bellard
    gen_op_cvttss2si,
2566 664e0f19 bellard
    gen_op_cvttsd2si,
2567 664e0f19 bellard
    X86_64_ONLY(gen_op_cvttss2sq),
2568 664e0f19 bellard
    X86_64_ONLY(gen_op_cvttsd2sq),
2569 664e0f19 bellard
2570 664e0f19 bellard
    gen_op_cvtss2si,
2571 664e0f19 bellard
    gen_op_cvtsd2si,
2572 664e0f19 bellard
    X86_64_ONLY(gen_op_cvtss2sq),
2573 664e0f19 bellard
    X86_64_ONLY(gen_op_cvtsd2sq),
2574 664e0f19 bellard
};
2575 3b46e624 ths
2576 664e0f19 bellard
static GenOpFunc2 *sse_op_table4[8][4] = {
2577 664e0f19 bellard
    SSE_FOP(cmpeq),
2578 664e0f19 bellard
    SSE_FOP(cmplt),
2579 664e0f19 bellard
    SSE_FOP(cmple),
2580 664e0f19 bellard
    SSE_FOP(cmpunord),
2581 664e0f19 bellard
    SSE_FOP(cmpneq),
2582 664e0f19 bellard
    SSE_FOP(cmpnlt),
2583 664e0f19 bellard
    SSE_FOP(cmpnle),
2584 664e0f19 bellard
    SSE_FOP(cmpord),
2585 664e0f19 bellard
};
2586 3b46e624 ths
2587 a35f3ec7 aurel32
static GenOpFunc2 *sse_op_table5[256] = {
2588 a35f3ec7 aurel32
    [0x0c] = gen_op_pi2fw,
2589 a35f3ec7 aurel32
    [0x0d] = gen_op_pi2fd,
2590 a35f3ec7 aurel32
    [0x1c] = gen_op_pf2iw,
2591 a35f3ec7 aurel32
    [0x1d] = gen_op_pf2id,
2592 a35f3ec7 aurel32
    [0x8a] = gen_op_pfnacc,
2593 a35f3ec7 aurel32
    [0x8e] = gen_op_pfpnacc,
2594 a35f3ec7 aurel32
    [0x90] = gen_op_pfcmpge,
2595 a35f3ec7 aurel32
    [0x94] = gen_op_pfmin,
2596 a35f3ec7 aurel32
    [0x96] = gen_op_pfrcp,
2597 a35f3ec7 aurel32
    [0x97] = gen_op_pfrsqrt,
2598 a35f3ec7 aurel32
    [0x9a] = gen_op_pfsub,
2599 a35f3ec7 aurel32
    [0x9e] = gen_op_pfadd,
2600 a35f3ec7 aurel32
    [0xa0] = gen_op_pfcmpgt,
2601 a35f3ec7 aurel32
    [0xa4] = gen_op_pfmax,
2602 a35f3ec7 aurel32
    [0xa6] = gen_op_movq, /* pfrcpit1; no need to actually increase precision */
2603 a35f3ec7 aurel32
    [0xa7] = gen_op_movq, /* pfrsqit1 */
2604 a35f3ec7 aurel32
    [0xaa] = gen_op_pfsubr,
2605 a35f3ec7 aurel32
    [0xae] = gen_op_pfacc,
2606 a35f3ec7 aurel32
    [0xb0] = gen_op_pfcmpeq,
2607 a35f3ec7 aurel32
    [0xb4] = gen_op_pfmul,
2608 a35f3ec7 aurel32
    [0xb6] = gen_op_movq, /* pfrcpit2 */
2609 a35f3ec7 aurel32
    [0xb7] = gen_op_pmulhrw_mmx,
2610 a35f3ec7 aurel32
    [0xbb] = gen_op_pswapd,
2611 a35f3ec7 aurel32
    [0xbf] = gen_op_pavgb_mmx /* pavgusb */
2612 a35f3ec7 aurel32
};
2613 a35f3ec7 aurel32
2614 664e0f19 bellard
static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2615 664e0f19 bellard
{
2616 664e0f19 bellard
    int b1, op1_offset, op2_offset, is_xmm, val, ot;
2617 664e0f19 bellard
    int modrm, mod, rm, reg, reg_addr, offset_addr;
2618 664e0f19 bellard
    GenOpFunc2 *sse_op2;
2619 664e0f19 bellard
    GenOpFunc3 *sse_op3;
2620 664e0f19 bellard
2621 664e0f19 bellard
    b &= 0xff;
2622 5fafdf24 ths
    if (s->prefix & PREFIX_DATA)
2623 664e0f19 bellard
        b1 = 1;
2624 5fafdf24 ths
    else if (s->prefix & PREFIX_REPZ)
2625 664e0f19 bellard
        b1 = 2;
2626 5fafdf24 ths
    else if (s->prefix & PREFIX_REPNZ)
2627 664e0f19 bellard
        b1 = 3;
2628 664e0f19 bellard
    else
2629 664e0f19 bellard
        b1 = 0;
2630 664e0f19 bellard
    sse_op2 = sse_op_table1[b][b1];
2631 5fafdf24 ths
    if (!sse_op2)
2632 664e0f19 bellard
        goto illegal_op;
2633 a35f3ec7 aurel32
    if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
2634 664e0f19 bellard
        is_xmm = 1;
2635 664e0f19 bellard
    } else {
2636 664e0f19 bellard
        if (b1 == 0) {
2637 664e0f19 bellard
            /* MMX case */
2638 664e0f19 bellard
            is_xmm = 0;
2639 664e0f19 bellard
        } else {
2640 664e0f19 bellard
            is_xmm = 1;
2641 664e0f19 bellard
        }
2642 664e0f19 bellard
    }
2643 664e0f19 bellard
    /* simple MMX/SSE operation */
2644 664e0f19 bellard
    if (s->flags & HF_TS_MASK) {
2645 664e0f19 bellard
        gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2646 664e0f19 bellard
        return;
2647 664e0f19 bellard
    }
2648 664e0f19 bellard
    if (s->flags & HF_EM_MASK) {
2649 664e0f19 bellard
    illegal_op:
2650 664e0f19 bellard
        gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2651 664e0f19 bellard
        return;
2652 664e0f19 bellard
    }
2653 664e0f19 bellard
    if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2654 664e0f19 bellard
        goto illegal_op;
2655 e771edab aurel32
    if (b == 0x0e) {
2656 e771edab aurel32
        if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
2657 e771edab aurel32
            goto illegal_op;
2658 e771edab aurel32
        /* femms */
2659 e771edab aurel32
        gen_op_emms();
2660 e771edab aurel32
        return;
2661 e771edab aurel32
    }
2662 e771edab aurel32
    if (b == 0x77) {
2663 e771edab aurel32
        /* emms */
2664 664e0f19 bellard
        gen_op_emms();
2665 664e0f19 bellard
        return;
2666 664e0f19 bellard
    }
2667 664e0f19 bellard
    /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2668 664e0f19 bellard
       the static cpu state) */
2669 664e0f19 bellard
    if (!is_xmm) {
2670 664e0f19 bellard
        gen_op_enter_mmx();
2671 664e0f19 bellard
    }
2672 664e0f19 bellard
2673 664e0f19 bellard
    modrm = ldub_code(s->pc++);
2674 664e0f19 bellard
    reg = ((modrm >> 3) & 7);
2675 664e0f19 bellard
    if (is_xmm)
2676 664e0f19 bellard
        reg |= rex_r;
2677 664e0f19 bellard
    mod = (modrm >> 6) & 3;
2678 664e0f19 bellard
    if (sse_op2 == SSE_SPECIAL) {
2679 664e0f19 bellard
        b |= (b1 << 8);
2680 664e0f19 bellard
        switch(b) {
2681 664e0f19 bellard
        case 0x0e7: /* movntq */
2682 5fafdf24 ths
            if (mod == 3)
2683 664e0f19 bellard
                goto illegal_op;
2684 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2685 8686c490 bellard
            gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
2686 664e0f19 bellard
            break;
2687 664e0f19 bellard
        case 0x1e7: /* movntdq */
2688 664e0f19 bellard
        case 0x02b: /* movntps */
2689 664e0f19 bellard
        case 0x12b: /* movntps */
2690 465e9838 bellard
        case 0x3f0: /* lddqu */
2691 465e9838 bellard
            if (mod == 3)
2692 664e0f19 bellard
                goto illegal_op;
2693 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2694 8686c490 bellard
            gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
2695 664e0f19 bellard
            break;
2696 664e0f19 bellard
        case 0x6e: /* movd mm, ea */
2697 dabd98dd bellard
#ifdef TARGET_X86_64
2698 dabd98dd bellard
            if (s->dflag == 2) {
2699 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2700 dabd98dd bellard
                gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2701 5fafdf24 ths
            } else
2702 dabd98dd bellard
#endif
2703 dabd98dd bellard
            {
2704 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2705 dabd98dd bellard
                gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2706 dabd98dd bellard
            }
2707 664e0f19 bellard
            break;
2708 664e0f19 bellard
        case 0x16e: /* movd xmm, ea */
2709 dabd98dd bellard
#ifdef TARGET_X86_64
2710 dabd98dd bellard
            if (s->dflag == 2) {
2711 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2712 dabd98dd bellard
                gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2713 5fafdf24 ths
            } else
2714 dabd98dd bellard
#endif
2715 dabd98dd bellard
            {
2716 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2717 dabd98dd bellard
                gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2718 dabd98dd bellard
            }
2719 664e0f19 bellard
            break;
2720 664e0f19 bellard
        case 0x6f: /* movq mm, ea */
2721 664e0f19 bellard
            if (mod != 3) {
2722 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2723 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
2724 664e0f19 bellard
            } else {
2725 664e0f19 bellard
                rm = (modrm & 7);
2726 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2727 664e0f19 bellard
                            offsetof(CPUX86State,fpregs[rm].mmx));
2728 664e0f19 bellard
            }
2729 664e0f19 bellard
            break;
2730 664e0f19 bellard
        case 0x010: /* movups */
2731 664e0f19 bellard
        case 0x110: /* movupd */
2732 664e0f19 bellard
        case 0x028: /* movaps */
2733 664e0f19 bellard
        case 0x128: /* movapd */
2734 664e0f19 bellard
        case 0x16f: /* movdqa xmm, ea */
2735 664e0f19 bellard
        case 0x26f: /* movdqu xmm, ea */
2736 664e0f19 bellard
            if (mod != 3) {
2737 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2738 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
2739 664e0f19 bellard
            } else {
2740 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2741 664e0f19 bellard
                gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2742 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm]));
2743 664e0f19 bellard
            }
2744 664e0f19 bellard
            break;
2745 664e0f19 bellard
        case 0x210: /* movss xmm, ea */
2746 664e0f19 bellard
            if (mod != 3) {
2747 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2748 57fec1fe bellard
                gen_op_ld_T0_A0(OT_LONG + s->mem_index);
2749 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2750 664e0f19 bellard
                gen_op_movl_T0_0();
2751 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2752 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2753 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2754 664e0f19 bellard
            } else {
2755 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2756 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2757 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2758 664e0f19 bellard
            }
2759 664e0f19 bellard
            break;
2760 664e0f19 bellard
        case 0x310: /* movsd xmm, ea */
2761 664e0f19 bellard
            if (mod != 3) {
2762 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2763 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2764 664e0f19 bellard
                gen_op_movl_T0_0();
2765 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2766 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2767 664e0f19 bellard
            } else {
2768 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2769 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2770 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2771 664e0f19 bellard
            }
2772 664e0f19 bellard
            break;
2773 664e0f19 bellard
        case 0x012: /* movlps */
2774 664e0f19 bellard
        case 0x112: /* movlpd */
2775 664e0f19 bellard
            if (mod != 3) {
2776 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2777 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2778 664e0f19 bellard
            } else {
2779 664e0f19 bellard
                /* movhlps */
2780 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2781 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2782 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2783 664e0f19 bellard
            }
2784 664e0f19 bellard
            break;
2785 465e9838 bellard
        case 0x212: /* movsldup */
2786 465e9838 bellard
            if (mod != 3) {
2787 465e9838 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2788 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
2789 465e9838 bellard
            } else {
2790 465e9838 bellard
                rm = (modrm & 7) | REX_B(s);
2791 465e9838 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2792 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2793 465e9838 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2794 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2795 465e9838 bellard
            }
2796 465e9838 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2797 465e9838 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2798 465e9838 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2799 465e9838 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2800 465e9838 bellard
            break;
2801 465e9838 bellard
        case 0x312: /* movddup */
2802 465e9838 bellard
            if (mod != 3) {
2803 465e9838 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2804 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2805 465e9838 bellard
            } else {
2806 465e9838 bellard
                rm = (modrm & 7) | REX_B(s);
2807 465e9838 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2808 465e9838 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2809 465e9838 bellard
            }
2810 465e9838 bellard
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2811 ba6526df bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2812 465e9838 bellard
            break;
2813 664e0f19 bellard
        case 0x016: /* movhps */
2814 664e0f19 bellard
        case 0x116: /* movhpd */
2815 664e0f19 bellard
            if (mod != 3) {
2816 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2817 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2818 664e0f19 bellard
            } else {
2819 664e0f19 bellard
                /* movlhps */
2820 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2821 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2822 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2823 664e0f19 bellard
            }
2824 664e0f19 bellard
            break;
2825 664e0f19 bellard
        case 0x216: /* movshdup */
2826 664e0f19 bellard
            if (mod != 3) {
2827 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2828 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
2829 664e0f19 bellard
            } else {
2830 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2831 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2832 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2833 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2834 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2835 664e0f19 bellard
            }
2836 664e0f19 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2837 664e0f19 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2838 664e0f19 bellard
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2839 664e0f19 bellard
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2840 664e0f19 bellard
            break;
2841 664e0f19 bellard
        case 0x7e: /* movd ea, mm */
2842 dabd98dd bellard
#ifdef TARGET_X86_64
2843 dabd98dd bellard
            if (s->dflag == 2) {
2844 dabd98dd bellard
                gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2845 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2846 5fafdf24 ths
            } else
2847 dabd98dd bellard
#endif
2848 dabd98dd bellard
            {
2849 dabd98dd bellard
                gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2850 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2851 dabd98dd bellard
            }
2852 664e0f19 bellard
            break;
2853 664e0f19 bellard
        case 0x17e: /* movd ea, xmm */
2854 dabd98dd bellard
#ifdef TARGET_X86_64
2855 dabd98dd bellard
            if (s->dflag == 2) {
2856 dabd98dd bellard
                gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2857 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2858 5fafdf24 ths
            } else
2859 dabd98dd bellard
#endif
2860 dabd98dd bellard
            {
2861 dabd98dd bellard
                gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2862 dabd98dd bellard
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2863 dabd98dd bellard
            }
2864 664e0f19 bellard
            break;
2865 664e0f19 bellard
        case 0x27e: /* movq xmm, ea */
2866 664e0f19 bellard
            if (mod != 3) {
2867 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2868 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2869 664e0f19 bellard
            } else {
2870 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2871 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2872 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2873 664e0f19 bellard
            }
2874 664e0f19 bellard
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2875 664e0f19 bellard
            break;
2876 664e0f19 bellard
        case 0x7f: /* movq ea, mm */
2877 664e0f19 bellard
            if (mod != 3) {
2878 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2879 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
2880 664e0f19 bellard
            } else {
2881 664e0f19 bellard
                rm = (modrm & 7);
2882 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2883 664e0f19 bellard
                            offsetof(CPUX86State,fpregs[reg].mmx));
2884 664e0f19 bellard
            }
2885 664e0f19 bellard
            break;
2886 664e0f19 bellard
        case 0x011: /* movups */
2887 664e0f19 bellard
        case 0x111: /* movupd */
2888 664e0f19 bellard
        case 0x029: /* movaps */
2889 664e0f19 bellard
        case 0x129: /* movapd */
2890 664e0f19 bellard
        case 0x17f: /* movdqa ea, xmm */
2891 664e0f19 bellard
        case 0x27f: /* movdqu ea, xmm */
2892 664e0f19 bellard
            if (mod != 3) {
2893 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2894 8686c490 bellard
                gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
2895 664e0f19 bellard
            } else {
2896 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2897 664e0f19 bellard
                gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2898 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg]));
2899 664e0f19 bellard
            }
2900 664e0f19 bellard
            break;
2901 664e0f19 bellard
        case 0x211: /* movss ea, xmm */
2902 664e0f19 bellard
            if (mod != 3) {
2903 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2904 664e0f19 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2905 57fec1fe bellard
                gen_op_st_T0_A0(OT_LONG + s->mem_index);
2906 664e0f19 bellard
            } else {
2907 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2908 664e0f19 bellard
                gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2909 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2910 664e0f19 bellard
            }
2911 664e0f19 bellard
            break;
2912 664e0f19 bellard
        case 0x311: /* movsd ea, xmm */
2913 664e0f19 bellard
            if (mod != 3) {
2914 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2915 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2916 664e0f19 bellard
            } else {
2917 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2918 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2919 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2920 664e0f19 bellard
            }
2921 664e0f19 bellard
            break;
2922 664e0f19 bellard
        case 0x013: /* movlps */
2923 664e0f19 bellard
        case 0x113: /* movlpd */
2924 664e0f19 bellard
            if (mod != 3) {
2925 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2926 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2927 664e0f19 bellard
            } else {
2928 664e0f19 bellard
                goto illegal_op;
2929 664e0f19 bellard
            }
2930 664e0f19 bellard
            break;
2931 664e0f19 bellard
        case 0x017: /* movhps */
2932 664e0f19 bellard
        case 0x117: /* movhpd */
2933 664e0f19 bellard
            if (mod != 3) {
2934 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2935 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2936 664e0f19 bellard
            } else {
2937 664e0f19 bellard
                goto illegal_op;
2938 664e0f19 bellard
            }
2939 664e0f19 bellard
            break;
2940 664e0f19 bellard
        case 0x71: /* shift mm, im */
2941 664e0f19 bellard
        case 0x72:
2942 664e0f19 bellard
        case 0x73:
2943 664e0f19 bellard
        case 0x171: /* shift xmm, im */
2944 664e0f19 bellard
        case 0x172:
2945 664e0f19 bellard
        case 0x173:
2946 664e0f19 bellard
            val = ldub_code(s->pc++);
2947 664e0f19 bellard
            if (is_xmm) {
2948 664e0f19 bellard
                gen_op_movl_T0_im(val);
2949 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2950 664e0f19 bellard
                gen_op_movl_T0_0();
2951 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2952 664e0f19 bellard
                op1_offset = offsetof(CPUX86State,xmm_t0);
2953 664e0f19 bellard
            } else {
2954 664e0f19 bellard
                gen_op_movl_T0_im(val);
2955 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2956 664e0f19 bellard
                gen_op_movl_T0_0();
2957 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2958 664e0f19 bellard
                op1_offset = offsetof(CPUX86State,mmx_t0);
2959 664e0f19 bellard
            }
2960 664e0f19 bellard
            sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2961 664e0f19 bellard
            if (!sse_op2)
2962 664e0f19 bellard
                goto illegal_op;
2963 664e0f19 bellard
            if (is_xmm) {
2964 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
2965 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2966 664e0f19 bellard
            } else {
2967 664e0f19 bellard
                rm = (modrm & 7);
2968 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2969 664e0f19 bellard
            }
2970 664e0f19 bellard
            sse_op2(op2_offset, op1_offset);
2971 664e0f19 bellard
            break;
2972 664e0f19 bellard
        case 0x050: /* movmskps */
2973 664e0f19 bellard
            rm = (modrm & 7) | REX_B(s);
2974 31313213 bellard
            gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2975 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
2976 664e0f19 bellard
            break;
2977 664e0f19 bellard
        case 0x150: /* movmskpd */
2978 664e0f19 bellard
            rm = (modrm & 7) | REX_B(s);
2979 31313213 bellard
            gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2980 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
2981 664e0f19 bellard
            break;
2982 664e0f19 bellard
        case 0x02a: /* cvtpi2ps */
2983 664e0f19 bellard
        case 0x12a: /* cvtpi2pd */
2984 664e0f19 bellard
            gen_op_enter_mmx();
2985 664e0f19 bellard
            if (mod != 3) {
2986 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2987 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,mmx_t0);
2988 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, op2_offset);
2989 664e0f19 bellard
            } else {
2990 664e0f19 bellard
                rm = (modrm & 7);
2991 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2992 664e0f19 bellard
            }
2993 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2994 664e0f19 bellard
            switch(b >> 8) {
2995 664e0f19 bellard
            case 0x0:
2996 664e0f19 bellard
                gen_op_cvtpi2ps(op1_offset, op2_offset);
2997 664e0f19 bellard
                break;
2998 664e0f19 bellard
            default:
2999 664e0f19 bellard
            case 0x1:
3000 664e0f19 bellard
                gen_op_cvtpi2pd(op1_offset, op2_offset);
3001 664e0f19 bellard
                break;
3002 664e0f19 bellard
            }
3003 664e0f19 bellard
            break;
3004 664e0f19 bellard
        case 0x22a: /* cvtsi2ss */
3005 664e0f19 bellard
        case 0x32a: /* cvtsi2sd */
3006 664e0f19 bellard
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3007 664e0f19 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3008 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3009 664e0f19 bellard
            sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
3010 664e0f19 bellard
            break;
3011 664e0f19 bellard
        case 0x02c: /* cvttps2pi */
3012 664e0f19 bellard
        case 0x12c: /* cvttpd2pi */
3013 664e0f19 bellard
        case 0x02d: /* cvtps2pi */
3014 664e0f19 bellard
        case 0x12d: /* cvtpd2pi */
3015 664e0f19 bellard
            gen_op_enter_mmx();
3016 664e0f19 bellard
            if (mod != 3) {
3017 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3018 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3019 8686c490 bellard
                gen_ldo_env_A0(s->mem_index, op2_offset);
3020 664e0f19 bellard
            } else {
3021 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3022 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3023 664e0f19 bellard
            }
3024 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3025 664e0f19 bellard
            switch(b) {
3026 664e0f19 bellard
            case 0x02c:
3027 664e0f19 bellard
                gen_op_cvttps2pi(op1_offset, op2_offset);
3028 664e0f19 bellard
                break;
3029 664e0f19 bellard
            case 0x12c:
3030 664e0f19 bellard
                gen_op_cvttpd2pi(op1_offset, op2_offset);
3031 664e0f19 bellard
                break;
3032 664e0f19 bellard
            case 0x02d:
3033 664e0f19 bellard
                gen_op_cvtps2pi(op1_offset, op2_offset);
3034 664e0f19 bellard
                break;
3035 664e0f19 bellard
            case 0x12d:
3036 664e0f19 bellard
                gen_op_cvtpd2pi(op1_offset, op2_offset);
3037 664e0f19 bellard
                break;
3038 664e0f19 bellard
            }
3039 664e0f19 bellard
            break;
3040 664e0f19 bellard
        case 0x22c: /* cvttss2si */
3041 664e0f19 bellard
        case 0x32c: /* cvttsd2si */
3042 664e0f19 bellard
        case 0x22d: /* cvtss2si */
3043 664e0f19 bellard
        case 0x32d: /* cvtsd2si */
3044 664e0f19 bellard
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3045 31313213 bellard
            if (mod != 3) {
3046 31313213 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3047 31313213 bellard
                if ((b >> 8) & 1) {
3048 8686c490 bellard
                    gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3049 31313213 bellard
                } else {
3050 57fec1fe bellard
                    gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3051 31313213 bellard
                    gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3052 31313213 bellard
                }
3053 31313213 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3054 31313213 bellard
            } else {
3055 31313213 bellard
                rm = (modrm & 7) | REX_B(s);
3056 31313213 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3057 31313213 bellard
            }
3058 5fafdf24 ths
            sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
3059 31313213 bellard
                          (b & 1) * 4](op2_offset);
3060 57fec1fe bellard
            gen_op_mov_reg_T0(ot, reg);
3061 664e0f19 bellard
            break;
3062 664e0f19 bellard
        case 0xc4: /* pinsrw */
3063 5fafdf24 ths
        case 0x1c4:
3064 d1e42c5c bellard
            s->rip_offset = 1;
3065 664e0f19 bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3066 664e0f19 bellard
            val = ldub_code(s->pc++);
3067 664e0f19 bellard
            if (b1) {
3068 664e0f19 bellard
                val &= 7;
3069 664e0f19 bellard
                gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
3070 664e0f19 bellard
            } else {
3071 664e0f19 bellard
                val &= 3;
3072 664e0f19 bellard
                gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3073 664e0f19 bellard
            }
3074 664e0f19 bellard
            break;
3075 664e0f19 bellard
        case 0xc5: /* pextrw */
3076 5fafdf24 ths
        case 0x1c5:
3077 664e0f19 bellard
            if (mod != 3)
3078 664e0f19 bellard
                goto illegal_op;
3079 664e0f19 bellard
            val = ldub_code(s->pc++);
3080 664e0f19 bellard
            if (b1) {
3081 664e0f19 bellard
                val &= 7;
3082 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3083 664e0f19 bellard
                gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3084 664e0f19 bellard
            } else {
3085 664e0f19 bellard
                val &= 3;
3086 664e0f19 bellard
                rm = (modrm & 7);
3087 664e0f19 bellard
                gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3088 664e0f19 bellard
            }
3089 664e0f19 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
3090 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3091 664e0f19 bellard
            break;
3092 664e0f19 bellard
        case 0x1d6: /* movq ea, xmm */
3093 664e0f19 bellard
            if (mod != 3) {
3094 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3095 8686c490 bellard
                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3096 664e0f19 bellard
            } else {
3097 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3098 664e0f19 bellard
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3099 664e0f19 bellard
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3100 664e0f19 bellard
                gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3101 664e0f19 bellard
            }
3102 664e0f19 bellard
            break;
3103 664e0f19 bellard
        case 0x2d6: /* movq2dq */
3104 664e0f19 bellard
            gen_op_enter_mmx();
3105 480c1cdb bellard
            rm = (modrm & 7);
3106 480c1cdb bellard
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3107 480c1cdb bellard
                        offsetof(CPUX86State,fpregs[rm].mmx));
3108 480c1cdb bellard
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3109 664e0f19 bellard
            break;
3110 664e0f19 bellard
        case 0x3d6: /* movdq2q */
3111 664e0f19 bellard
            gen_op_enter_mmx();
3112 480c1cdb bellard
            rm = (modrm & 7) | REX_B(s);
3113 480c1cdb bellard
            gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3114 480c1cdb bellard
                        offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3115 664e0f19 bellard
            break;
3116 664e0f19 bellard
        case 0xd7: /* pmovmskb */
3117 664e0f19 bellard
        case 0x1d7:
3118 664e0f19 bellard
            if (mod != 3)
3119 664e0f19 bellard
                goto illegal_op;
3120 664e0f19 bellard
            if (b1) {
3121 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3122 664e0f19 bellard
                gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3123 664e0f19 bellard
            } else {
3124 664e0f19 bellard
                rm = (modrm & 7);
3125 664e0f19 bellard
                gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3126 664e0f19 bellard
            }
3127 664e0f19 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
3128 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
3129 664e0f19 bellard
            break;
3130 664e0f19 bellard
        default:
3131 664e0f19 bellard
            goto illegal_op;
3132 664e0f19 bellard
        }
3133 664e0f19 bellard
    } else {
3134 664e0f19 bellard
        /* generic MMX or SSE operation */
3135 d1e42c5c bellard
        switch(b) {
3136 d1e42c5c bellard
        case 0xf7:
3137 664e0f19 bellard
            /* maskmov : we must prepare A0 */
3138 5fafdf24 ths
            if (mod != 3)
3139 664e0f19 bellard
                goto illegal_op;
3140 664e0f19 bellard
#ifdef TARGET_X86_64
3141 8f091a59 bellard
            if (s->aflag == 2) {
3142 57fec1fe bellard
                gen_op_movq_A0_reg(R_EDI);
3143 5fafdf24 ths
            } else
3144 664e0f19 bellard
#endif
3145 664e0f19 bellard
            {
3146 57fec1fe bellard
                gen_op_movl_A0_reg(R_EDI);
3147 664e0f19 bellard
                if (s->aflag == 0)
3148 664e0f19 bellard
                    gen_op_andl_A0_ffff();
3149 664e0f19 bellard
            }
3150 664e0f19 bellard
            gen_add_A0_ds_seg(s);
3151 d1e42c5c bellard
            break;
3152 d1e42c5c bellard
        case 0x70: /* pshufx insn */
3153 d1e42c5c bellard
        case 0xc6: /* pshufx insn */
3154 d1e42c5c bellard
        case 0xc2: /* compare insns */
3155 d1e42c5c bellard
            s->rip_offset = 1;
3156 d1e42c5c bellard
            break;
3157 d1e42c5c bellard
        default:
3158 d1e42c5c bellard
            break;
3159 664e0f19 bellard
        }
3160 664e0f19 bellard
        if (is_xmm) {
3161 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3162 664e0f19 bellard
            if (mod != 3) {
3163 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3164 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_t0);
3165 480c1cdb bellard
                if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
3166 664e0f19 bellard
                                b == 0xc2)) {
3167 664e0f19 bellard
                    /* specific case for SSE single instructions */
3168 664e0f19 bellard
                    if (b1 == 2) {
3169 664e0f19 bellard
                        /* 32 bit access */
3170 57fec1fe bellard
                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3171 664e0f19 bellard
                        gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3172 664e0f19 bellard
                    } else {
3173 664e0f19 bellard
                        /* 64 bit access */
3174 8686c490 bellard
                        gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3175 664e0f19 bellard
                    }
3176 664e0f19 bellard
                } else {
3177 8686c490 bellard
                    gen_ldo_env_A0(s->mem_index, op2_offset);
3178 664e0f19 bellard
                }
3179 664e0f19 bellard
            } else {
3180 664e0f19 bellard
                rm = (modrm & 7) | REX_B(s);
3181 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3182 664e0f19 bellard
            }
3183 664e0f19 bellard
        } else {
3184 664e0f19 bellard
            op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3185 664e0f19 bellard
            if (mod != 3) {
3186 664e0f19 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3187 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,mmx_t0);
3188 8686c490 bellard
                gen_ldq_env_A0(s->mem_index, op2_offset);
3189 664e0f19 bellard
            } else {
3190 664e0f19 bellard
                rm = (modrm & 7);
3191 664e0f19 bellard
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3192 664e0f19 bellard
            }
3193 664e0f19 bellard
        }
3194 664e0f19 bellard
        switch(b) {
3195 a35f3ec7 aurel32
        case 0x0f: /* 3DNow! data insns */
3196 e771edab aurel32
            if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3197 e771edab aurel32
                goto illegal_op;
3198 a35f3ec7 aurel32
            val = ldub_code(s->pc++);
3199 a35f3ec7 aurel32
            sse_op2 = sse_op_table5[val];
3200 a35f3ec7 aurel32
            if (!sse_op2)
3201 a35f3ec7 aurel32
                goto illegal_op;
3202 a35f3ec7 aurel32
            sse_op2(op1_offset, op2_offset);
3203 a35f3ec7 aurel32
            break;
3204 664e0f19 bellard
        case 0x70: /* pshufx insn */
3205 664e0f19 bellard
        case 0xc6: /* pshufx insn */
3206 664e0f19 bellard
            val = ldub_code(s->pc++);
3207 664e0f19 bellard
            sse_op3 = (GenOpFunc3 *)sse_op2;
3208 664e0f19 bellard
            sse_op3(op1_offset, op2_offset, val);
3209 664e0f19 bellard
            break;
3210 664e0f19 bellard
        case 0xc2:
3211 664e0f19 bellard
            /* compare insns */
3212 664e0f19 bellard
            val = ldub_code(s->pc++);
3213 664e0f19 bellard
            if (val >= 8)
3214 664e0f19 bellard
                goto illegal_op;
3215 664e0f19 bellard
            sse_op2 = sse_op_table4[val][b1];
3216 664e0f19 bellard
            sse_op2(op1_offset, op2_offset);
3217 664e0f19 bellard
            break;
3218 664e0f19 bellard
        default:
3219 664e0f19 bellard
            sse_op2(op1_offset, op2_offset);
3220 664e0f19 bellard
            break;
3221 664e0f19 bellard
        }
3222 664e0f19 bellard
        if (b == 0x2e || b == 0x2f) {
3223 664e0f19 bellard
            s->cc_op = CC_OP_EFLAGS;
3224 664e0f19 bellard
        }
3225 664e0f19 bellard
    }
3226 664e0f19 bellard
}
3227 664e0f19 bellard
3228 664e0f19 bellard
3229 2c0262af bellard
/* convert one instruction. s->is_jmp is set if the translation must
3230 2c0262af bellard
   be stopped. Return the next pc value */
3231 14ce26e7 bellard
static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3232 2c0262af bellard
{
3233 2c0262af bellard
    int b, prefixes, aflag, dflag;
3234 2c0262af bellard
    int shift, ot;
3235 2c0262af bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3236 14ce26e7 bellard
    target_ulong next_eip, tval;
3237 14ce26e7 bellard
    int rex_w, rex_r;
3238 2c0262af bellard
3239 2c0262af bellard
    s->pc = pc_start;
3240 2c0262af bellard
    prefixes = 0;
3241 2c0262af bellard
    aflag = s->code32;
3242 2c0262af bellard
    dflag = s->code32;
3243 2c0262af bellard
    s->override = -1;
3244 14ce26e7 bellard
    rex_w = -1;
3245 14ce26e7 bellard
    rex_r = 0;
3246 14ce26e7 bellard
#ifdef TARGET_X86_64
3247 14ce26e7 bellard
    s->rex_x = 0;
3248 14ce26e7 bellard
    s->rex_b = 0;
3249 5fafdf24 ths
    x86_64_hregs = 0;
3250 14ce26e7 bellard
#endif
3251 14ce26e7 bellard
    s->rip_offset = 0; /* for relative ip address */
3252 2c0262af bellard
 next_byte:
3253 61382a50 bellard
    b = ldub_code(s->pc);
3254 2c0262af bellard
    s->pc++;
3255 2c0262af bellard
    /* check prefixes */
3256 14ce26e7 bellard
#ifdef TARGET_X86_64
3257 14ce26e7 bellard
    if (CODE64(s)) {
3258 14ce26e7 bellard
        switch (b) {
3259 14ce26e7 bellard
        case 0xf3:
3260 14ce26e7 bellard
            prefixes |= PREFIX_REPZ;
3261 14ce26e7 bellard
            goto next_byte;
3262 14ce26e7 bellard
        case 0xf2:
3263 14ce26e7 bellard
            prefixes |= PREFIX_REPNZ;
3264 14ce26e7 bellard
            goto next_byte;
3265 14ce26e7 bellard
        case 0xf0:
3266 14ce26e7 bellard
            prefixes |= PREFIX_LOCK;
3267 14ce26e7 bellard
            goto next_byte;
3268 14ce26e7 bellard
        case 0x2e:
3269 14ce26e7 bellard
            s->override = R_CS;
3270 14ce26e7 bellard
            goto next_byte;
3271 14ce26e7 bellard
        case 0x36:
3272 14ce26e7 bellard
            s->override = R_SS;
3273 14ce26e7 bellard
            goto next_byte;
3274 14ce26e7 bellard
        case 0x3e:
3275 14ce26e7 bellard
            s->override = R_DS;
3276 14ce26e7 bellard
            goto next_byte;
3277 14ce26e7 bellard
        case 0x26:
3278 14ce26e7 bellard
            s->override = R_ES;
3279 14ce26e7 bellard
            goto next_byte;
3280 14ce26e7 bellard
        case 0x64:
3281 14ce26e7 bellard
            s->override = R_FS;
3282 14ce26e7 bellard
            goto next_byte;
3283 14ce26e7 bellard
        case 0x65:
3284 14ce26e7 bellard
            s->override = R_GS;
3285 14ce26e7 bellard
            goto next_byte;
3286 14ce26e7 bellard
        case 0x66:
3287 14ce26e7 bellard
            prefixes |= PREFIX_DATA;
3288 14ce26e7 bellard
            goto next_byte;
3289 14ce26e7 bellard
        case 0x67:
3290 14ce26e7 bellard
            prefixes |= PREFIX_ADR;
3291 14ce26e7 bellard
            goto next_byte;
3292 14ce26e7 bellard
        case 0x40 ... 0x4f:
3293 14ce26e7 bellard
            /* REX prefix */
3294 14ce26e7 bellard
            rex_w = (b >> 3) & 1;
3295 14ce26e7 bellard
            rex_r = (b & 0x4) << 1;
3296 14ce26e7 bellard
            s->rex_x = (b & 0x2) << 2;
3297 14ce26e7 bellard
            REX_B(s) = (b & 0x1) << 3;
3298 14ce26e7 bellard
            x86_64_hregs = 1; /* select uniform byte register addressing */
3299 14ce26e7 bellard
            goto next_byte;
3300 14ce26e7 bellard
        }
3301 14ce26e7 bellard
        if (rex_w == 1) {
3302 14ce26e7 bellard
            /* 0x66 is ignored if rex.w is set */
3303 14ce26e7 bellard
            dflag = 2;
3304 14ce26e7 bellard
        } else {
3305 14ce26e7 bellard
            if (prefixes & PREFIX_DATA)
3306 14ce26e7 bellard
                dflag ^= 1;
3307 14ce26e7 bellard
        }
3308 14ce26e7 bellard
        if (!(prefixes & PREFIX_ADR))
3309 14ce26e7 bellard
            aflag = 2;
3310 5fafdf24 ths
    } else
3311 14ce26e7 bellard
#endif
3312 14ce26e7 bellard
    {
3313 14ce26e7 bellard
        switch (b) {
3314 14ce26e7 bellard
        case 0xf3:
3315 14ce26e7 bellard
            prefixes |= PREFIX_REPZ;
3316 14ce26e7 bellard
            goto next_byte;
3317 14ce26e7 bellard
        case 0xf2:
3318 14ce26e7 bellard
            prefixes |= PREFIX_REPNZ;
3319 14ce26e7 bellard
            goto next_byte;
3320 14ce26e7 bellard
        case 0xf0:
3321 14ce26e7 bellard
            prefixes |= PREFIX_LOCK;
3322 14ce26e7 bellard
            goto next_byte;
3323 14ce26e7 bellard
        case 0x2e:
3324 14ce26e7 bellard
            s->override = R_CS;
3325 14ce26e7 bellard
            goto next_byte;
3326 14ce26e7 bellard
        case 0x36:
3327 14ce26e7 bellard
            s->override = R_SS;
3328 14ce26e7 bellard
            goto next_byte;
3329 14ce26e7 bellard
        case 0x3e:
3330 14ce26e7 bellard
            s->override = R_DS;
3331 14ce26e7 bellard
            goto next_byte;
3332 14ce26e7 bellard
        case 0x26:
3333 14ce26e7 bellard
            s->override = R_ES;
3334 14ce26e7 bellard
            goto next_byte;
3335 14ce26e7 bellard
        case 0x64:
3336 14ce26e7 bellard
            s->override = R_FS;
3337 14ce26e7 bellard
            goto next_byte;
3338 14ce26e7 bellard
        case 0x65:
3339 14ce26e7 bellard
            s->override = R_GS;
3340 14ce26e7 bellard
            goto next_byte;
3341 14ce26e7 bellard
        case 0x66:
3342 14ce26e7 bellard
            prefixes |= PREFIX_DATA;
3343 14ce26e7 bellard
            goto next_byte;
3344 14ce26e7 bellard
        case 0x67:
3345 14ce26e7 bellard
            prefixes |= PREFIX_ADR;
3346 14ce26e7 bellard
            goto next_byte;
3347 14ce26e7 bellard
        }
3348 14ce26e7 bellard
        if (prefixes & PREFIX_DATA)
3349 14ce26e7 bellard
            dflag ^= 1;
3350 14ce26e7 bellard
        if (prefixes & PREFIX_ADR)
3351 14ce26e7 bellard
            aflag ^= 1;
3352 2c0262af bellard
    }
3353 2c0262af bellard
3354 2c0262af bellard
    s->prefix = prefixes;
3355 2c0262af bellard
    s->aflag = aflag;
3356 2c0262af bellard
    s->dflag = dflag;
3357 2c0262af bellard
3358 2c0262af bellard
    /* lock generation */
3359 2c0262af bellard
    if (prefixes & PREFIX_LOCK)
3360 2c0262af bellard
        gen_op_lock();
3361 2c0262af bellard
3362 2c0262af bellard
    /* now check op code */
3363 2c0262af bellard
 reswitch:
3364 2c0262af bellard
    switch(b) {
3365 2c0262af bellard
    case 0x0f:
3366 2c0262af bellard
        /**************************/
3367 2c0262af bellard
        /* extended op code */
3368 61382a50 bellard
        b = ldub_code(s->pc++) | 0x100;
3369 2c0262af bellard
        goto reswitch;
3370 3b46e624 ths
3371 2c0262af bellard
        /**************************/
3372 2c0262af bellard
        /* arith & logic */
3373 2c0262af bellard
    case 0x00 ... 0x05:
3374 2c0262af bellard
    case 0x08 ... 0x0d:
3375 2c0262af bellard
    case 0x10 ... 0x15:
3376 2c0262af bellard
    case 0x18 ... 0x1d:
3377 2c0262af bellard
    case 0x20 ... 0x25:
3378 2c0262af bellard
    case 0x28 ... 0x2d:
3379 2c0262af bellard
    case 0x30 ... 0x35:
3380 2c0262af bellard
    case 0x38 ... 0x3d:
3381 2c0262af bellard
        {
3382 2c0262af bellard
            int op, f, val;
3383 2c0262af bellard
            op = (b >> 3) & 7;
3384 2c0262af bellard
            f = (b >> 1) & 3;
3385 2c0262af bellard
3386 2c0262af bellard
            if ((b & 1) == 0)
3387 2c0262af bellard
                ot = OT_BYTE;
3388 2c0262af bellard
            else
3389 14ce26e7 bellard
                ot = dflag + OT_WORD;
3390 3b46e624 ths
3391 2c0262af bellard
            switch(f) {
3392 2c0262af bellard
            case 0: /* OP Ev, Gv */
3393 61382a50 bellard
                modrm = ldub_code(s->pc++);
3394 14ce26e7 bellard
                reg = ((modrm >> 3) & 7) | rex_r;
3395 2c0262af bellard
                mod = (modrm >> 6) & 3;
3396 14ce26e7 bellard
                rm = (modrm & 7) | REX_B(s);
3397 2c0262af bellard
                if (mod != 3) {
3398 2c0262af bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3399 2c0262af bellard
                    opreg = OR_TMP0;
3400 2c0262af bellard
                } else if (op == OP_XORL && rm == reg) {
3401 2c0262af bellard
                xor_zero:
3402 2c0262af bellard
                    /* xor reg, reg optimisation */
3403 2c0262af bellard
                    gen_op_movl_T0_0();
3404 2c0262af bellard
                    s->cc_op = CC_OP_LOGICB + ot;
3405 57fec1fe bellard
                    gen_op_mov_reg_T0(ot, reg);
3406 2c0262af bellard
                    gen_op_update1_cc();
3407 2c0262af bellard
                    break;
3408 2c0262af bellard
                } else {
3409 2c0262af bellard
                    opreg = rm;
3410 2c0262af bellard
                }
3411 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 1, reg);
3412 2c0262af bellard
                gen_op(s, op, ot, opreg);
3413 2c0262af bellard
                break;
3414 2c0262af bellard
            case 1: /* OP Gv, Ev */
3415 61382a50 bellard
                modrm = ldub_code(s->pc++);
3416 2c0262af bellard
                mod = (modrm >> 6) & 3;
3417 14ce26e7 bellard
                reg = ((modrm >> 3) & 7) | rex_r;
3418 14ce26e7 bellard
                rm = (modrm & 7) | REX_B(s);
3419 2c0262af bellard
                if (mod != 3) {
3420 2c0262af bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3421 57fec1fe bellard
                    gen_op_ld_T1_A0(ot + s->mem_index);
3422 2c0262af bellard
                } else if (op == OP_XORL && rm == reg) {
3423 2c0262af bellard
                    goto xor_zero;
3424 2c0262af bellard
                } else {
3425 57fec1fe bellard
                    gen_op_mov_TN_reg(ot, 1, rm);
3426 2c0262af bellard
                }
3427 2c0262af bellard
                gen_op(s, op, ot, reg);
3428 2c0262af bellard
                break;
3429 2c0262af bellard
            case 2: /* OP A, Iv */
3430 2c0262af bellard
                val = insn_get(s, ot);
3431 2c0262af bellard
                gen_op_movl_T1_im(val);
3432 2c0262af bellard
                gen_op(s, op, ot, OR_EAX);
3433 2c0262af bellard
                break;
3434 2c0262af bellard
            }
3435 2c0262af bellard
        }
3436 2c0262af bellard
        break;
3437 2c0262af bellard
3438 2c0262af bellard
    case 0x80: /* GRP1 */
3439 2c0262af bellard
    case 0x81:
3440 d64477af bellard
    case 0x82:
3441 2c0262af bellard
    case 0x83:
3442 2c0262af bellard
        {
3443 2c0262af bellard
            int val;
3444 2c0262af bellard
3445 2c0262af bellard
            if ((b & 1) == 0)
3446 2c0262af bellard
                ot = OT_BYTE;
3447 2c0262af bellard
            else
3448 14ce26e7 bellard
                ot = dflag + OT_WORD;
3449 3b46e624 ths
3450 61382a50 bellard
            modrm = ldub_code(s->pc++);
3451 2c0262af bellard
            mod = (modrm >> 6) & 3;
3452 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
3453 2c0262af bellard
            op = (modrm >> 3) & 7;
3454 3b46e624 ths
3455 2c0262af bellard
            if (mod != 3) {
3456 14ce26e7 bellard
                if (b == 0x83)
3457 14ce26e7 bellard
                    s->rip_offset = 1;
3458 14ce26e7 bellard
                else
3459 14ce26e7 bellard
                    s->rip_offset = insn_const_size(ot);
3460 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3461 2c0262af bellard
                opreg = OR_TMP0;
3462 2c0262af bellard
            } else {
3463 14ce26e7 bellard
                opreg = rm;
3464 2c0262af bellard
            }
3465 2c0262af bellard
3466 2c0262af bellard
            switch(b) {
3467 2c0262af bellard
            default:
3468 2c0262af bellard
            case 0x80:
3469 2c0262af bellard
            case 0x81:
3470 d64477af bellard
            case 0x82:
3471 2c0262af bellard
                val = insn_get(s, ot);
3472 2c0262af bellard
                break;
3473 2c0262af bellard
            case 0x83:
3474 2c0262af bellard
                val = (int8_t)insn_get(s, OT_BYTE);
3475 2c0262af bellard
                break;
3476 2c0262af bellard
            }
3477 2c0262af bellard
            gen_op_movl_T1_im(val);
3478 2c0262af bellard
            gen_op(s, op, ot, opreg);
3479 2c0262af bellard
        }
3480 2c0262af bellard
        break;
3481 2c0262af bellard
3482 2c0262af bellard
        /**************************/
3483 2c0262af bellard
        /* inc, dec, and other misc arith */
3484 2c0262af bellard
    case 0x40 ... 0x47: /* inc Gv */
3485 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
3486 2c0262af bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
3487 2c0262af bellard
        break;
3488 2c0262af bellard
    case 0x48 ... 0x4f: /* dec Gv */
3489 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
3490 2c0262af bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
3491 2c0262af bellard
        break;
3492 2c0262af bellard
    case 0xf6: /* GRP3 */
3493 2c0262af bellard
    case 0xf7:
3494 2c0262af bellard
        if ((b & 1) == 0)
3495 2c0262af bellard
            ot = OT_BYTE;
3496 2c0262af bellard
        else
3497 14ce26e7 bellard
            ot = dflag + OT_WORD;
3498 2c0262af bellard
3499 61382a50 bellard
        modrm = ldub_code(s->pc++);
3500 2c0262af bellard
        mod = (modrm >> 6) & 3;
3501 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
3502 2c0262af bellard
        op = (modrm >> 3) & 7;
3503 2c0262af bellard
        if (mod != 3) {
3504 14ce26e7 bellard
            if (op == 0)
3505 14ce26e7 bellard
                s->rip_offset = insn_const_size(ot);
3506 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3507 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
3508 2c0262af bellard
        } else {
3509 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
3510 2c0262af bellard
        }
3511 2c0262af bellard
3512 2c0262af bellard
        switch(op) {
3513 2c0262af bellard
        case 0: /* test */
3514 2c0262af bellard
            val = insn_get(s, ot);
3515 2c0262af bellard
            gen_op_movl_T1_im(val);
3516 2c0262af bellard
            gen_op_testl_T0_T1_cc();
3517 2c0262af bellard
            s->cc_op = CC_OP_LOGICB + ot;
3518 2c0262af bellard
            break;
3519 2c0262af bellard
        case 2: /* not */
3520 2c0262af bellard
            gen_op_notl_T0();
3521 2c0262af bellard
            if (mod != 3) {
3522 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
3523 2c0262af bellard
            } else {
3524 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
3525 2c0262af bellard
            }
3526 2c0262af bellard
            break;
3527 2c0262af bellard
        case 3: /* neg */
3528 2c0262af bellard
            gen_op_negl_T0();
3529 2c0262af bellard
            if (mod != 3) {
3530 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
3531 2c0262af bellard
            } else {
3532 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
3533 2c0262af bellard
            }
3534 2c0262af bellard
            gen_op_update_neg_cc();
3535 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
3536 2c0262af bellard
            break;
3537 2c0262af bellard
        case 4: /* mul */
3538 2c0262af bellard
            switch(ot) {
3539 2c0262af bellard
            case OT_BYTE:
3540 2c0262af bellard
                gen_op_mulb_AL_T0();
3541 d36cd60e bellard
                s->cc_op = CC_OP_MULB;
3542 2c0262af bellard
                break;
3543 2c0262af bellard
            case OT_WORD:
3544 2c0262af bellard
                gen_op_mulw_AX_T0();
3545 d36cd60e bellard
                s->cc_op = CC_OP_MULW;
3546 2c0262af bellard
                break;
3547 2c0262af bellard
            default:
3548 2c0262af bellard
            case OT_LONG:
3549 2c0262af bellard
                gen_op_mull_EAX_T0();
3550 d36cd60e bellard
                s->cc_op = CC_OP_MULL;
3551 2c0262af bellard
                break;
3552 14ce26e7 bellard
#ifdef TARGET_X86_64
3553 14ce26e7 bellard
            case OT_QUAD:
3554 14ce26e7 bellard
                gen_op_mulq_EAX_T0();
3555 14ce26e7 bellard
                s->cc_op = CC_OP_MULQ;
3556 14ce26e7 bellard
                break;
3557 14ce26e7 bellard
#endif
3558 2c0262af bellard
            }
3559 2c0262af bellard
            break;
3560 2c0262af bellard
        case 5: /* imul */
3561 2c0262af bellard
            switch(ot) {
3562 2c0262af bellard
            case OT_BYTE:
3563 2c0262af bellard
                gen_op_imulb_AL_T0();
3564 d36cd60e bellard
                s->cc_op = CC_OP_MULB;
3565 2c0262af bellard
                break;
3566 2c0262af bellard
            case OT_WORD:
3567 2c0262af bellard
                gen_op_imulw_AX_T0();
3568 d36cd60e bellard
                s->cc_op = CC_OP_MULW;
3569 2c0262af bellard
                break;
3570 2c0262af bellard
            default:
3571 2c0262af bellard
            case OT_LONG:
3572 2c0262af bellard
                gen_op_imull_EAX_T0();
3573 d36cd60e bellard
                s->cc_op = CC_OP_MULL;
3574 2c0262af bellard
                break;
3575 14ce26e7 bellard
#ifdef TARGET_X86_64
3576 14ce26e7 bellard
            case OT_QUAD:
3577 14ce26e7 bellard
                gen_op_imulq_EAX_T0();
3578 14ce26e7 bellard
                s->cc_op = CC_OP_MULQ;
3579 14ce26e7 bellard
                break;
3580 14ce26e7 bellard
#endif
3581 2c0262af bellard
            }
3582 2c0262af bellard
            break;
3583 2c0262af bellard
        case 6: /* div */
3584 2c0262af bellard
            switch(ot) {
3585 2c0262af bellard
            case OT_BYTE:
3586 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3587 14ce26e7 bellard
                gen_op_divb_AL_T0();
3588 2c0262af bellard
                break;
3589 2c0262af bellard
            case OT_WORD:
3590 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3591 14ce26e7 bellard
                gen_op_divw_AX_T0();
3592 2c0262af bellard
                break;
3593 2c0262af bellard
            default:
3594 2c0262af bellard
            case OT_LONG:
3595 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3596 57fec1fe bellard
#ifdef MACRO_TEST
3597 57fec1fe bellard
                /* XXX: this is just a test */
3598 57fec1fe bellard
                tcg_gen_macro_2(cpu_T[0], cpu_T[0], MACRO_TEST);
3599 57fec1fe bellard
#else
3600 57fec1fe bellard
                tcg_gen_helper_0_1(helper_divl_EAX_T0, cpu_T[0]);
3601 57fec1fe bellard
#endif
3602 14ce26e7 bellard
                break;
3603 14ce26e7 bellard
#ifdef TARGET_X86_64
3604 14ce26e7 bellard
            case OT_QUAD:
3605 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3606 14ce26e7 bellard
                gen_op_divq_EAX_T0();
3607 2c0262af bellard
                break;
3608 14ce26e7 bellard
#endif
3609 2c0262af bellard
            }
3610 2c0262af bellard
            break;
3611 2c0262af bellard
        case 7: /* idiv */
3612 2c0262af bellard
            switch(ot) {
3613 2c0262af bellard
            case OT_BYTE:
3614 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3615 14ce26e7 bellard
                gen_op_idivb_AL_T0();
3616 2c0262af bellard
                break;
3617 2c0262af bellard
            case OT_WORD:
3618 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3619 14ce26e7 bellard
                gen_op_idivw_AX_T0();
3620 2c0262af bellard
                break;
3621 2c0262af bellard
            default:
3622 2c0262af bellard
            case OT_LONG:
3623 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3624 57fec1fe bellard
                tcg_gen_helper_0_1(helper_idivl_EAX_T0, cpu_T[0]);
3625 14ce26e7 bellard
                break;
3626 14ce26e7 bellard
#ifdef TARGET_X86_64
3627 14ce26e7 bellard
            case OT_QUAD:
3628 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3629 14ce26e7 bellard
                gen_op_idivq_EAX_T0();
3630 2c0262af bellard
                break;
3631 14ce26e7 bellard
#endif
3632 2c0262af bellard
            }
3633 2c0262af bellard
            break;
3634 2c0262af bellard
        default:
3635 2c0262af bellard
            goto illegal_op;
3636 2c0262af bellard
        }
3637 2c0262af bellard
        break;
3638 2c0262af bellard
3639 2c0262af bellard
    case 0xfe: /* GRP4 */
3640 2c0262af bellard
    case 0xff: /* GRP5 */
3641 2c0262af bellard
        if ((b & 1) == 0)
3642 2c0262af bellard
            ot = OT_BYTE;
3643 2c0262af bellard
        else
3644 14ce26e7 bellard
            ot = dflag + OT_WORD;
3645 2c0262af bellard
3646 61382a50 bellard
        modrm = ldub_code(s->pc++);
3647 2c0262af bellard
        mod = (modrm >> 6) & 3;
3648 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
3649 2c0262af bellard
        op = (modrm >> 3) & 7;
3650 2c0262af bellard
        if (op >= 2 && b == 0xfe) {
3651 2c0262af bellard
            goto illegal_op;
3652 2c0262af bellard
        }
3653 14ce26e7 bellard
        if (CODE64(s)) {
3654 aba9d61e bellard
            if (op == 2 || op == 4) {
3655 14ce26e7 bellard
                /* operand size for jumps is 64 bit */
3656 14ce26e7 bellard
                ot = OT_QUAD;
3657 aba9d61e bellard
            } else if (op == 3 || op == 5) {
3658 aba9d61e bellard
                /* for call calls, the operand is 16 or 32 bit, even
3659 aba9d61e bellard
                   in long mode */
3660 aba9d61e bellard
                ot = dflag ? OT_LONG : OT_WORD;
3661 14ce26e7 bellard
            } else if (op == 6) {
3662 14ce26e7 bellard
                /* default push size is 64 bit */
3663 14ce26e7 bellard
                ot = dflag ? OT_QUAD : OT_WORD;
3664 14ce26e7 bellard
            }
3665 14ce26e7 bellard
        }
3666 2c0262af bellard
        if (mod != 3) {
3667 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3668 2c0262af bellard
            if (op >= 2 && op != 3 && op != 5)
3669 57fec1fe bellard
                gen_op_ld_T0_A0(ot + s->mem_index);
3670 2c0262af bellard
        } else {
3671 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
3672 2c0262af bellard
        }
3673 2c0262af bellard
3674 2c0262af bellard
        switch(op) {
3675 2c0262af bellard
        case 0: /* inc Ev */
3676 2c0262af bellard
            if (mod != 3)
3677 2c0262af bellard
                opreg = OR_TMP0;
3678 2c0262af bellard
            else
3679 2c0262af bellard
                opreg = rm;
3680 2c0262af bellard
            gen_inc(s, ot, opreg, 1);
3681 2c0262af bellard
            break;
3682 2c0262af bellard
        case 1: /* dec Ev */
3683 2c0262af bellard
            if (mod != 3)
3684 2c0262af bellard
                opreg = OR_TMP0;
3685 2c0262af bellard
            else
3686 2c0262af bellard
                opreg = rm;
3687 2c0262af bellard
            gen_inc(s, ot, opreg, -1);
3688 2c0262af bellard
            break;
3689 2c0262af bellard
        case 2: /* call Ev */
3690 4f31916f bellard
            /* XXX: optimize if memory (no 'and' is necessary) */
3691 2c0262af bellard
            if (s->dflag == 0)
3692 2c0262af bellard
                gen_op_andl_T0_ffff();
3693 2c0262af bellard
            next_eip = s->pc - s->cs_base;
3694 1ef38687 bellard
            gen_movtl_T1_im(next_eip);
3695 4f31916f bellard
            gen_push_T1(s);
3696 4f31916f bellard
            gen_op_jmp_T0();
3697 2c0262af bellard
            gen_eob(s);
3698 2c0262af bellard
            break;
3699 61382a50 bellard
        case 3: /* lcall Ev */
3700 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
3701 aba9d61e bellard
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3702 57fec1fe bellard
            gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
3703 2c0262af bellard
        do_lcall:
3704 2c0262af bellard
            if (s->pe && !s->vm86) {
3705 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
3706 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
3707 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3708 aba9d61e bellard
                gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3709 2c0262af bellard
            } else {
3710 2c0262af bellard
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3711 2c0262af bellard
            }
3712 2c0262af bellard
            gen_eob(s);
3713 2c0262af bellard
            break;
3714 2c0262af bellard
        case 4: /* jmp Ev */
3715 2c0262af bellard
            if (s->dflag == 0)
3716 2c0262af bellard
                gen_op_andl_T0_ffff();
3717 2c0262af bellard
            gen_op_jmp_T0();
3718 2c0262af bellard
            gen_eob(s);
3719 2c0262af bellard
            break;
3720 2c0262af bellard
        case 5: /* ljmp Ev */
3721 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
3722 aba9d61e bellard
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3723 57fec1fe bellard
            gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
3724 2c0262af bellard
        do_ljmp:
3725 2c0262af bellard
            if (s->pe && !s->vm86) {
3726 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
3727 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
3728 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
3729 aba9d61e bellard
                gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3730 2c0262af bellard
            } else {
3731 2c0262af bellard
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3732 2c0262af bellard
                gen_op_movl_T0_T1();
3733 2c0262af bellard
                gen_op_jmp_T0();
3734 2c0262af bellard
            }
3735 2c0262af bellard
            gen_eob(s);
3736 2c0262af bellard
            break;
3737 2c0262af bellard
        case 6: /* push Ev */
3738 2c0262af bellard
            gen_push_T0(s);
3739 2c0262af bellard
            break;
3740 2c0262af bellard
        default:
3741 2c0262af bellard
            goto illegal_op;
3742 2c0262af bellard
        }
3743 2c0262af bellard
        break;
3744 2c0262af bellard
3745 2c0262af bellard
    case 0x84: /* test Ev, Gv */
3746 5fafdf24 ths
    case 0x85:
3747 2c0262af bellard
        if ((b & 1) == 0)
3748 2c0262af bellard
            ot = OT_BYTE;
3749 2c0262af bellard
        else
3750 14ce26e7 bellard
            ot = dflag + OT_WORD;
3751 2c0262af bellard
3752 61382a50 bellard
        modrm = ldub_code(s->pc++);
3753 2c0262af bellard
        mod = (modrm >> 6) & 3;
3754 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
3755 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
3756 3b46e624 ths
3757 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3758 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
3759 2c0262af bellard
        gen_op_testl_T0_T1_cc();
3760 2c0262af bellard
        s->cc_op = CC_OP_LOGICB + ot;
3761 2c0262af bellard
        break;
3762 3b46e624 ths
3763 2c0262af bellard
    case 0xa8: /* test eAX, Iv */
3764 2c0262af bellard
    case 0xa9:
3765 2c0262af bellard
        if ((b & 1) == 0)
3766 2c0262af bellard
            ot = OT_BYTE;
3767 2c0262af bellard
        else
3768 14ce26e7 bellard
            ot = dflag + OT_WORD;
3769 2c0262af bellard
        val = insn_get(s, ot);
3770 2c0262af bellard
3771 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, OR_EAX);
3772 2c0262af bellard
        gen_op_movl_T1_im(val);
3773 2c0262af bellard
        gen_op_testl_T0_T1_cc();
3774 2c0262af bellard
        s->cc_op = CC_OP_LOGICB + ot;
3775 2c0262af bellard
        break;
3776 3b46e624 ths
3777 2c0262af bellard
    case 0x98: /* CWDE/CBW */
3778 14ce26e7 bellard
#ifdef TARGET_X86_64
3779 14ce26e7 bellard
        if (dflag == 2) {
3780 14ce26e7 bellard
            gen_op_movslq_RAX_EAX();
3781 14ce26e7 bellard
        } else
3782 14ce26e7 bellard
#endif
3783 14ce26e7 bellard
        if (dflag == 1)
3784 2c0262af bellard
            gen_op_movswl_EAX_AX();
3785 2c0262af bellard
        else
3786 2c0262af bellard
            gen_op_movsbw_AX_AL();
3787 2c0262af bellard
        break;
3788 2c0262af bellard
    case 0x99: /* CDQ/CWD */
3789 14ce26e7 bellard
#ifdef TARGET_X86_64
3790 14ce26e7 bellard
        if (dflag == 2) {
3791 14ce26e7 bellard
            gen_op_movsqo_RDX_RAX();
3792 14ce26e7 bellard
        } else
3793 14ce26e7 bellard
#endif
3794 14ce26e7 bellard
        if (dflag == 1)
3795 2c0262af bellard
            gen_op_movslq_EDX_EAX();
3796 2c0262af bellard
        else
3797 2c0262af bellard
            gen_op_movswl_DX_AX();
3798 2c0262af bellard
        break;
3799 2c0262af bellard
    case 0x1af: /* imul Gv, Ev */
3800 2c0262af bellard
    case 0x69: /* imul Gv, Ev, I */
3801 2c0262af bellard
    case 0x6b:
3802 14ce26e7 bellard
        ot = dflag + OT_WORD;
3803 61382a50 bellard
        modrm = ldub_code(s->pc++);
3804 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
3805 14ce26e7 bellard
        if (b == 0x69)
3806 14ce26e7 bellard
            s->rip_offset = insn_const_size(ot);
3807 14ce26e7 bellard
        else if (b == 0x6b)
3808 14ce26e7 bellard
            s->rip_offset = 1;
3809 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3810 2c0262af bellard
        if (b == 0x69) {
3811 2c0262af bellard
            val = insn_get(s, ot);
3812 2c0262af bellard
            gen_op_movl_T1_im(val);
3813 2c0262af bellard
        } else if (b == 0x6b) {
3814 d64477af bellard
            val = (int8_t)insn_get(s, OT_BYTE);
3815 2c0262af bellard
            gen_op_movl_T1_im(val);
3816 2c0262af bellard
        } else {
3817 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, reg);
3818 2c0262af bellard
        }
3819 2c0262af bellard
3820 14ce26e7 bellard
#ifdef TARGET_X86_64
3821 14ce26e7 bellard
        if (ot == OT_QUAD) {
3822 14ce26e7 bellard
            gen_op_imulq_T0_T1();
3823 14ce26e7 bellard
        } else
3824 14ce26e7 bellard
#endif
3825 2c0262af bellard
        if (ot == OT_LONG) {
3826 2c0262af bellard
            gen_op_imull_T0_T1();
3827 2c0262af bellard
        } else {
3828 2c0262af bellard
            gen_op_imulw_T0_T1();
3829 2c0262af bellard
        }
3830 57fec1fe bellard
        gen_op_mov_reg_T0(ot, reg);
3831 d36cd60e bellard
        s->cc_op = CC_OP_MULB + ot;
3832 2c0262af bellard
        break;
3833 2c0262af bellard
    case 0x1c0:
3834 2c0262af bellard
    case 0x1c1: /* xadd Ev, Gv */
3835 2c0262af bellard
        if ((b & 1) == 0)
3836 2c0262af bellard
            ot = OT_BYTE;
3837 2c0262af bellard
        else
3838 14ce26e7 bellard
            ot = dflag + OT_WORD;
3839 61382a50 bellard
        modrm = ldub_code(s->pc++);
3840 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
3841 2c0262af bellard
        mod = (modrm >> 6) & 3;
3842 2c0262af bellard
        if (mod == 3) {
3843 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
3844 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
3845 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, rm);
3846 2c0262af bellard
            gen_op_addl_T0_T1();
3847 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
3848 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
3849 2c0262af bellard
        } else {
3850 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3851 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
3852 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
3853 2c0262af bellard
            gen_op_addl_T0_T1();
3854 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
3855 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
3856 2c0262af bellard
        }
3857 2c0262af bellard
        gen_op_update2_cc();
3858 2c0262af bellard
        s->cc_op = CC_OP_ADDB + ot;
3859 2c0262af bellard
        break;
3860 2c0262af bellard
    case 0x1b0:
3861 2c0262af bellard
    case 0x1b1: /* cmpxchg Ev, Gv */
3862 2c0262af bellard
        if ((b & 1) == 0)
3863 2c0262af bellard
            ot = OT_BYTE;
3864 2c0262af bellard
        else
3865 14ce26e7 bellard
            ot = dflag + OT_WORD;
3866 61382a50 bellard
        modrm = ldub_code(s->pc++);
3867 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
3868 2c0262af bellard
        mod = (modrm >> 6) & 3;
3869 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
3870 2c0262af bellard
        if (mod == 3) {
3871 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
3872 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
3873 2c0262af bellard
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3874 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
3875 2c0262af bellard
        } else {
3876 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3877 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
3878 4f31916f bellard
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3879 2c0262af bellard
        }
3880 2c0262af bellard
        s->cc_op = CC_OP_SUBB + ot;
3881 2c0262af bellard
        break;
3882 2c0262af bellard
    case 0x1c7: /* cmpxchg8b */
3883 61382a50 bellard
        modrm = ldub_code(s->pc++);
3884 2c0262af bellard
        mod = (modrm >> 6) & 3;
3885 71c3558e balrog
        if ((mod == 3) || ((modrm & 0x38) != 0x8))
3886 2c0262af bellard
            goto illegal_op;
3887 2f6ecc62 ths
        gen_jmp_im(pc_start - s->cs_base);
3888 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3889 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
3890 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3891 2c0262af bellard
        gen_op_cmpxchg8b();
3892 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
3893 2c0262af bellard
        break;
3894 3b46e624 ths
3895 2c0262af bellard
        /**************************/
3896 2c0262af bellard
        /* push/pop */
3897 2c0262af bellard
    case 0x50 ... 0x57: /* push */
3898 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
3899 2c0262af bellard
        gen_push_T0(s);
3900 2c0262af bellard
        break;
3901 2c0262af bellard
    case 0x58 ... 0x5f: /* pop */
3902 14ce26e7 bellard
        if (CODE64(s)) {
3903 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
3904 14ce26e7 bellard
        } else {
3905 14ce26e7 bellard
            ot = dflag + OT_WORD;
3906 14ce26e7 bellard
        }
3907 2c0262af bellard
        gen_pop_T0(s);
3908 77729c24 bellard
        /* NOTE: order is important for pop %sp */
3909 2c0262af bellard
        gen_pop_update(s);
3910 57fec1fe bellard
        gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
3911 2c0262af bellard
        break;
3912 2c0262af bellard
    case 0x60: /* pusha */
3913 14ce26e7 bellard
        if (CODE64(s))
3914 14ce26e7 bellard
            goto illegal_op;
3915 2c0262af bellard
        gen_pusha(s);
3916 2c0262af bellard
        break;
3917 2c0262af bellard
    case 0x61: /* popa */
3918 14ce26e7 bellard
        if (CODE64(s))
3919 14ce26e7 bellard
            goto illegal_op;
3920 2c0262af bellard
        gen_popa(s);
3921 2c0262af bellard
        break;
3922 2c0262af bellard
    case 0x68: /* push Iv */
3923 2c0262af bellard
    case 0x6a:
3924 14ce26e7 bellard
        if (CODE64(s)) {
3925 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
3926 14ce26e7 bellard
        } else {
3927 14ce26e7 bellard
            ot = dflag + OT_WORD;
3928 14ce26e7 bellard
        }
3929 2c0262af bellard
        if (b == 0x68)
3930 2c0262af bellard
            val = insn_get(s, ot);
3931 2c0262af bellard
        else
3932 2c0262af bellard
            val = (int8_t)insn_get(s, OT_BYTE);
3933 2c0262af bellard
        gen_op_movl_T0_im(val);
3934 2c0262af bellard
        gen_push_T0(s);
3935 2c0262af bellard
        break;
3936 2c0262af bellard
    case 0x8f: /* pop Ev */
3937 14ce26e7 bellard
        if (CODE64(s)) {
3938 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
3939 14ce26e7 bellard
        } else {
3940 14ce26e7 bellard
            ot = dflag + OT_WORD;
3941 14ce26e7 bellard
        }
3942 61382a50 bellard
        modrm = ldub_code(s->pc++);
3943 77729c24 bellard
        mod = (modrm >> 6) & 3;
3944 2c0262af bellard
        gen_pop_T0(s);
3945 77729c24 bellard
        if (mod == 3) {
3946 77729c24 bellard
            /* NOTE: order is important for pop %sp */
3947 77729c24 bellard
            gen_pop_update(s);
3948 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
3949 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
3950 77729c24 bellard
        } else {
3951 77729c24 bellard
            /* NOTE: order is important too for MMU exceptions */
3952 14ce26e7 bellard
            s->popl_esp_hack = 1 << ot;
3953 77729c24 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3954 77729c24 bellard
            s->popl_esp_hack = 0;
3955 77729c24 bellard
            gen_pop_update(s);
3956 77729c24 bellard
        }
3957 2c0262af bellard
        break;
3958 2c0262af bellard
    case 0xc8: /* enter */
3959 2c0262af bellard
        {
3960 2c0262af bellard
            int level;
3961 61382a50 bellard
            val = lduw_code(s->pc);
3962 2c0262af bellard
            s->pc += 2;
3963 61382a50 bellard
            level = ldub_code(s->pc++);
3964 2c0262af bellard
            gen_enter(s, val, level);
3965 2c0262af bellard
        }
3966 2c0262af bellard
        break;
3967 2c0262af bellard
    case 0xc9: /* leave */
3968 2c0262af bellard
        /* XXX: exception not precise (ESP is updated before potential exception) */
3969 14ce26e7 bellard
        if (CODE64(s)) {
3970 57fec1fe bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
3971 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, R_ESP);
3972 14ce26e7 bellard
        } else if (s->ss32) {
3973 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
3974 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, R_ESP);
3975 2c0262af bellard
        } else {
3976 57fec1fe bellard
            gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
3977 57fec1fe bellard
            gen_op_mov_reg_T0(OT_WORD, R_ESP);
3978 2c0262af bellard
        }
3979 2c0262af bellard
        gen_pop_T0(s);
3980 14ce26e7 bellard
        if (CODE64(s)) {
3981 14ce26e7 bellard
            ot = dflag ? OT_QUAD : OT_WORD;
3982 14ce26e7 bellard
        } else {
3983 14ce26e7 bellard
            ot = dflag + OT_WORD;
3984 14ce26e7 bellard
        }
3985 57fec1fe bellard
        gen_op_mov_reg_T0(ot, R_EBP);
3986 2c0262af bellard
        gen_pop_update(s);
3987 2c0262af bellard
        break;
3988 2c0262af bellard
    case 0x06: /* push es */
3989 2c0262af bellard
    case 0x0e: /* push cs */
3990 2c0262af bellard
    case 0x16: /* push ss */
3991 2c0262af bellard
    case 0x1e: /* push ds */
3992 14ce26e7 bellard
        if (CODE64(s))
3993 14ce26e7 bellard
            goto illegal_op;
3994 2c0262af bellard
        gen_op_movl_T0_seg(b >> 3);
3995 2c0262af bellard
        gen_push_T0(s);
3996 2c0262af bellard
        break;
3997 2c0262af bellard
    case 0x1a0: /* push fs */
3998 2c0262af bellard
    case 0x1a8: /* push gs */
3999 2c0262af bellard
        gen_op_movl_T0_seg((b >> 3) & 7);
4000 2c0262af bellard
        gen_push_T0(s);
4001 2c0262af bellard
        break;
4002 2c0262af bellard
    case 0x07: /* pop es */
4003 2c0262af bellard
    case 0x17: /* pop ss */
4004 2c0262af bellard
    case 0x1f: /* pop ds */
4005 14ce26e7 bellard
        if (CODE64(s))
4006 14ce26e7 bellard
            goto illegal_op;
4007 2c0262af bellard
        reg = b >> 3;
4008 2c0262af bellard
        gen_pop_T0(s);
4009 2c0262af bellard
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4010 2c0262af bellard
        gen_pop_update(s);
4011 2c0262af bellard
        if (reg == R_SS) {
4012 a2cc3b24 bellard
            /* if reg == SS, inhibit interrupts/trace. */
4013 a2cc3b24 bellard
            /* If several instructions disable interrupts, only the
4014 a2cc3b24 bellard
               _first_ does it */
4015 a2cc3b24 bellard
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4016 a2cc3b24 bellard
                gen_op_set_inhibit_irq();
4017 2c0262af bellard
            s->tf = 0;
4018 2c0262af bellard
        }
4019 2c0262af bellard
        if (s->is_jmp) {
4020 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4021 2c0262af bellard
            gen_eob(s);
4022 2c0262af bellard
        }
4023 2c0262af bellard
        break;
4024 2c0262af bellard
    case 0x1a1: /* pop fs */
4025 2c0262af bellard
    case 0x1a9: /* pop gs */
4026 2c0262af bellard
        gen_pop_T0(s);
4027 2c0262af bellard
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4028 2c0262af bellard
        gen_pop_update(s);
4029 2c0262af bellard
        if (s->is_jmp) {
4030 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4031 2c0262af bellard
            gen_eob(s);
4032 2c0262af bellard
        }
4033 2c0262af bellard
        break;
4034 2c0262af bellard
4035 2c0262af bellard
        /**************************/
4036 2c0262af bellard
        /* mov */
4037 2c0262af bellard
    case 0x88:
4038 2c0262af bellard
    case 0x89: /* mov Gv, Ev */
4039 2c0262af bellard
        if ((b & 1) == 0)
4040 2c0262af bellard
            ot = OT_BYTE;
4041 2c0262af bellard
        else
4042 14ce26e7 bellard
            ot = dflag + OT_WORD;
4043 61382a50 bellard
        modrm = ldub_code(s->pc++);
4044 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4045 3b46e624 ths
4046 2c0262af bellard
        /* generate a generic store */
4047 14ce26e7 bellard
        gen_ldst_modrm(s, modrm, ot, reg, 1);
4048 2c0262af bellard
        break;
4049 2c0262af bellard
    case 0xc6:
4050 2c0262af bellard
    case 0xc7: /* mov Ev, Iv */
4051 2c0262af bellard
        if ((b & 1) == 0)
4052 2c0262af bellard
            ot = OT_BYTE;
4053 2c0262af bellard
        else
4054 14ce26e7 bellard
            ot = dflag + OT_WORD;
4055 61382a50 bellard
        modrm = ldub_code(s->pc++);
4056 2c0262af bellard
        mod = (modrm >> 6) & 3;
4057 14ce26e7 bellard
        if (mod != 3) {
4058 14ce26e7 bellard
            s->rip_offset = insn_const_size(ot);
4059 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4060 14ce26e7 bellard
        }
4061 2c0262af bellard
        val = insn_get(s, ot);
4062 2c0262af bellard
        gen_op_movl_T0_im(val);
4063 2c0262af bellard
        if (mod != 3)
4064 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
4065 2c0262af bellard
        else
4066 57fec1fe bellard
            gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
4067 2c0262af bellard
        break;
4068 2c0262af bellard
    case 0x8a:
4069 2c0262af bellard
    case 0x8b: /* mov Ev, Gv */
4070 2c0262af bellard
        if ((b & 1) == 0)
4071 2c0262af bellard
            ot = OT_BYTE;
4072 2c0262af bellard
        else
4073 14ce26e7 bellard
            ot = OT_WORD + dflag;
4074 61382a50 bellard
        modrm = ldub_code(s->pc++);
4075 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4076 3b46e624 ths
4077 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4078 57fec1fe bellard
        gen_op_mov_reg_T0(ot, reg);
4079 2c0262af bellard
        break;
4080 2c0262af bellard
    case 0x8e: /* mov seg, Gv */
4081 61382a50 bellard
        modrm = ldub_code(s->pc++);
4082 2c0262af bellard
        reg = (modrm >> 3) & 7;
4083 2c0262af bellard
        if (reg >= 6 || reg == R_CS)
4084 2c0262af bellard
            goto illegal_op;
4085 2c0262af bellard
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4086 2c0262af bellard
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4087 2c0262af bellard
        if (reg == R_SS) {
4088 2c0262af bellard
            /* if reg == SS, inhibit interrupts/trace */
4089 a2cc3b24 bellard
            /* If several instructions disable interrupts, only the
4090 a2cc3b24 bellard
               _first_ does it */
4091 a2cc3b24 bellard
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4092 a2cc3b24 bellard
                gen_op_set_inhibit_irq();
4093 2c0262af bellard
            s->tf = 0;
4094 2c0262af bellard
        }
4095 2c0262af bellard
        if (s->is_jmp) {
4096 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4097 2c0262af bellard
            gen_eob(s);
4098 2c0262af bellard
        }
4099 2c0262af bellard
        break;
4100 2c0262af bellard
    case 0x8c: /* mov Gv, seg */
4101 61382a50 bellard
        modrm = ldub_code(s->pc++);
4102 2c0262af bellard
        reg = (modrm >> 3) & 7;
4103 2c0262af bellard
        mod = (modrm >> 6) & 3;
4104 2c0262af bellard
        if (reg >= 6)
4105 2c0262af bellard
            goto illegal_op;
4106 2c0262af bellard
        gen_op_movl_T0_seg(reg);
4107 14ce26e7 bellard
        if (mod == 3)
4108 14ce26e7 bellard
            ot = OT_WORD + dflag;
4109 14ce26e7 bellard
        else
4110 14ce26e7 bellard
            ot = OT_WORD;
4111 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4112 2c0262af bellard
        break;
4113 2c0262af bellard
4114 2c0262af bellard
    case 0x1b6: /* movzbS Gv, Eb */
4115 2c0262af bellard
    case 0x1b7: /* movzwS Gv, Eb */
4116 2c0262af bellard
    case 0x1be: /* movsbS Gv, Eb */
4117 2c0262af bellard
    case 0x1bf: /* movswS Gv, Eb */
4118 2c0262af bellard
        {
4119 2c0262af bellard
            int d_ot;
4120 2c0262af bellard
            /* d_ot is the size of destination */
4121 2c0262af bellard
            d_ot = dflag + OT_WORD;
4122 2c0262af bellard
            /* ot is the size of source */
4123 2c0262af bellard
            ot = (b & 1) + OT_BYTE;
4124 61382a50 bellard
            modrm = ldub_code(s->pc++);
4125 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
4126 2c0262af bellard
            mod = (modrm >> 6) & 3;
4127 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4128 3b46e624 ths
4129 2c0262af bellard
            if (mod == 3) {
4130 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, rm);
4131 2c0262af bellard
                switch(ot | (b & 8)) {
4132 2c0262af bellard
                case OT_BYTE:
4133 2c0262af bellard
                    gen_op_movzbl_T0_T0();
4134 2c0262af bellard
                    break;
4135 2c0262af bellard
                case OT_BYTE | 8:
4136 2c0262af bellard
                    gen_op_movsbl_T0_T0();
4137 2c0262af bellard
                    break;
4138 2c0262af bellard
                case OT_WORD:
4139 2c0262af bellard
                    gen_op_movzwl_T0_T0();
4140 2c0262af bellard
                    break;
4141 2c0262af bellard
                default:
4142 2c0262af bellard
                case OT_WORD | 8:
4143 2c0262af bellard
                    gen_op_movswl_T0_T0();
4144 2c0262af bellard
                    break;
4145 2c0262af bellard
                }
4146 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
4147 2c0262af bellard
            } else {
4148 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4149 2c0262af bellard
                if (b & 8) {
4150 57fec1fe bellard
                    gen_op_lds_T0_A0(ot + s->mem_index);
4151 2c0262af bellard
                } else {
4152 57fec1fe bellard
                    gen_op_ldu_T0_A0(ot + s->mem_index);
4153 2c0262af bellard
                }
4154 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
4155 2c0262af bellard
            }
4156 2c0262af bellard
        }
4157 2c0262af bellard
        break;
4158 2c0262af bellard
4159 2c0262af bellard
    case 0x8d: /* lea */
4160 14ce26e7 bellard
        ot = dflag + OT_WORD;
4161 61382a50 bellard
        modrm = ldub_code(s->pc++);
4162 3a1d9b8b bellard
        mod = (modrm >> 6) & 3;
4163 3a1d9b8b bellard
        if (mod == 3)
4164 3a1d9b8b bellard
            goto illegal_op;
4165 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4166 2c0262af bellard
        /* we must ensure that no segment is added */
4167 2c0262af bellard
        s->override = -1;
4168 2c0262af bellard
        val = s->addseg;
4169 2c0262af bellard
        s->addseg = 0;
4170 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4171 2c0262af bellard
        s->addseg = val;
4172 57fec1fe bellard
        gen_op_mov_reg_A0(ot - OT_WORD, reg);
4173 2c0262af bellard
        break;
4174 3b46e624 ths
4175 2c0262af bellard
    case 0xa0: /* mov EAX, Ov */
4176 2c0262af bellard
    case 0xa1:
4177 2c0262af bellard
    case 0xa2: /* mov Ov, EAX */
4178 2c0262af bellard
    case 0xa3:
4179 2c0262af bellard
        {
4180 14ce26e7 bellard
            target_ulong offset_addr;
4181 14ce26e7 bellard
4182 14ce26e7 bellard
            if ((b & 1) == 0)
4183 14ce26e7 bellard
                ot = OT_BYTE;
4184 14ce26e7 bellard
            else
4185 14ce26e7 bellard
                ot = dflag + OT_WORD;
4186 14ce26e7 bellard
#ifdef TARGET_X86_64
4187 8f091a59 bellard
            if (s->aflag == 2) {
4188 14ce26e7 bellard
                offset_addr = ldq_code(s->pc);
4189 14ce26e7 bellard
                s->pc += 8;
4190 57fec1fe bellard
                gen_op_movq_A0_im(offset_addr);
4191 5fafdf24 ths
            } else
4192 14ce26e7 bellard
#endif
4193 14ce26e7 bellard
            {
4194 14ce26e7 bellard
                if (s->aflag) {
4195 14ce26e7 bellard
                    offset_addr = insn_get(s, OT_LONG);
4196 14ce26e7 bellard
                } else {
4197 14ce26e7 bellard
                    offset_addr = insn_get(s, OT_WORD);
4198 14ce26e7 bellard
                }
4199 14ce26e7 bellard
                gen_op_movl_A0_im(offset_addr);
4200 14ce26e7 bellard
            }
4201 664e0f19 bellard
            gen_add_A0_ds_seg(s);
4202 14ce26e7 bellard
            if ((b & 2) == 0) {
4203 57fec1fe bellard
                gen_op_ld_T0_A0(ot + s->mem_index);
4204 57fec1fe bellard
                gen_op_mov_reg_T0(ot, R_EAX);
4205 14ce26e7 bellard
            } else {
4206 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, R_EAX);
4207 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
4208 2c0262af bellard
            }
4209 2c0262af bellard
        }
4210 2c0262af bellard
        break;
4211 2c0262af bellard
    case 0xd7: /* xlat */
4212 14ce26e7 bellard
#ifdef TARGET_X86_64
4213 8f091a59 bellard
        if (s->aflag == 2) {
4214 57fec1fe bellard
            gen_op_movq_A0_reg(R_EBX);
4215 14ce26e7 bellard
            gen_op_addq_A0_AL();
4216 5fafdf24 ths
        } else
4217 14ce26e7 bellard
#endif
4218 14ce26e7 bellard
        {
4219 57fec1fe bellard
            gen_op_movl_A0_reg(R_EBX);
4220 14ce26e7 bellard
            gen_op_addl_A0_AL();
4221 14ce26e7 bellard
            if (s->aflag == 0)
4222 14ce26e7 bellard
                gen_op_andl_A0_ffff();
4223 14ce26e7 bellard
        }
4224 664e0f19 bellard
        gen_add_A0_ds_seg(s);
4225 57fec1fe bellard
        gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
4226 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, R_EAX);
4227 2c0262af bellard
        break;
4228 2c0262af bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
4229 2c0262af bellard
        val = insn_get(s, OT_BYTE);
4230 2c0262af bellard
        gen_op_movl_T0_im(val);
4231 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
4232 2c0262af bellard
        break;
4233 2c0262af bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
4234 14ce26e7 bellard
#ifdef TARGET_X86_64
4235 14ce26e7 bellard
        if (dflag == 2) {
4236 14ce26e7 bellard
            uint64_t tmp;
4237 14ce26e7 bellard
            /* 64 bit case */
4238 14ce26e7 bellard
            tmp = ldq_code(s->pc);
4239 14ce26e7 bellard
            s->pc += 8;
4240 14ce26e7 bellard
            reg = (b & 7) | REX_B(s);
4241 14ce26e7 bellard
            gen_movtl_T0_im(tmp);
4242 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, reg);
4243 5fafdf24 ths
        } else
4244 14ce26e7 bellard
#endif
4245 14ce26e7 bellard
        {
4246 14ce26e7 bellard
            ot = dflag ? OT_LONG : OT_WORD;
4247 14ce26e7 bellard
            val = insn_get(s, ot);
4248 14ce26e7 bellard
            reg = (b & 7) | REX_B(s);
4249 14ce26e7 bellard
            gen_op_movl_T0_im(val);
4250 57fec1fe bellard
            gen_op_mov_reg_T0(ot, reg);
4251 14ce26e7 bellard
        }
4252 2c0262af bellard
        break;
4253 2c0262af bellard
4254 2c0262af bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
4255 14ce26e7 bellard
        ot = dflag + OT_WORD;
4256 14ce26e7 bellard
        reg = (b & 7) | REX_B(s);
4257 2c0262af bellard
        rm = R_EAX;
4258 2c0262af bellard
        goto do_xchg_reg;
4259 2c0262af bellard
    case 0x86:
4260 2c0262af bellard
    case 0x87: /* xchg Ev, Gv */
4261 2c0262af bellard
        if ((b & 1) == 0)
4262 2c0262af bellard
            ot = OT_BYTE;
4263 2c0262af bellard
        else
4264 14ce26e7 bellard
            ot = dflag + OT_WORD;
4265 61382a50 bellard
        modrm = ldub_code(s->pc++);
4266 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4267 2c0262af bellard
        mod = (modrm >> 6) & 3;
4268 2c0262af bellard
        if (mod == 3) {
4269 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
4270 2c0262af bellard
        do_xchg_reg:
4271 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4272 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, rm);
4273 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
4274 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4275 2c0262af bellard
        } else {
4276 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4277 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, reg);
4278 2c0262af bellard
            /* for xchg, lock is implicit */
4279 2c0262af bellard
            if (!(prefixes & PREFIX_LOCK))
4280 2c0262af bellard
                gen_op_lock();
4281 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
4282 57fec1fe bellard
            gen_op_st_T0_A0(ot + s->mem_index);
4283 2c0262af bellard
            if (!(prefixes & PREFIX_LOCK))
4284 2c0262af bellard
                gen_op_unlock();
4285 57fec1fe bellard
            gen_op_mov_reg_T1(ot, reg);
4286 2c0262af bellard
        }
4287 2c0262af bellard
        break;
4288 2c0262af bellard
    case 0xc4: /* les Gv */
4289 14ce26e7 bellard
        if (CODE64(s))
4290 14ce26e7 bellard
            goto illegal_op;
4291 2c0262af bellard
        op = R_ES;
4292 2c0262af bellard
        goto do_lxx;
4293 2c0262af bellard
    case 0xc5: /* lds Gv */
4294 14ce26e7 bellard
        if (CODE64(s))
4295 14ce26e7 bellard
            goto illegal_op;
4296 2c0262af bellard
        op = R_DS;
4297 2c0262af bellard
        goto do_lxx;
4298 2c0262af bellard
    case 0x1b2: /* lss Gv */
4299 2c0262af bellard
        op = R_SS;
4300 2c0262af bellard
        goto do_lxx;
4301 2c0262af bellard
    case 0x1b4: /* lfs Gv */
4302 2c0262af bellard
        op = R_FS;
4303 2c0262af bellard
        goto do_lxx;
4304 2c0262af bellard
    case 0x1b5: /* lgs Gv */
4305 2c0262af bellard
        op = R_GS;
4306 2c0262af bellard
    do_lxx:
4307 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
4308 61382a50 bellard
        modrm = ldub_code(s->pc++);
4309 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4310 2c0262af bellard
        mod = (modrm >> 6) & 3;
4311 2c0262af bellard
        if (mod == 3)
4312 2c0262af bellard
            goto illegal_op;
4313 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4314 57fec1fe bellard
        gen_op_ld_T1_A0(ot + s->mem_index);
4315 aba9d61e bellard
        gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4316 2c0262af bellard
        /* load the segment first to handle exceptions properly */
4317 57fec1fe bellard
        gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4318 2c0262af bellard
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4319 2c0262af bellard
        /* then put the data */
4320 57fec1fe bellard
        gen_op_mov_reg_T1(ot, reg);
4321 2c0262af bellard
        if (s->is_jmp) {
4322 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
4323 2c0262af bellard
            gen_eob(s);
4324 2c0262af bellard
        }
4325 2c0262af bellard
        break;
4326 3b46e624 ths
4327 2c0262af bellard
        /************************/
4328 2c0262af bellard
        /* shifts */
4329 2c0262af bellard
    case 0xc0:
4330 2c0262af bellard
    case 0xc1:
4331 2c0262af bellard
        /* shift Ev,Ib */
4332 2c0262af bellard
        shift = 2;
4333 2c0262af bellard
    grp2:
4334 2c0262af bellard
        {
4335 2c0262af bellard
            if ((b & 1) == 0)
4336 2c0262af bellard
                ot = OT_BYTE;
4337 2c0262af bellard
            else
4338 14ce26e7 bellard
                ot = dflag + OT_WORD;
4339 3b46e624 ths
4340 61382a50 bellard
            modrm = ldub_code(s->pc++);
4341 2c0262af bellard
            mod = (modrm >> 6) & 3;
4342 2c0262af bellard
            op = (modrm >> 3) & 7;
4343 3b46e624 ths
4344 2c0262af bellard
            if (mod != 3) {
4345 14ce26e7 bellard
                if (shift == 2) {
4346 14ce26e7 bellard
                    s->rip_offset = 1;
4347 14ce26e7 bellard
                }
4348 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4349 2c0262af bellard
                opreg = OR_TMP0;
4350 2c0262af bellard
            } else {
4351 14ce26e7 bellard
                opreg = (modrm & 7) | REX_B(s);
4352 2c0262af bellard
            }
4353 2c0262af bellard
4354 2c0262af bellard
            /* simpler op */
4355 2c0262af bellard
            if (shift == 0) {
4356 2c0262af bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
4357 2c0262af bellard
            } else {
4358 2c0262af bellard
                if (shift == 2) {
4359 61382a50 bellard
                    shift = ldub_code(s->pc++);
4360 2c0262af bellard
                }
4361 2c0262af bellard
                gen_shifti(s, op, ot, opreg, shift);
4362 2c0262af bellard
            }
4363 2c0262af bellard
        }
4364 2c0262af bellard
        break;
4365 2c0262af bellard
    case 0xd0:
4366 2c0262af bellard
    case 0xd1:
4367 2c0262af bellard
        /* shift Ev,1 */
4368 2c0262af bellard
        shift = 1;
4369 2c0262af bellard
        goto grp2;
4370 2c0262af bellard
    case 0xd2:
4371 2c0262af bellard
    case 0xd3:
4372 2c0262af bellard
        /* shift Ev,cl */
4373 2c0262af bellard
        shift = 0;
4374 2c0262af bellard
        goto grp2;
4375 2c0262af bellard
4376 2c0262af bellard
    case 0x1a4: /* shld imm */
4377 2c0262af bellard
        op = 0;
4378 2c0262af bellard
        shift = 1;
4379 2c0262af bellard
        goto do_shiftd;
4380 2c0262af bellard
    case 0x1a5: /* shld cl */
4381 2c0262af bellard
        op = 0;
4382 2c0262af bellard
        shift = 0;
4383 2c0262af bellard
        goto do_shiftd;
4384 2c0262af bellard
    case 0x1ac: /* shrd imm */
4385 2c0262af bellard
        op = 1;
4386 2c0262af bellard
        shift = 1;
4387 2c0262af bellard
        goto do_shiftd;
4388 2c0262af bellard
    case 0x1ad: /* shrd cl */
4389 2c0262af bellard
        op = 1;
4390 2c0262af bellard
        shift = 0;
4391 2c0262af bellard
    do_shiftd:
4392 14ce26e7 bellard
        ot = dflag + OT_WORD;
4393 61382a50 bellard
        modrm = ldub_code(s->pc++);
4394 2c0262af bellard
        mod = (modrm >> 6) & 3;
4395 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
4396 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
4397 3b46e624 ths
4398 2c0262af bellard
        if (mod != 3) {
4399 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4400 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
4401 2c0262af bellard
        } else {
4402 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
4403 2c0262af bellard
        }
4404 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
4405 3b46e624 ths
4406 2c0262af bellard
        if (shift) {
4407 61382a50 bellard
            val = ldub_code(s->pc++);
4408 14ce26e7 bellard
            if (ot == OT_QUAD)
4409 14ce26e7 bellard
                val &= 0x3f;
4410 14ce26e7 bellard
            else
4411 14ce26e7 bellard
                val &= 0x1f;
4412 2c0262af bellard
            if (val) {
4413 2c0262af bellard
                if (mod == 3)
4414 4f31916f bellard
                    gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4415 2c0262af bellard
                else
4416 4f31916f bellard
                    gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4417 2c0262af bellard
                if (op == 0 && ot != OT_WORD)
4418 2c0262af bellard
                    s->cc_op = CC_OP_SHLB + ot;
4419 2c0262af bellard
                else
4420 2c0262af bellard
                    s->cc_op = CC_OP_SARB + ot;
4421 2c0262af bellard
            }
4422 2c0262af bellard
        } else {
4423 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
4424 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
4425 2c0262af bellard
            if (mod == 3)
4426 4f31916f bellard
                gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4427 2c0262af bellard
            else
4428 4f31916f bellard
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4429 2c0262af bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4430 2c0262af bellard
        }
4431 2c0262af bellard
        if (mod == 3) {
4432 57fec1fe bellard
            gen_op_mov_reg_T0(ot, rm);
4433 2c0262af bellard
        }
4434 2c0262af bellard
        break;
4435 2c0262af bellard
4436 2c0262af bellard
        /************************/
4437 2c0262af bellard
        /* floats */
4438 5fafdf24 ths
    case 0xd8 ... 0xdf:
4439 7eee2a50 bellard
        if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4440 7eee2a50 bellard
            /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4441 7eee2a50 bellard
            /* XXX: what to do if illegal op ? */
4442 7eee2a50 bellard
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4443 7eee2a50 bellard
            break;
4444 7eee2a50 bellard
        }
4445 61382a50 bellard
        modrm = ldub_code(s->pc++);
4446 2c0262af bellard
        mod = (modrm >> 6) & 3;
4447 2c0262af bellard
        rm = modrm & 7;
4448 2c0262af bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4449 2c0262af bellard
        if (mod != 3) {
4450 2c0262af bellard
            /* memory op */
4451 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4452 2c0262af bellard
            switch(op) {
4453 2c0262af bellard
            case 0x00 ... 0x07: /* fxxxs */
4454 2c0262af bellard
            case 0x10 ... 0x17: /* fixxxl */
4455 2c0262af bellard
            case 0x20 ... 0x27: /* fxxxl */
4456 2c0262af bellard
            case 0x30 ... 0x37: /* fixxx */
4457 2c0262af bellard
                {
4458 2c0262af bellard
                    int op1;
4459 2c0262af bellard
                    op1 = op & 7;
4460 2c0262af bellard
4461 2c0262af bellard
                    switch(op >> 4) {
4462 2c0262af bellard
                    case 0:
4463 2c0262af bellard
                        gen_op_flds_FT0_A0();
4464 2c0262af bellard
                        break;
4465 2c0262af bellard
                    case 1:
4466 2c0262af bellard
                        gen_op_fildl_FT0_A0();
4467 2c0262af bellard
                        break;
4468 2c0262af bellard
                    case 2:
4469 2c0262af bellard
                        gen_op_fldl_FT0_A0();
4470 2c0262af bellard
                        break;
4471 2c0262af bellard
                    case 3:
4472 2c0262af bellard
                    default:
4473 2c0262af bellard
                        gen_op_fild_FT0_A0();
4474 2c0262af bellard
                        break;
4475 2c0262af bellard
                    }
4476 3b46e624 ths
4477 2c0262af bellard
                    gen_op_fp_arith_ST0_FT0[op1]();
4478 2c0262af bellard
                    if (op1 == 3) {
4479 2c0262af bellard
                        /* fcomp needs pop */
4480 2c0262af bellard
                        gen_op_fpop();
4481 2c0262af bellard
                    }
4482 2c0262af bellard
                }
4483 2c0262af bellard
                break;
4484 2c0262af bellard
            case 0x08: /* flds */
4485 2c0262af bellard
            case 0x0a: /* fsts */
4486 2c0262af bellard
            case 0x0b: /* fstps */
4487 465e9838 bellard
            case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4488 465e9838 bellard
            case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4489 465e9838 bellard
            case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
4490 2c0262af bellard
                switch(op & 7) {
4491 2c0262af bellard
                case 0:
4492 2c0262af bellard
                    switch(op >> 4) {
4493 2c0262af bellard
                    case 0:
4494 2c0262af bellard
                        gen_op_flds_ST0_A0();
4495 2c0262af bellard
                        break;
4496 2c0262af bellard
                    case 1:
4497 2c0262af bellard
                        gen_op_fildl_ST0_A0();
4498 2c0262af bellard
                        break;
4499 2c0262af bellard
                    case 2:
4500 2c0262af bellard
                        gen_op_fldl_ST0_A0();
4501 2c0262af bellard
                        break;
4502 2c0262af bellard
                    case 3:
4503 2c0262af bellard
                    default:
4504 2c0262af bellard
                        gen_op_fild_ST0_A0();
4505 2c0262af bellard
                        break;
4506 2c0262af bellard
                    }
4507 2c0262af bellard
                    break;
4508 465e9838 bellard
                case 1:
4509 465e9838 bellard
                    switch(op >> 4) {
4510 465e9838 bellard
                    case 1:
4511 465e9838 bellard
                        gen_op_fisttl_ST0_A0();
4512 465e9838 bellard
                        break;
4513 465e9838 bellard
                    case 2:
4514 465e9838 bellard
                        gen_op_fisttll_ST0_A0();
4515 465e9838 bellard
                        break;
4516 465e9838 bellard
                    case 3:
4517 465e9838 bellard
                    default:
4518 465e9838 bellard
                        gen_op_fistt_ST0_A0();
4519 465e9838 bellard
                    }
4520 465e9838 bellard
                    gen_op_fpop();
4521 465e9838 bellard
                    break;
4522 2c0262af bellard
                default:
4523 2c0262af bellard
                    switch(op >> 4) {
4524 2c0262af bellard
                    case 0:
4525 2c0262af bellard
                        gen_op_fsts_ST0_A0();
4526 2c0262af bellard
                        break;
4527 2c0262af bellard
                    case 1:
4528 2c0262af bellard
                        gen_op_fistl_ST0_A0();
4529 2c0262af bellard
                        break;
4530 2c0262af bellard
                    case 2:
4531 2c0262af bellard
                        gen_op_fstl_ST0_A0();
4532 2c0262af bellard
                        break;
4533 2c0262af bellard
                    case 3:
4534 2c0262af bellard
                    default:
4535 2c0262af bellard
                        gen_op_fist_ST0_A0();
4536 2c0262af bellard
                        break;
4537 2c0262af bellard
                    }
4538 2c0262af bellard
                    if ((op & 7) == 3)
4539 2c0262af bellard
                        gen_op_fpop();
4540 2c0262af bellard
                    break;
4541 2c0262af bellard
                }
4542 2c0262af bellard
                break;
4543 2c0262af bellard
            case 0x0c: /* fldenv mem */
4544 2c0262af bellard
                gen_op_fldenv_A0(s->dflag);
4545 2c0262af bellard
                break;
4546 2c0262af bellard
            case 0x0d: /* fldcw mem */
4547 2c0262af bellard
                gen_op_fldcw_A0();
4548 2c0262af bellard
                break;
4549 2c0262af bellard
            case 0x0e: /* fnstenv mem */
4550 2c0262af bellard
                gen_op_fnstenv_A0(s->dflag);
4551 2c0262af bellard
                break;
4552 2c0262af bellard
            case 0x0f: /* fnstcw mem */
4553 2c0262af bellard
                gen_op_fnstcw_A0();
4554 2c0262af bellard
                break;
4555 2c0262af bellard
            case 0x1d: /* fldt mem */
4556 2c0262af bellard
                gen_op_fldt_ST0_A0();
4557 2c0262af bellard
                break;
4558 2c0262af bellard
            case 0x1f: /* fstpt mem */
4559 2c0262af bellard
                gen_op_fstt_ST0_A0();
4560 2c0262af bellard
                gen_op_fpop();
4561 2c0262af bellard
                break;
4562 2c0262af bellard
            case 0x2c: /* frstor mem */
4563 2c0262af bellard
                gen_op_frstor_A0(s->dflag);
4564 2c0262af bellard
                break;
4565 2c0262af bellard
            case 0x2e: /* fnsave mem */
4566 2c0262af bellard
                gen_op_fnsave_A0(s->dflag);
4567 2c0262af bellard
                break;
4568 2c0262af bellard
            case 0x2f: /* fnstsw mem */
4569 2c0262af bellard
                gen_op_fnstsw_A0();
4570 2c0262af bellard
                break;
4571 2c0262af bellard
            case 0x3c: /* fbld */
4572 2c0262af bellard
                gen_op_fbld_ST0_A0();
4573 2c0262af bellard
                break;
4574 2c0262af bellard
            case 0x3e: /* fbstp */
4575 2c0262af bellard
                gen_op_fbst_ST0_A0();
4576 2c0262af bellard
                gen_op_fpop();
4577 2c0262af bellard
                break;
4578 2c0262af bellard
            case 0x3d: /* fildll */
4579 2c0262af bellard
                gen_op_fildll_ST0_A0();
4580 2c0262af bellard
                break;
4581 2c0262af bellard
            case 0x3f: /* fistpll */
4582 2c0262af bellard
                gen_op_fistll_ST0_A0();
4583 2c0262af bellard
                gen_op_fpop();
4584 2c0262af bellard
                break;
4585 2c0262af bellard
            default:
4586 2c0262af bellard
                goto illegal_op;
4587 2c0262af bellard
            }
4588 2c0262af bellard
        } else {
4589 2c0262af bellard
            /* register float ops */
4590 2c0262af bellard
            opreg = rm;
4591 2c0262af bellard
4592 2c0262af bellard
            switch(op) {
4593 2c0262af bellard
            case 0x08: /* fld sti */
4594 2c0262af bellard
                gen_op_fpush();
4595 2c0262af bellard
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
4596 2c0262af bellard
                break;
4597 2c0262af bellard
            case 0x09: /* fxchg sti */
4598 c169c906 bellard
            case 0x29: /* fxchg4 sti, undocumented op */
4599 c169c906 bellard
            case 0x39: /* fxchg7 sti, undocumented op */
4600 2c0262af bellard
                gen_op_fxchg_ST0_STN(opreg);
4601 2c0262af bellard
                break;
4602 2c0262af bellard
            case 0x0a: /* grp d9/2 */
4603 2c0262af bellard
                switch(rm) {
4604 2c0262af bellard
                case 0: /* fnop */
4605 023fe10d bellard
                    /* check exceptions (FreeBSD FPU probe) */
4606 023fe10d bellard
                    if (s->cc_op != CC_OP_DYNAMIC)
4607 023fe10d bellard
                        gen_op_set_cc_op(s->cc_op);
4608 14ce26e7 bellard
                    gen_jmp_im(pc_start - s->cs_base);
4609 023fe10d bellard
                    gen_op_fwait();
4610 2c0262af bellard
                    break;
4611 2c0262af bellard
                default:
4612 2c0262af bellard
                    goto illegal_op;
4613 2c0262af bellard
                }
4614 2c0262af bellard
                break;
4615 2c0262af bellard
            case 0x0c: /* grp d9/4 */
4616 2c0262af bellard
                switch(rm) {
4617 2c0262af bellard
                case 0: /* fchs */
4618 2c0262af bellard
                    gen_op_fchs_ST0();
4619 2c0262af bellard
                    break;
4620 2c0262af bellard
                case 1: /* fabs */
4621 2c0262af bellard
                    gen_op_fabs_ST0();
4622 2c0262af bellard
                    break;
4623 2c0262af bellard
                case 4: /* ftst */
4624 2c0262af bellard
                    gen_op_fldz_FT0();
4625 2c0262af bellard
                    gen_op_fcom_ST0_FT0();
4626 2c0262af bellard
                    break;
4627 2c0262af bellard
                case 5: /* fxam */
4628 2c0262af bellard
                    gen_op_fxam_ST0();
4629 2c0262af bellard
                    break;
4630 2c0262af bellard
                default:
4631 2c0262af bellard
                    goto illegal_op;
4632 2c0262af bellard
                }
4633 2c0262af bellard
                break;
4634 2c0262af bellard
            case 0x0d: /* grp d9/5 */
4635 2c0262af bellard
                {
4636 2c0262af bellard
                    switch(rm) {
4637 2c0262af bellard
                    case 0:
4638 2c0262af bellard
                        gen_op_fpush();
4639 2c0262af bellard
                        gen_op_fld1_ST0();
4640 2c0262af bellard
                        break;
4641 2c0262af bellard
                    case 1:
4642 2c0262af bellard
                        gen_op_fpush();
4643 2c0262af bellard
                        gen_op_fldl2t_ST0();
4644 2c0262af bellard
                        break;
4645 2c0262af bellard
                    case 2:
4646 2c0262af bellard
                        gen_op_fpush();
4647 2c0262af bellard
                        gen_op_fldl2e_ST0();
4648 2c0262af bellard
                        break;
4649 2c0262af bellard
                    case 3:
4650 2c0262af bellard
                        gen_op_fpush();
4651 2c0262af bellard
                        gen_op_fldpi_ST0();
4652 2c0262af bellard
                        break;
4653 2c0262af bellard
                    case 4:
4654 2c0262af bellard
                        gen_op_fpush();
4655 2c0262af bellard
                        gen_op_fldlg2_ST0();
4656 2c0262af bellard
                        break;
4657 2c0262af bellard
                    case 5:
4658 2c0262af bellard
                        gen_op_fpush();
4659 2c0262af bellard
                        gen_op_fldln2_ST0();
4660 2c0262af bellard
                        break;
4661 2c0262af bellard
                    case 6:
4662 2c0262af bellard
                        gen_op_fpush();
4663 2c0262af bellard
                        gen_op_fldz_ST0();
4664 2c0262af bellard
                        break;
4665 2c0262af bellard
                    default:
4666 2c0262af bellard
                        goto illegal_op;
4667 2c0262af bellard
                    }
4668 2c0262af bellard
                }
4669 2c0262af bellard
                break;
4670 2c0262af bellard
            case 0x0e: /* grp d9/6 */
4671 2c0262af bellard
                switch(rm) {
4672 2c0262af bellard
                case 0: /* f2xm1 */
4673 2c0262af bellard
                    gen_op_f2xm1();
4674 2c0262af bellard
                    break;
4675 2c0262af bellard
                case 1: /* fyl2x */
4676 2c0262af bellard
                    gen_op_fyl2x();
4677 2c0262af bellard
                    break;
4678 2c0262af bellard
                case 2: /* fptan */
4679 2c0262af bellard
                    gen_op_fptan();
4680 2c0262af bellard
                    break;
4681 2c0262af bellard
                case 3: /* fpatan */
4682 2c0262af bellard
                    gen_op_fpatan();
4683 2c0262af bellard
                    break;
4684 2c0262af bellard
                case 4: /* fxtract */
4685 2c0262af bellard
                    gen_op_fxtract();
4686 2c0262af bellard
                    break;
4687 2c0262af bellard
                case 5: /* fprem1 */
4688 2c0262af bellard
                    gen_op_fprem1();
4689 2c0262af bellard
                    break;
4690 2c0262af bellard
                case 6: /* fdecstp */
4691 2c0262af bellard
                    gen_op_fdecstp();
4692 2c0262af bellard
                    break;
4693 2c0262af bellard
                default:
4694 2c0262af bellard
                case 7: /* fincstp */
4695 2c0262af bellard
                    gen_op_fincstp();
4696 2c0262af bellard
                    break;
4697 2c0262af bellard
                }
4698 2c0262af bellard
                break;
4699 2c0262af bellard
            case 0x0f: /* grp d9/7 */
4700 2c0262af bellard
                switch(rm) {
4701 2c0262af bellard
                case 0: /* fprem */
4702 2c0262af bellard
                    gen_op_fprem();
4703 2c0262af bellard
                    break;
4704 2c0262af bellard
                case 1: /* fyl2xp1 */
4705 2c0262af bellard
                    gen_op_fyl2xp1();
4706 2c0262af bellard
                    break;
4707 2c0262af bellard
                case 2: /* fsqrt */
4708 2c0262af bellard
                    gen_op_fsqrt();
4709 2c0262af bellard
                    break;
4710 2c0262af bellard
                case 3: /* fsincos */
4711 2c0262af bellard
                    gen_op_fsincos();
4712 2c0262af bellard
                    break;
4713 2c0262af bellard
                case 5: /* fscale */
4714 2c0262af bellard
                    gen_op_fscale();
4715 2c0262af bellard
                    break;
4716 2c0262af bellard
                case 4: /* frndint */
4717 2c0262af bellard
                    gen_op_frndint();
4718 2c0262af bellard
                    break;
4719 2c0262af bellard
                case 6: /* fsin */
4720 2c0262af bellard
                    gen_op_fsin();
4721 2c0262af bellard
                    break;
4722 2c0262af bellard
                default:
4723 2c0262af bellard
                case 7: /* fcos */
4724 2c0262af bellard
                    gen_op_fcos();
4725 2c0262af bellard
                    break;
4726 2c0262af bellard
                }
4727 2c0262af bellard
                break;
4728 2c0262af bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4729 2c0262af bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4730 2c0262af bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4731 2c0262af bellard
                {
4732 2c0262af bellard
                    int op1;
4733 3b46e624 ths
4734 2c0262af bellard
                    op1 = op & 7;
4735 2c0262af bellard
                    if (op >= 0x20) {
4736 2c0262af bellard
                        gen_op_fp_arith_STN_ST0[op1](opreg);
4737 2c0262af bellard
                        if (op >= 0x30)
4738 2c0262af bellard
                            gen_op_fpop();
4739 2c0262af bellard
                    } else {
4740 2c0262af bellard
                        gen_op_fmov_FT0_STN(opreg);
4741 2c0262af bellard
                        gen_op_fp_arith_ST0_FT0[op1]();
4742 2c0262af bellard
                    }
4743 2c0262af bellard
                }
4744 2c0262af bellard
                break;
4745 2c0262af bellard
            case 0x02: /* fcom */
4746 c169c906 bellard
            case 0x22: /* fcom2, undocumented op */
4747 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4748 2c0262af bellard
                gen_op_fcom_ST0_FT0();
4749 2c0262af bellard
                break;
4750 2c0262af bellard
            case 0x03: /* fcomp */
4751 c169c906 bellard
            case 0x23: /* fcomp3, undocumented op */
4752 c169c906 bellard
            case 0x32: /* fcomp5, undocumented op */
4753 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4754 2c0262af bellard
                gen_op_fcom_ST0_FT0();
4755 2c0262af bellard
                gen_op_fpop();
4756 2c0262af bellard
                break;
4757 2c0262af bellard
            case 0x15: /* da/5 */
4758 2c0262af bellard
                switch(rm) {
4759 2c0262af bellard
                case 1: /* fucompp */
4760 2c0262af bellard
                    gen_op_fmov_FT0_STN(1);
4761 2c0262af bellard
                    gen_op_fucom_ST0_FT0();
4762 2c0262af bellard
                    gen_op_fpop();
4763 2c0262af bellard
                    gen_op_fpop();
4764 2c0262af bellard
                    break;
4765 2c0262af bellard
                default:
4766 2c0262af bellard
                    goto illegal_op;
4767 2c0262af bellard
                }
4768 2c0262af bellard
                break;
4769 2c0262af bellard
            case 0x1c:
4770 2c0262af bellard
                switch(rm) {
4771 2c0262af bellard
                case 0: /* feni (287 only, just do nop here) */
4772 2c0262af bellard
                    break;
4773 2c0262af bellard
                case 1: /* fdisi (287 only, just do nop here) */
4774 2c0262af bellard
                    break;
4775 2c0262af bellard
                case 2: /* fclex */
4776 2c0262af bellard
                    gen_op_fclex();
4777 2c0262af bellard
                    break;
4778 2c0262af bellard
                case 3: /* fninit */
4779 2c0262af bellard
                    gen_op_fninit();
4780 2c0262af bellard
                    break;
4781 2c0262af bellard
                case 4: /* fsetpm (287 only, just do nop here) */
4782 2c0262af bellard
                    break;
4783 2c0262af bellard
                default:
4784 2c0262af bellard
                    goto illegal_op;
4785 2c0262af bellard
                }
4786 2c0262af bellard
                break;
4787 2c0262af bellard
            case 0x1d: /* fucomi */
4788 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4789 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4790 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4791 2c0262af bellard
                gen_op_fucomi_ST0_FT0();
4792 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
4793 2c0262af bellard
                break;
4794 2c0262af bellard
            case 0x1e: /* fcomi */
4795 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4796 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4797 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4798 2c0262af bellard
                gen_op_fcomi_ST0_FT0();
4799 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
4800 2c0262af bellard
                break;
4801 658c8bda bellard
            case 0x28: /* ffree sti */
4802 658c8bda bellard
                gen_op_ffree_STN(opreg);
4803 5fafdf24 ths
                break;
4804 2c0262af bellard
            case 0x2a: /* fst sti */
4805 2c0262af bellard
                gen_op_fmov_STN_ST0(opreg);
4806 2c0262af bellard
                break;
4807 2c0262af bellard
            case 0x2b: /* fstp sti */
4808 c169c906 bellard
            case 0x0b: /* fstp1 sti, undocumented op */
4809 c169c906 bellard
            case 0x3a: /* fstp8 sti, undocumented op */
4810 c169c906 bellard
            case 0x3b: /* fstp9 sti, undocumented op */
4811 2c0262af bellard
                gen_op_fmov_STN_ST0(opreg);
4812 2c0262af bellard
                gen_op_fpop();
4813 2c0262af bellard
                break;
4814 2c0262af bellard
            case 0x2c: /* fucom st(i) */
4815 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4816 2c0262af bellard
                gen_op_fucom_ST0_FT0();
4817 2c0262af bellard
                break;
4818 2c0262af bellard
            case 0x2d: /* fucomp st(i) */
4819 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4820 2c0262af bellard
                gen_op_fucom_ST0_FT0();
4821 2c0262af bellard
                gen_op_fpop();
4822 2c0262af bellard
                break;
4823 2c0262af bellard
            case 0x33: /* de/3 */
4824 2c0262af bellard
                switch(rm) {
4825 2c0262af bellard
                case 1: /* fcompp */
4826 2c0262af bellard
                    gen_op_fmov_FT0_STN(1);
4827 2c0262af bellard
                    gen_op_fcom_ST0_FT0();
4828 2c0262af bellard
                    gen_op_fpop();
4829 2c0262af bellard
                    gen_op_fpop();
4830 2c0262af bellard
                    break;
4831 2c0262af bellard
                default:
4832 2c0262af bellard
                    goto illegal_op;
4833 2c0262af bellard
                }
4834 2c0262af bellard
                break;
4835 c169c906 bellard
            case 0x38: /* ffreep sti, undocumented op */
4836 c169c906 bellard
                gen_op_ffree_STN(opreg);
4837 c169c906 bellard
                gen_op_fpop();
4838 c169c906 bellard
                break;
4839 2c0262af bellard
            case 0x3c: /* df/4 */
4840 2c0262af bellard
                switch(rm) {
4841 2c0262af bellard
                case 0:
4842 2c0262af bellard
                    gen_op_fnstsw_EAX();
4843 2c0262af bellard
                    break;
4844 2c0262af bellard
                default:
4845 2c0262af bellard
                    goto illegal_op;
4846 2c0262af bellard
                }
4847 2c0262af bellard
                break;
4848 2c0262af bellard
            case 0x3d: /* fucomip */
4849 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4850 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4851 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4852 2c0262af bellard
                gen_op_fucomi_ST0_FT0();
4853 2c0262af bellard
                gen_op_fpop();
4854 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
4855 2c0262af bellard
                break;
4856 2c0262af bellard
            case 0x3e: /* fcomip */
4857 2c0262af bellard
                if (s->cc_op != CC_OP_DYNAMIC)
4858 2c0262af bellard
                    gen_op_set_cc_op(s->cc_op);
4859 2c0262af bellard
                gen_op_fmov_FT0_STN(opreg);
4860 2c0262af bellard
                gen_op_fcomi_ST0_FT0();
4861 2c0262af bellard
                gen_op_fpop();
4862 2c0262af bellard
                s->cc_op = CC_OP_EFLAGS;
4863 2c0262af bellard
                break;
4864 a2cc3b24 bellard
            case 0x10 ... 0x13: /* fcmovxx */
4865 a2cc3b24 bellard
            case 0x18 ... 0x1b:
4866 a2cc3b24 bellard
                {
4867 a2cc3b24 bellard
                    int op1;
4868 a2cc3b24 bellard
                    const static uint8_t fcmov_cc[8] = {
4869 a2cc3b24 bellard
                        (JCC_B << 1),
4870 a2cc3b24 bellard
                        (JCC_Z << 1),
4871 a2cc3b24 bellard
                        (JCC_BE << 1),
4872 a2cc3b24 bellard
                        (JCC_P << 1),
4873 a2cc3b24 bellard
                    };
4874 a2cc3b24 bellard
                    op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4875 a2cc3b24 bellard
                    gen_setcc(s, op1);
4876 a2cc3b24 bellard
                    gen_op_fcmov_ST0_STN_T0(opreg);
4877 a2cc3b24 bellard
                }
4878 a2cc3b24 bellard
                break;
4879 2c0262af bellard
            default:
4880 2c0262af bellard
                goto illegal_op;
4881 2c0262af bellard
            }
4882 2c0262af bellard
        }
4883 2c0262af bellard
        break;
4884 2c0262af bellard
        /************************/
4885 2c0262af bellard
        /* string ops */
4886 2c0262af bellard
4887 2c0262af bellard
    case 0xa4: /* movsS */
4888 2c0262af bellard
    case 0xa5:
4889 2c0262af bellard
        if ((b & 1) == 0)
4890 2c0262af bellard
            ot = OT_BYTE;
4891 2c0262af bellard
        else
4892 14ce26e7 bellard
            ot = dflag + OT_WORD;
4893 2c0262af bellard
4894 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4895 2c0262af bellard
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4896 2c0262af bellard
        } else {
4897 2c0262af bellard
            gen_movs(s, ot);
4898 2c0262af bellard
        }
4899 2c0262af bellard
        break;
4900 3b46e624 ths
4901 2c0262af bellard
    case 0xaa: /* stosS */
4902 2c0262af bellard
    case 0xab:
4903 2c0262af bellard
        if ((b & 1) == 0)
4904 2c0262af bellard
            ot = OT_BYTE;
4905 2c0262af bellard
        else
4906 14ce26e7 bellard
            ot = dflag + OT_WORD;
4907 2c0262af bellard
4908 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4909 2c0262af bellard
            gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4910 2c0262af bellard
        } else {
4911 2c0262af bellard
            gen_stos(s, ot);
4912 2c0262af bellard
        }
4913 2c0262af bellard
        break;
4914 2c0262af bellard
    case 0xac: /* lodsS */
4915 2c0262af bellard
    case 0xad:
4916 2c0262af bellard
        if ((b & 1) == 0)
4917 2c0262af bellard
            ot = OT_BYTE;
4918 2c0262af bellard
        else
4919 14ce26e7 bellard
            ot = dflag + OT_WORD;
4920 2c0262af bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4921 2c0262af bellard
            gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4922 2c0262af bellard
        } else {
4923 2c0262af bellard
            gen_lods(s, ot);
4924 2c0262af bellard
        }
4925 2c0262af bellard
        break;
4926 2c0262af bellard
    case 0xae: /* scasS */
4927 2c0262af bellard
    case 0xaf:
4928 2c0262af bellard
        if ((b & 1) == 0)
4929 2c0262af bellard
            ot = OT_BYTE;
4930 2c0262af bellard
        else
4931 14ce26e7 bellard
            ot = dflag + OT_WORD;
4932 2c0262af bellard
        if (prefixes & PREFIX_REPNZ) {
4933 2c0262af bellard
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4934 2c0262af bellard
        } else if (prefixes & PREFIX_REPZ) {
4935 2c0262af bellard
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4936 2c0262af bellard
        } else {
4937 2c0262af bellard
            gen_scas(s, ot);
4938 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
4939 2c0262af bellard
        }
4940 2c0262af bellard
        break;
4941 2c0262af bellard
4942 2c0262af bellard
    case 0xa6: /* cmpsS */
4943 2c0262af bellard
    case 0xa7:
4944 2c0262af bellard
        if ((b & 1) == 0)
4945 2c0262af bellard
            ot = OT_BYTE;
4946 2c0262af bellard
        else
4947 14ce26e7 bellard
            ot = dflag + OT_WORD;
4948 2c0262af bellard
        if (prefixes & PREFIX_REPNZ) {
4949 2c0262af bellard
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4950 2c0262af bellard
        } else if (prefixes & PREFIX_REPZ) {
4951 2c0262af bellard
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4952 2c0262af bellard
        } else {
4953 2c0262af bellard
            gen_cmps(s, ot);
4954 2c0262af bellard
            s->cc_op = CC_OP_SUBB + ot;
4955 2c0262af bellard
        }
4956 2c0262af bellard
        break;
4957 2c0262af bellard
    case 0x6c: /* insS */
4958 2c0262af bellard
    case 0x6d:
4959 f115e911 bellard
        if ((b & 1) == 0)
4960 f115e911 bellard
            ot = OT_BYTE;
4961 f115e911 bellard
        else
4962 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
4963 f115e911 bellard
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
4964 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4965 0573fbfc ths
        gen_op_andl_T0_ffff();
4966 0573fbfc ths
        if (gen_svm_check_io(s, pc_start,
4967 0573fbfc ths
                             SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4968 0573fbfc ths
                             svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4969 0573fbfc ths
            break;
4970 f115e911 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4971 f115e911 bellard
            gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4972 2c0262af bellard
        } else {
4973 f115e911 bellard
            gen_ins(s, ot);
4974 2c0262af bellard
        }
4975 2c0262af bellard
        break;
4976 2c0262af bellard
    case 0x6e: /* outsS */
4977 2c0262af bellard
    case 0x6f:
4978 f115e911 bellard
        if ((b & 1) == 0)
4979 f115e911 bellard
            ot = OT_BYTE;
4980 f115e911 bellard
        else
4981 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
4982 f115e911 bellard
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
4983 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4984 0573fbfc ths
        gen_op_andl_T0_ffff();
4985 0573fbfc ths
        if (gen_svm_check_io(s, pc_start,
4986 0573fbfc ths
                             (1 << (4+ot)) | svm_is_rep(prefixes) |
4987 0573fbfc ths
                             4 | (1 << (7+s->aflag))))
4988 0573fbfc ths
            break;
4989 f115e911 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4990 f115e911 bellard
            gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4991 2c0262af bellard
        } else {
4992 f115e911 bellard
            gen_outs(s, ot);
4993 2c0262af bellard
        }
4994 2c0262af bellard
        break;
4995 2c0262af bellard
4996 2c0262af bellard
        /************************/
4997 2c0262af bellard
        /* port I/O */
4998 0573fbfc ths
4999 2c0262af bellard
    case 0xe4:
5000 2c0262af bellard
    case 0xe5:
5001 f115e911 bellard
        if ((b & 1) == 0)
5002 f115e911 bellard
            ot = OT_BYTE;
5003 f115e911 bellard
        else
5004 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5005 f115e911 bellard
        val = ldub_code(s->pc++);
5006 f115e911 bellard
        gen_op_movl_T0_im(val);
5007 f115e911 bellard
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
5008 0573fbfc ths
        if (gen_svm_check_io(s, pc_start,
5009 0573fbfc ths
                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5010 0573fbfc ths
                             (1 << (4+ot))))
5011 0573fbfc ths
            break;
5012 f115e911 bellard
        gen_op_in[ot]();
5013 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EAX);
5014 2c0262af bellard
        break;
5015 2c0262af bellard
    case 0xe6:
5016 2c0262af bellard
    case 0xe7:
5017 f115e911 bellard
        if ((b & 1) == 0)
5018 f115e911 bellard
            ot = OT_BYTE;
5019 f115e911 bellard
        else
5020 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5021 f115e911 bellard
        val = ldub_code(s->pc++);
5022 f115e911 bellard
        gen_op_movl_T0_im(val);
5023 f115e911 bellard
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
5024 0573fbfc ths
        if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
5025 0573fbfc ths
                             (1 << (4+ot))))
5026 0573fbfc ths
            break;
5027 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, R_EAX);
5028 f115e911 bellard
        gen_op_out[ot]();
5029 2c0262af bellard
        break;
5030 2c0262af bellard
    case 0xec:
5031 2c0262af bellard
    case 0xed:
5032 f115e911 bellard
        if ((b & 1) == 0)
5033 f115e911 bellard
            ot = OT_BYTE;
5034 f115e911 bellard
        else
5035 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5036 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5037 4f31916f bellard
        gen_op_andl_T0_ffff();
5038 f115e911 bellard
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
5039 0573fbfc ths
        if (gen_svm_check_io(s, pc_start,
5040 0573fbfc ths
                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5041 0573fbfc ths
                             (1 << (4+ot))))
5042 0573fbfc ths
            break;
5043 f115e911 bellard
        gen_op_in[ot]();
5044 57fec1fe bellard
        gen_op_mov_reg_T1(ot, R_EAX);
5045 2c0262af bellard
        break;
5046 2c0262af bellard
    case 0xee:
5047 2c0262af bellard
    case 0xef:
5048 f115e911 bellard
        if ((b & 1) == 0)
5049 f115e911 bellard
            ot = OT_BYTE;
5050 f115e911 bellard
        else
5051 f115e911 bellard
            ot = dflag ? OT_LONG : OT_WORD;
5052 57fec1fe bellard
        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
5053 4f31916f bellard
        gen_op_andl_T0_ffff();
5054 f115e911 bellard
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
5055 0573fbfc ths
        if (gen_svm_check_io(s, pc_start,
5056 0573fbfc ths
                             svm_is_rep(prefixes) | (1 << (4+ot))))
5057 0573fbfc ths
            break;
5058 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, R_EAX);
5059 f115e911 bellard
        gen_op_out[ot]();
5060 2c0262af bellard
        break;
5061 2c0262af bellard
5062 2c0262af bellard
        /************************/
5063 2c0262af bellard
        /* control */
5064 2c0262af bellard
    case 0xc2: /* ret im */
5065 61382a50 bellard
        val = ldsw_code(s->pc);
5066 2c0262af bellard
        s->pc += 2;
5067 2c0262af bellard
        gen_pop_T0(s);
5068 8f091a59 bellard
        if (CODE64(s) && s->dflag)
5069 8f091a59 bellard
            s->dflag = 2;
5070 2c0262af bellard
        gen_stack_update(s, val + (2 << s->dflag));
5071 2c0262af bellard
        if (s->dflag == 0)
5072 2c0262af bellard
            gen_op_andl_T0_ffff();
5073 2c0262af bellard
        gen_op_jmp_T0();
5074 2c0262af bellard
        gen_eob(s);
5075 2c0262af bellard
        break;
5076 2c0262af bellard
    case 0xc3: /* ret */
5077 2c0262af bellard
        gen_pop_T0(s);
5078 2c0262af bellard
        gen_pop_update(s);
5079 2c0262af bellard
        if (s->dflag == 0)
5080 2c0262af bellard
            gen_op_andl_T0_ffff();
5081 2c0262af bellard
        gen_op_jmp_T0();
5082 2c0262af bellard
        gen_eob(s);
5083 2c0262af bellard
        break;
5084 2c0262af bellard
    case 0xca: /* lret im */
5085 61382a50 bellard
        val = ldsw_code(s->pc);
5086 2c0262af bellard
        s->pc += 2;
5087 2c0262af bellard
    do_lret:
5088 2c0262af bellard
        if (s->pe && !s->vm86) {
5089 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5090 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5091 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5092 2c0262af bellard
            gen_op_lret_protected(s->dflag, val);
5093 2c0262af bellard
        } else {
5094 2c0262af bellard
            gen_stack_A0(s);
5095 2c0262af bellard
            /* pop offset */
5096 57fec1fe bellard
            gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
5097 2c0262af bellard
            if (s->dflag == 0)
5098 2c0262af bellard
                gen_op_andl_T0_ffff();
5099 2c0262af bellard
            /* NOTE: keeping EIP updated is not a problem in case of
5100 2c0262af bellard
               exception */
5101 2c0262af bellard
            gen_op_jmp_T0();
5102 2c0262af bellard
            /* pop selector */
5103 2c0262af bellard
            gen_op_addl_A0_im(2 << s->dflag);
5104 57fec1fe bellard
            gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
5105 2c0262af bellard
            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5106 2c0262af bellard
            /* add stack offset */
5107 2c0262af bellard
            gen_stack_update(s, val + (4 << s->dflag));
5108 2c0262af bellard
        }
5109 2c0262af bellard
        gen_eob(s);
5110 2c0262af bellard
        break;
5111 2c0262af bellard
    case 0xcb: /* lret */
5112 2c0262af bellard
        val = 0;
5113 2c0262af bellard
        goto do_lret;
5114 2c0262af bellard
    case 0xcf: /* iret */
5115 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
5116 0573fbfc ths
            break;
5117 2c0262af bellard
        if (!s->pe) {
5118 2c0262af bellard
            /* real mode */
5119 2c0262af bellard
            gen_op_iret_real(s->dflag);
5120 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5121 f115e911 bellard
        } else if (s->vm86) {
5122 f115e911 bellard
            if (s->iopl != 3) {
5123 f115e911 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5124 f115e911 bellard
            } else {
5125 f115e911 bellard
                gen_op_iret_real(s->dflag);
5126 f115e911 bellard
                s->cc_op = CC_OP_EFLAGS;
5127 f115e911 bellard
            }
5128 2c0262af bellard
        } else {
5129 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5130 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5131 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5132 08cea4ee bellard
            gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
5133 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5134 2c0262af bellard
        }
5135 2c0262af bellard
        gen_eob(s);
5136 2c0262af bellard
        break;
5137 2c0262af bellard
    case 0xe8: /* call im */
5138 2c0262af bellard
        {
5139 14ce26e7 bellard
            if (dflag)
5140 14ce26e7 bellard
                tval = (int32_t)insn_get(s, OT_LONG);
5141 14ce26e7 bellard
            else
5142 14ce26e7 bellard
                tval = (int16_t)insn_get(s, OT_WORD);
5143 2c0262af bellard
            next_eip = s->pc - s->cs_base;
5144 14ce26e7 bellard
            tval += next_eip;
5145 2c0262af bellard
            if (s->dflag == 0)
5146 14ce26e7 bellard
                tval &= 0xffff;
5147 14ce26e7 bellard
            gen_movtl_T0_im(next_eip);
5148 2c0262af bellard
            gen_push_T0(s);
5149 14ce26e7 bellard
            gen_jmp(s, tval);
5150 2c0262af bellard
        }
5151 2c0262af bellard
        break;
5152 2c0262af bellard
    case 0x9a: /* lcall im */
5153 2c0262af bellard
        {
5154 2c0262af bellard
            unsigned int selector, offset;
5155 3b46e624 ths
5156 14ce26e7 bellard
            if (CODE64(s))
5157 14ce26e7 bellard
                goto illegal_op;
5158 2c0262af bellard
            ot = dflag ? OT_LONG : OT_WORD;
5159 2c0262af bellard
            offset = insn_get(s, ot);
5160 2c0262af bellard
            selector = insn_get(s, OT_WORD);
5161 3b46e624 ths
5162 2c0262af bellard
            gen_op_movl_T0_im(selector);
5163 14ce26e7 bellard
            gen_op_movl_T1_imu(offset);
5164 2c0262af bellard
        }
5165 2c0262af bellard
        goto do_lcall;
5166 ecada8a2 bellard
    case 0xe9: /* jmp im */
5167 14ce26e7 bellard
        if (dflag)
5168 14ce26e7 bellard
            tval = (int32_t)insn_get(s, OT_LONG);
5169 14ce26e7 bellard
        else
5170 14ce26e7 bellard
            tval = (int16_t)insn_get(s, OT_WORD);
5171 14ce26e7 bellard
        tval += s->pc - s->cs_base;
5172 2c0262af bellard
        if (s->dflag == 0)
5173 14ce26e7 bellard
            tval &= 0xffff;
5174 14ce26e7 bellard
        gen_jmp(s, tval);
5175 2c0262af bellard
        break;
5176 2c0262af bellard
    case 0xea: /* ljmp im */
5177 2c0262af bellard
        {
5178 2c0262af bellard
            unsigned int selector, offset;
5179 2c0262af bellard
5180 14ce26e7 bellard
            if (CODE64(s))
5181 14ce26e7 bellard
                goto illegal_op;
5182 2c0262af bellard
            ot = dflag ? OT_LONG : OT_WORD;
5183 2c0262af bellard
            offset = insn_get(s, ot);
5184 2c0262af bellard
            selector = insn_get(s, OT_WORD);
5185 3b46e624 ths
5186 2c0262af bellard
            gen_op_movl_T0_im(selector);
5187 14ce26e7 bellard
            gen_op_movl_T1_imu(offset);
5188 2c0262af bellard
        }
5189 2c0262af bellard
        goto do_ljmp;
5190 2c0262af bellard
    case 0xeb: /* jmp Jb */
5191 14ce26e7 bellard
        tval = (int8_t)insn_get(s, OT_BYTE);
5192 14ce26e7 bellard
        tval += s->pc - s->cs_base;
5193 2c0262af bellard
        if (s->dflag == 0)
5194 14ce26e7 bellard
            tval &= 0xffff;
5195 14ce26e7 bellard
        gen_jmp(s, tval);
5196 2c0262af bellard
        break;
5197 2c0262af bellard
    case 0x70 ... 0x7f: /* jcc Jb */
5198 14ce26e7 bellard
        tval = (int8_t)insn_get(s, OT_BYTE);
5199 2c0262af bellard
        goto do_jcc;
5200 2c0262af bellard
    case 0x180 ... 0x18f: /* jcc Jv */
5201 2c0262af bellard
        if (dflag) {
5202 14ce26e7 bellard
            tval = (int32_t)insn_get(s, OT_LONG);
5203 2c0262af bellard
        } else {
5204 5fafdf24 ths
            tval = (int16_t)insn_get(s, OT_WORD);
5205 2c0262af bellard
        }
5206 2c0262af bellard
    do_jcc:
5207 2c0262af bellard
        next_eip = s->pc - s->cs_base;
5208 14ce26e7 bellard
        tval += next_eip;
5209 2c0262af bellard
        if (s->dflag == 0)
5210 14ce26e7 bellard
            tval &= 0xffff;
5211 14ce26e7 bellard
        gen_jcc(s, b, tval, next_eip);
5212 2c0262af bellard
        break;
5213 2c0262af bellard
5214 2c0262af bellard
    case 0x190 ... 0x19f: /* setcc Gv */
5215 61382a50 bellard
        modrm = ldub_code(s->pc++);
5216 2c0262af bellard
        gen_setcc(s, b);
5217 2c0262af bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5218 2c0262af bellard
        break;
5219 2c0262af bellard
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
5220 14ce26e7 bellard
        ot = dflag + OT_WORD;
5221 61382a50 bellard
        modrm = ldub_code(s->pc++);
5222 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
5223 2c0262af bellard
        mod = (modrm >> 6) & 3;
5224 2c0262af bellard
        gen_setcc(s, b);
5225 2c0262af bellard
        if (mod != 3) {
5226 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5227 57fec1fe bellard
            gen_op_ld_T1_A0(ot + s->mem_index);
5228 2c0262af bellard
        } else {
5229 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
5230 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 1, rm);
5231 2c0262af bellard
        }
5232 2c0262af bellard
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5233 2c0262af bellard
        break;
5234 3b46e624 ths
5235 2c0262af bellard
        /************************/
5236 2c0262af bellard
        /* flags */
5237 2c0262af bellard
    case 0x9c: /* pushf */
5238 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
5239 0573fbfc ths
            break;
5240 2c0262af bellard
        if (s->vm86 && s->iopl != 3) {
5241 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5242 2c0262af bellard
        } else {
5243 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5244 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5245 2c0262af bellard
            gen_op_movl_T0_eflags();
5246 2c0262af bellard
            gen_push_T0(s);
5247 2c0262af bellard
        }
5248 2c0262af bellard
        break;
5249 2c0262af bellard
    case 0x9d: /* popf */
5250 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
5251 0573fbfc ths
            break;
5252 2c0262af bellard
        if (s->vm86 && s->iopl != 3) {
5253 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5254 2c0262af bellard
        } else {
5255 2c0262af bellard
            gen_pop_T0(s);
5256 2c0262af bellard
            if (s->cpl == 0) {
5257 2c0262af bellard
                if (s->dflag) {
5258 2c0262af bellard
                    gen_op_movl_eflags_T0_cpl0();
5259 2c0262af bellard
                } else {
5260 2c0262af bellard
                    gen_op_movw_eflags_T0_cpl0();
5261 2c0262af bellard
                }
5262 2c0262af bellard
            } else {
5263 4136f33c bellard
                if (s->cpl <= s->iopl) {
5264 4136f33c bellard
                    if (s->dflag) {
5265 4136f33c bellard
                        gen_op_movl_eflags_T0_io();
5266 4136f33c bellard
                    } else {
5267 4136f33c bellard
                        gen_op_movw_eflags_T0_io();
5268 4136f33c bellard
                    }
5269 2c0262af bellard
                } else {
5270 4136f33c bellard
                    if (s->dflag) {
5271 4136f33c bellard
                        gen_op_movl_eflags_T0();
5272 4136f33c bellard
                    } else {
5273 4136f33c bellard
                        gen_op_movw_eflags_T0();
5274 4136f33c bellard
                    }
5275 2c0262af bellard
                }
5276 2c0262af bellard
            }
5277 2c0262af bellard
            gen_pop_update(s);
5278 2c0262af bellard
            s->cc_op = CC_OP_EFLAGS;
5279 2c0262af bellard
            /* abort translation because TF flag may change */
5280 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
5281 2c0262af bellard
            gen_eob(s);
5282 2c0262af bellard
        }
5283 2c0262af bellard
        break;
5284 2c0262af bellard
    case 0x9e: /* sahf */
5285 14ce26e7 bellard
        if (CODE64(s))
5286 14ce26e7 bellard
            goto illegal_op;
5287 57fec1fe bellard
        gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
5288 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5289 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5290 2c0262af bellard
        gen_op_movb_eflags_T0();
5291 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5292 2c0262af bellard
        break;
5293 2c0262af bellard
    case 0x9f: /* lahf */
5294 14ce26e7 bellard
        if (CODE64(s))
5295 14ce26e7 bellard
            goto illegal_op;
5296 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5297 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5298 2c0262af bellard
        gen_op_movl_T0_eflags();
5299 57fec1fe bellard
        gen_op_mov_reg_T0(OT_BYTE, R_AH);
5300 2c0262af bellard
        break;
5301 2c0262af bellard
    case 0xf5: /* cmc */
5302 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5303 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5304 2c0262af bellard
        gen_op_cmc();
5305 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5306 2c0262af bellard
        break;
5307 2c0262af bellard
    case 0xf8: /* clc */
5308 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5309 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5310 2c0262af bellard
        gen_op_clc();
5311 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5312 2c0262af bellard
        break;
5313 2c0262af bellard
    case 0xf9: /* stc */
5314 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5315 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5316 2c0262af bellard
        gen_op_stc();
5317 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5318 2c0262af bellard
        break;
5319 2c0262af bellard
    case 0xfc: /* cld */
5320 2c0262af bellard
        gen_op_cld();
5321 2c0262af bellard
        break;
5322 2c0262af bellard
    case 0xfd: /* std */
5323 2c0262af bellard
        gen_op_std();
5324 2c0262af bellard
        break;
5325 2c0262af bellard
5326 2c0262af bellard
        /************************/
5327 2c0262af bellard
        /* bit operations */
5328 2c0262af bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
5329 14ce26e7 bellard
        ot = dflag + OT_WORD;
5330 61382a50 bellard
        modrm = ldub_code(s->pc++);
5331 33698e5f bellard
        op = (modrm >> 3) & 7;
5332 2c0262af bellard
        mod = (modrm >> 6) & 3;
5333 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
5334 2c0262af bellard
        if (mod != 3) {
5335 14ce26e7 bellard
            s->rip_offset = 1;
5336 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5337 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
5338 2c0262af bellard
        } else {
5339 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
5340 2c0262af bellard
        }
5341 2c0262af bellard
        /* load shift */
5342 61382a50 bellard
        val = ldub_code(s->pc++);
5343 2c0262af bellard
        gen_op_movl_T1_im(val);
5344 2c0262af bellard
        if (op < 4)
5345 2c0262af bellard
            goto illegal_op;
5346 2c0262af bellard
        op -= 4;
5347 2c0262af bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5348 2c0262af bellard
        s->cc_op = CC_OP_SARB + ot;
5349 2c0262af bellard
        if (op != 0) {
5350 2c0262af bellard
            if (mod != 3)
5351 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
5352 2c0262af bellard
            else
5353 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
5354 2c0262af bellard
            gen_op_update_bt_cc();
5355 2c0262af bellard
        }
5356 2c0262af bellard
        break;
5357 2c0262af bellard
    case 0x1a3: /* bt Gv, Ev */
5358 2c0262af bellard
        op = 0;
5359 2c0262af bellard
        goto do_btx;
5360 2c0262af bellard
    case 0x1ab: /* bts */
5361 2c0262af bellard
        op = 1;
5362 2c0262af bellard
        goto do_btx;
5363 2c0262af bellard
    case 0x1b3: /* btr */
5364 2c0262af bellard
        op = 2;
5365 2c0262af bellard
        goto do_btx;
5366 2c0262af bellard
    case 0x1bb: /* btc */
5367 2c0262af bellard
        op = 3;
5368 2c0262af bellard
    do_btx:
5369 14ce26e7 bellard
        ot = dflag + OT_WORD;
5370 61382a50 bellard
        modrm = ldub_code(s->pc++);
5371 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
5372 2c0262af bellard
        mod = (modrm >> 6) & 3;
5373 14ce26e7 bellard
        rm = (modrm & 7) | REX_B(s);
5374 57fec1fe bellard
        gen_op_mov_TN_reg(OT_LONG, 1, reg);
5375 2c0262af bellard
        if (mod != 3) {
5376 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5377 2c0262af bellard
            /* specific case: we need to add a displacement */
5378 14ce26e7 bellard
            gen_op_add_bit_A0_T1[ot - OT_WORD]();
5379 57fec1fe bellard
            gen_op_ld_T0_A0(ot + s->mem_index);
5380 2c0262af bellard
        } else {
5381 57fec1fe bellard
            gen_op_mov_TN_reg(ot, 0, rm);
5382 2c0262af bellard
        }
5383 2c0262af bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5384 2c0262af bellard
        s->cc_op = CC_OP_SARB + ot;
5385 2c0262af bellard
        if (op != 0) {
5386 2c0262af bellard
            if (mod != 3)
5387 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
5388 2c0262af bellard
            else
5389 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
5390 2c0262af bellard
            gen_op_update_bt_cc();
5391 2c0262af bellard
        }
5392 2c0262af bellard
        break;
5393 2c0262af bellard
    case 0x1bc: /* bsf */
5394 2c0262af bellard
    case 0x1bd: /* bsr */
5395 14ce26e7 bellard
        ot = dflag + OT_WORD;
5396 61382a50 bellard
        modrm = ldub_code(s->pc++);
5397 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
5398 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5399 686f3f26 bellard
        /* NOTE: in order to handle the 0 case, we must load the
5400 686f3f26 bellard
           result. It could be optimized with a generated jump */
5401 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
5402 2c0262af bellard
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5403 57fec1fe bellard
        gen_op_mov_reg_T1(ot, reg);
5404 2c0262af bellard
        s->cc_op = CC_OP_LOGICB + ot;
5405 2c0262af bellard
        break;
5406 2c0262af bellard
        /************************/
5407 2c0262af bellard
        /* bcd */
5408 2c0262af bellard
    case 0x27: /* daa */
5409 14ce26e7 bellard
        if (CODE64(s))
5410 14ce26e7 bellard
            goto illegal_op;
5411 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5412 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5413 2c0262af bellard
        gen_op_daa();
5414 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5415 2c0262af bellard
        break;
5416 2c0262af bellard
    case 0x2f: /* das */
5417 14ce26e7 bellard
        if (CODE64(s))
5418 14ce26e7 bellard
            goto illegal_op;
5419 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5420 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5421 2c0262af bellard
        gen_op_das();
5422 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5423 2c0262af bellard
        break;
5424 2c0262af bellard
    case 0x37: /* aaa */
5425 14ce26e7 bellard
        if (CODE64(s))
5426 14ce26e7 bellard
            goto illegal_op;
5427 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5428 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5429 2c0262af bellard
        gen_op_aaa();
5430 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5431 2c0262af bellard
        break;
5432 2c0262af bellard
    case 0x3f: /* aas */
5433 14ce26e7 bellard
        if (CODE64(s))
5434 14ce26e7 bellard
            goto illegal_op;
5435 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5436 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5437 2c0262af bellard
        gen_op_aas();
5438 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
5439 2c0262af bellard
        break;
5440 2c0262af bellard
    case 0xd4: /* aam */
5441 14ce26e7 bellard
        if (CODE64(s))
5442 14ce26e7 bellard
            goto illegal_op;
5443 61382a50 bellard
        val = ldub_code(s->pc++);
5444 b6d7c3db ths
        if (val == 0) {
5445 b6d7c3db ths
            gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5446 b6d7c3db ths
        } else {
5447 b6d7c3db ths
            gen_op_aam(val);
5448 b6d7c3db ths
            s->cc_op = CC_OP_LOGICB;
5449 b6d7c3db ths
        }
5450 2c0262af bellard
        break;
5451 2c0262af bellard
    case 0xd5: /* aad */
5452 14ce26e7 bellard
        if (CODE64(s))
5453 14ce26e7 bellard
            goto illegal_op;
5454 61382a50 bellard
        val = ldub_code(s->pc++);
5455 2c0262af bellard
        gen_op_aad(val);
5456 2c0262af bellard
        s->cc_op = CC_OP_LOGICB;
5457 2c0262af bellard
        break;
5458 2c0262af bellard
        /************************/
5459 2c0262af bellard
        /* misc */
5460 2c0262af bellard
    case 0x90: /* nop */
5461 14ce26e7 bellard
        /* XXX: xchg + rex handling */
5462 ab1f142b bellard
        /* XXX: correct lock test for all insn */
5463 ab1f142b bellard
        if (prefixes & PREFIX_LOCK)
5464 ab1f142b bellard
            goto illegal_op;
5465 0573fbfc ths
        if (prefixes & PREFIX_REPZ) {
5466 0573fbfc ths
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
5467 0573fbfc ths
        }
5468 2c0262af bellard
        break;
5469 2c0262af bellard
    case 0x9b: /* fwait */
5470 5fafdf24 ths
        if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
5471 7eee2a50 bellard
            (HF_MP_MASK | HF_TS_MASK)) {
5472 7eee2a50 bellard
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5473 2ee73ac3 bellard
        } else {
5474 2ee73ac3 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5475 2ee73ac3 bellard
                gen_op_set_cc_op(s->cc_op);
5476 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5477 2ee73ac3 bellard
            gen_op_fwait();
5478 7eee2a50 bellard
        }
5479 2c0262af bellard
        break;
5480 2c0262af bellard
    case 0xcc: /* int3 */
5481 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5482 0573fbfc ths
            break;
5483 2c0262af bellard
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5484 2c0262af bellard
        break;
5485 2c0262af bellard
    case 0xcd: /* int N */
5486 61382a50 bellard
        val = ldub_code(s->pc++);
5487 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5488 0573fbfc ths
            break;
5489 f115e911 bellard
        if (s->vm86 && s->iopl != 3) {
5490 5fafdf24 ths
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5491 f115e911 bellard
        } else {
5492 f115e911 bellard
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5493 f115e911 bellard
        }
5494 2c0262af bellard
        break;
5495 2c0262af bellard
    case 0xce: /* into */
5496 14ce26e7 bellard
        if (CODE64(s))
5497 14ce26e7 bellard
            goto illegal_op;
5498 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5499 0573fbfc ths
            break;
5500 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5501 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5502 a8ede8ba bellard
        gen_jmp_im(pc_start - s->cs_base);
5503 a8ede8ba bellard
        gen_op_into(s->pc - pc_start);
5504 2c0262af bellard
        break;
5505 2c0262af bellard
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
5506 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
5507 0573fbfc ths
            break;
5508 aba9d61e bellard
#if 1
5509 2c0262af bellard
        gen_debug(s, pc_start - s->cs_base);
5510 aba9d61e bellard
#else
5511 aba9d61e bellard
        /* start debug */
5512 aba9d61e bellard
        tb_flush(cpu_single_env);
5513 aba9d61e bellard
        cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5514 aba9d61e bellard
#endif
5515 2c0262af bellard
        break;
5516 2c0262af bellard
    case 0xfa: /* cli */
5517 2c0262af bellard
        if (!s->vm86) {
5518 2c0262af bellard
            if (s->cpl <= s->iopl) {
5519 2c0262af bellard
                gen_op_cli();
5520 2c0262af bellard
            } else {
5521 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5522 2c0262af bellard
            }
5523 2c0262af bellard
        } else {
5524 2c0262af bellard
            if (s->iopl == 3) {
5525 2c0262af bellard
                gen_op_cli();
5526 2c0262af bellard
            } else {
5527 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5528 2c0262af bellard
            }
5529 2c0262af bellard
        }
5530 2c0262af bellard
        break;
5531 2c0262af bellard
    case 0xfb: /* sti */
5532 2c0262af bellard
        if (!s->vm86) {
5533 2c0262af bellard
            if (s->cpl <= s->iopl) {
5534 2c0262af bellard
            gen_sti:
5535 2c0262af bellard
                gen_op_sti();
5536 2c0262af bellard
                /* interruptions are enabled only the first insn after sti */
5537 a2cc3b24 bellard
                /* If several instructions disable interrupts, only the
5538 a2cc3b24 bellard
                   _first_ does it */
5539 a2cc3b24 bellard
                if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5540 a2cc3b24 bellard
                    gen_op_set_inhibit_irq();
5541 2c0262af bellard
                /* give a chance to handle pending irqs */
5542 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
5543 2c0262af bellard
                gen_eob(s);
5544 2c0262af bellard
            } else {
5545 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5546 2c0262af bellard
            }
5547 2c0262af bellard
        } else {
5548 2c0262af bellard
            if (s->iopl == 3) {
5549 2c0262af bellard
                goto gen_sti;
5550 2c0262af bellard
            } else {
5551 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5552 2c0262af bellard
            }
5553 2c0262af bellard
        }
5554 2c0262af bellard
        break;
5555 2c0262af bellard
    case 0x62: /* bound */
5556 14ce26e7 bellard
        if (CODE64(s))
5557 14ce26e7 bellard
            goto illegal_op;
5558 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
5559 61382a50 bellard
        modrm = ldub_code(s->pc++);
5560 2c0262af bellard
        reg = (modrm >> 3) & 7;
5561 2c0262af bellard
        mod = (modrm >> 6) & 3;
5562 2c0262af bellard
        if (mod == 3)
5563 2c0262af bellard
            goto illegal_op;
5564 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 0, reg);
5565 2c0262af bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5566 14ce26e7 bellard
        gen_jmp_im(pc_start - s->cs_base);
5567 2c0262af bellard
        if (ot == OT_WORD)
5568 14ce26e7 bellard
            gen_op_boundw();
5569 2c0262af bellard
        else
5570 14ce26e7 bellard
            gen_op_boundl();
5571 2c0262af bellard
        break;
5572 2c0262af bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
5573 14ce26e7 bellard
        reg = (b & 7) | REX_B(s);
5574 14ce26e7 bellard
#ifdef TARGET_X86_64
5575 14ce26e7 bellard
        if (dflag == 2) {
5576 57fec1fe bellard
            gen_op_mov_TN_reg(OT_QUAD, 0, reg);
5577 57fec1fe bellard
            tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]);
5578 57fec1fe bellard
            gen_op_mov_reg_T0(OT_QUAD, reg);
5579 5fafdf24 ths
        } else
5580 14ce26e7 bellard
        {
5581 ac56dd48 pbrook
            TCGv tmp0;
5582 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, reg);
5583 57fec1fe bellard
            
5584 57fec1fe bellard
            tmp0 = tcg_temp_new(TCG_TYPE_I32);
5585 57fec1fe bellard
            tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]);
5586 57fec1fe bellard
            tcg_gen_bswap_i32(tmp0, tmp0);
5587 57fec1fe bellard
            tcg_gen_extu_i32_i64(cpu_T[0], tmp0);
5588 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
5589 57fec1fe bellard
        }
5590 57fec1fe bellard
#else
5591 57fec1fe bellard
        {
5592 57fec1fe bellard
            gen_op_mov_TN_reg(OT_LONG, 0, reg);
5593 57fec1fe bellard
            tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]);
5594 57fec1fe bellard
            gen_op_mov_reg_T0(OT_LONG, reg);
5595 14ce26e7 bellard
        }
5596 57fec1fe bellard
#endif
5597 2c0262af bellard
        break;
5598 2c0262af bellard
    case 0xd6: /* salc */
5599 14ce26e7 bellard
        if (CODE64(s))
5600 14ce26e7 bellard
            goto illegal_op;
5601 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5602 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5603 2c0262af bellard
        gen_op_salc();
5604 2c0262af bellard
        break;
5605 2c0262af bellard
    case 0xe0: /* loopnz */
5606 2c0262af bellard
    case 0xe1: /* loopz */
5607 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
5608 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
5609 2c0262af bellard
        /* FALL THRU */
5610 2c0262af bellard
    case 0xe2: /* loop */
5611 2c0262af bellard
    case 0xe3: /* jecxz */
5612 14ce26e7 bellard
        {
5613 14ce26e7 bellard
            int l1, l2;
5614 14ce26e7 bellard
5615 14ce26e7 bellard
            tval = (int8_t)insn_get(s, OT_BYTE);
5616 14ce26e7 bellard
            next_eip = s->pc - s->cs_base;
5617 14ce26e7 bellard
            tval += next_eip;
5618 14ce26e7 bellard
            if (s->dflag == 0)
5619 14ce26e7 bellard
                tval &= 0xffff;
5620 3b46e624 ths
5621 14ce26e7 bellard
            l1 = gen_new_label();
5622 14ce26e7 bellard
            l2 = gen_new_label();
5623 14ce26e7 bellard
            b &= 3;
5624 14ce26e7 bellard
            if (b == 3) {
5625 14ce26e7 bellard
                gen_op_jz_ecx[s->aflag](l1);
5626 14ce26e7 bellard
            } else {
5627 14ce26e7 bellard
                gen_op_dec_ECX[s->aflag]();
5628 0b9dc5e4 bellard
                if (b <= 1)
5629 0b9dc5e4 bellard
                    gen_op_mov_T0_cc();
5630 14ce26e7 bellard
                gen_op_loop[s->aflag][b](l1);
5631 14ce26e7 bellard
            }
5632 14ce26e7 bellard
5633 14ce26e7 bellard
            gen_jmp_im(next_eip);
5634 14ce26e7 bellard
            gen_op_jmp_label(l2);
5635 14ce26e7 bellard
            gen_set_label(l1);
5636 14ce26e7 bellard
            gen_jmp_im(tval);
5637 14ce26e7 bellard
            gen_set_label(l2);
5638 14ce26e7 bellard
            gen_eob(s);
5639 14ce26e7 bellard
        }
5640 2c0262af bellard
        break;
5641 2c0262af bellard
    case 0x130: /* wrmsr */
5642 2c0262af bellard
    case 0x132: /* rdmsr */
5643 2c0262af bellard
        if (s->cpl != 0) {
5644 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5645 2c0262af bellard
        } else {
5646 0573fbfc ths
            int retval = 0;
5647 0573fbfc ths
            if (b & 2) {
5648 0573fbfc ths
                retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
5649 2c0262af bellard
                gen_op_rdmsr();
5650 0573fbfc ths
            } else {
5651 0573fbfc ths
                retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
5652 2c0262af bellard
                gen_op_wrmsr();
5653 0573fbfc ths
            }
5654 0573fbfc ths
            if(retval)
5655 0573fbfc ths
                gen_eob(s);
5656 2c0262af bellard
        }
5657 2c0262af bellard
        break;
5658 2c0262af bellard
    case 0x131: /* rdtsc */
5659 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
5660 0573fbfc ths
            break;
5661 ecada8a2 bellard
        gen_jmp_im(pc_start - s->cs_base);
5662 2c0262af bellard
        gen_op_rdtsc();
5663 2c0262af bellard
        break;
5664 df01e0fc balrog
    case 0x133: /* rdpmc */
5665 df01e0fc balrog
        gen_jmp_im(pc_start - s->cs_base);
5666 df01e0fc balrog
        gen_op_rdpmc();
5667 df01e0fc balrog
        break;
5668 023fe10d bellard
    case 0x134: /* sysenter */
5669 14ce26e7 bellard
        if (CODE64(s))
5670 14ce26e7 bellard
            goto illegal_op;
5671 023fe10d bellard
        if (!s->pe) {
5672 023fe10d bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5673 023fe10d bellard
        } else {
5674 023fe10d bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
5675 023fe10d bellard
                gen_op_set_cc_op(s->cc_op);
5676 023fe10d bellard
                s->cc_op = CC_OP_DYNAMIC;
5677 023fe10d bellard
            }
5678 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5679 023fe10d bellard
            gen_op_sysenter();
5680 023fe10d bellard
            gen_eob(s);
5681 023fe10d bellard
        }
5682 023fe10d bellard
        break;
5683 023fe10d bellard
    case 0x135: /* sysexit */
5684 14ce26e7 bellard
        if (CODE64(s))
5685 14ce26e7 bellard
            goto illegal_op;
5686 023fe10d bellard
        if (!s->pe) {
5687 023fe10d bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5688 023fe10d bellard
        } else {
5689 023fe10d bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
5690 023fe10d bellard
                gen_op_set_cc_op(s->cc_op);
5691 023fe10d bellard
                s->cc_op = CC_OP_DYNAMIC;
5692 023fe10d bellard
            }
5693 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5694 023fe10d bellard
            gen_op_sysexit();
5695 023fe10d bellard
            gen_eob(s);
5696 023fe10d bellard
        }
5697 023fe10d bellard
        break;
5698 14ce26e7 bellard
#ifdef TARGET_X86_64
5699 14ce26e7 bellard
    case 0x105: /* syscall */
5700 14ce26e7 bellard
        /* XXX: is it usable in real mode ? */
5701 14ce26e7 bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
5702 14ce26e7 bellard
            gen_op_set_cc_op(s->cc_op);
5703 14ce26e7 bellard
            s->cc_op = CC_OP_DYNAMIC;
5704 14ce26e7 bellard
        }
5705 14ce26e7 bellard
        gen_jmp_im(pc_start - s->cs_base);
5706 06c2f506 bellard
        gen_op_syscall(s->pc - pc_start);
5707 14ce26e7 bellard
        gen_eob(s);
5708 14ce26e7 bellard
        break;
5709 14ce26e7 bellard
    case 0x107: /* sysret */
5710 14ce26e7 bellard
        if (!s->pe) {
5711 14ce26e7 bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5712 14ce26e7 bellard
        } else {
5713 14ce26e7 bellard
            if (s->cc_op != CC_OP_DYNAMIC) {
5714 14ce26e7 bellard
                gen_op_set_cc_op(s->cc_op);
5715 14ce26e7 bellard
                s->cc_op = CC_OP_DYNAMIC;
5716 14ce26e7 bellard
            }
5717 14ce26e7 bellard
            gen_jmp_im(pc_start - s->cs_base);
5718 14ce26e7 bellard
            gen_op_sysret(s->dflag);
5719 aba9d61e bellard
            /* condition codes are modified only in long mode */
5720 aba9d61e bellard
            if (s->lma)
5721 aba9d61e bellard
                s->cc_op = CC_OP_EFLAGS;
5722 14ce26e7 bellard
            gen_eob(s);
5723 14ce26e7 bellard
        }
5724 14ce26e7 bellard
        break;
5725 14ce26e7 bellard
#endif
5726 2c0262af bellard
    case 0x1a2: /* cpuid */
5727 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
5728 0573fbfc ths
            break;
5729 2c0262af bellard
        gen_op_cpuid();
5730 2c0262af bellard
        break;
5731 2c0262af bellard
    case 0xf4: /* hlt */
5732 2c0262af bellard
        if (s->cpl != 0) {
5733 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5734 2c0262af bellard
        } else {
5735 0573fbfc ths
            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
5736 0573fbfc ths
                break;
5737 2c0262af bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5738 2c0262af bellard
                gen_op_set_cc_op(s->cc_op);
5739 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
5740 2c0262af bellard
            gen_op_hlt();
5741 2c0262af bellard
            s->is_jmp = 3;
5742 2c0262af bellard
        }
5743 2c0262af bellard
        break;
5744 2c0262af bellard
    case 0x100:
5745 61382a50 bellard
        modrm = ldub_code(s->pc++);
5746 2c0262af bellard
        mod = (modrm >> 6) & 3;
5747 2c0262af bellard
        op = (modrm >> 3) & 7;
5748 2c0262af bellard
        switch(op) {
5749 2c0262af bellard
        case 0: /* sldt */
5750 f115e911 bellard
            if (!s->pe || s->vm86)
5751 f115e911 bellard
                goto illegal_op;
5752 0573fbfc ths
            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
5753 0573fbfc ths
                break;
5754 2c0262af bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5755 2c0262af bellard
            ot = OT_WORD;
5756 2c0262af bellard
            if (mod == 3)
5757 2c0262af bellard
                ot += s->dflag;
5758 2c0262af bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5759 2c0262af bellard
            break;
5760 2c0262af bellard
        case 2: /* lldt */
5761 f115e911 bellard
            if (!s->pe || s->vm86)
5762 f115e911 bellard
                goto illegal_op;
5763 2c0262af bellard
            if (s->cpl != 0) {
5764 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5765 2c0262af bellard
            } else {
5766 0573fbfc ths
                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
5767 0573fbfc ths
                    break;
5768 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5769 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
5770 2c0262af bellard
                gen_op_lldt_T0();
5771 2c0262af bellard
            }
5772 2c0262af bellard
            break;
5773 2c0262af bellard
        case 1: /* str */
5774 f115e911 bellard
            if (!s->pe || s->vm86)
5775 f115e911 bellard
                goto illegal_op;
5776 0573fbfc ths
            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
5777 0573fbfc ths
                break;
5778 2c0262af bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5779 2c0262af bellard
            ot = OT_WORD;
5780 2c0262af bellard
            if (mod == 3)
5781 2c0262af bellard
                ot += s->dflag;
5782 2c0262af bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5783 2c0262af bellard
            break;
5784 2c0262af bellard
        case 3: /* ltr */
5785 f115e911 bellard
            if (!s->pe || s->vm86)
5786 f115e911 bellard
                goto illegal_op;
5787 2c0262af bellard
            if (s->cpl != 0) {
5788 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5789 2c0262af bellard
            } else {
5790 0573fbfc ths
                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
5791 0573fbfc ths
                    break;
5792 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5793 14ce26e7 bellard
                gen_jmp_im(pc_start - s->cs_base);
5794 2c0262af bellard
                gen_op_ltr_T0();
5795 2c0262af bellard
            }
5796 2c0262af bellard
            break;
5797 2c0262af bellard
        case 4: /* verr */
5798 2c0262af bellard
        case 5: /* verw */
5799 f115e911 bellard
            if (!s->pe || s->vm86)
5800 f115e911 bellard
                goto illegal_op;
5801 f115e911 bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5802 f115e911 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
5803 f115e911 bellard
                gen_op_set_cc_op(s->cc_op);
5804 f115e911 bellard
            if (op == 4)
5805 f115e911 bellard
                gen_op_verr();
5806 f115e911 bellard
            else
5807 f115e911 bellard
                gen_op_verw();
5808 f115e911 bellard
            s->cc_op = CC_OP_EFLAGS;
5809 f115e911 bellard
            break;
5810 2c0262af bellard
        default:
5811 2c0262af bellard
            goto illegal_op;
5812 2c0262af bellard
        }
5813 2c0262af bellard
        break;
5814 2c0262af bellard
    case 0x101:
5815 61382a50 bellard
        modrm = ldub_code(s->pc++);
5816 2c0262af bellard
        mod = (modrm >> 6) & 3;
5817 2c0262af bellard
        op = (modrm >> 3) & 7;
5818 3d7374c5 bellard
        rm = modrm & 7;
5819 2c0262af bellard
        switch(op) {
5820 2c0262af bellard
        case 0: /* sgdt */
5821 2c0262af bellard
            if (mod == 3)
5822 2c0262af bellard
                goto illegal_op;
5823 0573fbfc ths
            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
5824 0573fbfc ths
                break;
5825 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5826 3d7374c5 bellard
            gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
5827 57fec1fe bellard
            gen_op_st_T0_A0(OT_WORD + s->mem_index);
5828 aba9d61e bellard
            gen_add_A0_im(s, 2);
5829 3d7374c5 bellard
            gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
5830 2c0262af bellard
            if (!s->dflag)
5831 2c0262af bellard
                gen_op_andl_T0_im(0xffffff);
5832 57fec1fe bellard
            gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
5833 2c0262af bellard
            break;
5834 3d7374c5 bellard
        case 1:
5835 3d7374c5 bellard
            if (mod == 3) {
5836 3d7374c5 bellard
                switch (rm) {
5837 3d7374c5 bellard
                case 0: /* monitor */
5838 3d7374c5 bellard
                    if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5839 3d7374c5 bellard
                        s->cpl != 0)
5840 3d7374c5 bellard
                        goto illegal_op;
5841 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
5842 0573fbfc ths
                        break;
5843 3d7374c5 bellard
                    gen_jmp_im(pc_start - s->cs_base);
5844 3d7374c5 bellard
#ifdef TARGET_X86_64
5845 3d7374c5 bellard
                    if (s->aflag == 2) {
5846 57fec1fe bellard
                        gen_op_movq_A0_reg(R_EBX);
5847 3d7374c5 bellard
                        gen_op_addq_A0_AL();
5848 5fafdf24 ths
                    } else
5849 3d7374c5 bellard
#endif
5850 3d7374c5 bellard
                    {
5851 57fec1fe bellard
                        gen_op_movl_A0_reg(R_EBX);
5852 3d7374c5 bellard
                        gen_op_addl_A0_AL();
5853 3d7374c5 bellard
                        if (s->aflag == 0)
5854 3d7374c5 bellard
                            gen_op_andl_A0_ffff();
5855 3d7374c5 bellard
                    }
5856 3d7374c5 bellard
                    gen_add_A0_ds_seg(s);
5857 3d7374c5 bellard
                    gen_op_monitor();
5858 3d7374c5 bellard
                    break;
5859 3d7374c5 bellard
                case 1: /* mwait */
5860 3d7374c5 bellard
                    if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5861 3d7374c5 bellard
                        s->cpl != 0)
5862 3d7374c5 bellard
                        goto illegal_op;
5863 3d7374c5 bellard
                    if (s->cc_op != CC_OP_DYNAMIC) {
5864 3d7374c5 bellard
                        gen_op_set_cc_op(s->cc_op);
5865 3d7374c5 bellard
                        s->cc_op = CC_OP_DYNAMIC;
5866 3d7374c5 bellard
                    }
5867 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
5868 0573fbfc ths
                        break;
5869 3d7374c5 bellard
                    gen_jmp_im(s->pc - s->cs_base);
5870 3d7374c5 bellard
                    gen_op_mwait();
5871 3d7374c5 bellard
                    gen_eob(s);
5872 3d7374c5 bellard
                    break;
5873 3d7374c5 bellard
                default:
5874 3d7374c5 bellard
                    goto illegal_op;
5875 3d7374c5 bellard
                }
5876 3d7374c5 bellard
            } else { /* sidt */
5877 0573fbfc ths
                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
5878 0573fbfc ths
                    break;
5879 3d7374c5 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5880 3d7374c5 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5881 57fec1fe bellard
                gen_op_st_T0_A0(OT_WORD + s->mem_index);
5882 3d7374c5 bellard
                gen_add_A0_im(s, 2);
5883 3d7374c5 bellard
                gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5884 3d7374c5 bellard
                if (!s->dflag)
5885 3d7374c5 bellard
                    gen_op_andl_T0_im(0xffffff);
5886 57fec1fe bellard
                gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
5887 3d7374c5 bellard
            }
5888 3d7374c5 bellard
            break;
5889 2c0262af bellard
        case 2: /* lgdt */
5890 2c0262af bellard
        case 3: /* lidt */
5891 0573fbfc ths
            if (mod == 3) {
5892 0573fbfc ths
                switch(rm) {
5893 0573fbfc ths
                case 0: /* VMRUN */
5894 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
5895 0573fbfc ths
                        break;
5896 0573fbfc ths
                    if (s->cc_op != CC_OP_DYNAMIC)
5897 0573fbfc ths
                        gen_op_set_cc_op(s->cc_op);
5898 0573fbfc ths
                    gen_jmp_im(s->pc - s->cs_base);
5899 0573fbfc ths
                    gen_op_vmrun();
5900 0573fbfc ths
                    s->cc_op = CC_OP_EFLAGS;
5901 0573fbfc ths
                    gen_eob(s);
5902 0573fbfc ths
                    break;
5903 0573fbfc ths
                case 1: /* VMMCALL */
5904 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
5905 0573fbfc ths
                         break;
5906 0573fbfc ths
                    /* FIXME: cause #UD if hflags & SVM */
5907 0573fbfc ths
                    gen_op_vmmcall();
5908 0573fbfc ths
                    break;
5909 0573fbfc ths
                case 2: /* VMLOAD */
5910 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
5911 0573fbfc ths
                         break;
5912 0573fbfc ths
                    gen_op_vmload();
5913 0573fbfc ths
                    break;
5914 0573fbfc ths
                case 3: /* VMSAVE */
5915 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
5916 0573fbfc ths
                         break;
5917 0573fbfc ths
                    gen_op_vmsave();
5918 0573fbfc ths
                    break;
5919 0573fbfc ths
                case 4: /* STGI */
5920 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
5921 0573fbfc ths
                         break;
5922 0573fbfc ths
                    gen_op_stgi();
5923 0573fbfc ths
                    break;
5924 0573fbfc ths
                case 5: /* CLGI */
5925 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
5926 0573fbfc ths
                         break;
5927 0573fbfc ths
                    gen_op_clgi();
5928 0573fbfc ths
                    break;
5929 0573fbfc ths
                case 6: /* SKINIT */
5930 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
5931 0573fbfc ths
                         break;
5932 0573fbfc ths
                    gen_op_skinit();
5933 0573fbfc ths
                    break;
5934 0573fbfc ths
                case 7: /* INVLPGA */
5935 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
5936 0573fbfc ths
                         break;
5937 0573fbfc ths
                    gen_op_invlpga();
5938 0573fbfc ths
                    break;
5939 0573fbfc ths
                default:
5940 0573fbfc ths
                    goto illegal_op;
5941 0573fbfc ths
                }
5942 0573fbfc ths
            } else if (s->cpl != 0) {
5943 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5944 2c0262af bellard
            } else {
5945 0573fbfc ths
                if (gen_svm_check_intercept(s, pc_start,
5946 0573fbfc ths
                                            op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
5947 0573fbfc ths
                    break;
5948 2c0262af bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5949 57fec1fe bellard
                gen_op_ld_T1_A0(OT_WORD + s->mem_index);
5950 aba9d61e bellard
                gen_add_A0_im(s, 2);
5951 57fec1fe bellard
                gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
5952 2c0262af bellard
                if (!s->dflag)
5953 2c0262af bellard
                    gen_op_andl_T0_im(0xffffff);
5954 2c0262af bellard
                if (op == 2) {
5955 14ce26e7 bellard
                    gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5956 2c0262af bellard
                    gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5957 2c0262af bellard
                } else {
5958 14ce26e7 bellard
                    gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5959 2c0262af bellard
                    gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5960 2c0262af bellard
                }
5961 2c0262af bellard
            }
5962 2c0262af bellard
            break;
5963 2c0262af bellard
        case 4: /* smsw */
5964 0573fbfc ths
            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
5965 0573fbfc ths
                break;
5966 2c0262af bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5967 2c0262af bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5968 2c0262af bellard
            break;
5969 2c0262af bellard
        case 6: /* lmsw */
5970 2c0262af bellard
            if (s->cpl != 0) {
5971 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5972 2c0262af bellard
            } else {
5973 0573fbfc ths
                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
5974 0573fbfc ths
                    break;
5975 2c0262af bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5976 2c0262af bellard
                gen_op_lmsw_T0();
5977 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
5978 d71b9a8b bellard
                gen_eob(s);
5979 2c0262af bellard
            }
5980 2c0262af bellard
            break;
5981 2c0262af bellard
        case 7: /* invlpg */
5982 2c0262af bellard
            if (s->cpl != 0) {
5983 2c0262af bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5984 2c0262af bellard
            } else {
5985 14ce26e7 bellard
                if (mod == 3) {
5986 14ce26e7 bellard
#ifdef TARGET_X86_64
5987 3d7374c5 bellard
                    if (CODE64(s) && rm == 0) {
5988 14ce26e7 bellard
                        /* swapgs */
5989 14ce26e7 bellard
                        gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5990 14ce26e7 bellard
                        gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5991 14ce26e7 bellard
                        gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5992 14ce26e7 bellard
                        gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5993 5fafdf24 ths
                    } else
5994 14ce26e7 bellard
#endif
5995 14ce26e7 bellard
                    {
5996 14ce26e7 bellard
                        goto illegal_op;
5997 14ce26e7 bellard
                    }
5998 14ce26e7 bellard
                } else {
5999 0573fbfc ths
                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
6000 0573fbfc ths
                        break;
6001 14ce26e7 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6002 14ce26e7 bellard
                    gen_op_invlpg_A0();
6003 14ce26e7 bellard
                    gen_jmp_im(s->pc - s->cs_base);
6004 14ce26e7 bellard
                    gen_eob(s);
6005 14ce26e7 bellard
                }
6006 2c0262af bellard
            }
6007 2c0262af bellard
            break;
6008 2c0262af bellard
        default:
6009 2c0262af bellard
            goto illegal_op;
6010 2c0262af bellard
        }
6011 2c0262af bellard
        break;
6012 3415a4dd bellard
    case 0x108: /* invd */
6013 3415a4dd bellard
    case 0x109: /* wbinvd */
6014 3415a4dd bellard
        if (s->cpl != 0) {
6015 3415a4dd bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6016 3415a4dd bellard
        } else {
6017 ad848875 balrog
            if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD))
6018 0573fbfc ths
                break;
6019 3415a4dd bellard
            /* nothing to do */
6020 3415a4dd bellard
        }
6021 3415a4dd bellard
        break;
6022 14ce26e7 bellard
    case 0x63: /* arpl or movslS (x86_64) */
6023 14ce26e7 bellard
#ifdef TARGET_X86_64
6024 14ce26e7 bellard
        if (CODE64(s)) {
6025 14ce26e7 bellard
            int d_ot;
6026 14ce26e7 bellard
            /* d_ot is the size of destination */
6027 14ce26e7 bellard
            d_ot = dflag + OT_WORD;
6028 14ce26e7 bellard
6029 14ce26e7 bellard
            modrm = ldub_code(s->pc++);
6030 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6031 14ce26e7 bellard
            mod = (modrm >> 6) & 3;
6032 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6033 3b46e624 ths
6034 14ce26e7 bellard
            if (mod == 3) {
6035 57fec1fe bellard
                gen_op_mov_TN_reg(OT_LONG, 0, rm);
6036 14ce26e7 bellard
                /* sign extend */
6037 14ce26e7 bellard
                if (d_ot == OT_QUAD)
6038 14ce26e7 bellard
                    gen_op_movslq_T0_T0();
6039 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
6040 14ce26e7 bellard
            } else {
6041 14ce26e7 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6042 14ce26e7 bellard
                if (d_ot == OT_QUAD) {
6043 57fec1fe bellard
                    gen_op_lds_T0_A0(OT_LONG + s->mem_index);
6044 14ce26e7 bellard
                } else {
6045 57fec1fe bellard
                    gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6046 14ce26e7 bellard
                }
6047 57fec1fe bellard
                gen_op_mov_reg_T0(d_ot, reg);
6048 14ce26e7 bellard
            }
6049 5fafdf24 ths
        } else
6050 14ce26e7 bellard
#endif
6051 14ce26e7 bellard
        {
6052 14ce26e7 bellard
            if (!s->pe || s->vm86)
6053 14ce26e7 bellard
                goto illegal_op;
6054 14ce26e7 bellard
            ot = dflag ? OT_LONG : OT_WORD;
6055 14ce26e7 bellard
            modrm = ldub_code(s->pc++);
6056 14ce26e7 bellard
            reg = (modrm >> 3) & 7;
6057 14ce26e7 bellard
            mod = (modrm >> 6) & 3;
6058 14ce26e7 bellard
            rm = modrm & 7;
6059 14ce26e7 bellard
            if (mod != 3) {
6060 14ce26e7 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6061 57fec1fe bellard
                gen_op_ld_T0_A0(ot + s->mem_index);
6062 14ce26e7 bellard
            } else {
6063 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, rm);
6064 14ce26e7 bellard
            }
6065 14ce26e7 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
6066 14ce26e7 bellard
                gen_op_set_cc_op(s->cc_op);
6067 14ce26e7 bellard
            gen_op_arpl();
6068 14ce26e7 bellard
            s->cc_op = CC_OP_EFLAGS;
6069 14ce26e7 bellard
            if (mod != 3) {
6070 57fec1fe bellard
                gen_op_st_T0_A0(ot + s->mem_index);
6071 14ce26e7 bellard
            } else {
6072 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
6073 14ce26e7 bellard
            }
6074 14ce26e7 bellard
            gen_op_arpl_update();
6075 f115e911 bellard
        }
6076 f115e911 bellard
        break;
6077 2c0262af bellard
    case 0x102: /* lar */
6078 2c0262af bellard
    case 0x103: /* lsl */
6079 2c0262af bellard
        if (!s->pe || s->vm86)
6080 2c0262af bellard
            goto illegal_op;
6081 2c0262af bellard
        ot = dflag ? OT_LONG : OT_WORD;
6082 61382a50 bellard
        modrm = ldub_code(s->pc++);
6083 14ce26e7 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
6084 2c0262af bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6085 57fec1fe bellard
        gen_op_mov_TN_reg(ot, 1, reg);
6086 2c0262af bellard
        if (s->cc_op != CC_OP_DYNAMIC)
6087 2c0262af bellard
            gen_op_set_cc_op(s->cc_op);
6088 2c0262af bellard
        if (b == 0x102)
6089 2c0262af bellard
            gen_op_lar();
6090 2c0262af bellard
        else
6091 2c0262af bellard
            gen_op_lsl();
6092 2c0262af bellard
        s->cc_op = CC_OP_EFLAGS;
6093 57fec1fe bellard
        gen_op_mov_reg_T1(ot, reg);
6094 2c0262af bellard
        break;
6095 2c0262af bellard
    case 0x118:
6096 61382a50 bellard
        modrm = ldub_code(s->pc++);
6097 2c0262af bellard
        mod = (modrm >> 6) & 3;
6098 2c0262af bellard
        op = (modrm >> 3) & 7;
6099 2c0262af bellard
        switch(op) {
6100 2c0262af bellard
        case 0: /* prefetchnta */
6101 2c0262af bellard
        case 1: /* prefetchnt0 */
6102 2c0262af bellard
        case 2: /* prefetchnt0 */
6103 2c0262af bellard
        case 3: /* prefetchnt0 */
6104 2c0262af bellard
            if (mod == 3)
6105 2c0262af bellard
                goto illegal_op;
6106 2c0262af bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6107 2c0262af bellard
            /* nothing more to do */
6108 2c0262af bellard
            break;
6109 e17a36ce bellard
        default: /* nop (multi byte) */
6110 e17a36ce bellard
            gen_nop_modrm(s, modrm);
6111 e17a36ce bellard
            break;
6112 2c0262af bellard
        }
6113 2c0262af bellard
        break;
6114 e17a36ce bellard
    case 0x119 ... 0x11f: /* nop (multi byte) */
6115 e17a36ce bellard
        modrm = ldub_code(s->pc++);
6116 e17a36ce bellard
        gen_nop_modrm(s, modrm);
6117 e17a36ce bellard
        break;
6118 2c0262af bellard
    case 0x120: /* mov reg, crN */
6119 2c0262af bellard
    case 0x122: /* mov crN, reg */
6120 2c0262af bellard
        if (s->cpl != 0) {
6121 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6122 2c0262af bellard
        } else {
6123 61382a50 bellard
            modrm = ldub_code(s->pc++);
6124 2c0262af bellard
            if ((modrm & 0xc0) != 0xc0)
6125 2c0262af bellard
                goto illegal_op;
6126 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6127 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6128 14ce26e7 bellard
            if (CODE64(s))
6129 14ce26e7 bellard
                ot = OT_QUAD;
6130 14ce26e7 bellard
            else
6131 14ce26e7 bellard
                ot = OT_LONG;
6132 2c0262af bellard
            switch(reg) {
6133 2c0262af bellard
            case 0:
6134 2c0262af bellard
            case 2:
6135 2c0262af bellard
            case 3:
6136 2c0262af bellard
            case 4:
6137 9230e66e bellard
            case 8:
6138 2c0262af bellard
                if (b & 2) {
6139 0573fbfc ths
                    gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
6140 57fec1fe bellard
                    gen_op_mov_TN_reg(ot, 0, rm);
6141 2c0262af bellard
                    gen_op_movl_crN_T0(reg);
6142 14ce26e7 bellard
                    gen_jmp_im(s->pc - s->cs_base);
6143 2c0262af bellard
                    gen_eob(s);
6144 2c0262af bellard
                } else {
6145 0573fbfc ths
                    gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
6146 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
6147 9230e66e bellard
                    if (reg == 8)
6148 9230e66e bellard
                        gen_op_movtl_T0_cr8();
6149 9230e66e bellard
                    else
6150 82e41634 bellard
#endif
6151 9230e66e bellard
                        gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
6152 57fec1fe bellard
                    gen_op_mov_reg_T0(ot, rm);
6153 2c0262af bellard
                }
6154 2c0262af bellard
                break;
6155 2c0262af bellard
            default:
6156 2c0262af bellard
                goto illegal_op;
6157 2c0262af bellard
            }
6158 2c0262af bellard
        }
6159 2c0262af bellard
        break;
6160 2c0262af bellard
    case 0x121: /* mov reg, drN */
6161 2c0262af bellard
    case 0x123: /* mov drN, reg */
6162 2c0262af bellard
        if (s->cpl != 0) {
6163 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6164 2c0262af bellard
        } else {
6165 61382a50 bellard
            modrm = ldub_code(s->pc++);
6166 2c0262af bellard
            if ((modrm & 0xc0) != 0xc0)
6167 2c0262af bellard
                goto illegal_op;
6168 14ce26e7 bellard
            rm = (modrm & 7) | REX_B(s);
6169 14ce26e7 bellard
            reg = ((modrm >> 3) & 7) | rex_r;
6170 14ce26e7 bellard
            if (CODE64(s))
6171 14ce26e7 bellard
                ot = OT_QUAD;
6172 14ce26e7 bellard
            else
6173 14ce26e7 bellard
                ot = OT_LONG;
6174 2c0262af bellard
            /* XXX: do it dynamically with CR4.DE bit */
6175 14ce26e7 bellard
            if (reg == 4 || reg == 5 || reg >= 8)
6176 2c0262af bellard
                goto illegal_op;
6177 2c0262af bellard
            if (b & 2) {
6178 0573fbfc ths
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
6179 57fec1fe bellard
                gen_op_mov_TN_reg(ot, 0, rm);
6180 2c0262af bellard
                gen_op_movl_drN_T0(reg);
6181 14ce26e7 bellard
                gen_jmp_im(s->pc - s->cs_base);
6182 2c0262af bellard
                gen_eob(s);
6183 2c0262af bellard
            } else {
6184 0573fbfc ths
                gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
6185 14ce26e7 bellard
                gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6186 57fec1fe bellard
                gen_op_mov_reg_T0(ot, rm);
6187 2c0262af bellard
            }
6188 2c0262af bellard
        }
6189 2c0262af bellard
        break;
6190 2c0262af bellard
    case 0x106: /* clts */
6191 2c0262af bellard
        if (s->cpl != 0) {
6192 2c0262af bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6193 2c0262af bellard
        } else {
6194 0573fbfc ths
            gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
6195 2c0262af bellard
            gen_op_clts();
6196 7eee2a50 bellard
            /* abort block because static cpu state changed */
6197 14ce26e7 bellard
            gen_jmp_im(s->pc - s->cs_base);
6198 7eee2a50 bellard
            gen_eob(s);
6199 2c0262af bellard
        }
6200 2c0262af bellard
        break;
6201 a35f3ec7 aurel32
    /* MMX/3DNow!/SSE/SSE2/SSE3 support */
6202 664e0f19 bellard
    case 0x1c3: /* MOVNTI reg, mem */
6203 664e0f19 bellard
        if (!(s->cpuid_features & CPUID_SSE2))
6204 14ce26e7 bellard
            goto illegal_op;
6205 664e0f19 bellard
        ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6206 664e0f19 bellard
        modrm = ldub_code(s->pc++);
6207 664e0f19 bellard
        mod = (modrm >> 6) & 3;
6208 664e0f19 bellard
        if (mod == 3)
6209 664e0f19 bellard
            goto illegal_op;
6210 664e0f19 bellard
        reg = ((modrm >> 3) & 7) | rex_r;
6211 664e0f19 bellard
        /* generate a generic store */
6212 664e0f19 bellard
        gen_ldst_modrm(s, modrm, ot, reg, 1);
6213 14ce26e7 bellard
        break;
6214 664e0f19 bellard
    case 0x1ae:
6215 664e0f19 bellard
        modrm = ldub_code(s->pc++);
6216 664e0f19 bellard
        mod = (modrm >> 6) & 3;
6217 664e0f19 bellard
        op = (modrm >> 3) & 7;
6218 664e0f19 bellard
        switch(op) {
6219 664e0f19 bellard
        case 0: /* fxsave */
6220 5fafdf24 ths
            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6221 0fd14b72 bellard
                (s->flags & HF_EM_MASK))
6222 14ce26e7 bellard
                goto illegal_op;
6223 0fd14b72 bellard
            if (s->flags & HF_TS_MASK) {
6224 0fd14b72 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6225 0fd14b72 bellard
                break;
6226 0fd14b72 bellard
            }
6227 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6228 664e0f19 bellard
            gen_op_fxsave_A0((s->dflag == 2));
6229 664e0f19 bellard
            break;
6230 664e0f19 bellard
        case 1: /* fxrstor */
6231 5fafdf24 ths
            if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6232 0fd14b72 bellard
                (s->flags & HF_EM_MASK))
6233 14ce26e7 bellard
                goto illegal_op;
6234 0fd14b72 bellard
            if (s->flags & HF_TS_MASK) {
6235 0fd14b72 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6236 0fd14b72 bellard
                break;
6237 0fd14b72 bellard
            }
6238 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6239 664e0f19 bellard
            gen_op_fxrstor_A0((s->dflag == 2));
6240 664e0f19 bellard
            break;
6241 664e0f19 bellard
        case 2: /* ldmxcsr */
6242 664e0f19 bellard
        case 3: /* stmxcsr */
6243 664e0f19 bellard
            if (s->flags & HF_TS_MASK) {
6244 664e0f19 bellard
                gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6245 664e0f19 bellard
                break;
6246 14ce26e7 bellard
            }
6247 664e0f19 bellard
            if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6248 664e0f19 bellard
                mod == 3)
6249 14ce26e7 bellard
                goto illegal_op;
6250 664e0f19 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6251 664e0f19 bellard
            if (op == 2) {
6252 57fec1fe bellard
                gen_op_ld_T0_A0(OT_LONG + s->mem_index);
6253 664e0f19 bellard
                gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
6254 14ce26e7 bellard
            } else {
6255 664e0f19 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6256 57fec1fe bellard
                gen_op_st_T0_A0(OT_LONG + s->mem_index);
6257 14ce26e7 bellard
            }
6258 664e0f19 bellard
            break;
6259 664e0f19 bellard
        case 5: /* lfence */
6260 664e0f19 bellard
        case 6: /* mfence */
6261 664e0f19 bellard
            if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6262 664e0f19 bellard
                goto illegal_op;
6263 664e0f19 bellard
            break;
6264 8f091a59 bellard
        case 7: /* sfence / clflush */
6265 8f091a59 bellard
            if ((modrm & 0xc7) == 0xc0) {
6266 8f091a59 bellard
                /* sfence */
6267 a35f3ec7 aurel32
                /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
6268 8f091a59 bellard
                if (!(s->cpuid_features & CPUID_SSE))
6269 8f091a59 bellard
                    goto illegal_op;
6270 8f091a59 bellard
            } else {
6271 8f091a59 bellard
                /* clflush */
6272 8f091a59 bellard
                if (!(s->cpuid_features & CPUID_CLFLUSH))
6273 8f091a59 bellard
                    goto illegal_op;
6274 8f091a59 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6275 8f091a59 bellard
            }
6276 8f091a59 bellard
            break;
6277 664e0f19 bellard
        default:
6278 14ce26e7 bellard
            goto illegal_op;
6279 14ce26e7 bellard
        }
6280 14ce26e7 bellard
        break;
6281 a35f3ec7 aurel32
    case 0x10d: /* 3DNow! prefetch(w) */
6282 8f091a59 bellard
        modrm = ldub_code(s->pc++);
6283 a35f3ec7 aurel32
        mod = (modrm >> 6) & 3;
6284 a35f3ec7 aurel32
        if (mod == 3)
6285 a35f3ec7 aurel32
            goto illegal_op;
6286 8f091a59 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6287 8f091a59 bellard
        /* ignore for now */
6288 8f091a59 bellard
        break;
6289 3b21e03e bellard
    case 0x1aa: /* rsm */
6290 0573fbfc ths
        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
6291 0573fbfc ths
            break;
6292 3b21e03e bellard
        if (!(s->flags & HF_SMM_MASK))
6293 3b21e03e bellard
            goto illegal_op;
6294 3b21e03e bellard
        if (s->cc_op != CC_OP_DYNAMIC) {
6295 3b21e03e bellard
            gen_op_set_cc_op(s->cc_op);
6296 3b21e03e bellard
            s->cc_op = CC_OP_DYNAMIC;
6297 3b21e03e bellard
        }
6298 3b21e03e bellard
        gen_jmp_im(s->pc - s->cs_base);
6299 3b21e03e bellard
        gen_op_rsm();
6300 3b21e03e bellard
        gen_eob(s);
6301 3b21e03e bellard
        break;
6302 a35f3ec7 aurel32
    case 0x10e ... 0x10f:
6303 a35f3ec7 aurel32
        /* 3DNow! instructions, ignore prefixes */
6304 a35f3ec7 aurel32
        s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
6305 664e0f19 bellard
    case 0x110 ... 0x117:
6306 664e0f19 bellard
    case 0x128 ... 0x12f:
6307 664e0f19 bellard
    case 0x150 ... 0x177:
6308 664e0f19 bellard
    case 0x17c ... 0x17f:
6309 664e0f19 bellard
    case 0x1c2:
6310 664e0f19 bellard
    case 0x1c4 ... 0x1c6:
6311 664e0f19 bellard
    case 0x1d0 ... 0x1fe:
6312 664e0f19 bellard
        gen_sse(s, b, pc_start, rex_r);
6313 664e0f19 bellard
        break;
6314 2c0262af bellard
    default:
6315 2c0262af bellard
        goto illegal_op;
6316 2c0262af bellard
    }
6317 2c0262af bellard
    /* lock generation */
6318 2c0262af bellard
    if (s->prefix & PREFIX_LOCK)
6319 2c0262af bellard
        gen_op_unlock();
6320 2c0262af bellard
    return s->pc;
6321 2c0262af bellard
 illegal_op:
6322 ab1f142b bellard
    if (s->prefix & PREFIX_LOCK)
6323 ab1f142b bellard
        gen_op_unlock();
6324 2c0262af bellard
    /* XXX: ensure that no lock was generated */
6325 2c0262af bellard
    gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6326 2c0262af bellard
    return s->pc;
6327 2c0262af bellard
}
6328 2c0262af bellard
6329 2c0262af bellard
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6330 2c0262af bellard
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6331 2c0262af bellard
6332 2c0262af bellard
/* flags read by an operation */
6333 5fafdf24 ths
static uint16_t opc_read_flags[NB_OPS] = {
6334 2c0262af bellard
    [INDEX_op_aas] = CC_A,
6335 2c0262af bellard
    [INDEX_op_aaa] = CC_A,
6336 2c0262af bellard
    [INDEX_op_das] = CC_A | CC_C,
6337 2c0262af bellard
    [INDEX_op_daa] = CC_A | CC_C,
6338 2c0262af bellard
6339 2c0262af bellard
    /* subtle: due to the incl/decl implementation, C is used */
6340 5fafdf24 ths
    [INDEX_op_update_inc_cc] = CC_C,
6341 2c0262af bellard
6342 2c0262af bellard
    [INDEX_op_into] = CC_O,
6343 2c0262af bellard
6344 2c0262af bellard
    [INDEX_op_jb_subb] = CC_C,
6345 2c0262af bellard
    [INDEX_op_jb_subw] = CC_C,
6346 2c0262af bellard
    [INDEX_op_jb_subl] = CC_C,
6347 2c0262af bellard
6348 2c0262af bellard
    [INDEX_op_jz_subb] = CC_Z,
6349 2c0262af bellard
    [INDEX_op_jz_subw] = CC_Z,
6350 2c0262af bellard
    [INDEX_op_jz_subl] = CC_Z,
6351 2c0262af bellard
6352 2c0262af bellard
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
6353 2c0262af bellard
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
6354 2c0262af bellard
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
6355 2c0262af bellard
6356 2c0262af bellard
    [INDEX_op_js_subb] = CC_S,
6357 2c0262af bellard
    [INDEX_op_js_subw] = CC_S,
6358 2c0262af bellard
    [INDEX_op_js_subl] = CC_S,
6359 2c0262af bellard
6360 2c0262af bellard
    [INDEX_op_jl_subb] = CC_O | CC_S,
6361 2c0262af bellard
    [INDEX_op_jl_subw] = CC_O | CC_S,
6362 2c0262af bellard
    [INDEX_op_jl_subl] = CC_O | CC_S,
6363 2c0262af bellard
6364 2c0262af bellard
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6365 2c0262af bellard
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6366 2c0262af bellard
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6367 2c0262af bellard
6368 2c0262af bellard
    [INDEX_op_loopnzw] = CC_Z,
6369 2c0262af bellard
    [INDEX_op_loopnzl] = CC_Z,
6370 2c0262af bellard
    [INDEX_op_loopzw] = CC_Z,
6371 2c0262af bellard
    [INDEX_op_loopzl] = CC_Z,
6372 2c0262af bellard
6373 2c0262af bellard
    [INDEX_op_seto_T0_cc] = CC_O,
6374 2c0262af bellard
    [INDEX_op_setb_T0_cc] = CC_C,
6375 2c0262af bellard
    [INDEX_op_setz_T0_cc] = CC_Z,
6376 2c0262af bellard
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6377 2c0262af bellard
    [INDEX_op_sets_T0_cc] = CC_S,
6378 2c0262af bellard
    [INDEX_op_setp_T0_cc] = CC_P,
6379 2c0262af bellard
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6380 2c0262af bellard
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6381 2c0262af bellard
6382 2c0262af bellard
    [INDEX_op_setb_T0_subb] = CC_C,
6383 2c0262af bellard
    [INDEX_op_setb_T0_subw] = CC_C,
6384 2c0262af bellard
    [INDEX_op_setb_T0_subl] = CC_C,
6385 2c0262af bellard
6386 2c0262af bellard
    [INDEX_op_setz_T0_subb] = CC_Z,
6387 2c0262af bellard
    [INDEX_op_setz_T0_subw] = CC_Z,
6388 2c0262af bellard
    [INDEX_op_setz_T0_subl] = CC_Z,
6389 2c0262af bellard
6390 2c0262af bellard
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6391 2c0262af bellard
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6392 2c0262af bellard
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6393 2c0262af bellard
6394 2c0262af bellard
    [INDEX_op_sets_T0_subb] = CC_S,
6395 2c0262af bellard
    [INDEX_op_sets_T0_subw] = CC_S,
6396 2c0262af bellard
    [INDEX_op_sets_T0_subl] = CC_S,
6397 2c0262af bellard
6398 2c0262af bellard
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6399 2c0262af bellard
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6400 2c0262af bellard
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6401 2c0262af bellard
6402 2c0262af bellard
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6403 2c0262af bellard
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6404 2c0262af bellard
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6405 2c0262af bellard
6406 2c0262af bellard
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6407 2c0262af bellard
    [INDEX_op_cmc] = CC_C,
6408 2c0262af bellard
    [INDEX_op_salc] = CC_C,
6409 2c0262af bellard
6410 7399c5a9 bellard
    /* needed for correct flag optimisation before string ops */
6411 14ce26e7 bellard
    [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6412 14ce26e7 bellard
    [INDEX_op_jnz_ecxl] = CC_OSZAPC,
6413 7399c5a9 bellard
    [INDEX_op_jz_ecxw] = CC_OSZAPC,
6414 7399c5a9 bellard
    [INDEX_op_jz_ecxl] = CC_OSZAPC,
6415 14ce26e7 bellard
6416 14ce26e7 bellard
#ifdef TARGET_X86_64
6417 14ce26e7 bellard
    [INDEX_op_jb_subq] = CC_C,
6418 14ce26e7 bellard
    [INDEX_op_jz_subq] = CC_Z,
6419 14ce26e7 bellard
    [INDEX_op_jbe_subq] = CC_Z | CC_C,
6420 14ce26e7 bellard
    [INDEX_op_js_subq] = CC_S,
6421 14ce26e7 bellard
    [INDEX_op_jl_subq] = CC_O | CC_S,
6422 14ce26e7 bellard
    [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6423 14ce26e7 bellard
6424 14ce26e7 bellard
    [INDEX_op_loopnzq] = CC_Z,
6425 14ce26e7 bellard
    [INDEX_op_loopzq] = CC_Z,
6426 14ce26e7 bellard
6427 14ce26e7 bellard
    [INDEX_op_setb_T0_subq] = CC_C,
6428 14ce26e7 bellard
    [INDEX_op_setz_T0_subq] = CC_Z,
6429 14ce26e7 bellard
    [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6430 14ce26e7 bellard
    [INDEX_op_sets_T0_subq] = CC_S,
6431 14ce26e7 bellard
    [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6432 14ce26e7 bellard
    [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6433 14ce26e7 bellard
6434 14ce26e7 bellard
    [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6435 14ce26e7 bellard
    [INDEX_op_jz_ecxq] = CC_OSZAPC,
6436 14ce26e7 bellard
#endif
6437 7399c5a9 bellard
6438 4f31916f bellard
#define DEF_READF(SUFFIX)\
6439 4f31916f bellard
    [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6440 4f31916f bellard
    [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6441 4f31916f bellard
    [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6442 14ce26e7 bellard
    X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6443 4f31916f bellard
    [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6444 4f31916f bellard
    [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6445 4f31916f bellard
    [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6446 14ce26e7 bellard
    X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6447 4f31916f bellard
\
6448 4f31916f bellard
    [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6449 4f31916f bellard
    [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6450 4f31916f bellard
    [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
6451 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6452 4f31916f bellard
    [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6453 4f31916f bellard
    [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6454 14ce26e7 bellard
    [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6455 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
6456 4f31916f bellard
6457 4bb2fcc7 bellard
    DEF_READF( )
6458 4f31916f bellard
    DEF_READF(_raw)
6459 4f31916f bellard
#ifndef CONFIG_USER_ONLY
6460 4f31916f bellard
    DEF_READF(_kernel)
6461 4f31916f bellard
    DEF_READF(_user)
6462 4f31916f bellard
#endif
6463 2c0262af bellard
};
6464 2c0262af bellard
6465 2c0262af bellard
/* flags written by an operation */
6466 5fafdf24 ths
static uint16_t opc_write_flags[NB_OPS] = {
6467 2c0262af bellard
    [INDEX_op_update2_cc] = CC_OSZAPC,
6468 2c0262af bellard
    [INDEX_op_update1_cc] = CC_OSZAPC,
6469 2c0262af bellard
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6470 2c0262af bellard
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
6471 2c0262af bellard
    /* subtle: due to the incl/decl implementation, C is used */
6472 5fafdf24 ths
    [INDEX_op_update_inc_cc] = CC_OSZAPC,
6473 2c0262af bellard
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6474 2c0262af bellard
6475 2c0262af bellard
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6476 2c0262af bellard
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6477 2c0262af bellard
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6478 14ce26e7 bellard
    X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6479 14ce26e7 bellard
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6480 14ce26e7 bellard
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6481 2c0262af bellard
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6482 14ce26e7 bellard
    X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6483 2c0262af bellard
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6484 2c0262af bellard
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6485 14ce26e7 bellard
    X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6486 14ce26e7 bellard
6487 664e0f19 bellard
    /* sse */
6488 664e0f19 bellard
    [INDEX_op_ucomiss] = CC_OSZAPC,
6489 664e0f19 bellard
    [INDEX_op_ucomisd] = CC_OSZAPC,
6490 664e0f19 bellard
    [INDEX_op_comiss] = CC_OSZAPC,
6491 664e0f19 bellard
    [INDEX_op_comisd] = CC_OSZAPC,
6492 664e0f19 bellard
6493 2c0262af bellard
    /* bcd */
6494 2c0262af bellard
    [INDEX_op_aam] = CC_OSZAPC,
6495 2c0262af bellard
    [INDEX_op_aad] = CC_OSZAPC,
6496 2c0262af bellard
    [INDEX_op_aas] = CC_OSZAPC,
6497 2c0262af bellard
    [INDEX_op_aaa] = CC_OSZAPC,
6498 2c0262af bellard
    [INDEX_op_das] = CC_OSZAPC,
6499 2c0262af bellard
    [INDEX_op_daa] = CC_OSZAPC,
6500 2c0262af bellard
6501 2c0262af bellard
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6502 2c0262af bellard
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6503 2c0262af bellard
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6504 4136f33c bellard
    [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6505 4136f33c bellard
    [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6506 4136f33c bellard
    [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6507 4136f33c bellard
    [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6508 2c0262af bellard
    [INDEX_op_clc] = CC_C,
6509 2c0262af bellard
    [INDEX_op_stc] = CC_C,
6510 2c0262af bellard
    [INDEX_op_cmc] = CC_C,
6511 2c0262af bellard
6512 2c0262af bellard
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6513 2c0262af bellard
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6514 14ce26e7 bellard
    X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6515 2c0262af bellard
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6516 2c0262af bellard
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6517 14ce26e7 bellard
    X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6518 2c0262af bellard
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6519 2c0262af bellard
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6520 14ce26e7 bellard
    X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6521 2c0262af bellard
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6522 2c0262af bellard
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6523 14ce26e7 bellard
    X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6524 2c0262af bellard
6525 2c0262af bellard
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6526 2c0262af bellard
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6527 14ce26e7 bellard
    X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6528 2c0262af bellard
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6529 2c0262af bellard
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6530 14ce26e7 bellard
    X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6531 2c0262af bellard
6532 2c0262af bellard
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6533 2c0262af bellard
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6534 2c0262af bellard
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6535 14ce26e7 bellard
    X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6536 2c0262af bellard
6537 2c0262af bellard
    [INDEX_op_cmpxchg8b] = CC_Z,
6538 2c0262af bellard
    [INDEX_op_lar] = CC_Z,
6539 2c0262af bellard
    [INDEX_op_lsl] = CC_Z,
6540 cc6f538b bellard
    [INDEX_op_verr] = CC_Z,
6541 cc6f538b bellard
    [INDEX_op_verw] = CC_Z,
6542 2c0262af bellard
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6543 2c0262af bellard
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6544 4f31916f bellard
6545 4f31916f bellard
#define DEF_WRITEF(SUFFIX)\
6546 4f31916f bellard
    [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6547 4f31916f bellard
    [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6548 4f31916f bellard
    [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6549 14ce26e7 bellard
    X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6550 4f31916f bellard
    [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6551 4f31916f bellard
    [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6552 4f31916f bellard
    [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6553 14ce26e7 bellard
    X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6554 4f31916f bellard
\
6555 4f31916f bellard
    [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556 4f31916f bellard
    [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6557 4f31916f bellard
    [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6558 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6559 4f31916f bellard
    [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6560 4f31916f bellard
    [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6561 4f31916f bellard
    [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6562 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6563 4f31916f bellard
\
6564 4f31916f bellard
    [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6565 4f31916f bellard
    [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6566 4f31916f bellard
    [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6567 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6568 4f31916f bellard
    [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6569 4f31916f bellard
    [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6570 4f31916f bellard
    [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6571 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6572 4f31916f bellard
\
6573 4f31916f bellard
    [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6574 4f31916f bellard
    [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6575 4f31916f bellard
    [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6576 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6577 4f31916f bellard
\
6578 4f31916f bellard
    [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6579 4f31916f bellard
    [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6580 4f31916f bellard
    [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6581 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6582 4f31916f bellard
\
6583 4f31916f bellard
    [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6584 4f31916f bellard
    [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6585 4f31916f bellard
    [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6586 14ce26e7 bellard
    X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6587 4f31916f bellard
\
6588 4f31916f bellard
    [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6589 4f31916f bellard
    [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6590 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6591 4f31916f bellard
    [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6592 4f31916f bellard
    [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6593 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6594 4f31916f bellard
\
6595 4f31916f bellard
    [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6596 4f31916f bellard
    [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6597 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6598 4f31916f bellard
    [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6599 4f31916f bellard
    [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6600 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6601 4f31916f bellard
\
6602 4f31916f bellard
    [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6603 4f31916f bellard
    [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6604 14ce26e7 bellard
    [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6605 14ce26e7 bellard
    X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6606 4f31916f bellard
6607 4f31916f bellard
6608 4bb2fcc7 bellard
    DEF_WRITEF( )
6609 4f31916f bellard
    DEF_WRITEF(_raw)
6610 4f31916f bellard
#ifndef CONFIG_USER_ONLY
6611 4f31916f bellard
    DEF_WRITEF(_kernel)
6612 4f31916f bellard
    DEF_WRITEF(_user)
6613 4f31916f bellard
#endif
6614 2c0262af bellard
};
6615 2c0262af bellard
6616 2c0262af bellard
/* simpler form of an operation if no flags need to be generated */
6617 5fafdf24 ths
static uint16_t opc_simpler[NB_OPS] = {
6618 2c0262af bellard
    [INDEX_op_update2_cc] = INDEX_op_nop,
6619 2c0262af bellard
    [INDEX_op_update1_cc] = INDEX_op_nop,
6620 2c0262af bellard
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
6621 2c0262af bellard
#if 0
6622 2c0262af bellard
    /* broken: CC_OP logic must be rewritten */
6623 2c0262af bellard
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
6624 2c0262af bellard
#endif
6625 2c0262af bellard
6626 2c0262af bellard
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6627 2c0262af bellard
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6628 2c0262af bellard
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6629 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6630 2c0262af bellard
6631 2c0262af bellard
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6632 2c0262af bellard
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6633 2c0262af bellard
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6634 14ce26e7 bellard
    X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6635 2c0262af bellard
6636 2c0262af bellard
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6637 2c0262af bellard
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6638 2c0262af bellard
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6639 14ce26e7 bellard
    X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6640 4f31916f bellard
6641 4f31916f bellard
#define DEF_SIMPLER(SUFFIX)\
6642 4f31916f bellard
    [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6643 4f31916f bellard
    [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6644 4f31916f bellard
    [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6645 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6646 4f31916f bellard
\
6647 4f31916f bellard
    [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6648 4f31916f bellard
    [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6649 14ce26e7 bellard
    [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6650 14ce26e7 bellard
    X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6651 4f31916f bellard
6652 4bb2fcc7 bellard
    DEF_SIMPLER( )
6653 4f31916f bellard
    DEF_SIMPLER(_raw)
6654 4f31916f bellard
#ifndef CONFIG_USER_ONLY
6655 4f31916f bellard
    DEF_SIMPLER(_kernel)
6656 4f31916f bellard
    DEF_SIMPLER(_user)
6657 4f31916f bellard
#endif
6658 2c0262af bellard
};
6659 2c0262af bellard
6660 57fec1fe bellard
static void tcg_macro_func(TCGContext *s, int macro_id, const int *dead_args)
6661 57fec1fe bellard
{
6662 57fec1fe bellard
    switch(macro_id) {
6663 57fec1fe bellard
#ifdef MACRO_TEST
6664 57fec1fe bellard
    case MACRO_TEST:
6665 57fec1fe bellard
        tcg_gen_helper_0_1(helper_divl_EAX_T0, cpu_T[0]);
6666 57fec1fe bellard
        break;
6667 57fec1fe bellard
#endif
6668 57fec1fe bellard
    }
6669 57fec1fe bellard
}
6670 57fec1fe bellard
6671 2c0262af bellard
void optimize_flags_init(void)
6672 2c0262af bellard
{
6673 2c0262af bellard
    int i;
6674 2c0262af bellard
    /* put default values in arrays */
6675 2c0262af bellard
    for(i = 0; i < NB_OPS; i++) {
6676 2c0262af bellard
        if (opc_simpler[i] == 0)
6677 2c0262af bellard
            opc_simpler[i] = i;
6678 2c0262af bellard
    }
6679 57fec1fe bellard
6680 57fec1fe bellard
    tcg_set_macro_func(&tcg_ctx, tcg_macro_func);
6681 57fec1fe bellard
6682 57fec1fe bellard
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
6683 57fec1fe bellard
#if TARGET_LONG_BITS > HOST_LONG_BITS
6684 57fec1fe bellard
    cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL, 
6685 57fec1fe bellard
                                  TCG_AREG0, offsetof(CPUState, t0), "T0");
6686 57fec1fe bellard
    cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
6687 57fec1fe bellard
                                  TCG_AREG0, offsetof(CPUState, t1), "T1");
6688 57fec1fe bellard
    cpu_A0 = tcg_global_mem_new(TCG_TYPE_TL,
6689 57fec1fe bellard
                                TCG_AREG0, offsetof(CPUState, t2), "A0");
6690 57fec1fe bellard
#else
6691 57fec1fe bellard
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
6692 57fec1fe bellard
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
6693 57fec1fe bellard
    cpu_A0 = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "A0");
6694 8686c490 bellard
    cpu_tmp1 = tcg_global_reg2_new_hack(TCG_TYPE_I64, TCG_AREG1, TCG_AREG2, "tmp1");
6695 57fec1fe bellard
#endif
6696 57fec1fe bellard
    /* the helpers are only registered to print debug info */
6697 57fec1fe bellard
    TCG_HELPER(helper_divl_EAX_T0);
6698 57fec1fe bellard
    TCG_HELPER(helper_idivl_EAX_T0);
6699 2c0262af bellard
}
6700 2c0262af bellard
6701 2c0262af bellard
/* CPU flags computation optimization: we move backward thru the
6702 2c0262af bellard
   generated code to see which flags are needed. The operation is
6703 2c0262af bellard
   modified if suitable */
6704 2c0262af bellard
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6705 2c0262af bellard
{
6706 2c0262af bellard
    uint16_t *opc_ptr;
6707 2c0262af bellard
    int live_flags, write_flags, op;
6708 2c0262af bellard
6709 2c0262af bellard
    opc_ptr = opc_buf + opc_buf_len;
6710 2c0262af bellard
    /* live_flags contains the flags needed by the next instructions
6711 e91c8a77 ths
       in the code. At the end of the block, we consider that all the
6712 2c0262af bellard
       flags are live. */
6713 2c0262af bellard
    live_flags = CC_OSZAPC;
6714 2c0262af bellard
    while (opc_ptr > opc_buf) {
6715 2c0262af bellard
        op = *--opc_ptr;
6716 2c0262af bellard
        /* if none of the flags written by the instruction is used,
6717 2c0262af bellard
           then we can try to find a simpler instruction */
6718 2c0262af bellard
        write_flags = opc_write_flags[op];
6719 2c0262af bellard
        if ((live_flags & write_flags) == 0) {
6720 2c0262af bellard
            *opc_ptr = opc_simpler[op];
6721 2c0262af bellard
        }
6722 2c0262af bellard
        /* compute the live flags before the instruction */
6723 2c0262af bellard
        live_flags &= ~write_flags;
6724 2c0262af bellard
        live_flags |= opc_read_flags[op];
6725 2c0262af bellard
    }
6726 2c0262af bellard
}
6727 2c0262af bellard
6728 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6729 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
6730 2c0262af bellard
   information for each intermediate instruction. */
6731 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env,
6732 5fafdf24 ths
                                                 TranslationBlock *tb,
6733 2c0262af bellard
                                                 int search_pc)
6734 2c0262af bellard
{
6735 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
6736 14ce26e7 bellard
    target_ulong pc_ptr;
6737 2c0262af bellard
    uint16_t *gen_opc_end;
6738 c068688b j_mayer
    int j, lj, cflags;
6739 c068688b j_mayer
    uint64_t flags;
6740 14ce26e7 bellard
    target_ulong pc_start;
6741 14ce26e7 bellard
    target_ulong cs_base;
6742 3b46e624 ths
6743 2c0262af bellard
    /* generate intermediate code */
6744 14ce26e7 bellard
    pc_start = tb->pc;
6745 14ce26e7 bellard
    cs_base = tb->cs_base;
6746 2c0262af bellard
    flags = tb->flags;
6747 d720b93d bellard
    cflags = tb->cflags;
6748 3a1d9b8b bellard
6749 4f31916f bellard
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
6750 2c0262af bellard
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6751 2c0262af bellard
    dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6752 2c0262af bellard
    dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6753 2c0262af bellard
    dc->f_st = 0;
6754 2c0262af bellard
    dc->vm86 = (flags >> VM_SHIFT) & 1;
6755 2c0262af bellard
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6756 2c0262af bellard
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
6757 2c0262af bellard
    dc->tf = (flags >> TF_SHIFT) & 1;
6758 34865134 bellard
    dc->singlestep_enabled = env->singlestep_enabled;
6759 2c0262af bellard
    dc->cc_op = CC_OP_DYNAMIC;
6760 2c0262af bellard
    dc->cs_base = cs_base;
6761 2c0262af bellard
    dc->tb = tb;
6762 2c0262af bellard
    dc->popl_esp_hack = 0;
6763 2c0262af bellard
    /* select memory access functions */
6764 2c0262af bellard
    dc->mem_index = 0;
6765 2c0262af bellard
    if (flags & HF_SOFTMMU_MASK) {
6766 2c0262af bellard
        if (dc->cpl == 3)
6767 14ce26e7 bellard
            dc->mem_index = 2 * 4;
6768 2c0262af bellard
        else
6769 14ce26e7 bellard
            dc->mem_index = 1 * 4;
6770 2c0262af bellard
    }
6771 14ce26e7 bellard
    dc->cpuid_features = env->cpuid_features;
6772 3d7374c5 bellard
    dc->cpuid_ext_features = env->cpuid_ext_features;
6773 e771edab aurel32
    dc->cpuid_ext2_features = env->cpuid_ext2_features;
6774 14ce26e7 bellard
#ifdef TARGET_X86_64
6775 14ce26e7 bellard
    dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6776 14ce26e7 bellard
    dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6777 14ce26e7 bellard
#endif
6778 7eee2a50 bellard
    dc->flags = flags;
6779 a2cc3b24 bellard
    dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6780 a2cc3b24 bellard
                    (flags & HF_INHIBIT_IRQ_MASK)
6781 415fa2ea bellard
#ifndef CONFIG_SOFTMMU
6782 2c0262af bellard
                    || (flags & HF_SOFTMMU_MASK)
6783 2c0262af bellard
#endif
6784 2c0262af bellard
                    );
6785 4f31916f bellard
#if 0
6786 4f31916f bellard
    /* check addseg logic */
6787 dc196a57 bellard
    if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6788 4f31916f bellard
        printf("ERROR addseg\n");
6789 4f31916f bellard
#endif
6790 4f31916f bellard
6791 57fec1fe bellard
    cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);
6792 8686c490 bellard
#if TARGET_LONG_BITS > HOST_LONG_BITS
6793 8686c490 bellard
    cpu_tmp1 = tcg_temp_new(TCG_TYPE_I64);
6794 8686c490 bellard
#endif
6795 57fec1fe bellard
6796 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6797 2c0262af bellard
6798 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
6799 2c0262af bellard
    pc_ptr = pc_start;
6800 2c0262af bellard
    lj = -1;
6801 2c0262af bellard
6802 2c0262af bellard
    for(;;) {
6803 2c0262af bellard
        if (env->nb_breakpoints > 0) {
6804 2c0262af bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
6805 14ce26e7 bellard
                if (env->breakpoints[j] == pc_ptr) {
6806 2c0262af bellard
                    gen_debug(dc, pc_ptr - dc->cs_base);
6807 2c0262af bellard
                    break;
6808 2c0262af bellard
                }
6809 2c0262af bellard
            }
6810 2c0262af bellard
        }
6811 2c0262af bellard
        if (search_pc) {
6812 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
6813 2c0262af bellard
            if (lj < j) {
6814 2c0262af bellard
                lj++;
6815 2c0262af bellard
                while (lj < j)
6816 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
6817 2c0262af bellard
            }
6818 14ce26e7 bellard
            gen_opc_pc[lj] = pc_ptr;
6819 2c0262af bellard
            gen_opc_cc_op[lj] = dc->cc_op;
6820 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
6821 2c0262af bellard
        }
6822 2c0262af bellard
        pc_ptr = disas_insn(dc, pc_ptr);
6823 2c0262af bellard
        /* stop translation if indicated */
6824 2c0262af bellard
        if (dc->is_jmp)
6825 2c0262af bellard
            break;
6826 2c0262af bellard
        /* if single step mode, we generate only one instruction and
6827 2c0262af bellard
           generate an exception */
6828 a2cc3b24 bellard
        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6829 a2cc3b24 bellard
           the flag and abort the translation to give the irqs a
6830 a2cc3b24 bellard
           change to be happen */
6831 5fafdf24 ths
        if (dc->tf || dc->singlestep_enabled ||
6832 d720b93d bellard
            (flags & HF_INHIBIT_IRQ_MASK) ||
6833 d720b93d bellard
            (cflags & CF_SINGLE_INSN)) {
6834 14ce26e7 bellard
            gen_jmp_im(pc_ptr - dc->cs_base);
6835 2c0262af bellard
            gen_eob(dc);
6836 2c0262af bellard
            break;
6837 2c0262af bellard
        }
6838 2c0262af bellard
        /* if too long translation, stop generation too */
6839 2c0262af bellard
        if (gen_opc_ptr >= gen_opc_end ||
6840 2c0262af bellard
            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6841 14ce26e7 bellard
            gen_jmp_im(pc_ptr - dc->cs_base);
6842 2c0262af bellard
            gen_eob(dc);
6843 2c0262af bellard
            break;
6844 2c0262af bellard
        }
6845 2c0262af bellard
    }
6846 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
6847 2c0262af bellard
    /* we don't forget to fill the last values */
6848 2c0262af bellard
    if (search_pc) {
6849 2c0262af bellard
        j = gen_opc_ptr - gen_opc_buf;
6850 2c0262af bellard
        lj++;
6851 2c0262af bellard
        while (lj <= j)
6852 2c0262af bellard
            gen_opc_instr_start[lj++] = 0;
6853 2c0262af bellard
    }
6854 3b46e624 ths
6855 2c0262af bellard
#ifdef DEBUG_DISAS
6856 658c8bda bellard
    if (loglevel & CPU_LOG_TB_CPU) {
6857 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6858 658c8bda bellard
    }
6859 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6860 14ce26e7 bellard
        int disas_flags;
6861 2c0262af bellard
        fprintf(logfile, "----------------\n");
6862 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6863 14ce26e7 bellard
#ifdef TARGET_X86_64
6864 14ce26e7 bellard
        if (dc->code64)
6865 14ce26e7 bellard
            disas_flags = 2;
6866 14ce26e7 bellard
        else
6867 14ce26e7 bellard
#endif
6868 14ce26e7 bellard
            disas_flags = !dc->code32;
6869 14ce26e7 bellard
        target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6870 2c0262af bellard
        fprintf(logfile, "\n");
6871 57fec1fe bellard
        if (loglevel & CPU_LOG_TB_OP_OPT) {
6872 57fec1fe bellard
            fprintf(logfile, "OP before opt:\n");
6873 57fec1fe bellard
            tcg_dump_ops(&tcg_ctx, logfile);
6874 e19e89a5 bellard
            fprintf(logfile, "\n");
6875 e19e89a5 bellard
        }
6876 2c0262af bellard
    }
6877 2c0262af bellard
#endif
6878 2c0262af bellard
6879 2c0262af bellard
    /* optimize flag computations */
6880 2c0262af bellard
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6881 2c0262af bellard
6882 2c0262af bellard
    if (!search_pc)
6883 2c0262af bellard
        tb->size = pc_ptr - pc_start;
6884 2c0262af bellard
    return 0;
6885 2c0262af bellard
}
6886 2c0262af bellard
6887 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6888 2c0262af bellard
{
6889 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
6890 2c0262af bellard
}
6891 2c0262af bellard
6892 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6893 2c0262af bellard
{
6894 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
6895 2c0262af bellard
}
6896 2c0262af bellard
6897 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
6898 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
6899 d2856f1a aurel32
{
6900 d2856f1a aurel32
    int cc_op;
6901 d2856f1a aurel32
#ifdef DEBUG_DISAS
6902 d2856f1a aurel32
    if (loglevel & CPU_LOG_TB_OP) {
6903 d2856f1a aurel32
        int i;
6904 d2856f1a aurel32
        fprintf(logfile, "RESTORE:\n");
6905 d2856f1a aurel32
        for(i = 0;i <= pc_pos; i++) {
6906 d2856f1a aurel32
            if (gen_opc_instr_start[i]) {
6907 d2856f1a aurel32
                fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
6908 d2856f1a aurel32
            }
6909 d2856f1a aurel32
        }
6910 d2856f1a aurel32
        fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
6911 d2856f1a aurel32
                searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
6912 d2856f1a aurel32
                (uint32_t)tb->cs_base);
6913 d2856f1a aurel32
    }
6914 d2856f1a aurel32
#endif
6915 d2856f1a aurel32
    env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
6916 d2856f1a aurel32
    cc_op = gen_opc_cc_op[pc_pos];
6917 d2856f1a aurel32
    if (cc_op != CC_OP_DYNAMIC)
6918 d2856f1a aurel32
        env->cc_op = cc_op;
6919 d2856f1a aurel32
}