Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ a35f3ec7

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