Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 977d5710

History | View | Annotate | Download (186.8 kB)

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