Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 14ce26e7

History | View | Annotate | Download (160.8 kB)

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