Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 0573fbfc

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