Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 5fafdf24

History | View | Annotate | Download (196.9 kB)

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