Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 19e6c4b8

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