Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ b8b6a50b

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