Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ bd7a7b33

History | View | Annotate | Download (230.5 kB)

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