Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ cad3a37d

History | View | Annotate | Download (219.8 kB)

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