Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 3e382bc8

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