Statistics
| Branch: | Revision:

root / translate-i386.c @ 366c1b8b

History | View | Annotate | Download (105.9 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 translation
3 7d13299d bellard
 * 
4 7d13299d bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 7d13299d bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 7d13299d bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 7d13299d bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7d13299d bellard
 */
20 367e86e8 bellard
#include <stdarg.h>
21 367e86e8 bellard
#include <stdlib.h>
22 367e86e8 bellard
#include <stdio.h>
23 367e86e8 bellard
#include <string.h>
24 367e86e8 bellard
#include <inttypes.h>
25 9de5e440 bellard
#include <signal.h>
26 367e86e8 bellard
#include <assert.h>
27 367e86e8 bellard
28 b9adb4a6 bellard
#include "disas.h"
29 b9adb4a6 bellard
30 0ecfa993 bellard
#define DEBUG_DISAS
31 0ecfa993 bellard
32 586314f2 bellard
#define IN_OP_I386
33 586314f2 bellard
#include "cpu-i386.h"
34 586314f2 bellard
35 6dbad63e bellard
#ifndef offsetof
36 6dbad63e bellard
#define offsetof(type, field) ((size_t) &((type *)0)->field)
37 6dbad63e bellard
#endif
38 6dbad63e bellard
39 04369ff2 bellard
/* XXX: move that elsewhere */
40 dc99065b bellard
static uint16_t *gen_opc_ptr;
41 dc99065b bellard
static uint32_t *gen_opparam_ptr;
42 367e86e8 bellard
int __op_param1, __op_param2, __op_param3;
43 367e86e8 bellard
44 04369ff2 bellard
#ifdef __i386__
45 04369ff2 bellard
static inline void flush_icache_range(unsigned long start, unsigned long stop)
46 04369ff2 bellard
{
47 04369ff2 bellard
}
48 04369ff2 bellard
#endif
49 04369ff2 bellard
50 fb3e5849 bellard
#ifdef __s390__
51 fb3e5849 bellard
static inline void flush_icache_range(unsigned long start, unsigned long stop)
52 fb3e5849 bellard
{
53 fb3e5849 bellard
}
54 fb3e5849 bellard
#endif
55 fb3e5849 bellard
56 efdea7bf bellard
#ifdef __ia64__
57 efdea7bf bellard
static inline void flush_icache_range(unsigned long start, unsigned long stop)
58 efdea7bf bellard
{
59 efdea7bf bellard
}
60 efdea7bf bellard
#endif
61 efdea7bf bellard
62 04369ff2 bellard
#ifdef __powerpc__
63 04369ff2 bellard
64 04369ff2 bellard
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
65 04369ff2 bellard
66 04369ff2 bellard
static void inline flush_icache_range(unsigned long start, unsigned long stop)
67 04369ff2 bellard
{
68 04369ff2 bellard
    unsigned long p;
69 04369ff2 bellard
70 04369ff2 bellard
    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
71 04369ff2 bellard
    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
72 04369ff2 bellard
    
73 04369ff2 bellard
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
74 04369ff2 bellard
        asm ("dcbst 0,%0;" : : "r"(p) : "memory");
75 04369ff2 bellard
    }
76 04369ff2 bellard
    asm ("sync");
77 04369ff2 bellard
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
78 04369ff2 bellard
        asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
79 04369ff2 bellard
    }
80 04369ff2 bellard
    asm ("sync");
81 04369ff2 bellard
    asm ("isync");
82 04369ff2 bellard
}
83 04369ff2 bellard
#endif
84 04369ff2 bellard
85 efdea7bf bellard
#ifdef __alpha__
86 efdea7bf bellard
static inline void flush_icache_range(unsigned long start, unsigned long stop)
87 efdea7bf bellard
{
88 efdea7bf bellard
    asm ("imb");
89 efdea7bf bellard
}
90 efdea7bf bellard
#endif
91 efdea7bf bellard
92 d014c98c bellard
#ifdef __sparc__
93 d014c98c bellard
94 d014c98c bellard
static void inline flush_icache_range(unsigned long start, unsigned long stop)
95 d014c98c bellard
{
96 d014c98c bellard
        unsigned long p;
97 d014c98c bellard
98 d014c98c bellard
        p = start & ~(8UL - 1UL);
99 d014c98c bellard
        stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
100 d014c98c bellard
101 d014c98c bellard
        for (; p < stop; p += 8)
102 d014c98c bellard
                __asm__ __volatile__("flush\t%0" : : "r" (p));
103 d014c98c bellard
}
104 d014c98c bellard
105 d014c98c bellard
#endif
106 d014c98c bellard
107 586314f2 bellard
extern FILE *logfile;
108 586314f2 bellard
extern int loglevel;
109 0ecfa993 bellard
110 9c605cb1 bellard
#define PREFIX_REPZ   0x01
111 9c605cb1 bellard
#define PREFIX_REPNZ  0x02
112 9c605cb1 bellard
#define PREFIX_LOCK   0x04
113 9c605cb1 bellard
#define PREFIX_DATA   0x08
114 9c605cb1 bellard
#define PREFIX_ADR    0x10
115 9c605cb1 bellard
#define PREFIX_FWAIT  0x20
116 367e86e8 bellard
117 367e86e8 bellard
typedef struct DisasContext {
118 367e86e8 bellard
    /* current insn context */
119 9c605cb1 bellard
    int override; /* -1 if no override */
120 367e86e8 bellard
    int prefix;
121 367e86e8 bellard
    int aflag, dflag;
122 dab2ed99 bellard
    uint8_t *pc; /* pc = eip + cs_base */
123 6dbad63e bellard
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
124 6dbad63e bellard
                   static state change (stop translation) */
125 6dbad63e bellard
    /* current block context */
126 dab2ed99 bellard
    uint8_t *cs_base; /* base of CS segment */
127 6dbad63e bellard
    int code32; /* 32 bit code segment */
128 dab2ed99 bellard
    int ss32;   /* 32 bit stack segment */
129 6dbad63e bellard
    int cc_op;  /* current CC operation */
130 6dbad63e bellard
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
131 6dbad63e bellard
    int f_st;   /* currently unused */
132 9c605cb1 bellard
    int vm86;   /* vm86 mode */
133 982b4315 bellard
    int cpl;
134 982b4315 bellard
    int iopl;
135 c50c0c3f bellard
    int tf;     /* TF cpu flag */
136 367e86e8 bellard
} DisasContext;
137 367e86e8 bellard
138 367e86e8 bellard
/* i386 arith/logic operations */
139 367e86e8 bellard
enum {
140 367e86e8 bellard
    OP_ADDL, 
141 367e86e8 bellard
    OP_ORL, 
142 367e86e8 bellard
    OP_ADCL, 
143 367e86e8 bellard
    OP_SBBL,
144 367e86e8 bellard
    OP_ANDL, 
145 367e86e8 bellard
    OP_SUBL, 
146 367e86e8 bellard
    OP_XORL, 
147 367e86e8 bellard
    OP_CMPL,
148 367e86e8 bellard
};
149 367e86e8 bellard
150 367e86e8 bellard
/* i386 shift ops */
151 367e86e8 bellard
enum {
152 367e86e8 bellard
    OP_ROL, 
153 367e86e8 bellard
    OP_ROR, 
154 367e86e8 bellard
    OP_RCL, 
155 367e86e8 bellard
    OP_RCR, 
156 367e86e8 bellard
    OP_SHL, 
157 367e86e8 bellard
    OP_SHR, 
158 367e86e8 bellard
    OP_SHL1, /* undocumented */
159 367e86e8 bellard
    OP_SAR = 7,
160 367e86e8 bellard
};
161 367e86e8 bellard
162 dc99065b bellard
enum {
163 9c605cb1 bellard
#define DEF(s, n) INDEX_op_ ## s,
164 dc99065b bellard
#include "opc-i386.h"
165 dc99065b bellard
#undef DEF
166 dc99065b bellard
    NB_OPS,
167 dc99065b bellard
};
168 dc99065b bellard
169 367e86e8 bellard
#include "op-i386.h"
170 367e86e8 bellard
171 367e86e8 bellard
/* operand size */
172 367e86e8 bellard
enum {
173 367e86e8 bellard
    OT_BYTE = 0,
174 367e86e8 bellard
    OT_WORD,
175 367e86e8 bellard
    OT_LONG, 
176 367e86e8 bellard
    OT_QUAD,
177 367e86e8 bellard
};
178 367e86e8 bellard
179 367e86e8 bellard
enum {
180 367e86e8 bellard
    /* I386 int registers */
181 367e86e8 bellard
    OR_EAX,   /* MUST be even numbered */
182 367e86e8 bellard
    OR_ECX,
183 367e86e8 bellard
    OR_EDX,
184 367e86e8 bellard
    OR_EBX,
185 367e86e8 bellard
    OR_ESP,
186 367e86e8 bellard
    OR_EBP,
187 367e86e8 bellard
    OR_ESI,
188 367e86e8 bellard
    OR_EDI,
189 367e86e8 bellard
    OR_TMP0,    /* temporary operand register */
190 367e86e8 bellard
    OR_TMP1,
191 367e86e8 bellard
    OR_A0, /* temporary register used when doing address evaluation */
192 367e86e8 bellard
    OR_ZERO, /* fixed zero register */
193 367e86e8 bellard
    NB_OREGS,
194 367e86e8 bellard
};
195 367e86e8 bellard
196 367e86e8 bellard
typedef void (GenOpFunc)(void);
197 367e86e8 bellard
typedef void (GenOpFunc1)(long);
198 367e86e8 bellard
typedef void (GenOpFunc2)(long, long);
199 367e86e8 bellard
                    
200 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
201 367e86e8 bellard
    [OT_BYTE] = {
202 367e86e8 bellard
        gen_op_movb_EAX_T0,
203 367e86e8 bellard
        gen_op_movb_ECX_T0,
204 367e86e8 bellard
        gen_op_movb_EDX_T0,
205 367e86e8 bellard
        gen_op_movb_EBX_T0,
206 367e86e8 bellard
        gen_op_movh_EAX_T0,
207 367e86e8 bellard
        gen_op_movh_ECX_T0,
208 367e86e8 bellard
        gen_op_movh_EDX_T0,
209 367e86e8 bellard
        gen_op_movh_EBX_T0,
210 367e86e8 bellard
    },
211 367e86e8 bellard
    [OT_WORD] = {
212 367e86e8 bellard
        gen_op_movw_EAX_T0,
213 367e86e8 bellard
        gen_op_movw_ECX_T0,
214 367e86e8 bellard
        gen_op_movw_EDX_T0,
215 367e86e8 bellard
        gen_op_movw_EBX_T0,
216 367e86e8 bellard
        gen_op_movw_ESP_T0,
217 367e86e8 bellard
        gen_op_movw_EBP_T0,
218 367e86e8 bellard
        gen_op_movw_ESI_T0,
219 367e86e8 bellard
        gen_op_movw_EDI_T0,
220 367e86e8 bellard
    },
221 367e86e8 bellard
    [OT_LONG] = {
222 367e86e8 bellard
        gen_op_movl_EAX_T0,
223 367e86e8 bellard
        gen_op_movl_ECX_T0,
224 367e86e8 bellard
        gen_op_movl_EDX_T0,
225 367e86e8 bellard
        gen_op_movl_EBX_T0,
226 367e86e8 bellard
        gen_op_movl_ESP_T0,
227 367e86e8 bellard
        gen_op_movl_EBP_T0,
228 367e86e8 bellard
        gen_op_movl_ESI_T0,
229 367e86e8 bellard
        gen_op_movl_EDI_T0,
230 367e86e8 bellard
    },
231 367e86e8 bellard
};
232 367e86e8 bellard
233 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
234 367e86e8 bellard
    [OT_BYTE] = {
235 367e86e8 bellard
        gen_op_movb_EAX_T1,
236 367e86e8 bellard
        gen_op_movb_ECX_T1,
237 367e86e8 bellard
        gen_op_movb_EDX_T1,
238 367e86e8 bellard
        gen_op_movb_EBX_T1,
239 367e86e8 bellard
        gen_op_movh_EAX_T1,
240 367e86e8 bellard
        gen_op_movh_ECX_T1,
241 367e86e8 bellard
        gen_op_movh_EDX_T1,
242 367e86e8 bellard
        gen_op_movh_EBX_T1,
243 367e86e8 bellard
    },
244 367e86e8 bellard
    [OT_WORD] = {
245 367e86e8 bellard
        gen_op_movw_EAX_T1,
246 367e86e8 bellard
        gen_op_movw_ECX_T1,
247 367e86e8 bellard
        gen_op_movw_EDX_T1,
248 367e86e8 bellard
        gen_op_movw_EBX_T1,
249 367e86e8 bellard
        gen_op_movw_ESP_T1,
250 367e86e8 bellard
        gen_op_movw_EBP_T1,
251 367e86e8 bellard
        gen_op_movw_ESI_T1,
252 367e86e8 bellard
        gen_op_movw_EDI_T1,
253 367e86e8 bellard
    },
254 367e86e8 bellard
    [OT_LONG] = {
255 367e86e8 bellard
        gen_op_movl_EAX_T1,
256 367e86e8 bellard
        gen_op_movl_ECX_T1,
257 367e86e8 bellard
        gen_op_movl_EDX_T1,
258 367e86e8 bellard
        gen_op_movl_EBX_T1,
259 367e86e8 bellard
        gen_op_movl_ESP_T1,
260 367e86e8 bellard
        gen_op_movl_EBP_T1,
261 367e86e8 bellard
        gen_op_movl_ESI_T1,
262 367e86e8 bellard
        gen_op_movl_EDI_T1,
263 367e86e8 bellard
    },
264 367e86e8 bellard
};
265 367e86e8 bellard
266 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
267 367e86e8 bellard
    [0] = {
268 367e86e8 bellard
        gen_op_movw_EAX_A0,
269 367e86e8 bellard
        gen_op_movw_ECX_A0,
270 367e86e8 bellard
        gen_op_movw_EDX_A0,
271 367e86e8 bellard
        gen_op_movw_EBX_A0,
272 367e86e8 bellard
        gen_op_movw_ESP_A0,
273 367e86e8 bellard
        gen_op_movw_EBP_A0,
274 367e86e8 bellard
        gen_op_movw_ESI_A0,
275 367e86e8 bellard
        gen_op_movw_EDI_A0,
276 367e86e8 bellard
    },
277 367e86e8 bellard
    [1] = {
278 367e86e8 bellard
        gen_op_movl_EAX_A0,
279 367e86e8 bellard
        gen_op_movl_ECX_A0,
280 367e86e8 bellard
        gen_op_movl_EDX_A0,
281 367e86e8 bellard
        gen_op_movl_EBX_A0,
282 367e86e8 bellard
        gen_op_movl_ESP_A0,
283 367e86e8 bellard
        gen_op_movl_EBP_A0,
284 367e86e8 bellard
        gen_op_movl_ESI_A0,
285 367e86e8 bellard
        gen_op_movl_EDI_A0,
286 367e86e8 bellard
    },
287 367e86e8 bellard
};
288 367e86e8 bellard
289 367e86e8 bellard
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
290 367e86e8 bellard
{
291 367e86e8 bellard
    [OT_BYTE] = {
292 367e86e8 bellard
        {
293 367e86e8 bellard
            gen_op_movl_T0_EAX,
294 367e86e8 bellard
            gen_op_movl_T0_ECX,
295 367e86e8 bellard
            gen_op_movl_T0_EDX,
296 367e86e8 bellard
            gen_op_movl_T0_EBX,
297 367e86e8 bellard
            gen_op_movh_T0_EAX,
298 367e86e8 bellard
            gen_op_movh_T0_ECX,
299 367e86e8 bellard
            gen_op_movh_T0_EDX,
300 367e86e8 bellard
            gen_op_movh_T0_EBX,
301 367e86e8 bellard
        },
302 367e86e8 bellard
        {
303 367e86e8 bellard
            gen_op_movl_T1_EAX,
304 367e86e8 bellard
            gen_op_movl_T1_ECX,
305 367e86e8 bellard
            gen_op_movl_T1_EDX,
306 367e86e8 bellard
            gen_op_movl_T1_EBX,
307 367e86e8 bellard
            gen_op_movh_T1_EAX,
308 367e86e8 bellard
            gen_op_movh_T1_ECX,
309 367e86e8 bellard
            gen_op_movh_T1_EDX,
310 367e86e8 bellard
            gen_op_movh_T1_EBX,
311 367e86e8 bellard
        },
312 367e86e8 bellard
    },
313 367e86e8 bellard
    [OT_WORD] = {
314 367e86e8 bellard
        {
315 367e86e8 bellard
            gen_op_movl_T0_EAX,
316 367e86e8 bellard
            gen_op_movl_T0_ECX,
317 367e86e8 bellard
            gen_op_movl_T0_EDX,
318 367e86e8 bellard
            gen_op_movl_T0_EBX,
319 367e86e8 bellard
            gen_op_movl_T0_ESP,
320 367e86e8 bellard
            gen_op_movl_T0_EBP,
321 367e86e8 bellard
            gen_op_movl_T0_ESI,
322 367e86e8 bellard
            gen_op_movl_T0_EDI,
323 367e86e8 bellard
        },
324 367e86e8 bellard
        {
325 367e86e8 bellard
            gen_op_movl_T1_EAX,
326 367e86e8 bellard
            gen_op_movl_T1_ECX,
327 367e86e8 bellard
            gen_op_movl_T1_EDX,
328 367e86e8 bellard
            gen_op_movl_T1_EBX,
329 367e86e8 bellard
            gen_op_movl_T1_ESP,
330 367e86e8 bellard
            gen_op_movl_T1_EBP,
331 367e86e8 bellard
            gen_op_movl_T1_ESI,
332 367e86e8 bellard
            gen_op_movl_T1_EDI,
333 367e86e8 bellard
        },
334 367e86e8 bellard
    },
335 367e86e8 bellard
    [OT_LONG] = {
336 367e86e8 bellard
        {
337 367e86e8 bellard
            gen_op_movl_T0_EAX,
338 367e86e8 bellard
            gen_op_movl_T0_ECX,
339 367e86e8 bellard
            gen_op_movl_T0_EDX,
340 367e86e8 bellard
            gen_op_movl_T0_EBX,
341 367e86e8 bellard
            gen_op_movl_T0_ESP,
342 367e86e8 bellard
            gen_op_movl_T0_EBP,
343 367e86e8 bellard
            gen_op_movl_T0_ESI,
344 367e86e8 bellard
            gen_op_movl_T0_EDI,
345 367e86e8 bellard
        },
346 367e86e8 bellard
        {
347 367e86e8 bellard
            gen_op_movl_T1_EAX,
348 367e86e8 bellard
            gen_op_movl_T1_ECX,
349 367e86e8 bellard
            gen_op_movl_T1_EDX,
350 367e86e8 bellard
            gen_op_movl_T1_EBX,
351 367e86e8 bellard
            gen_op_movl_T1_ESP,
352 367e86e8 bellard
            gen_op_movl_T1_EBP,
353 367e86e8 bellard
            gen_op_movl_T1_ESI,
354 367e86e8 bellard
            gen_op_movl_T1_EDI,
355 367e86e8 bellard
        },
356 367e86e8 bellard
    },
357 367e86e8 bellard
};
358 367e86e8 bellard
359 367e86e8 bellard
static GenOpFunc *gen_op_movl_A0_reg[8] = {
360 367e86e8 bellard
    gen_op_movl_A0_EAX,
361 367e86e8 bellard
    gen_op_movl_A0_ECX,
362 367e86e8 bellard
    gen_op_movl_A0_EDX,
363 367e86e8 bellard
    gen_op_movl_A0_EBX,
364 367e86e8 bellard
    gen_op_movl_A0_ESP,
365 367e86e8 bellard
    gen_op_movl_A0_EBP,
366 367e86e8 bellard
    gen_op_movl_A0_ESI,
367 367e86e8 bellard
    gen_op_movl_A0_EDI,
368 367e86e8 bellard
};
369 367e86e8 bellard
370 367e86e8 bellard
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
371 367e86e8 bellard
    [0] = {
372 367e86e8 bellard
        gen_op_addl_A0_EAX,
373 367e86e8 bellard
        gen_op_addl_A0_ECX,
374 367e86e8 bellard
        gen_op_addl_A0_EDX,
375 367e86e8 bellard
        gen_op_addl_A0_EBX,
376 367e86e8 bellard
        gen_op_addl_A0_ESP,
377 367e86e8 bellard
        gen_op_addl_A0_EBP,
378 367e86e8 bellard
        gen_op_addl_A0_ESI,
379 367e86e8 bellard
        gen_op_addl_A0_EDI,
380 367e86e8 bellard
    },
381 367e86e8 bellard
    [1] = {
382 367e86e8 bellard
        gen_op_addl_A0_EAX_s1,
383 367e86e8 bellard
        gen_op_addl_A0_ECX_s1,
384 367e86e8 bellard
        gen_op_addl_A0_EDX_s1,
385 367e86e8 bellard
        gen_op_addl_A0_EBX_s1,
386 367e86e8 bellard
        gen_op_addl_A0_ESP_s1,
387 367e86e8 bellard
        gen_op_addl_A0_EBP_s1,
388 367e86e8 bellard
        gen_op_addl_A0_ESI_s1,
389 367e86e8 bellard
        gen_op_addl_A0_EDI_s1,
390 367e86e8 bellard
    },
391 367e86e8 bellard
    [2] = {
392 367e86e8 bellard
        gen_op_addl_A0_EAX_s2,
393 367e86e8 bellard
        gen_op_addl_A0_ECX_s2,
394 367e86e8 bellard
        gen_op_addl_A0_EDX_s2,
395 367e86e8 bellard
        gen_op_addl_A0_EBX_s2,
396 367e86e8 bellard
        gen_op_addl_A0_ESP_s2,
397 367e86e8 bellard
        gen_op_addl_A0_EBP_s2,
398 367e86e8 bellard
        gen_op_addl_A0_ESI_s2,
399 367e86e8 bellard
        gen_op_addl_A0_EDI_s2,
400 367e86e8 bellard
    },
401 367e86e8 bellard
    [3] = {
402 367e86e8 bellard
        gen_op_addl_A0_EAX_s3,
403 367e86e8 bellard
        gen_op_addl_A0_ECX_s3,
404 367e86e8 bellard
        gen_op_addl_A0_EDX_s3,
405 367e86e8 bellard
        gen_op_addl_A0_EBX_s3,
406 367e86e8 bellard
        gen_op_addl_A0_ESP_s3,
407 367e86e8 bellard
        gen_op_addl_A0_EBP_s3,
408 367e86e8 bellard
        gen_op_addl_A0_ESI_s3,
409 367e86e8 bellard
        gen_op_addl_A0_EDI_s3,
410 367e86e8 bellard
    },
411 367e86e8 bellard
};
412 367e86e8 bellard
413 5dd9488c bellard
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
414 5dd9488c bellard
    [0] = {
415 5dd9488c bellard
        gen_op_cmovw_EAX_T1_T0,
416 5dd9488c bellard
        gen_op_cmovw_ECX_T1_T0,
417 5dd9488c bellard
        gen_op_cmovw_EDX_T1_T0,
418 5dd9488c bellard
        gen_op_cmovw_EBX_T1_T0,
419 5dd9488c bellard
        gen_op_cmovw_ESP_T1_T0,
420 5dd9488c bellard
        gen_op_cmovw_EBP_T1_T0,
421 5dd9488c bellard
        gen_op_cmovw_ESI_T1_T0,
422 5dd9488c bellard
        gen_op_cmovw_EDI_T1_T0,
423 5dd9488c bellard
    },
424 5dd9488c bellard
    [1] = {
425 5dd9488c bellard
        gen_op_cmovl_EAX_T1_T0,
426 5dd9488c bellard
        gen_op_cmovl_ECX_T1_T0,
427 5dd9488c bellard
        gen_op_cmovl_EDX_T1_T0,
428 5dd9488c bellard
        gen_op_cmovl_EBX_T1_T0,
429 5dd9488c bellard
        gen_op_cmovl_ESP_T1_T0,
430 5dd9488c bellard
        gen_op_cmovl_EBP_T1_T0,
431 5dd9488c bellard
        gen_op_cmovl_ESI_T1_T0,
432 5dd9488c bellard
        gen_op_cmovl_EDI_T1_T0,
433 5dd9488c bellard
    },
434 5dd9488c bellard
};
435 5dd9488c bellard
436 367e86e8 bellard
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
437 367e86e8 bellard
    gen_op_addl_T0_T1_cc,
438 367e86e8 bellard
    gen_op_orl_T0_T1_cc,
439 4b74fe1f bellard
    NULL,
440 4b74fe1f bellard
    NULL,
441 367e86e8 bellard
    gen_op_andl_T0_T1_cc,
442 367e86e8 bellard
    gen_op_subl_T0_T1_cc,
443 367e86e8 bellard
    gen_op_xorl_T0_T1_cc,
444 367e86e8 bellard
    gen_op_cmpl_T0_T1_cc,
445 367e86e8 bellard
};
446 367e86e8 bellard
447 4b74fe1f bellard
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
448 4b74fe1f bellard
    [OT_BYTE] = {
449 4b74fe1f bellard
        gen_op_adcb_T0_T1_cc,
450 4b74fe1f bellard
        gen_op_sbbb_T0_T1_cc,
451 4b74fe1f bellard
    },
452 4b74fe1f bellard
    [OT_WORD] = {
453 4b74fe1f bellard
        gen_op_adcw_T0_T1_cc,
454 4b74fe1f bellard
        gen_op_sbbw_T0_T1_cc,
455 4b74fe1f bellard
    },
456 4b74fe1f bellard
    [OT_LONG] = {
457 4b74fe1f bellard
        gen_op_adcl_T0_T1_cc,
458 4b74fe1f bellard
        gen_op_sbbl_T0_T1_cc,
459 4b74fe1f bellard
    },
460 4b74fe1f bellard
};
461 4b74fe1f bellard
462 367e86e8 bellard
static const int cc_op_arithb[8] = {
463 367e86e8 bellard
    CC_OP_ADDB,
464 367e86e8 bellard
    CC_OP_LOGICB,
465 367e86e8 bellard
    CC_OP_ADDB,
466 367e86e8 bellard
    CC_OP_SUBB,
467 367e86e8 bellard
    CC_OP_LOGICB,
468 367e86e8 bellard
    CC_OP_SUBB,
469 367e86e8 bellard
    CC_OP_LOGICB,
470 367e86e8 bellard
    CC_OP_SUBB,
471 367e86e8 bellard
};
472 367e86e8 bellard
473 1a9353d2 bellard
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
474 1a9353d2 bellard
    gen_op_cmpxchgb_T0_T1_EAX_cc,
475 1a9353d2 bellard
    gen_op_cmpxchgw_T0_T1_EAX_cc,
476 1a9353d2 bellard
    gen_op_cmpxchgl_T0_T1_EAX_cc,
477 1a9353d2 bellard
};
478 1a9353d2 bellard
479 367e86e8 bellard
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
480 367e86e8 bellard
    [OT_BYTE] = {
481 367e86e8 bellard
        gen_op_rolb_T0_T1_cc,
482 367e86e8 bellard
        gen_op_rorb_T0_T1_cc,
483 367e86e8 bellard
        gen_op_rclb_T0_T1_cc,
484 367e86e8 bellard
        gen_op_rcrb_T0_T1_cc,
485 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
486 367e86e8 bellard
        gen_op_shrb_T0_T1_cc,
487 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
488 367e86e8 bellard
        gen_op_sarb_T0_T1_cc,
489 367e86e8 bellard
    },
490 367e86e8 bellard
    [OT_WORD] = {
491 367e86e8 bellard
        gen_op_rolw_T0_T1_cc,
492 367e86e8 bellard
        gen_op_rorw_T0_T1_cc,
493 367e86e8 bellard
        gen_op_rclw_T0_T1_cc,
494 367e86e8 bellard
        gen_op_rcrw_T0_T1_cc,
495 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
496 367e86e8 bellard
        gen_op_shrw_T0_T1_cc,
497 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
498 367e86e8 bellard
        gen_op_sarw_T0_T1_cc,
499 367e86e8 bellard
    },
500 367e86e8 bellard
    [OT_LONG] = {
501 367e86e8 bellard
        gen_op_roll_T0_T1_cc,
502 367e86e8 bellard
        gen_op_rorl_T0_T1_cc,
503 367e86e8 bellard
        gen_op_rcll_T0_T1_cc,
504 367e86e8 bellard
        gen_op_rcrl_T0_T1_cc,
505 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
506 367e86e8 bellard
        gen_op_shrl_T0_T1_cc,
507 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
508 367e86e8 bellard
        gen_op_sarl_T0_T1_cc,
509 367e86e8 bellard
    },
510 367e86e8 bellard
};
511 367e86e8 bellard
512 d57c4e01 bellard
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
513 d57c4e01 bellard
    [0] = {
514 d57c4e01 bellard
        gen_op_shldw_T0_T1_im_cc,
515 d57c4e01 bellard
        gen_op_shrdw_T0_T1_im_cc,
516 d57c4e01 bellard
    },
517 d57c4e01 bellard
    [1] = {
518 d57c4e01 bellard
        gen_op_shldl_T0_T1_im_cc,
519 d57c4e01 bellard
        gen_op_shrdl_T0_T1_im_cc,
520 d57c4e01 bellard
    },
521 d57c4e01 bellard
};
522 d57c4e01 bellard
523 d57c4e01 bellard
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
524 d57c4e01 bellard
    [0] = {
525 d57c4e01 bellard
        gen_op_shldw_T0_T1_ECX_cc,
526 d57c4e01 bellard
        gen_op_shrdw_T0_T1_ECX_cc,
527 d57c4e01 bellard
    },
528 d57c4e01 bellard
    [1] = {
529 d57c4e01 bellard
        gen_op_shldl_T0_T1_ECX_cc,
530 d57c4e01 bellard
        gen_op_shrdl_T0_T1_ECX_cc,
531 d57c4e01 bellard
    },
532 d57c4e01 bellard
};
533 d57c4e01 bellard
534 4b74fe1f bellard
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
535 4b74fe1f bellard
    [0] = {
536 4b74fe1f bellard
        gen_op_btw_T0_T1_cc,
537 4b74fe1f bellard
        gen_op_btsw_T0_T1_cc,
538 4b74fe1f bellard
        gen_op_btrw_T0_T1_cc,
539 4b74fe1f bellard
        gen_op_btcw_T0_T1_cc,
540 4b74fe1f bellard
    },
541 4b74fe1f bellard
    [1] = {
542 4b74fe1f bellard
        gen_op_btl_T0_T1_cc,
543 4b74fe1f bellard
        gen_op_btsl_T0_T1_cc,
544 4b74fe1f bellard
        gen_op_btrl_T0_T1_cc,
545 4b74fe1f bellard
        gen_op_btcl_T0_T1_cc,
546 4b74fe1f bellard
    },
547 4b74fe1f bellard
};
548 4b74fe1f bellard
549 77f8dd5a bellard
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
550 77f8dd5a bellard
    [0] = {
551 77f8dd5a bellard
        gen_op_bsfw_T0_cc,
552 77f8dd5a bellard
        gen_op_bsrw_T0_cc,
553 77f8dd5a bellard
    },
554 77f8dd5a bellard
    [1] = {
555 77f8dd5a bellard
        gen_op_bsfl_T0_cc,
556 77f8dd5a bellard
        gen_op_bsrl_T0_cc,
557 77f8dd5a bellard
    },
558 77f8dd5a bellard
};
559 77f8dd5a bellard
560 367e86e8 bellard
static GenOpFunc *gen_op_lds_T0_A0[3] = {
561 367e86e8 bellard
    gen_op_ldsb_T0_A0,
562 367e86e8 bellard
    gen_op_ldsw_T0_A0,
563 367e86e8 bellard
};
564 367e86e8 bellard
565 367e86e8 bellard
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
566 367e86e8 bellard
    gen_op_ldub_T0_A0,
567 367e86e8 bellard
    gen_op_lduw_T0_A0,
568 367e86e8 bellard
};
569 367e86e8 bellard
570 367e86e8 bellard
/* sign does not matter */
571 367e86e8 bellard
static GenOpFunc *gen_op_ld_T0_A0[3] = {
572 367e86e8 bellard
    gen_op_ldub_T0_A0,
573 367e86e8 bellard
    gen_op_lduw_T0_A0,
574 367e86e8 bellard
    gen_op_ldl_T0_A0,
575 367e86e8 bellard
};
576 367e86e8 bellard
577 367e86e8 bellard
static GenOpFunc *gen_op_ld_T1_A0[3] = {
578 367e86e8 bellard
    gen_op_ldub_T1_A0,
579 367e86e8 bellard
    gen_op_lduw_T1_A0,
580 367e86e8 bellard
    gen_op_ldl_T1_A0,
581 367e86e8 bellard
};
582 367e86e8 bellard
583 367e86e8 bellard
static GenOpFunc *gen_op_st_T0_A0[3] = {
584 367e86e8 bellard
    gen_op_stb_T0_A0,
585 367e86e8 bellard
    gen_op_stw_T0_A0,
586 367e86e8 bellard
    gen_op_stl_T0_A0,
587 367e86e8 bellard
};
588 367e86e8 bellard
589 9c605cb1 bellard
/* the _a32 and _a16 string operations use A0 as the base register. */
590 9c605cb1 bellard
591 9c605cb1 bellard
#define STRINGOP(x) \
592 9c605cb1 bellard
    gen_op_ ## x ## b_fast, \
593 9c605cb1 bellard
    gen_op_ ## x ## w_fast, \
594 9c605cb1 bellard
    gen_op_ ## x ## l_fast, \
595 9c605cb1 bellard
    gen_op_ ## x ## b_a32, \
596 9c605cb1 bellard
    gen_op_ ## x ## w_a32, \
597 9c605cb1 bellard
    gen_op_ ## x ## l_a32, \
598 9c605cb1 bellard
    gen_op_ ## x ## b_a16, \
599 9c605cb1 bellard
    gen_op_ ## x ## w_a16, \
600 9c605cb1 bellard
    gen_op_ ## x ## l_a16,
601 9c605cb1 bellard
     
602 9c605cb1 bellard
static GenOpFunc *gen_op_movs[9 * 2] = {
603 9c605cb1 bellard
    STRINGOP(movs)
604 9c605cb1 bellard
    STRINGOP(rep_movs)
605 367e86e8 bellard
};
606 367e86e8 bellard
607 9c605cb1 bellard
static GenOpFunc *gen_op_stos[9 * 2] = {
608 9c605cb1 bellard
    STRINGOP(stos)
609 9c605cb1 bellard
    STRINGOP(rep_stos)
610 367e86e8 bellard
};
611 367e86e8 bellard
612 9c605cb1 bellard
static GenOpFunc *gen_op_lods[9 * 2] = {
613 9c605cb1 bellard
    STRINGOP(lods)
614 9c605cb1 bellard
    STRINGOP(rep_lods)
615 367e86e8 bellard
};
616 367e86e8 bellard
617 9c605cb1 bellard
static GenOpFunc *gen_op_scas[9 * 3] = {
618 9c605cb1 bellard
    STRINGOP(scas)
619 9c605cb1 bellard
    STRINGOP(repz_scas)
620 9c605cb1 bellard
    STRINGOP(repnz_scas)
621 367e86e8 bellard
};
622 367e86e8 bellard
623 9c605cb1 bellard
static GenOpFunc *gen_op_cmps[9 * 3] = {
624 9c605cb1 bellard
    STRINGOP(cmps)
625 9c605cb1 bellard
    STRINGOP(repz_cmps)
626 9c605cb1 bellard
    STRINGOP(repnz_cmps)
627 367e86e8 bellard
};
628 367e86e8 bellard
629 9c605cb1 bellard
static GenOpFunc *gen_op_ins[9 * 2] = {
630 9c605cb1 bellard
    STRINGOP(ins)
631 9c605cb1 bellard
    STRINGOP(rep_ins)
632 367e86e8 bellard
};
633 367e86e8 bellard
634 367e86e8 bellard
635 9c605cb1 bellard
static GenOpFunc *gen_op_outs[9 * 2] = {
636 9c605cb1 bellard
    STRINGOP(outs)
637 9c605cb1 bellard
    STRINGOP(rep_outs)
638 367e86e8 bellard
};
639 367e86e8 bellard
640 9c605cb1 bellard
641 9c605cb1 bellard
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
642 9c605cb1 bellard
{
643 9c605cb1 bellard
    int index, override;
644 9c605cb1 bellard
645 9c605cb1 bellard
    override = s->override;
646 9c605cb1 bellard
    if (s->aflag) {
647 9c605cb1 bellard
        /* 32 bit address */
648 9c605cb1 bellard
        if (s->addseg && override < 0)
649 9c605cb1 bellard
            override = R_DS;
650 9c605cb1 bellard
        if (override >= 0) {
651 9c605cb1 bellard
            gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
652 9c605cb1 bellard
            index = 3 + ot;
653 9c605cb1 bellard
        } else {
654 9c605cb1 bellard
            index = ot;
655 9c605cb1 bellard
        }
656 9c605cb1 bellard
    } else {
657 9c605cb1 bellard
        if (override < 0)
658 9c605cb1 bellard
            override = R_DS;
659 9c605cb1 bellard
        gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
660 9c605cb1 bellard
        /* 16 address, always override */
661 9c605cb1 bellard
        index = 6 + ot;
662 9c605cb1 bellard
    }
663 9c605cb1 bellard
    func[index]();
664 9c605cb1 bellard
}
665 9c605cb1 bellard
666 9c605cb1 bellard
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
667 9c605cb1 bellard
{
668 9c605cb1 bellard
    int index;
669 9c605cb1 bellard
            
670 9c605cb1 bellard
    if (s->aflag) {
671 9c605cb1 bellard
        if (s->addseg) {
672 9c605cb1 bellard
            index = 3 + ot;
673 9c605cb1 bellard
        } else {
674 9c605cb1 bellard
            index = ot;
675 9c605cb1 bellard
        }
676 9c605cb1 bellard
    } else {
677 9c605cb1 bellard
        index = 6 + ot;
678 9c605cb1 bellard
    }
679 9c605cb1 bellard
    func[index]();
680 9c605cb1 bellard
}
681 9c605cb1 bellard
682 9c605cb1 bellard
683 ba1c6e37 bellard
static GenOpFunc *gen_op_in[3] = {
684 ba1c6e37 bellard
    gen_op_inb_T0_T1,
685 ba1c6e37 bellard
    gen_op_inw_T0_T1,
686 ba1c6e37 bellard
    gen_op_inl_T0_T1,
687 ba1c6e37 bellard
};
688 ba1c6e37 bellard
689 ba1c6e37 bellard
static GenOpFunc *gen_op_out[3] = {
690 ba1c6e37 bellard
    gen_op_outb_T0_T1,
691 ba1c6e37 bellard
    gen_op_outw_T0_T1,
692 ba1c6e37 bellard
    gen_op_outl_T0_T1,
693 ba1c6e37 bellard
};
694 ba1c6e37 bellard
695 367e86e8 bellard
enum {
696 367e86e8 bellard
    JCC_O,
697 367e86e8 bellard
    JCC_B,
698 367e86e8 bellard
    JCC_Z,
699 367e86e8 bellard
    JCC_BE,
700 367e86e8 bellard
    JCC_S,
701 367e86e8 bellard
    JCC_P,
702 367e86e8 bellard
    JCC_L,
703 367e86e8 bellard
    JCC_LE,
704 367e86e8 bellard
};
705 367e86e8 bellard
706 367e86e8 bellard
static GenOpFunc2 *gen_jcc_slow[8] = {
707 367e86e8 bellard
    gen_op_jo_cc,
708 367e86e8 bellard
    gen_op_jb_cc,
709 367e86e8 bellard
    gen_op_jz_cc,
710 367e86e8 bellard
    gen_op_jbe_cc,
711 367e86e8 bellard
    gen_op_js_cc,
712 367e86e8 bellard
    gen_op_jp_cc,
713 367e86e8 bellard
    gen_op_jl_cc,
714 367e86e8 bellard
    gen_op_jle_cc,
715 367e86e8 bellard
};
716 367e86e8 bellard
    
717 367e86e8 bellard
static GenOpFunc2 *gen_jcc_sub[3][8] = {
718 367e86e8 bellard
    [OT_BYTE] = {
719 367e86e8 bellard
        NULL,
720 367e86e8 bellard
        gen_op_jb_subb,
721 367e86e8 bellard
        gen_op_jz_subb,
722 367e86e8 bellard
        gen_op_jbe_subb,
723 367e86e8 bellard
        gen_op_js_subb,
724 367e86e8 bellard
        NULL,
725 367e86e8 bellard
        gen_op_jl_subb,
726 367e86e8 bellard
        gen_op_jle_subb,
727 367e86e8 bellard
    },
728 367e86e8 bellard
    [OT_WORD] = {
729 367e86e8 bellard
        NULL,
730 367e86e8 bellard
        gen_op_jb_subw,
731 367e86e8 bellard
        gen_op_jz_subw,
732 367e86e8 bellard
        gen_op_jbe_subw,
733 367e86e8 bellard
        gen_op_js_subw,
734 367e86e8 bellard
        NULL,
735 367e86e8 bellard
        gen_op_jl_subw,
736 367e86e8 bellard
        gen_op_jle_subw,
737 367e86e8 bellard
    },
738 367e86e8 bellard
    [OT_LONG] = {
739 367e86e8 bellard
        NULL,
740 367e86e8 bellard
        gen_op_jb_subl,
741 367e86e8 bellard
        gen_op_jz_subl,
742 367e86e8 bellard
        gen_op_jbe_subl,
743 367e86e8 bellard
        gen_op_js_subl,
744 367e86e8 bellard
        NULL,
745 367e86e8 bellard
        gen_op_jl_subl,
746 367e86e8 bellard
        gen_op_jle_subl,
747 367e86e8 bellard
    },
748 367e86e8 bellard
};
749 1a9353d2 bellard
static GenOpFunc2 *gen_op_loop[2][4] = {
750 1a9353d2 bellard
    [0] = {
751 1a9353d2 bellard
        gen_op_loopnzw,
752 1a9353d2 bellard
        gen_op_loopzw,
753 1a9353d2 bellard
        gen_op_loopw,
754 1a9353d2 bellard
        gen_op_jecxzw,
755 1a9353d2 bellard
    },
756 1a9353d2 bellard
    [1] = {
757 1a9353d2 bellard
        gen_op_loopnzl,
758 1a9353d2 bellard
        gen_op_loopzl,
759 1a9353d2 bellard
        gen_op_loopl,
760 1a9353d2 bellard
        gen_op_jecxzl,
761 1a9353d2 bellard
    },
762 1a9353d2 bellard
};
763 367e86e8 bellard
764 367e86e8 bellard
static GenOpFunc *gen_setcc_slow[8] = {
765 367e86e8 bellard
    gen_op_seto_T0_cc,
766 367e86e8 bellard
    gen_op_setb_T0_cc,
767 367e86e8 bellard
    gen_op_setz_T0_cc,
768 367e86e8 bellard
    gen_op_setbe_T0_cc,
769 367e86e8 bellard
    gen_op_sets_T0_cc,
770 367e86e8 bellard
    gen_op_setp_T0_cc,
771 367e86e8 bellard
    gen_op_setl_T0_cc,
772 367e86e8 bellard
    gen_op_setle_T0_cc,
773 367e86e8 bellard
};
774 367e86e8 bellard
775 367e86e8 bellard
static GenOpFunc *gen_setcc_sub[3][8] = {
776 367e86e8 bellard
    [OT_BYTE] = {
777 367e86e8 bellard
        NULL,
778 367e86e8 bellard
        gen_op_setb_T0_subb,
779 367e86e8 bellard
        gen_op_setz_T0_subb,
780 367e86e8 bellard
        gen_op_setbe_T0_subb,
781 367e86e8 bellard
        gen_op_sets_T0_subb,
782 367e86e8 bellard
        NULL,
783 367e86e8 bellard
        gen_op_setl_T0_subb,
784 367e86e8 bellard
        gen_op_setle_T0_subb,
785 367e86e8 bellard
    },
786 367e86e8 bellard
    [OT_WORD] = {
787 367e86e8 bellard
        NULL,
788 367e86e8 bellard
        gen_op_setb_T0_subw,
789 367e86e8 bellard
        gen_op_setz_T0_subw,
790 367e86e8 bellard
        gen_op_setbe_T0_subw,
791 367e86e8 bellard
        gen_op_sets_T0_subw,
792 367e86e8 bellard
        NULL,
793 367e86e8 bellard
        gen_op_setl_T0_subw,
794 367e86e8 bellard
        gen_op_setle_T0_subw,
795 367e86e8 bellard
    },
796 367e86e8 bellard
    [OT_LONG] = {
797 367e86e8 bellard
        NULL,
798 367e86e8 bellard
        gen_op_setb_T0_subl,
799 367e86e8 bellard
        gen_op_setz_T0_subl,
800 367e86e8 bellard
        gen_op_setbe_T0_subl,
801 367e86e8 bellard
        gen_op_sets_T0_subl,
802 367e86e8 bellard
        NULL,
803 367e86e8 bellard
        gen_op_setl_T0_subl,
804 367e86e8 bellard
        gen_op_setle_T0_subl,
805 367e86e8 bellard
    },
806 367e86e8 bellard
};
807 367e86e8 bellard
808 927f621e bellard
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
809 927f621e bellard
    gen_op_fadd_ST0_FT0,
810 927f621e bellard
    gen_op_fmul_ST0_FT0,
811 927f621e bellard
    gen_op_fcom_ST0_FT0,
812 927f621e bellard
    gen_op_fcom_ST0_FT0,
813 927f621e bellard
    gen_op_fsub_ST0_FT0,
814 927f621e bellard
    gen_op_fsubr_ST0_FT0,
815 927f621e bellard
    gen_op_fdiv_ST0_FT0,
816 927f621e bellard
    gen_op_fdivr_ST0_FT0,
817 927f621e bellard
};
818 927f621e bellard
819 77f8dd5a bellard
/* NOTE the exception in "r" op ordering */
820 927f621e bellard
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
821 927f621e bellard
    gen_op_fadd_STN_ST0,
822 927f621e bellard
    gen_op_fmul_STN_ST0,
823 927f621e bellard
    NULL,
824 927f621e bellard
    NULL,
825 927f621e bellard
    gen_op_fsubr_STN_ST0,
826 77f8dd5a bellard
    gen_op_fsub_STN_ST0,
827 927f621e bellard
    gen_op_fdivr_STN_ST0,
828 77f8dd5a bellard
    gen_op_fdiv_STN_ST0,
829 927f621e bellard
};
830 927f621e bellard
831 367e86e8 bellard
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
832 367e86e8 bellard
{
833 367e86e8 bellard
    if (d != OR_TMP0)
834 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
835 367e86e8 bellard
    if (s != OR_TMP1)
836 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
837 4b74fe1f bellard
    if (op == OP_ADCL || op == OP_SBBL) {
838 4b74fe1f bellard
        if (s1->cc_op != CC_OP_DYNAMIC)
839 4b74fe1f bellard
            gen_op_set_cc_op(s1->cc_op);
840 4b74fe1f bellard
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
841 4b74fe1f bellard
        s1->cc_op = CC_OP_DYNAMIC;
842 4b74fe1f bellard
    } else {
843 4b74fe1f bellard
        gen_op_arith_T0_T1_cc[op]();
844 4b74fe1f bellard
        s1->cc_op = cc_op_arithb[op] + ot;
845 4b74fe1f bellard
    }
846 367e86e8 bellard
    if (d != OR_TMP0 && op != OP_CMPL)
847 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
848 367e86e8 bellard
}
849 367e86e8 bellard
850 367e86e8 bellard
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
851 367e86e8 bellard
{
852 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
853 4b74fe1f bellard
    gen_op(s1, op, ot, d, OR_TMP1);
854 367e86e8 bellard
}
855 367e86e8 bellard
856 367e86e8 bellard
static void gen_inc(DisasContext *s1, int ot, int d, int c)
857 367e86e8 bellard
{
858 367e86e8 bellard
    if (d != OR_TMP0)
859 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
860 367e86e8 bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
861 367e86e8 bellard
        gen_op_set_cc_op(s1->cc_op);
862 4b74fe1f bellard
    if (c > 0) {
863 367e86e8 bellard
        gen_op_incl_T0_cc();
864 4b74fe1f bellard
        s1->cc_op = CC_OP_INCB + ot;
865 4b74fe1f bellard
    } else {
866 367e86e8 bellard
        gen_op_decl_T0_cc();
867 4b74fe1f bellard
        s1->cc_op = CC_OP_DECB + ot;
868 4b74fe1f bellard
    }
869 367e86e8 bellard
    if (d != OR_TMP0)
870 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
871 367e86e8 bellard
}
872 367e86e8 bellard
873 367e86e8 bellard
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
874 367e86e8 bellard
{
875 367e86e8 bellard
    if (d != OR_TMP0)
876 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
877 367e86e8 bellard
    if (s != OR_TMP1)
878 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
879 4b74fe1f bellard
    /* for zero counts, flags are not updated, so must do it dynamically */
880 4b74fe1f bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
881 4b74fe1f bellard
        gen_op_set_cc_op(s1->cc_op);
882 4b74fe1f bellard
883 4b74fe1f bellard
    gen_op_shift_T0_T1_cc[ot][op]();
884 4b74fe1f bellard
885 367e86e8 bellard
    if (d != OR_TMP0)
886 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
887 367e86e8 bellard
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
888 367e86e8 bellard
}
889 367e86e8 bellard
890 367e86e8 bellard
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
891 367e86e8 bellard
{
892 367e86e8 bellard
    /* currently not optimized */
893 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
894 367e86e8 bellard
    gen_shift(s1, op, ot, d, OR_TMP1);
895 367e86e8 bellard
}
896 367e86e8 bellard
897 367e86e8 bellard
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
898 367e86e8 bellard
{
899 367e86e8 bellard
    int havesib;
900 367e86e8 bellard
    int base, disp;
901 6dbad63e bellard
    int index;
902 6dbad63e bellard
    int scale;
903 6dbad63e bellard
    int opreg;
904 6dbad63e bellard
    int mod, rm, code, override, must_add_seg;
905 6dbad63e bellard
906 9c605cb1 bellard
    override = s->override;
907 6dbad63e bellard
    must_add_seg = s->addseg;
908 9c605cb1 bellard
    if (override >= 0)
909 6dbad63e bellard
        must_add_seg = 1;
910 367e86e8 bellard
    mod = (modrm >> 6) & 3;
911 367e86e8 bellard
    rm = modrm & 7;
912 367e86e8 bellard
913 367e86e8 bellard
    if (s->aflag) {
914 367e86e8 bellard
915 367e86e8 bellard
        havesib = 0;
916 367e86e8 bellard
        base = rm;
917 6dbad63e bellard
        index = 0;
918 6dbad63e bellard
        scale = 0;
919 367e86e8 bellard
        
920 367e86e8 bellard
        if (base == 4) {
921 367e86e8 bellard
            havesib = 1;
922 367e86e8 bellard
            code = ldub(s->pc++);
923 367e86e8 bellard
            scale = (code >> 6) & 3;
924 367e86e8 bellard
            index = (code >> 3) & 7;
925 367e86e8 bellard
            base = code & 7;
926 367e86e8 bellard
        }
927 367e86e8 bellard
928 367e86e8 bellard
        switch (mod) {
929 367e86e8 bellard
        case 0:
930 367e86e8 bellard
            if (base == 5) {
931 6dbad63e bellard
                base = -1;
932 367e86e8 bellard
                disp = ldl(s->pc);
933 367e86e8 bellard
                s->pc += 4;
934 367e86e8 bellard
            } else {
935 367e86e8 bellard
                disp = 0;
936 367e86e8 bellard
            }
937 367e86e8 bellard
            break;
938 367e86e8 bellard
        case 1:
939 367e86e8 bellard
            disp = (int8_t)ldub(s->pc++);
940 367e86e8 bellard
            break;
941 367e86e8 bellard
        default:
942 367e86e8 bellard
        case 2:
943 367e86e8 bellard
            disp = ldl(s->pc);
944 367e86e8 bellard
            s->pc += 4;
945 367e86e8 bellard
            break;
946 367e86e8 bellard
        }
947 6dbad63e bellard
        
948 6dbad63e bellard
        if (base >= 0) {
949 6dbad63e bellard
            gen_op_movl_A0_reg[base]();
950 6dbad63e bellard
            if (disp != 0)
951 6dbad63e bellard
                gen_op_addl_A0_im(disp);
952 367e86e8 bellard
        } else {
953 6dbad63e bellard
            gen_op_movl_A0_im(disp);
954 6dbad63e bellard
        }
955 6dbad63e bellard
        if (havesib && (index != 4 || scale != 0)) {
956 6dbad63e bellard
            gen_op_addl_A0_reg_sN[scale][index]();
957 6dbad63e bellard
        }
958 6dbad63e bellard
        if (must_add_seg) {
959 6dbad63e bellard
            if (override < 0) {
960 6dbad63e bellard
                if (base == R_EBP || base == R_ESP)
961 6dbad63e bellard
                    override = R_SS;
962 6dbad63e bellard
                else
963 6dbad63e bellard
                    override = R_DS;
964 367e86e8 bellard
            }
965 6dbad63e bellard
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
966 367e86e8 bellard
        }
967 367e86e8 bellard
    } else {
968 4b74fe1f bellard
        switch (mod) {
969 4b74fe1f bellard
        case 0:
970 4b74fe1f bellard
            if (rm == 6) {
971 4b74fe1f bellard
                disp = lduw(s->pc);
972 4b74fe1f bellard
                s->pc += 2;
973 4b74fe1f bellard
                gen_op_movl_A0_im(disp);
974 6dbad63e bellard
                rm = 0; /* avoid SS override */
975 4b74fe1f bellard
                goto no_rm;
976 4b74fe1f bellard
            } else {
977 4b74fe1f bellard
                disp = 0;
978 4b74fe1f bellard
            }
979 4b74fe1f bellard
            break;
980 4b74fe1f bellard
        case 1:
981 4b74fe1f bellard
            disp = (int8_t)ldub(s->pc++);
982 4b74fe1f bellard
            break;
983 4b74fe1f bellard
        default:
984 4b74fe1f bellard
        case 2:
985 4b74fe1f bellard
            disp = lduw(s->pc);
986 4b74fe1f bellard
            s->pc += 2;
987 4b74fe1f bellard
            break;
988 4b74fe1f bellard
        }
989 4b74fe1f bellard
        switch(rm) {
990 4b74fe1f bellard
        case 0:
991 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
992 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_ESI]();
993 4b74fe1f bellard
            break;
994 4b74fe1f bellard
        case 1:
995 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
996 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_EDI]();
997 4b74fe1f bellard
            break;
998 4b74fe1f bellard
        case 2:
999 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
1000 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1001 4b74fe1f bellard
            break;
1002 4b74fe1f bellard
        case 3:
1003 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
1004 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1005 4b74fe1f bellard
            break;
1006 4b74fe1f bellard
        case 4:
1007 4b74fe1f bellard
            gen_op_movl_A0_reg[R_ESI]();
1008 4b74fe1f bellard
            break;
1009 4b74fe1f bellard
        case 5:
1010 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EDI]();
1011 4b74fe1f bellard
            break;
1012 4b74fe1f bellard
        case 6:
1013 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
1014 4b74fe1f bellard
            break;
1015 4b74fe1f bellard
        default:
1016 4b74fe1f bellard
        case 7:
1017 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
1018 4b74fe1f bellard
            break;
1019 4b74fe1f bellard
        }
1020 4b74fe1f bellard
        if (disp != 0)
1021 4b74fe1f bellard
            gen_op_addl_A0_im(disp);
1022 4b74fe1f bellard
        gen_op_andl_A0_ffff();
1023 6dbad63e bellard
    no_rm:
1024 6dbad63e bellard
        if (must_add_seg) {
1025 6dbad63e bellard
            if (override < 0) {
1026 6dbad63e bellard
                if (rm == 2 || rm == 3 || rm == 6)
1027 6dbad63e bellard
                    override = R_SS;
1028 6dbad63e bellard
                else
1029 6dbad63e bellard
                    override = R_DS;
1030 6dbad63e bellard
            }
1031 6dbad63e bellard
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1032 6dbad63e bellard
        }
1033 367e86e8 bellard
    }
1034 6dbad63e bellard
1035 4b74fe1f bellard
    opreg = OR_A0;
1036 4b74fe1f bellard
    disp = 0;
1037 367e86e8 bellard
    *reg_ptr = opreg;
1038 367e86e8 bellard
    *offset_ptr = disp;
1039 367e86e8 bellard
}
1040 367e86e8 bellard
1041 367e86e8 bellard
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1042 367e86e8 bellard
   OR_TMP0 */
1043 367e86e8 bellard
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1044 367e86e8 bellard
{
1045 367e86e8 bellard
    int mod, rm, opreg, disp;
1046 367e86e8 bellard
1047 367e86e8 bellard
    mod = (modrm >> 6) & 3;
1048 367e86e8 bellard
    rm = modrm & 7;
1049 367e86e8 bellard
    if (mod == 3) {
1050 367e86e8 bellard
        if (is_store) {
1051 367e86e8 bellard
            if (reg != OR_TMP0)
1052 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
1053 367e86e8 bellard
            gen_op_mov_reg_T0[ot][rm]();
1054 367e86e8 bellard
        } else {
1055 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1056 367e86e8 bellard
            if (reg != OR_TMP0)
1057 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
1058 367e86e8 bellard
        }
1059 367e86e8 bellard
    } else {
1060 367e86e8 bellard
        gen_lea_modrm(s, modrm, &opreg, &disp);
1061 367e86e8 bellard
        if (is_store) {
1062 367e86e8 bellard
            if (reg != OR_TMP0)
1063 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
1064 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
1065 367e86e8 bellard
        } else {
1066 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1067 367e86e8 bellard
            if (reg != OR_TMP0)
1068 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
1069 367e86e8 bellard
        }
1070 367e86e8 bellard
    }
1071 367e86e8 bellard
}
1072 367e86e8 bellard
1073 367e86e8 bellard
static inline uint32_t insn_get(DisasContext *s, int ot)
1074 367e86e8 bellard
{
1075 367e86e8 bellard
    uint32_t ret;
1076 367e86e8 bellard
1077 367e86e8 bellard
    switch(ot) {
1078 367e86e8 bellard
    case OT_BYTE:
1079 367e86e8 bellard
        ret = ldub(s->pc);
1080 367e86e8 bellard
        s->pc++;
1081 367e86e8 bellard
        break;
1082 367e86e8 bellard
    case OT_WORD:
1083 367e86e8 bellard
        ret = lduw(s->pc);
1084 367e86e8 bellard
        s->pc += 2;
1085 367e86e8 bellard
        break;
1086 367e86e8 bellard
    default:
1087 367e86e8 bellard
    case OT_LONG:
1088 367e86e8 bellard
        ret = ldl(s->pc);
1089 367e86e8 bellard
        s->pc += 4;
1090 367e86e8 bellard
        break;
1091 367e86e8 bellard
    }
1092 367e86e8 bellard
    return ret;
1093 367e86e8 bellard
}
1094 367e86e8 bellard
1095 dab2ed99 bellard
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1096 367e86e8 bellard
{
1097 367e86e8 bellard
    int inv, jcc_op;
1098 367e86e8 bellard
    GenOpFunc2 *func;
1099 367e86e8 bellard
1100 367e86e8 bellard
    inv = b & 1;
1101 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
1102 367e86e8 bellard
    switch(s->cc_op) {
1103 367e86e8 bellard
        /* we optimize the cmp/jcc case */
1104 367e86e8 bellard
    case CC_OP_SUBB:
1105 367e86e8 bellard
    case CC_OP_SUBW:
1106 367e86e8 bellard
    case CC_OP_SUBL:
1107 367e86e8 bellard
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1108 367e86e8 bellard
        if (!func)
1109 367e86e8 bellard
            goto slow_jcc;
1110 367e86e8 bellard
        break;
1111 367e86e8 bellard
        
1112 367e86e8 bellard
        /* some jumps are easy to compute */
1113 367e86e8 bellard
    case CC_OP_ADDB:
1114 367e86e8 bellard
    case CC_OP_ADDW:
1115 367e86e8 bellard
    case CC_OP_ADDL:
1116 4b74fe1f bellard
    case CC_OP_ADCB:
1117 4b74fe1f bellard
    case CC_OP_ADCW:
1118 4b74fe1f bellard
    case CC_OP_ADCL:
1119 4b74fe1f bellard
    case CC_OP_SBBB:
1120 4b74fe1f bellard
    case CC_OP_SBBW:
1121 4b74fe1f bellard
    case CC_OP_SBBL:
1122 367e86e8 bellard
    case CC_OP_LOGICB:
1123 367e86e8 bellard
    case CC_OP_LOGICW:
1124 367e86e8 bellard
    case CC_OP_LOGICL:
1125 367e86e8 bellard
    case CC_OP_INCB:
1126 367e86e8 bellard
    case CC_OP_INCW:
1127 367e86e8 bellard
    case CC_OP_INCL:
1128 367e86e8 bellard
    case CC_OP_DECB:
1129 367e86e8 bellard
    case CC_OP_DECW:
1130 367e86e8 bellard
    case CC_OP_DECL:
1131 367e86e8 bellard
    case CC_OP_SHLB:
1132 367e86e8 bellard
    case CC_OP_SHLW:
1133 367e86e8 bellard
    case CC_OP_SHLL:
1134 4b74fe1f bellard
    case CC_OP_SARB:
1135 4b74fe1f bellard
    case CC_OP_SARW:
1136 4b74fe1f bellard
    case CC_OP_SARL:
1137 367e86e8 bellard
        switch(jcc_op) {
1138 367e86e8 bellard
        case JCC_Z:
1139 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1140 367e86e8 bellard
            break;
1141 367e86e8 bellard
        case JCC_S:
1142 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1143 367e86e8 bellard
            break;
1144 367e86e8 bellard
        default:
1145 367e86e8 bellard
            goto slow_jcc;
1146 367e86e8 bellard
        }
1147 367e86e8 bellard
        break;
1148 367e86e8 bellard
    default:
1149 367e86e8 bellard
    slow_jcc:
1150 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1151 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
1152 367e86e8 bellard
        func = gen_jcc_slow[jcc_op];
1153 367e86e8 bellard
        break;
1154 367e86e8 bellard
    }
1155 367e86e8 bellard
    if (!inv) {
1156 dab2ed99 bellard
        func(val, next_eip);
1157 367e86e8 bellard
    } else {
1158 dab2ed99 bellard
        func(next_eip, val);
1159 367e86e8 bellard
    }
1160 367e86e8 bellard
}
1161 367e86e8 bellard
1162 367e86e8 bellard
static void gen_setcc(DisasContext *s, int b)
1163 367e86e8 bellard
{
1164 367e86e8 bellard
    int inv, jcc_op;
1165 367e86e8 bellard
    GenOpFunc *func;
1166 367e86e8 bellard
1167 367e86e8 bellard
    inv = b & 1;
1168 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
1169 367e86e8 bellard
    switch(s->cc_op) {
1170 367e86e8 bellard
        /* we optimize the cmp/jcc case */
1171 367e86e8 bellard
    case CC_OP_SUBB:
1172 367e86e8 bellard
    case CC_OP_SUBW:
1173 367e86e8 bellard
    case CC_OP_SUBL:
1174 367e86e8 bellard
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1175 367e86e8 bellard
        if (!func)
1176 367e86e8 bellard
            goto slow_jcc;
1177 367e86e8 bellard
        break;
1178 367e86e8 bellard
        
1179 367e86e8 bellard
        /* some jumps are easy to compute */
1180 367e86e8 bellard
    case CC_OP_ADDB:
1181 367e86e8 bellard
    case CC_OP_ADDW:
1182 367e86e8 bellard
    case CC_OP_ADDL:
1183 367e86e8 bellard
    case CC_OP_LOGICB:
1184 367e86e8 bellard
    case CC_OP_LOGICW:
1185 367e86e8 bellard
    case CC_OP_LOGICL:
1186 367e86e8 bellard
    case CC_OP_INCB:
1187 367e86e8 bellard
    case CC_OP_INCW:
1188 367e86e8 bellard
    case CC_OP_INCL:
1189 367e86e8 bellard
    case CC_OP_DECB:
1190 367e86e8 bellard
    case CC_OP_DECW:
1191 367e86e8 bellard
    case CC_OP_DECL:
1192 367e86e8 bellard
    case CC_OP_SHLB:
1193 367e86e8 bellard
    case CC_OP_SHLW:
1194 367e86e8 bellard
    case CC_OP_SHLL:
1195 367e86e8 bellard
        switch(jcc_op) {
1196 367e86e8 bellard
        case JCC_Z:
1197 1017ebe9 bellard
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1198 367e86e8 bellard
            break;
1199 367e86e8 bellard
        case JCC_S:
1200 1017ebe9 bellard
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1201 367e86e8 bellard
            break;
1202 367e86e8 bellard
        default:
1203 367e86e8 bellard
            goto slow_jcc;
1204 367e86e8 bellard
        }
1205 367e86e8 bellard
        break;
1206 367e86e8 bellard
    default:
1207 367e86e8 bellard
    slow_jcc:
1208 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1209 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
1210 367e86e8 bellard
        func = gen_setcc_slow[jcc_op];
1211 367e86e8 bellard
        break;
1212 367e86e8 bellard
    }
1213 367e86e8 bellard
    func();
1214 367e86e8 bellard
    if (inv) {
1215 367e86e8 bellard
        gen_op_xor_T0_1();
1216 367e86e8 bellard
    }
1217 367e86e8 bellard
}
1218 367e86e8 bellard
1219 6dbad63e bellard
/* move T0 to seg_reg and compute if the CPU state may change */
1220 dab2ed99 bellard
static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1221 6dbad63e bellard
{
1222 6dbad63e bellard
    gen_op_movl_seg_T0(seg_reg);
1223 6dbad63e bellard
    if (!s->addseg && seg_reg < R_FS)
1224 6dbad63e bellard
        s->is_jmp = 2; /* abort translation because the register may
1225 6dbad63e bellard
                          have a non zero base */
1226 6dbad63e bellard
}
1227 6dbad63e bellard
1228 dab2ed99 bellard
/* generate a push. It depends on ss32, addseg and dflag */
1229 dab2ed99 bellard
static void gen_push_T0(DisasContext *s)
1230 dab2ed99 bellard
{
1231 dab2ed99 bellard
    if (s->ss32) {
1232 dab2ed99 bellard
        if (!s->addseg) {
1233 dab2ed99 bellard
            if (s->dflag)
1234 dab2ed99 bellard
                gen_op_pushl_T0();
1235 dab2ed99 bellard
            else
1236 dab2ed99 bellard
                gen_op_pushw_T0();
1237 dab2ed99 bellard
        } else {
1238 dab2ed99 bellard
            if (s->dflag)
1239 dab2ed99 bellard
                gen_op_pushl_ss32_T0();
1240 dab2ed99 bellard
            else
1241 dab2ed99 bellard
                gen_op_pushw_ss32_T0();
1242 dab2ed99 bellard
        }
1243 dab2ed99 bellard
    } else {
1244 dab2ed99 bellard
        if (s->dflag)
1245 dab2ed99 bellard
            gen_op_pushl_ss16_T0();
1246 dab2ed99 bellard
        else
1247 dab2ed99 bellard
            gen_op_pushw_ss16_T0();
1248 dab2ed99 bellard
    }
1249 dab2ed99 bellard
}
1250 dab2ed99 bellard
1251 dab2ed99 bellard
/* two step pop is necessary for precise exceptions */
1252 dab2ed99 bellard
static void gen_pop_T0(DisasContext *s)
1253 dab2ed99 bellard
{
1254 dab2ed99 bellard
    if (s->ss32) {
1255 dab2ed99 bellard
        if (!s->addseg) {
1256 dab2ed99 bellard
            if (s->dflag)
1257 dab2ed99 bellard
                gen_op_popl_T0();
1258 dab2ed99 bellard
            else
1259 dab2ed99 bellard
                gen_op_popw_T0();
1260 dab2ed99 bellard
        } else {
1261 dab2ed99 bellard
            if (s->dflag)
1262 dab2ed99 bellard
                gen_op_popl_ss32_T0();
1263 dab2ed99 bellard
            else
1264 dab2ed99 bellard
                gen_op_popw_ss32_T0();
1265 dab2ed99 bellard
        }
1266 dab2ed99 bellard
    } else {
1267 dab2ed99 bellard
        if (s->dflag)
1268 dab2ed99 bellard
            gen_op_popl_ss16_T0();
1269 dab2ed99 bellard
        else
1270 dab2ed99 bellard
            gen_op_popw_ss16_T0();
1271 dab2ed99 bellard
    }
1272 dab2ed99 bellard
}
1273 dab2ed99 bellard
1274 dab2ed99 bellard
static void gen_pop_update(DisasContext *s)
1275 dab2ed99 bellard
{
1276 dab2ed99 bellard
    if (s->ss32) {
1277 dab2ed99 bellard
        if (s->dflag)
1278 dab2ed99 bellard
            gen_op_addl_ESP_4();
1279 dab2ed99 bellard
        else
1280 dab2ed99 bellard
            gen_op_addl_ESP_2();
1281 dab2ed99 bellard
    } else {
1282 dab2ed99 bellard
        if (s->dflag)
1283 dab2ed99 bellard
            gen_op_addw_ESP_4();
1284 dab2ed99 bellard
        else
1285 dab2ed99 bellard
            gen_op_addw_ESP_2();
1286 dab2ed99 bellard
    }
1287 dab2ed99 bellard
}
1288 dab2ed99 bellard
1289 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1290 dab2ed99 bellard
static void gen_pusha(DisasContext *s)
1291 dab2ed99 bellard
{
1292 dab2ed99 bellard
    int i;
1293 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1294 dab2ed99 bellard
    gen_op_addl_A0_im(-16 <<  s->dflag);
1295 dab2ed99 bellard
    if (!s->ss32)
1296 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1297 dab2ed99 bellard
    gen_op_movl_T1_A0();
1298 dab2ed99 bellard
    if (s->addseg)
1299 dab2ed99 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1300 dab2ed99 bellard
    for(i = 0;i < 8; i++) {
1301 dab2ed99 bellard
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1302 dab2ed99 bellard
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1303 dab2ed99 bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
1304 dab2ed99 bellard
    }
1305 dab2ed99 bellard
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1306 dab2ed99 bellard
}
1307 dab2ed99 bellard
1308 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1309 dab2ed99 bellard
static void gen_popa(DisasContext *s)
1310 dab2ed99 bellard
{
1311 dab2ed99 bellard
    int i;
1312 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1313 dab2ed99 bellard
    if (!s->ss32)
1314 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1315 dab2ed99 bellard
    gen_op_movl_T1_A0();
1316 dab2ed99 bellard
    gen_op_addl_T1_im(16 <<  s->dflag);
1317 dab2ed99 bellard
    if (s->addseg)
1318 dab2ed99 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1319 dab2ed99 bellard
    for(i = 0;i < 8; i++) {
1320 dab2ed99 bellard
        /* ESP is not reloaded */
1321 dab2ed99 bellard
        if (i != 3) {
1322 dab2ed99 bellard
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1323 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1324 dab2ed99 bellard
        }
1325 dab2ed99 bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
1326 dab2ed99 bellard
    }
1327 dab2ed99 bellard
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1328 dab2ed99 bellard
}
1329 dab2ed99 bellard
1330 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1331 dab2ed99 bellard
/* XXX: check this */
1332 dab2ed99 bellard
static void gen_enter(DisasContext *s, int esp_addend, int level)
1333 dab2ed99 bellard
{
1334 dab2ed99 bellard
    int ot, level1, addend, opsize;
1335 dab2ed99 bellard
1336 dab2ed99 bellard
    ot = s->dflag + OT_WORD;
1337 dab2ed99 bellard
    level &= 0x1f;
1338 dab2ed99 bellard
    level1 = level;
1339 dab2ed99 bellard
    opsize = 2 << s->dflag;
1340 dab2ed99 bellard
1341 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1342 dab2ed99 bellard
    gen_op_addl_A0_im(-opsize);
1343 dab2ed99 bellard
    if (!s->ss32)
1344 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1345 dab2ed99 bellard
    gen_op_movl_T1_A0();
1346 dab2ed99 bellard
    if (s->addseg)
1347 dab2ed99 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1348 dab2ed99 bellard
    /* push bp */
1349 dab2ed99 bellard
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1350 dab2ed99 bellard
    gen_op_st_T0_A0[ot]();
1351 dab2ed99 bellard
    if (level) {
1352 dab2ed99 bellard
        while (level--) {
1353 dab2ed99 bellard
            gen_op_addl_A0_im(-opsize);
1354 dab2ed99 bellard
            gen_op_addl_T0_im(-opsize);
1355 dab2ed99 bellard
            gen_op_st_T0_A0[ot]();
1356 dab2ed99 bellard
        }
1357 dab2ed99 bellard
        gen_op_addl_A0_im(-opsize);
1358 dab2ed99 bellard
        /* XXX: add st_T1_A0 ? */
1359 dab2ed99 bellard
        gen_op_movl_T0_T1();
1360 dab2ed99 bellard
        gen_op_st_T0_A0[ot]();
1361 dab2ed99 bellard
    }
1362 dab2ed99 bellard
    gen_op_mov_reg_T1[ot][R_EBP]();
1363 dab2ed99 bellard
    addend = -esp_addend;
1364 dab2ed99 bellard
    if (level1)
1365 dab2ed99 bellard
        addend -= opsize * (level1 + 1);
1366 dab2ed99 bellard
    gen_op_addl_T1_im(addend);
1367 dab2ed99 bellard
    gen_op_mov_reg_T1[ot][R_ESP]();
1368 dab2ed99 bellard
}
1369 dab2ed99 bellard
1370 c50c0c3f bellard
static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1371 c50c0c3f bellard
{
1372 c50c0c3f bellard
    if (s->cc_op != CC_OP_DYNAMIC)
1373 c50c0c3f bellard
        gen_op_set_cc_op(s->cc_op);
1374 c50c0c3f bellard
    gen_op_jmp_im(cur_eip);
1375 c50c0c3f bellard
    gen_op_raise_exception(trapno);
1376 c50c0c3f bellard
    s->is_jmp = 1;
1377 c50c0c3f bellard
}
1378 c50c0c3f bellard
1379 0ecfa993 bellard
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1380 0ecfa993 bellard
   is set to true if the instruction sets the PC (last instruction of
1381 0ecfa993 bellard
   a basic block) */
1382 6dbad63e bellard
long disas_insn(DisasContext *s, uint8_t *pc_start)
1383 367e86e8 bellard
{
1384 367e86e8 bellard
    int b, prefixes, aflag, dflag;
1385 367e86e8 bellard
    int shift, ot;
1386 367e86e8 bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1387 dab2ed99 bellard
    unsigned int next_eip;
1388 367e86e8 bellard
1389 367e86e8 bellard
    s->pc = pc_start;
1390 367e86e8 bellard
    prefixes = 0;
1391 6dbad63e bellard
    aflag = s->code32;
1392 6dbad63e bellard
    dflag = s->code32;
1393 9c605cb1 bellard
    s->override = -1;
1394 367e86e8 bellard
 next_byte:
1395 367e86e8 bellard
    b = ldub(s->pc);
1396 367e86e8 bellard
    s->pc++;
1397 367e86e8 bellard
    /* check prefixes */
1398 367e86e8 bellard
    switch (b) {
1399 367e86e8 bellard
    case 0xf3:
1400 367e86e8 bellard
        prefixes |= PREFIX_REPZ;
1401 367e86e8 bellard
        goto next_byte;
1402 367e86e8 bellard
    case 0xf2:
1403 367e86e8 bellard
        prefixes |= PREFIX_REPNZ;
1404 367e86e8 bellard
        goto next_byte;
1405 367e86e8 bellard
    case 0xf0:
1406 367e86e8 bellard
        prefixes |= PREFIX_LOCK;
1407 367e86e8 bellard
        goto next_byte;
1408 367e86e8 bellard
    case 0x2e:
1409 9c605cb1 bellard
        s->override = R_CS;
1410 367e86e8 bellard
        goto next_byte;
1411 367e86e8 bellard
    case 0x36:
1412 9c605cb1 bellard
        s->override = R_SS;
1413 367e86e8 bellard
        goto next_byte;
1414 367e86e8 bellard
    case 0x3e:
1415 9c605cb1 bellard
        s->override = R_DS;
1416 367e86e8 bellard
        goto next_byte;
1417 367e86e8 bellard
    case 0x26:
1418 9c605cb1 bellard
        s->override = R_ES;
1419 367e86e8 bellard
        goto next_byte;
1420 367e86e8 bellard
    case 0x64:
1421 9c605cb1 bellard
        s->override = R_FS;
1422 367e86e8 bellard
        goto next_byte;
1423 367e86e8 bellard
    case 0x65:
1424 9c605cb1 bellard
        s->override = R_GS;
1425 367e86e8 bellard
        goto next_byte;
1426 367e86e8 bellard
    case 0x66:
1427 367e86e8 bellard
        prefixes |= PREFIX_DATA;
1428 367e86e8 bellard
        goto next_byte;
1429 367e86e8 bellard
    case 0x67:
1430 367e86e8 bellard
        prefixes |= PREFIX_ADR;
1431 367e86e8 bellard
        goto next_byte;
1432 367e86e8 bellard
    case 0x9b:
1433 367e86e8 bellard
        prefixes |= PREFIX_FWAIT;
1434 367e86e8 bellard
        goto next_byte;
1435 367e86e8 bellard
    }
1436 367e86e8 bellard
1437 367e86e8 bellard
    if (prefixes & PREFIX_DATA)
1438 367e86e8 bellard
        dflag ^= 1;
1439 367e86e8 bellard
    if (prefixes & PREFIX_ADR)
1440 367e86e8 bellard
        aflag ^= 1;
1441 367e86e8 bellard
1442 367e86e8 bellard
    s->prefix = prefixes;
1443 367e86e8 bellard
    s->aflag = aflag;
1444 367e86e8 bellard
    s->dflag = dflag;
1445 367e86e8 bellard
1446 1b6b029e bellard
    /* lock generation */
1447 1b6b029e bellard
    if (prefixes & PREFIX_LOCK)
1448 1b6b029e bellard
        gen_op_lock();
1449 1b6b029e bellard
1450 367e86e8 bellard
    /* now check op code */
1451 367e86e8 bellard
 reswitch:
1452 367e86e8 bellard
    switch(b) {
1453 367e86e8 bellard
    case 0x0f:
1454 367e86e8 bellard
        /**************************/
1455 367e86e8 bellard
        /* extended op code */
1456 367e86e8 bellard
        b = ldub(s->pc++) | 0x100;
1457 367e86e8 bellard
        goto reswitch;
1458 367e86e8 bellard
        
1459 367e86e8 bellard
        /**************************/
1460 367e86e8 bellard
        /* arith & logic */
1461 367e86e8 bellard
    case 0x00 ... 0x05:
1462 367e86e8 bellard
    case 0x08 ... 0x0d:
1463 367e86e8 bellard
    case 0x10 ... 0x15:
1464 367e86e8 bellard
    case 0x18 ... 0x1d:
1465 367e86e8 bellard
    case 0x20 ... 0x25:
1466 367e86e8 bellard
    case 0x28 ... 0x2d:
1467 367e86e8 bellard
    case 0x30 ... 0x35:
1468 367e86e8 bellard
    case 0x38 ... 0x3d:
1469 367e86e8 bellard
        {
1470 367e86e8 bellard
            int op, f, val;
1471 367e86e8 bellard
            op = (b >> 3) & 7;
1472 367e86e8 bellard
            f = (b >> 1) & 3;
1473 367e86e8 bellard
1474 367e86e8 bellard
            if ((b & 1) == 0)
1475 367e86e8 bellard
                ot = OT_BYTE;
1476 367e86e8 bellard
            else
1477 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1478 367e86e8 bellard
            
1479 367e86e8 bellard
            switch(f) {
1480 367e86e8 bellard
            case 0: /* OP Ev, Gv */
1481 367e86e8 bellard
                modrm = ldub(s->pc++);
1482 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1483 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1484 367e86e8 bellard
                rm = modrm & 7;
1485 367e86e8 bellard
                if (mod != 3) {
1486 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1487 367e86e8 bellard
                    gen_op_ld_T0_A0[ot]();
1488 367e86e8 bellard
                    opreg = OR_TMP0;
1489 367e86e8 bellard
                } else {
1490 367e86e8 bellard
                    opreg = OR_EAX + rm;
1491 367e86e8 bellard
                }
1492 367e86e8 bellard
                gen_op(s, op, ot, opreg, reg);
1493 367e86e8 bellard
                if (mod != 3 && op != 7) {
1494 367e86e8 bellard
                    gen_op_st_T0_A0[ot]();
1495 367e86e8 bellard
                }
1496 367e86e8 bellard
                break;
1497 367e86e8 bellard
            case 1: /* OP Gv, Ev */
1498 367e86e8 bellard
                modrm = ldub(s->pc++);
1499 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1500 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1501 367e86e8 bellard
                rm = modrm & 7;
1502 367e86e8 bellard
                if (mod != 3) {
1503 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1504 367e86e8 bellard
                    gen_op_ld_T1_A0[ot]();
1505 367e86e8 bellard
                    opreg = OR_TMP1;
1506 367e86e8 bellard
                } else {
1507 367e86e8 bellard
                    opreg = OR_EAX + rm;
1508 367e86e8 bellard
                }
1509 367e86e8 bellard
                gen_op(s, op, ot, reg, opreg);
1510 367e86e8 bellard
                break;
1511 367e86e8 bellard
            case 2: /* OP A, Iv */
1512 367e86e8 bellard
                val = insn_get(s, ot);
1513 367e86e8 bellard
                gen_opi(s, op, ot, OR_EAX, val);
1514 367e86e8 bellard
                break;
1515 367e86e8 bellard
            }
1516 367e86e8 bellard
        }
1517 367e86e8 bellard
        break;
1518 367e86e8 bellard
1519 367e86e8 bellard
    case 0x80: /* GRP1 */
1520 367e86e8 bellard
    case 0x81:
1521 367e86e8 bellard
    case 0x83:
1522 367e86e8 bellard
        {
1523 367e86e8 bellard
            int val;
1524 367e86e8 bellard
1525 367e86e8 bellard
            if ((b & 1) == 0)
1526 367e86e8 bellard
                ot = OT_BYTE;
1527 367e86e8 bellard
            else
1528 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1529 367e86e8 bellard
            
1530 367e86e8 bellard
            modrm = ldub(s->pc++);
1531 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1532 367e86e8 bellard
            rm = modrm & 7;
1533 367e86e8 bellard
            op = (modrm >> 3) & 7;
1534 367e86e8 bellard
            
1535 367e86e8 bellard
            if (mod != 3) {
1536 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1537 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
1538 367e86e8 bellard
                opreg = OR_TMP0;
1539 367e86e8 bellard
            } else {
1540 367e86e8 bellard
                opreg = rm + OR_EAX;
1541 367e86e8 bellard
            }
1542 367e86e8 bellard
1543 367e86e8 bellard
            switch(b) {
1544 367e86e8 bellard
            default:
1545 367e86e8 bellard
            case 0x80:
1546 367e86e8 bellard
            case 0x81:
1547 367e86e8 bellard
                val = insn_get(s, ot);
1548 367e86e8 bellard
                break;
1549 367e86e8 bellard
            case 0x83:
1550 367e86e8 bellard
                val = (int8_t)insn_get(s, OT_BYTE);
1551 367e86e8 bellard
                break;
1552 367e86e8 bellard
            }
1553 367e86e8 bellard
1554 367e86e8 bellard
            gen_opi(s, op, ot, opreg, val);
1555 367e86e8 bellard
            if (op != 7 && mod != 3) {
1556 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1557 367e86e8 bellard
            }
1558 367e86e8 bellard
        }
1559 367e86e8 bellard
        break;
1560 367e86e8 bellard
1561 367e86e8 bellard
        /**************************/
1562 367e86e8 bellard
        /* inc, dec, and other misc arith */
1563 367e86e8 bellard
    case 0x40 ... 0x47: /* inc Gv */
1564 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1565 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1566 367e86e8 bellard
        break;
1567 367e86e8 bellard
    case 0x48 ... 0x4f: /* dec Gv */
1568 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1569 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1570 367e86e8 bellard
        break;
1571 367e86e8 bellard
    case 0xf6: /* GRP3 */
1572 367e86e8 bellard
    case 0xf7:
1573 367e86e8 bellard
        if ((b & 1) == 0)
1574 367e86e8 bellard
            ot = OT_BYTE;
1575 367e86e8 bellard
        else
1576 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1577 367e86e8 bellard
1578 367e86e8 bellard
        modrm = ldub(s->pc++);
1579 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1580 367e86e8 bellard
        rm = modrm & 7;
1581 367e86e8 bellard
        op = (modrm >> 3) & 7;
1582 367e86e8 bellard
        if (mod != 3) {
1583 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1584 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1585 367e86e8 bellard
        } else {
1586 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1587 367e86e8 bellard
        }
1588 367e86e8 bellard
1589 367e86e8 bellard
        switch(op) {
1590 367e86e8 bellard
        case 0: /* test */
1591 367e86e8 bellard
            val = insn_get(s, ot);
1592 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1593 367e86e8 bellard
            gen_op_testl_T0_T1_cc();
1594 367e86e8 bellard
            s->cc_op = CC_OP_LOGICB + ot;
1595 367e86e8 bellard
            break;
1596 367e86e8 bellard
        case 2: /* not */
1597 367e86e8 bellard
            gen_op_notl_T0();
1598 367e86e8 bellard
            if (mod != 3) {
1599 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1600 367e86e8 bellard
            } else {
1601 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1602 367e86e8 bellard
            }
1603 367e86e8 bellard
            break;
1604 367e86e8 bellard
        case 3: /* neg */
1605 367e86e8 bellard
            gen_op_negl_T0_cc();
1606 367e86e8 bellard
            if (mod != 3) {
1607 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1608 367e86e8 bellard
            } else {
1609 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1610 367e86e8 bellard
            }
1611 367e86e8 bellard
            s->cc_op = CC_OP_SUBB + ot;
1612 367e86e8 bellard
            break;
1613 367e86e8 bellard
        case 4: /* mul */
1614 367e86e8 bellard
            switch(ot) {
1615 367e86e8 bellard
            case OT_BYTE:
1616 367e86e8 bellard
                gen_op_mulb_AL_T0();
1617 367e86e8 bellard
                break;
1618 367e86e8 bellard
            case OT_WORD:
1619 367e86e8 bellard
                gen_op_mulw_AX_T0();
1620 367e86e8 bellard
                break;
1621 367e86e8 bellard
            default:
1622 367e86e8 bellard
            case OT_LONG:
1623 367e86e8 bellard
                gen_op_mull_EAX_T0();
1624 367e86e8 bellard
                break;
1625 367e86e8 bellard
            }
1626 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1627 367e86e8 bellard
            break;
1628 367e86e8 bellard
        case 5: /* imul */
1629 367e86e8 bellard
            switch(ot) {
1630 367e86e8 bellard
            case OT_BYTE:
1631 367e86e8 bellard
                gen_op_imulb_AL_T0();
1632 367e86e8 bellard
                break;
1633 367e86e8 bellard
            case OT_WORD:
1634 367e86e8 bellard
                gen_op_imulw_AX_T0();
1635 367e86e8 bellard
                break;
1636 367e86e8 bellard
            default:
1637 367e86e8 bellard
            case OT_LONG:
1638 367e86e8 bellard
                gen_op_imull_EAX_T0();
1639 367e86e8 bellard
                break;
1640 367e86e8 bellard
            }
1641 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1642 367e86e8 bellard
            break;
1643 367e86e8 bellard
        case 6: /* div */
1644 367e86e8 bellard
            switch(ot) {
1645 367e86e8 bellard
            case OT_BYTE:
1646 367e86e8 bellard
                gen_op_divb_AL_T0();
1647 367e86e8 bellard
                break;
1648 367e86e8 bellard
            case OT_WORD:
1649 367e86e8 bellard
                gen_op_divw_AX_T0();
1650 367e86e8 bellard
                break;
1651 367e86e8 bellard
            default:
1652 367e86e8 bellard
            case OT_LONG:
1653 367e86e8 bellard
                gen_op_divl_EAX_T0();
1654 367e86e8 bellard
                break;
1655 367e86e8 bellard
            }
1656 367e86e8 bellard
            break;
1657 367e86e8 bellard
        case 7: /* idiv */
1658 367e86e8 bellard
            switch(ot) {
1659 367e86e8 bellard
            case OT_BYTE:
1660 367e86e8 bellard
                gen_op_idivb_AL_T0();
1661 367e86e8 bellard
                break;
1662 367e86e8 bellard
            case OT_WORD:
1663 367e86e8 bellard
                gen_op_idivw_AX_T0();
1664 367e86e8 bellard
                break;
1665 367e86e8 bellard
            default:
1666 367e86e8 bellard
            case OT_LONG:
1667 367e86e8 bellard
                gen_op_idivl_EAX_T0();
1668 367e86e8 bellard
                break;
1669 367e86e8 bellard
            }
1670 367e86e8 bellard
            break;
1671 367e86e8 bellard
        default:
1672 1a9353d2 bellard
            goto illegal_op;
1673 367e86e8 bellard
        }
1674 367e86e8 bellard
        break;
1675 367e86e8 bellard
1676 367e86e8 bellard
    case 0xfe: /* GRP4 */
1677 367e86e8 bellard
    case 0xff: /* GRP5 */
1678 367e86e8 bellard
        if ((b & 1) == 0)
1679 367e86e8 bellard
            ot = OT_BYTE;
1680 367e86e8 bellard
        else
1681 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1682 367e86e8 bellard
1683 367e86e8 bellard
        modrm = ldub(s->pc++);
1684 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1685 367e86e8 bellard
        rm = modrm & 7;
1686 367e86e8 bellard
        op = (modrm >> 3) & 7;
1687 367e86e8 bellard
        if (op >= 2 && b == 0xfe) {
1688 1a9353d2 bellard
            goto illegal_op;
1689 367e86e8 bellard
        }
1690 367e86e8 bellard
        if (mod != 3) {
1691 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1692 dab2ed99 bellard
            if (op != 3 && op != 5)
1693 dab2ed99 bellard
                gen_op_ld_T0_A0[ot]();
1694 367e86e8 bellard
        } else {
1695 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1696 367e86e8 bellard
        }
1697 367e86e8 bellard
1698 367e86e8 bellard
        switch(op) {
1699 367e86e8 bellard
        case 0: /* inc Ev */
1700 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, 1);
1701 367e86e8 bellard
            if (mod != 3)
1702 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1703 4b74fe1f bellard
            else
1704 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
1705 367e86e8 bellard
            break;
1706 367e86e8 bellard
        case 1: /* dec Ev */
1707 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, -1);
1708 367e86e8 bellard
            if (mod != 3)
1709 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1710 4b74fe1f bellard
            else
1711 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
1712 367e86e8 bellard
            break;
1713 367e86e8 bellard
        case 2: /* call Ev */
1714 dab2ed99 bellard
            /* XXX: optimize if memory (no and is necessary) */
1715 dab2ed99 bellard
            if (s->dflag == 0)
1716 dab2ed99 bellard
                gen_op_andl_T0_ffff();
1717 dab2ed99 bellard
            gen_op_jmp_T0();
1718 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
1719 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
1720 dab2ed99 bellard
            gen_push_T0(s);
1721 dab2ed99 bellard
            s->is_jmp = 1;
1722 dab2ed99 bellard
            break;
1723 dab2ed99 bellard
        case 3: /* lcall Ev */
1724 dab2ed99 bellard
            /* push return segment + offset */
1725 dab2ed99 bellard
            gen_op_movl_T0_seg(R_CS);
1726 dab2ed99 bellard
            gen_push_T0(s);
1727 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
1728 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
1729 dab2ed99 bellard
            gen_push_T0(s);
1730 dab2ed99 bellard
1731 dab2ed99 bellard
            gen_op_ld_T1_A0[ot]();
1732 dab2ed99 bellard
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1733 dab2ed99 bellard
            gen_op_lduw_T0_A0();
1734 dab2ed99 bellard
            gen_movl_seg_T0(s, R_CS);
1735 dab2ed99 bellard
            gen_op_movl_T0_T1();
1736 367e86e8 bellard
            gen_op_jmp_T0();
1737 6dbad63e bellard
            s->is_jmp = 1;
1738 367e86e8 bellard
            break;
1739 367e86e8 bellard
        case 4: /* jmp Ev */
1740 dab2ed99 bellard
            if (s->dflag == 0)
1741 dab2ed99 bellard
                gen_op_andl_T0_ffff();
1742 dab2ed99 bellard
            gen_op_jmp_T0();
1743 dab2ed99 bellard
            s->is_jmp = 1;
1744 dab2ed99 bellard
            break;
1745 dab2ed99 bellard
        case 5: /* ljmp Ev */
1746 dab2ed99 bellard
            gen_op_ld_T1_A0[ot]();
1747 dab2ed99 bellard
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1748 dab2ed99 bellard
            gen_op_lduw_T0_A0();
1749 dab2ed99 bellard
            gen_movl_seg_T0(s, R_CS);
1750 dab2ed99 bellard
            gen_op_movl_T0_T1();
1751 367e86e8 bellard
            gen_op_jmp_T0();
1752 6dbad63e bellard
            s->is_jmp = 1;
1753 367e86e8 bellard
            break;
1754 367e86e8 bellard
        case 6: /* push Ev */
1755 dab2ed99 bellard
            gen_push_T0(s);
1756 367e86e8 bellard
            break;
1757 367e86e8 bellard
        default:
1758 1a9353d2 bellard
            goto illegal_op;
1759 367e86e8 bellard
        }
1760 367e86e8 bellard
        break;
1761 367e86e8 bellard
1762 367e86e8 bellard
    case 0x84: /* test Ev, Gv */
1763 367e86e8 bellard
    case 0x85: 
1764 367e86e8 bellard
        if ((b & 1) == 0)
1765 367e86e8 bellard
            ot = OT_BYTE;
1766 367e86e8 bellard
        else
1767 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1768 367e86e8 bellard
1769 367e86e8 bellard
        modrm = ldub(s->pc++);
1770 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1771 367e86e8 bellard
        rm = modrm & 7;
1772 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1773 367e86e8 bellard
        
1774 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1775 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1776 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1777 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1778 367e86e8 bellard
        break;
1779 367e86e8 bellard
        
1780 367e86e8 bellard
    case 0xa8: /* test eAX, Iv */
1781 367e86e8 bellard
    case 0xa9:
1782 367e86e8 bellard
        if ((b & 1) == 0)
1783 367e86e8 bellard
            ot = OT_BYTE;
1784 367e86e8 bellard
        else
1785 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1786 367e86e8 bellard
        val = insn_get(s, ot);
1787 367e86e8 bellard
1788 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1789 ba1c6e37 bellard
        gen_op_movl_T1_im(val);
1790 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1791 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1792 367e86e8 bellard
        break;
1793 367e86e8 bellard
        
1794 367e86e8 bellard
    case 0x98: /* CWDE/CBW */
1795 367e86e8 bellard
        if (dflag)
1796 367e86e8 bellard
            gen_op_movswl_EAX_AX();
1797 367e86e8 bellard
        else
1798 367e86e8 bellard
            gen_op_movsbw_AX_AL();
1799 367e86e8 bellard
        break;
1800 367e86e8 bellard
    case 0x99: /* CDQ/CWD */
1801 367e86e8 bellard
        if (dflag)
1802 367e86e8 bellard
            gen_op_movslq_EDX_EAX();
1803 367e86e8 bellard
        else
1804 367e86e8 bellard
            gen_op_movswl_DX_AX();
1805 367e86e8 bellard
        break;
1806 367e86e8 bellard
    case 0x1af: /* imul Gv, Ev */
1807 367e86e8 bellard
    case 0x69: /* imul Gv, Ev, I */
1808 367e86e8 bellard
    case 0x6b:
1809 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1810 367e86e8 bellard
        modrm = ldub(s->pc++);
1811 367e86e8 bellard
        reg = ((modrm >> 3) & 7) + OR_EAX;
1812 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1813 367e86e8 bellard
        if (b == 0x69) {
1814 367e86e8 bellard
            val = insn_get(s, ot);
1815 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1816 367e86e8 bellard
        } else if (b == 0x6b) {
1817 367e86e8 bellard
            val = insn_get(s, OT_BYTE);
1818 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1819 367e86e8 bellard
        } else {
1820 367e86e8 bellard
            gen_op_mov_TN_reg[ot][1][reg]();
1821 367e86e8 bellard
        }
1822 367e86e8 bellard
1823 367e86e8 bellard
        if (ot == OT_LONG) {
1824 4b74fe1f bellard
            gen_op_imull_T0_T1();
1825 367e86e8 bellard
        } else {
1826 4b74fe1f bellard
            gen_op_imulw_T0_T1();
1827 367e86e8 bellard
        }
1828 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1829 0ecfa993 bellard
        s->cc_op = CC_OP_MUL;
1830 367e86e8 bellard
        break;
1831 1a9353d2 bellard
    case 0x1c0:
1832 1a9353d2 bellard
    case 0x1c1: /* xadd Ev, Gv */
1833 1a9353d2 bellard
        if ((b & 1) == 0)
1834 1a9353d2 bellard
            ot = OT_BYTE;
1835 1a9353d2 bellard
        else
1836 1a9353d2 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1837 1a9353d2 bellard
        modrm = ldub(s->pc++);
1838 1a9353d2 bellard
        reg = (modrm >> 3) & 7;
1839 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
1840 1a9353d2 bellard
        if (mod == 3) {
1841 1a9353d2 bellard
            rm = modrm & 7;
1842 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
1843 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][1][rm]();
1844 1a9353d2 bellard
            gen_op_addl_T0_T1_cc();
1845 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
1846 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
1847 1a9353d2 bellard
        } else {
1848 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1849 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
1850 1a9353d2 bellard
            gen_op_ld_T1_A0[ot]();
1851 1a9353d2 bellard
            gen_op_addl_T0_T1_cc();
1852 1a9353d2 bellard
            gen_op_st_T0_A0[ot]();
1853 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
1854 1a9353d2 bellard
        }
1855 1a9353d2 bellard
        s->cc_op = CC_OP_ADDB + ot;
1856 1a9353d2 bellard
        break;
1857 1a9353d2 bellard
    case 0x1b0:
1858 1a9353d2 bellard
    case 0x1b1: /* cmpxchg Ev, Gv */
1859 1a9353d2 bellard
        if ((b & 1) == 0)
1860 1a9353d2 bellard
            ot = OT_BYTE;
1861 1a9353d2 bellard
        else
1862 1a9353d2 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1863 1a9353d2 bellard
        modrm = ldub(s->pc++);
1864 1a9353d2 bellard
        reg = (modrm >> 3) & 7;
1865 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
1866 1a9353d2 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
1867 1a9353d2 bellard
        if (mod == 3) {
1868 1a9353d2 bellard
            rm = modrm & 7;
1869 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1870 1a9353d2 bellard
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1871 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
1872 1a9353d2 bellard
        } else {
1873 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1874 1a9353d2 bellard
            gen_op_ld_T0_A0[ot]();
1875 1a9353d2 bellard
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1876 1a9353d2 bellard
            gen_op_st_T0_A0[ot]();
1877 1a9353d2 bellard
        }
1878 1a9353d2 bellard
        s->cc_op = CC_OP_SUBB + ot;
1879 1a9353d2 bellard
        break;
1880 9c605cb1 bellard
    case 0x1c7: /* cmpxchg8b */
1881 9c605cb1 bellard
        modrm = ldub(s->pc++);
1882 9c605cb1 bellard
        mod = (modrm >> 6) & 3;
1883 9c605cb1 bellard
        if (mod == 3)
1884 9c605cb1 bellard
            goto illegal_op;
1885 9c605cb1 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1886 9c605cb1 bellard
            gen_op_set_cc_op(s->cc_op);
1887 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1888 9c605cb1 bellard
        gen_op_cmpxchg8b();
1889 9c605cb1 bellard
        s->cc_op = CC_OP_EFLAGS;
1890 9c605cb1 bellard
        break;
1891 367e86e8 bellard
        
1892 367e86e8 bellard
        /**************************/
1893 367e86e8 bellard
        /* push/pop */
1894 367e86e8 bellard
    case 0x50 ... 0x57: /* push */
1895 927f621e bellard
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1896 dab2ed99 bellard
        gen_push_T0(s);
1897 367e86e8 bellard
        break;
1898 367e86e8 bellard
    case 0x58 ... 0x5f: /* pop */
1899 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1900 dab2ed99 bellard
        gen_pop_T0(s);
1901 dab2ed99 bellard
        gen_op_mov_reg_T0[ot][b & 7]();
1902 dab2ed99 bellard
        gen_pop_update(s);
1903 367e86e8 bellard
        break;
1904 27362c82 bellard
    case 0x60: /* pusha */
1905 dab2ed99 bellard
        gen_pusha(s);
1906 27362c82 bellard
        break;
1907 27362c82 bellard
    case 0x61: /* popa */
1908 dab2ed99 bellard
        gen_popa(s);
1909 27362c82 bellard
        break;
1910 367e86e8 bellard
    case 0x68: /* push Iv */
1911 367e86e8 bellard
    case 0x6a:
1912 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1913 367e86e8 bellard
        if (b == 0x68)
1914 367e86e8 bellard
            val = insn_get(s, ot);
1915 367e86e8 bellard
        else
1916 367e86e8 bellard
            val = (int8_t)insn_get(s, OT_BYTE);
1917 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1918 dab2ed99 bellard
        gen_push_T0(s);
1919 367e86e8 bellard
        break;
1920 367e86e8 bellard
    case 0x8f: /* pop Ev */
1921 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1922 367e86e8 bellard
        modrm = ldub(s->pc++);
1923 dab2ed99 bellard
        gen_pop_T0(s);
1924 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1925 dab2ed99 bellard
        gen_pop_update(s);
1926 367e86e8 bellard
        break;
1927 27362c82 bellard
    case 0xc8: /* enter */
1928 27362c82 bellard
        {
1929 27362c82 bellard
            int level;
1930 27362c82 bellard
            val = lduw(s->pc);
1931 27362c82 bellard
            s->pc += 2;
1932 27362c82 bellard
            level = ldub(s->pc++);
1933 dab2ed99 bellard
            gen_enter(s, val, level);
1934 27362c82 bellard
        }
1935 27362c82 bellard
        break;
1936 367e86e8 bellard
    case 0xc9: /* leave */
1937 dab2ed99 bellard
        /* XXX: exception not precise (ESP is update before potential exception) */
1938 dab2ed99 bellard
        if (s->ss32) {
1939 dab2ed99 bellard
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1940 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1941 dab2ed99 bellard
        } else {
1942 dab2ed99 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1943 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1944 dab2ed99 bellard
        }
1945 dab2ed99 bellard
        gen_pop_T0(s);
1946 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1947 dab2ed99 bellard
        gen_op_mov_reg_T0[ot][R_EBP]();
1948 dab2ed99 bellard
        gen_pop_update(s);
1949 367e86e8 bellard
        break;
1950 6dbad63e bellard
    case 0x06: /* push es */
1951 6dbad63e bellard
    case 0x0e: /* push cs */
1952 6dbad63e bellard
    case 0x16: /* push ss */
1953 6dbad63e bellard
    case 0x1e: /* push ds */
1954 6dbad63e bellard
        gen_op_movl_T0_seg(b >> 3);
1955 dab2ed99 bellard
        gen_push_T0(s);
1956 6dbad63e bellard
        break;
1957 6dbad63e bellard
    case 0x1a0: /* push fs */
1958 6dbad63e bellard
    case 0x1a8: /* push gs */
1959 f631ef9b bellard
        gen_op_movl_T0_seg((b >> 3) & 7);
1960 dab2ed99 bellard
        gen_push_T0(s);
1961 6dbad63e bellard
        break;
1962 6dbad63e bellard
    case 0x07: /* pop es */
1963 6dbad63e bellard
    case 0x17: /* pop ss */
1964 6dbad63e bellard
    case 0x1f: /* pop ds */
1965 dab2ed99 bellard
        gen_pop_T0(s);
1966 6dbad63e bellard
        gen_movl_seg_T0(s, b >> 3);
1967 dab2ed99 bellard
        gen_pop_update(s);
1968 6dbad63e bellard
        break;
1969 6dbad63e bellard
    case 0x1a1: /* pop fs */
1970 6dbad63e bellard
    case 0x1a9: /* pop gs */
1971 dab2ed99 bellard
        gen_pop_T0(s);
1972 f631ef9b bellard
        gen_movl_seg_T0(s, (b >> 3) & 7);
1973 dab2ed99 bellard
        gen_pop_update(s);
1974 6dbad63e bellard
        break;
1975 6dbad63e bellard
1976 367e86e8 bellard
        /**************************/
1977 367e86e8 bellard
        /* mov */
1978 367e86e8 bellard
    case 0x88:
1979 367e86e8 bellard
    case 0x89: /* mov Gv, Ev */
1980 367e86e8 bellard
        if ((b & 1) == 0)
1981 367e86e8 bellard
            ot = OT_BYTE;
1982 367e86e8 bellard
        else
1983 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1984 367e86e8 bellard
        modrm = ldub(s->pc++);
1985 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1986 367e86e8 bellard
        
1987 367e86e8 bellard
        /* generate a generic store */
1988 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1989 367e86e8 bellard
        break;
1990 367e86e8 bellard
    case 0xc6:
1991 367e86e8 bellard
    case 0xc7: /* mov Ev, Iv */
1992 367e86e8 bellard
        if ((b & 1) == 0)
1993 367e86e8 bellard
            ot = OT_BYTE;
1994 367e86e8 bellard
        else
1995 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1996 367e86e8 bellard
        modrm = ldub(s->pc++);
1997 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1998 0ecfa993 bellard
        if (mod != 3)
1999 0ecfa993 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2000 367e86e8 bellard
        val = insn_get(s, ot);
2001 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2002 0ecfa993 bellard
        if (mod != 3)
2003 0ecfa993 bellard
            gen_op_st_T0_A0[ot]();
2004 0ecfa993 bellard
        else
2005 0ecfa993 bellard
            gen_op_mov_reg_T0[ot][modrm & 7]();
2006 367e86e8 bellard
        break;
2007 367e86e8 bellard
    case 0x8a:
2008 367e86e8 bellard
    case 0x8b: /* mov Ev, Gv */
2009 367e86e8 bellard
        if ((b & 1) == 0)
2010 367e86e8 bellard
            ot = OT_BYTE;
2011 367e86e8 bellard
        else
2012 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2013 367e86e8 bellard
        modrm = ldub(s->pc++);
2014 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2015 367e86e8 bellard
        
2016 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2017 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
2018 367e86e8 bellard
        break;
2019 6dbad63e bellard
    case 0x8e: /* mov seg, Gv */
2020 6dbad63e bellard
        ot = dflag ? OT_LONG : OT_WORD;
2021 6dbad63e bellard
        modrm = ldub(s->pc++);
2022 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2023 6dbad63e bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2024 dab2ed99 bellard
        if (reg >= 6 || reg == R_CS)
2025 6dbad63e bellard
            goto illegal_op;
2026 6dbad63e bellard
        gen_movl_seg_T0(s, reg);
2027 6dbad63e bellard
        break;
2028 6dbad63e bellard
    case 0x8c: /* mov Gv, seg */
2029 6dbad63e bellard
        ot = dflag ? OT_LONG : OT_WORD;
2030 6dbad63e bellard
        modrm = ldub(s->pc++);
2031 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2032 6dbad63e bellard
        if (reg >= 6)
2033 6dbad63e bellard
            goto illegal_op;
2034 6dbad63e bellard
        gen_op_movl_T0_seg(reg);
2035 6dbad63e bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2036 6dbad63e bellard
        break;
2037 367e86e8 bellard
2038 367e86e8 bellard
    case 0x1b6: /* movzbS Gv, Eb */
2039 367e86e8 bellard
    case 0x1b7: /* movzwS Gv, Eb */
2040 367e86e8 bellard
    case 0x1be: /* movsbS Gv, Eb */
2041 367e86e8 bellard
    case 0x1bf: /* movswS Gv, Eb */
2042 367e86e8 bellard
        {
2043 367e86e8 bellard
            int d_ot;
2044 367e86e8 bellard
            /* d_ot is the size of destination */
2045 367e86e8 bellard
            d_ot = dflag + OT_WORD;
2046 367e86e8 bellard
            /* ot is the size of source */
2047 367e86e8 bellard
            ot = (b & 1) + OT_BYTE;
2048 367e86e8 bellard
            modrm = ldub(s->pc++);
2049 367e86e8 bellard
            reg = ((modrm >> 3) & 7) + OR_EAX;
2050 367e86e8 bellard
            mod = (modrm >> 6) & 3;
2051 367e86e8 bellard
            rm = modrm & 7;
2052 367e86e8 bellard
            
2053 367e86e8 bellard
            if (mod == 3) {
2054 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][rm]();
2055 367e86e8 bellard
                switch(ot | (b & 8)) {
2056 367e86e8 bellard
                case OT_BYTE:
2057 367e86e8 bellard
                    gen_op_movzbl_T0_T0();
2058 367e86e8 bellard
                    break;
2059 367e86e8 bellard
                case OT_BYTE | 8:
2060 367e86e8 bellard
                    gen_op_movsbl_T0_T0();
2061 367e86e8 bellard
                    break;
2062 367e86e8 bellard
                case OT_WORD:
2063 367e86e8 bellard
                    gen_op_movzwl_T0_T0();
2064 367e86e8 bellard
                    break;
2065 367e86e8 bellard
                default:
2066 367e86e8 bellard
                case OT_WORD | 8:
2067 367e86e8 bellard
                    gen_op_movswl_T0_T0();
2068 367e86e8 bellard
                    break;
2069 367e86e8 bellard
                }
2070 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
2071 367e86e8 bellard
            } else {
2072 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2073 367e86e8 bellard
                if (b & 8) {
2074 367e86e8 bellard
                    gen_op_lds_T0_A0[ot]();
2075 367e86e8 bellard
                } else {
2076 367e86e8 bellard
                    gen_op_ldu_T0_A0[ot]();
2077 367e86e8 bellard
                }
2078 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
2079 367e86e8 bellard
            }
2080 367e86e8 bellard
        }
2081 367e86e8 bellard
        break;
2082 367e86e8 bellard
2083 367e86e8 bellard
    case 0x8d: /* lea */
2084 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2085 367e86e8 bellard
        modrm = ldub(s->pc++);
2086 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2087 6dbad63e bellard
        /* we must ensure that no segment is added */
2088 9c605cb1 bellard
        s->override = -1;
2089 6dbad63e bellard
        val = s->addseg;
2090 6dbad63e bellard
        s->addseg = 0;
2091 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2092 6dbad63e bellard
        s->addseg = val;
2093 367e86e8 bellard
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2094 367e86e8 bellard
        break;
2095 367e86e8 bellard
        
2096 367e86e8 bellard
    case 0xa0: /* mov EAX, Ov */
2097 367e86e8 bellard
    case 0xa1:
2098 367e86e8 bellard
    case 0xa2: /* mov Ov, EAX */
2099 367e86e8 bellard
    case 0xa3:
2100 367e86e8 bellard
        if ((b & 1) == 0)
2101 367e86e8 bellard
            ot = OT_BYTE;
2102 367e86e8 bellard
        else
2103 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2104 367e86e8 bellard
        if (s->aflag)
2105 367e86e8 bellard
            offset_addr = insn_get(s, OT_LONG);
2106 367e86e8 bellard
        else
2107 367e86e8 bellard
            offset_addr = insn_get(s, OT_WORD);
2108 4b74fe1f bellard
        gen_op_movl_A0_im(offset_addr);
2109 1a9353d2 bellard
        /* handle override */
2110 1a9353d2 bellard
        {
2111 1a9353d2 bellard
            int override, must_add_seg;
2112 1a9353d2 bellard
            must_add_seg = s->addseg;
2113 9c605cb1 bellard
            if (s->override >= 0) {
2114 9c605cb1 bellard
                override = s->override;
2115 1a9353d2 bellard
                must_add_seg = 1;
2116 9c605cb1 bellard
            } else {
2117 9c605cb1 bellard
                override = R_DS;
2118 1a9353d2 bellard
            }
2119 1a9353d2 bellard
            if (must_add_seg) {
2120 1a9353d2 bellard
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2121 1a9353d2 bellard
            }
2122 1a9353d2 bellard
        }
2123 367e86e8 bellard
        if ((b & 2) == 0) {
2124 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
2125 367e86e8 bellard
            gen_op_mov_reg_T0[ot][R_EAX]();
2126 367e86e8 bellard
        } else {
2127 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2128 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
2129 367e86e8 bellard
        }
2130 367e86e8 bellard
        break;
2131 31bb950b bellard
    case 0xd7: /* xlat */
2132 31bb950b bellard
        gen_op_movl_A0_reg[R_EBX]();
2133 31bb950b bellard
        gen_op_addl_A0_AL();
2134 31bb950b bellard
        if (s->aflag == 0)
2135 31bb950b bellard
            gen_op_andl_A0_ffff();
2136 9c605cb1 bellard
        /* handle override */
2137 31bb950b bellard
        {
2138 31bb950b bellard
            int override, must_add_seg;
2139 31bb950b bellard
            must_add_seg = s->addseg;
2140 9c605cb1 bellard
            override = R_DS;
2141 9c605cb1 bellard
            if (s->override >= 0) {
2142 9c605cb1 bellard
                override = s->override;
2143 31bb950b bellard
                must_add_seg = 1;
2144 9c605cb1 bellard
            } else {
2145 9c605cb1 bellard
                override = R_DS;
2146 31bb950b bellard
            }
2147 31bb950b bellard
            if (must_add_seg) {
2148 31bb950b bellard
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2149 31bb950b bellard
            }
2150 31bb950b bellard
        }
2151 31bb950b bellard
        gen_op_ldub_T0_A0();
2152 31bb950b bellard
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2153 31bb950b bellard
        break;
2154 367e86e8 bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
2155 367e86e8 bellard
        val = insn_get(s, OT_BYTE);
2156 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2157 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2158 367e86e8 bellard
        break;
2159 367e86e8 bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
2160 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2161 367e86e8 bellard
        val = insn_get(s, ot);
2162 367e86e8 bellard
        reg = OR_EAX + (b & 7);
2163 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2164 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
2165 367e86e8 bellard
        break;
2166 367e86e8 bellard
2167 367e86e8 bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
2168 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2169 367e86e8 bellard
        reg = b & 7;
2170 1a9353d2 bellard
        rm = R_EAX;
2171 1a9353d2 bellard
        goto do_xchg_reg;
2172 367e86e8 bellard
    case 0x86:
2173 367e86e8 bellard
    case 0x87: /* xchg Ev, Gv */
2174 367e86e8 bellard
        if ((b & 1) == 0)
2175 367e86e8 bellard
            ot = OT_BYTE;
2176 367e86e8 bellard
        else
2177 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2178 367e86e8 bellard
        modrm = ldub(s->pc++);
2179 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2180 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
2181 1a9353d2 bellard
        if (mod == 3) {
2182 1a9353d2 bellard
            rm = modrm & 7;
2183 1a9353d2 bellard
        do_xchg_reg:
2184 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
2185 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][1][rm]();
2186 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
2187 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
2188 1a9353d2 bellard
        } else {
2189 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2190 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
2191 31bb950b bellard
            /* for xchg, lock is implicit */
2192 31bb950b bellard
            if (!(prefixes & PREFIX_LOCK))
2193 31bb950b bellard
                gen_op_lock();
2194 1a9353d2 bellard
            gen_op_ld_T1_A0[ot]();
2195 1a9353d2 bellard
            gen_op_st_T0_A0[ot]();
2196 31bb950b bellard
            if (!(prefixes & PREFIX_LOCK))
2197 31bb950b bellard
                gen_op_unlock();
2198 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
2199 1a9353d2 bellard
        }
2200 367e86e8 bellard
        break;
2201 6dbad63e bellard
    case 0xc4: /* les Gv */
2202 6dbad63e bellard
        op = R_ES;
2203 6dbad63e bellard
        goto do_lxx;
2204 6dbad63e bellard
    case 0xc5: /* lds Gv */
2205 6dbad63e bellard
        op = R_DS;
2206 6dbad63e bellard
        goto do_lxx;
2207 6dbad63e bellard
    case 0x1b2: /* lss Gv */
2208 6dbad63e bellard
        op = R_SS;
2209 6dbad63e bellard
        goto do_lxx;
2210 6dbad63e bellard
    case 0x1b4: /* lfs Gv */
2211 6dbad63e bellard
        op = R_FS;
2212 6dbad63e bellard
        goto do_lxx;
2213 6dbad63e bellard
    case 0x1b5: /* lgs Gv */
2214 6dbad63e bellard
        op = R_GS;
2215 6dbad63e bellard
    do_lxx:
2216 6dbad63e bellard
        ot = dflag ? OT_LONG : OT_WORD;
2217 6dbad63e bellard
        modrm = ldub(s->pc++);
2218 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2219 6dbad63e bellard
        mod = (modrm >> 6) & 3;
2220 6dbad63e bellard
        if (mod == 3)
2221 6dbad63e bellard
            goto illegal_op;
2222 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2223 6dbad63e bellard
        gen_op_ld_T1_A0[ot]();
2224 dc99065b bellard
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2225 6dbad63e bellard
        /* load the segment first to handle exceptions properly */
2226 6dbad63e bellard
        gen_op_lduw_T0_A0();
2227 6dbad63e bellard
        gen_movl_seg_T0(s, op);
2228 6dbad63e bellard
        /* then put the data */
2229 6dbad63e bellard
        gen_op_mov_reg_T1[ot][reg]();
2230 6dbad63e bellard
        break;
2231 367e86e8 bellard
        
2232 367e86e8 bellard
        /************************/
2233 367e86e8 bellard
        /* shifts */
2234 367e86e8 bellard
    case 0xc0:
2235 367e86e8 bellard
    case 0xc1:
2236 367e86e8 bellard
        /* shift Ev,Ib */
2237 367e86e8 bellard
        shift = 2;
2238 367e86e8 bellard
    grp2:
2239 367e86e8 bellard
        {
2240 367e86e8 bellard
            if ((b & 1) == 0)
2241 367e86e8 bellard
                ot = OT_BYTE;
2242 367e86e8 bellard
            else
2243 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2244 367e86e8 bellard
            
2245 367e86e8 bellard
            modrm = ldub(s->pc++);
2246 367e86e8 bellard
            mod = (modrm >> 6) & 3;
2247 367e86e8 bellard
            rm = modrm & 7;
2248 367e86e8 bellard
            op = (modrm >> 3) & 7;
2249 367e86e8 bellard
            
2250 367e86e8 bellard
            if (mod != 3) {
2251 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2252 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
2253 367e86e8 bellard
                opreg = OR_TMP0;
2254 367e86e8 bellard
            } else {
2255 367e86e8 bellard
                opreg = rm + OR_EAX;
2256 367e86e8 bellard
            }
2257 367e86e8 bellard
2258 367e86e8 bellard
            /* simpler op */
2259 367e86e8 bellard
            if (shift == 0) {
2260 367e86e8 bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
2261 367e86e8 bellard
            } else {
2262 367e86e8 bellard
                if (shift == 2) {
2263 367e86e8 bellard
                    shift = ldub(s->pc++);
2264 367e86e8 bellard
                }
2265 367e86e8 bellard
                gen_shifti(s, op, ot, opreg, shift);
2266 367e86e8 bellard
            }
2267 367e86e8 bellard
2268 367e86e8 bellard
            if (mod != 3) {
2269 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
2270 367e86e8 bellard
            }
2271 367e86e8 bellard
        }
2272 367e86e8 bellard
        break;
2273 367e86e8 bellard
    case 0xd0:
2274 367e86e8 bellard
    case 0xd1:
2275 367e86e8 bellard
        /* shift Ev,1 */
2276 367e86e8 bellard
        shift = 1;
2277 367e86e8 bellard
        goto grp2;
2278 367e86e8 bellard
    case 0xd2:
2279 367e86e8 bellard
    case 0xd3:
2280 367e86e8 bellard
        /* shift Ev,cl */
2281 367e86e8 bellard
        shift = 0;
2282 367e86e8 bellard
        goto grp2;
2283 367e86e8 bellard
2284 d57c4e01 bellard
    case 0x1a4: /* shld imm */
2285 d57c4e01 bellard
        op = 0;
2286 d57c4e01 bellard
        shift = 1;
2287 d57c4e01 bellard
        goto do_shiftd;
2288 d57c4e01 bellard
    case 0x1a5: /* shld cl */
2289 d57c4e01 bellard
        op = 0;
2290 d57c4e01 bellard
        shift = 0;
2291 d57c4e01 bellard
        goto do_shiftd;
2292 d57c4e01 bellard
    case 0x1ac: /* shrd imm */
2293 d57c4e01 bellard
        op = 1;
2294 d57c4e01 bellard
        shift = 1;
2295 d57c4e01 bellard
        goto do_shiftd;
2296 d57c4e01 bellard
    case 0x1ad: /* shrd cl */
2297 d57c4e01 bellard
        op = 1;
2298 d57c4e01 bellard
        shift = 0;
2299 d57c4e01 bellard
    do_shiftd:
2300 d57c4e01 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2301 d57c4e01 bellard
        modrm = ldub(s->pc++);
2302 d57c4e01 bellard
        mod = (modrm >> 6) & 3;
2303 d57c4e01 bellard
        rm = modrm & 7;
2304 d57c4e01 bellard
        reg = (modrm >> 3) & 7;
2305 d57c4e01 bellard
        
2306 d57c4e01 bellard
        if (mod != 3) {
2307 d57c4e01 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2308 d57c4e01 bellard
            gen_op_ld_T0_A0[ot]();
2309 d57c4e01 bellard
        } else {
2310 d57c4e01 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
2311 d57c4e01 bellard
        }
2312 d57c4e01 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
2313 d57c4e01 bellard
        
2314 d57c4e01 bellard
        if (shift) {
2315 d57c4e01 bellard
            val = ldub(s->pc++);
2316 d57c4e01 bellard
            val &= 0x1f;
2317 d57c4e01 bellard
            if (val) {
2318 d57c4e01 bellard
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2319 d57c4e01 bellard
                if (op == 0 && ot != OT_WORD)
2320 d57c4e01 bellard
                    s->cc_op = CC_OP_SHLB + ot;
2321 d57c4e01 bellard
                else
2322 d57c4e01 bellard
                    s->cc_op = CC_OP_SARB + ot;
2323 d57c4e01 bellard
            }
2324 d57c4e01 bellard
        } else {
2325 d57c4e01 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2326 d57c4e01 bellard
                gen_op_set_cc_op(s->cc_op);
2327 d57c4e01 bellard
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2328 d57c4e01 bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2329 d57c4e01 bellard
        }
2330 d57c4e01 bellard
        if (mod != 3) {
2331 d57c4e01 bellard
            gen_op_st_T0_A0[ot]();
2332 d57c4e01 bellard
        } else {
2333 d57c4e01 bellard
            gen_op_mov_reg_T0[ot][rm]();
2334 d57c4e01 bellard
        }
2335 d57c4e01 bellard
        break;
2336 d57c4e01 bellard
2337 367e86e8 bellard
        /************************/
2338 367e86e8 bellard
        /* floats */
2339 367e86e8 bellard
    case 0xd8 ... 0xdf: 
2340 367e86e8 bellard
        modrm = ldub(s->pc++);
2341 367e86e8 bellard
        mod = (modrm >> 6) & 3;
2342 367e86e8 bellard
        rm = modrm & 7;
2343 367e86e8 bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2344 367e86e8 bellard
        
2345 367e86e8 bellard
        if (mod != 3) {
2346 367e86e8 bellard
            /* memory op */
2347 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2348 367e86e8 bellard
            switch(op) {
2349 367e86e8 bellard
            case 0x00 ... 0x07: /* fxxxs */
2350 367e86e8 bellard
            case 0x10 ... 0x17: /* fixxxl */
2351 367e86e8 bellard
            case 0x20 ... 0x27: /* fxxxl */
2352 367e86e8 bellard
            case 0x30 ... 0x37: /* fixxx */
2353 367e86e8 bellard
                {
2354 927f621e bellard
                    int op1;
2355 927f621e bellard
                    op1 = op & 7;
2356 367e86e8 bellard
2357 367e86e8 bellard
                    switch(op >> 4) {
2358 367e86e8 bellard
                    case 0:
2359 927f621e bellard
                        gen_op_flds_FT0_A0();
2360 367e86e8 bellard
                        break;
2361 367e86e8 bellard
                    case 1:
2362 927f621e bellard
                        gen_op_fildl_FT0_A0();
2363 367e86e8 bellard
                        break;
2364 367e86e8 bellard
                    case 2:
2365 927f621e bellard
                        gen_op_fldl_FT0_A0();
2366 367e86e8 bellard
                        break;
2367 367e86e8 bellard
                    case 3:
2368 367e86e8 bellard
                    default:
2369 927f621e bellard
                        gen_op_fild_FT0_A0();
2370 367e86e8 bellard
                        break;
2371 367e86e8 bellard
                    }
2372 367e86e8 bellard
                    
2373 927f621e bellard
                    gen_op_fp_arith_ST0_FT0[op1]();
2374 927f621e bellard
                    if (op1 == 3) {
2375 367e86e8 bellard
                        /* fcomp needs pop */
2376 927f621e bellard
                        gen_op_fpop();
2377 367e86e8 bellard
                    }
2378 367e86e8 bellard
                }
2379 367e86e8 bellard
                break;
2380 367e86e8 bellard
            case 0x08: /* flds */
2381 367e86e8 bellard
            case 0x0a: /* fsts */
2382 367e86e8 bellard
            case 0x0b: /* fstps */
2383 367e86e8 bellard
            case 0x18: /* fildl */
2384 367e86e8 bellard
            case 0x1a: /* fistl */
2385 367e86e8 bellard
            case 0x1b: /* fistpl */
2386 367e86e8 bellard
            case 0x28: /* fldl */
2387 367e86e8 bellard
            case 0x2a: /* fstl */
2388 367e86e8 bellard
            case 0x2b: /* fstpl */
2389 367e86e8 bellard
            case 0x38: /* filds */
2390 367e86e8 bellard
            case 0x3a: /* fists */
2391 367e86e8 bellard
            case 0x3b: /* fistps */
2392 367e86e8 bellard
                
2393 367e86e8 bellard
                switch(op & 7) {
2394 367e86e8 bellard
                case 0:
2395 927f621e bellard
                    gen_op_fpush();
2396 927f621e bellard
                    switch(op >> 4) {
2397 927f621e bellard
                    case 0:
2398 927f621e bellard
                        gen_op_flds_ST0_A0();
2399 927f621e bellard
                        break;
2400 927f621e bellard
                    case 1:
2401 927f621e bellard
                        gen_op_fildl_ST0_A0();
2402 927f621e bellard
                        break;
2403 927f621e bellard
                    case 2:
2404 927f621e bellard
                        gen_op_fldl_ST0_A0();
2405 927f621e bellard
                        break;
2406 927f621e bellard
                    case 3:
2407 927f621e bellard
                    default:
2408 927f621e bellard
                        gen_op_fild_ST0_A0();
2409 927f621e bellard
                        break;
2410 367e86e8 bellard
                    }
2411 367e86e8 bellard
                    break;
2412 367e86e8 bellard
                default:
2413 927f621e bellard
                    switch(op >> 4) {
2414 927f621e bellard
                    case 0:
2415 927f621e bellard
                        gen_op_fsts_ST0_A0();
2416 927f621e bellard
                        break;
2417 927f621e bellard
                    case 1:
2418 927f621e bellard
                        gen_op_fistl_ST0_A0();
2419 927f621e bellard
                        break;
2420 927f621e bellard
                    case 2:
2421 927f621e bellard
                        gen_op_fstl_ST0_A0();
2422 927f621e bellard
                        break;
2423 927f621e bellard
                    case 3:
2424 927f621e bellard
                    default:
2425 927f621e bellard
                        gen_op_fist_ST0_A0();
2426 927f621e bellard
                        break;
2427 367e86e8 bellard
                    }
2428 367e86e8 bellard
                    if ((op & 7) == 3)
2429 927f621e bellard
                        gen_op_fpop();
2430 367e86e8 bellard
                    break;
2431 367e86e8 bellard
                }
2432 367e86e8 bellard
                break;
2433 4b74fe1f bellard
            case 0x0d: /* fldcw mem */
2434 4b74fe1f bellard
                gen_op_fldcw_A0();
2435 4b74fe1f bellard
                break;
2436 4b74fe1f bellard
            case 0x0f: /* fnstcw mem */
2437 4b74fe1f bellard
                gen_op_fnstcw_A0();
2438 4b74fe1f bellard
                break;
2439 77f8dd5a bellard
            case 0x1d: /* fldt mem */
2440 77f8dd5a bellard
                gen_op_fpush();
2441 77f8dd5a bellard
                gen_op_fldt_ST0_A0();
2442 77f8dd5a bellard
                break;
2443 77f8dd5a bellard
            case 0x1f: /* fstpt mem */
2444 77f8dd5a bellard
                gen_op_fstt_ST0_A0();
2445 77f8dd5a bellard
                gen_op_fpop();
2446 77f8dd5a bellard
                break;
2447 367e86e8 bellard
            case 0x2f: /* fnstsw mem */
2448 4b74fe1f bellard
                gen_op_fnstsw_A0();
2449 367e86e8 bellard
                break;
2450 367e86e8 bellard
            case 0x3c: /* fbld */
2451 77f8dd5a bellard
                gen_op_fpush();
2452 1017ebe9 bellard
                gen_op_fbld_ST0_A0();
2453 77f8dd5a bellard
                break;
2454 367e86e8 bellard
            case 0x3e: /* fbstp */
2455 77f8dd5a bellard
                gen_op_fbst_ST0_A0();
2456 77f8dd5a bellard
                gen_op_fpop();
2457 77f8dd5a bellard
                break;
2458 367e86e8 bellard
            case 0x3d: /* fildll */
2459 927f621e bellard
                gen_op_fpush();
2460 927f621e bellard
                gen_op_fildll_ST0_A0();
2461 367e86e8 bellard
                break;
2462 367e86e8 bellard
            case 0x3f: /* fistpll */
2463 927f621e bellard
                gen_op_fistll_ST0_A0();
2464 927f621e bellard
                gen_op_fpop();
2465 367e86e8 bellard
                break;
2466 367e86e8 bellard
            default:
2467 1a9353d2 bellard
                goto illegal_op;
2468 367e86e8 bellard
            }
2469 367e86e8 bellard
        } else {
2470 367e86e8 bellard
            /* register float ops */
2471 927f621e bellard
            opreg = rm;
2472 367e86e8 bellard
2473 367e86e8 bellard
            switch(op) {
2474 367e86e8 bellard
            case 0x08: /* fld sti */
2475 927f621e bellard
                gen_op_fpush();
2476 927f621e bellard
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2477 367e86e8 bellard
                break;
2478 367e86e8 bellard
            case 0x09: /* fxchg sti */
2479 77f8dd5a bellard
                gen_op_fxchg_ST0_STN(opreg);
2480 367e86e8 bellard
                break;
2481 367e86e8 bellard
            case 0x0a: /* grp d9/2 */
2482 367e86e8 bellard
                switch(rm) {
2483 367e86e8 bellard
                case 0: /* fnop */
2484 367e86e8 bellard
                    break;
2485 367e86e8 bellard
                default:
2486 1a9353d2 bellard
                    goto illegal_op;
2487 367e86e8 bellard
                }
2488 367e86e8 bellard
                break;
2489 367e86e8 bellard
            case 0x0c: /* grp d9/4 */
2490 367e86e8 bellard
                switch(rm) {
2491 367e86e8 bellard
                case 0: /* fchs */
2492 927f621e bellard
                    gen_op_fchs_ST0();
2493 367e86e8 bellard
                    break;
2494 367e86e8 bellard
                case 1: /* fabs */
2495 927f621e bellard
                    gen_op_fabs_ST0();
2496 367e86e8 bellard
                    break;
2497 367e86e8 bellard
                case 4: /* ftst */
2498 927f621e bellard
                    gen_op_fldz_FT0();
2499 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2500 367e86e8 bellard
                    break;
2501 367e86e8 bellard
                case 5: /* fxam */
2502 927f621e bellard
                    gen_op_fxam_ST0();
2503 367e86e8 bellard
                    break;
2504 367e86e8 bellard
                default:
2505 1a9353d2 bellard
                    goto illegal_op;
2506 367e86e8 bellard
                }
2507 367e86e8 bellard
                break;
2508 367e86e8 bellard
            case 0x0d: /* grp d9/5 */
2509 367e86e8 bellard
                {
2510 927f621e bellard
                    switch(rm) {
2511 927f621e bellard
                    case 0:
2512 77f8dd5a bellard
                        gen_op_fpush();
2513 927f621e bellard
                        gen_op_fld1_ST0();
2514 927f621e bellard
                        break;
2515 927f621e bellard
                    case 1:
2516 77f8dd5a bellard
                        gen_op_fpush();
2517 77f8dd5a bellard
                        gen_op_fldl2t_ST0();
2518 927f621e bellard
                        break;
2519 927f621e bellard
                    case 2:
2520 77f8dd5a bellard
                        gen_op_fpush();
2521 77f8dd5a bellard
                        gen_op_fldl2e_ST0();
2522 927f621e bellard
                        break;
2523 927f621e bellard
                    case 3:
2524 77f8dd5a bellard
                        gen_op_fpush();
2525 927f621e bellard
                        gen_op_fldpi_ST0();
2526 927f621e bellard
                        break;
2527 927f621e bellard
                    case 4:
2528 77f8dd5a bellard
                        gen_op_fpush();
2529 927f621e bellard
                        gen_op_fldlg2_ST0();
2530 927f621e bellard
                        break;
2531 927f621e bellard
                    case 5:
2532 77f8dd5a bellard
                        gen_op_fpush();
2533 927f621e bellard
                        gen_op_fldln2_ST0();
2534 927f621e bellard
                        break;
2535 927f621e bellard
                    case 6:
2536 77f8dd5a bellard
                        gen_op_fpush();
2537 927f621e bellard
                        gen_op_fldz_ST0();
2538 927f621e bellard
                        break;
2539 927f621e bellard
                    default:
2540 1a9353d2 bellard
                        goto illegal_op;
2541 367e86e8 bellard
                    }
2542 367e86e8 bellard
                }
2543 367e86e8 bellard
                break;
2544 367e86e8 bellard
            case 0x0e: /* grp d9/6 */
2545 367e86e8 bellard
                switch(rm) {
2546 367e86e8 bellard
                case 0: /* f2xm1 */
2547 927f621e bellard
                    gen_op_f2xm1();
2548 367e86e8 bellard
                    break;
2549 367e86e8 bellard
                case 1: /* fyl2x */
2550 927f621e bellard
                    gen_op_fyl2x();
2551 367e86e8 bellard
                    break;
2552 367e86e8 bellard
                case 2: /* fptan */
2553 927f621e bellard
                    gen_op_fptan();
2554 367e86e8 bellard
                    break;
2555 367e86e8 bellard
                case 3: /* fpatan */
2556 927f621e bellard
                    gen_op_fpatan();
2557 367e86e8 bellard
                    break;
2558 367e86e8 bellard
                case 4: /* fxtract */
2559 927f621e bellard
                    gen_op_fxtract();
2560 367e86e8 bellard
                    break;
2561 367e86e8 bellard
                case 5: /* fprem1 */
2562 927f621e bellard
                    gen_op_fprem1();
2563 367e86e8 bellard
                    break;
2564 367e86e8 bellard
                case 6: /* fdecstp */
2565 927f621e bellard
                    gen_op_fdecstp();
2566 367e86e8 bellard
                    break;
2567 367e86e8 bellard
                default:
2568 927f621e bellard
                case 7: /* fincstp */
2569 927f621e bellard
                    gen_op_fincstp();
2570 367e86e8 bellard
                    break;
2571 367e86e8 bellard
                }
2572 367e86e8 bellard
                break;
2573 367e86e8 bellard
            case 0x0f: /* grp d9/7 */
2574 367e86e8 bellard
                switch(rm) {
2575 367e86e8 bellard
                case 0: /* fprem */
2576 927f621e bellard
                    gen_op_fprem();
2577 367e86e8 bellard
                    break;
2578 367e86e8 bellard
                case 1: /* fyl2xp1 */
2579 927f621e bellard
                    gen_op_fyl2xp1();
2580 927f621e bellard
                    break;
2581 927f621e bellard
                case 2: /* fsqrt */
2582 927f621e bellard
                    gen_op_fsqrt();
2583 367e86e8 bellard
                    break;
2584 367e86e8 bellard
                case 3: /* fsincos */
2585 927f621e bellard
                    gen_op_fsincos();
2586 367e86e8 bellard
                    break;
2587 367e86e8 bellard
                case 5: /* fscale */
2588 927f621e bellard
                    gen_op_fscale();
2589 367e86e8 bellard
                    break;
2590 367e86e8 bellard
                case 4: /* frndint */
2591 927f621e bellard
                    gen_op_frndint();
2592 927f621e bellard
                    break;
2593 367e86e8 bellard
                case 6: /* fsin */
2594 927f621e bellard
                    gen_op_fsin();
2595 927f621e bellard
                    break;
2596 367e86e8 bellard
                default:
2597 367e86e8 bellard
                case 7: /* fcos */
2598 927f621e bellard
                    gen_op_fcos();
2599 367e86e8 bellard
                    break;
2600 367e86e8 bellard
                }
2601 367e86e8 bellard
                break;
2602 367e86e8 bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2603 367e86e8 bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2604 367e86e8 bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2605 367e86e8 bellard
                {
2606 927f621e bellard
                    int op1;
2607 367e86e8 bellard
                    
2608 927f621e bellard
                    op1 = op & 7;
2609 367e86e8 bellard
                    if (op >= 0x20) {
2610 927f621e bellard
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2611 77f8dd5a bellard
                        if (op >= 0x30)
2612 77f8dd5a bellard
                            gen_op_fpop();
2613 367e86e8 bellard
                    } else {
2614 927f621e bellard
                        gen_op_fmov_FT0_STN(opreg);
2615 927f621e bellard
                        gen_op_fp_arith_ST0_FT0[op1]();
2616 367e86e8 bellard
                    }
2617 367e86e8 bellard
                }
2618 367e86e8 bellard
                break;
2619 367e86e8 bellard
            case 0x02: /* fcom */
2620 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2621 927f621e bellard
                gen_op_fcom_ST0_FT0();
2622 367e86e8 bellard
                break;
2623 367e86e8 bellard
            case 0x03: /* fcomp */
2624 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2625 927f621e bellard
                gen_op_fcom_ST0_FT0();
2626 927f621e bellard
                gen_op_fpop();
2627 367e86e8 bellard
                break;
2628 367e86e8 bellard
            case 0x15: /* da/5 */
2629 367e86e8 bellard
                switch(rm) {
2630 367e86e8 bellard
                case 1: /* fucompp */
2631 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2632 77f8dd5a bellard
                    gen_op_fucom_ST0_FT0();
2633 927f621e bellard
                    gen_op_fpop();
2634 927f621e bellard
                    gen_op_fpop();
2635 367e86e8 bellard
                    break;
2636 367e86e8 bellard
                default:
2637 1a9353d2 bellard
                    goto illegal_op;
2638 1a9353d2 bellard
                }
2639 1a9353d2 bellard
                break;
2640 1a9353d2 bellard
            case 0x1c:
2641 1a9353d2 bellard
                switch(rm) {
2642 1a9353d2 bellard
                case 2: /* fclex */
2643 1a9353d2 bellard
                    gen_op_fclex();
2644 1a9353d2 bellard
                    break;
2645 1a9353d2 bellard
                case 3: /* fninit */
2646 1a9353d2 bellard
                    gen_op_fninit();
2647 1a9353d2 bellard
                    break;
2648 1a9353d2 bellard
                default:
2649 1a9353d2 bellard
                    goto illegal_op;
2650 367e86e8 bellard
                }
2651 367e86e8 bellard
                break;
2652 367e86e8 bellard
            case 0x2a: /* fst sti */
2653 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2654 367e86e8 bellard
                break;
2655 367e86e8 bellard
            case 0x2b: /* fstp sti */
2656 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2657 927f621e bellard
                gen_op_fpop();
2658 367e86e8 bellard
                break;
2659 77f8dd5a bellard
            case 0x2c: /* fucom st(i) */
2660 77f8dd5a bellard
                gen_op_fmov_FT0_STN(opreg);
2661 77f8dd5a bellard
                gen_op_fucom_ST0_FT0();
2662 77f8dd5a bellard
                break;
2663 77f8dd5a bellard
            case 0x2d: /* fucomp st(i) */
2664 77f8dd5a bellard
                gen_op_fmov_FT0_STN(opreg);
2665 77f8dd5a bellard
                gen_op_fucom_ST0_FT0();
2666 77f8dd5a bellard
                gen_op_fpop();
2667 77f8dd5a bellard
                break;
2668 367e86e8 bellard
            case 0x33: /* de/3 */
2669 367e86e8 bellard
                switch(rm) {
2670 367e86e8 bellard
                case 1: /* fcompp */
2671 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2672 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2673 927f621e bellard
                    gen_op_fpop();
2674 927f621e bellard
                    gen_op_fpop();
2675 367e86e8 bellard
                    break;
2676 367e86e8 bellard
                default:
2677 1a9353d2 bellard
                    goto illegal_op;
2678 367e86e8 bellard
                }
2679 367e86e8 bellard
                break;
2680 367e86e8 bellard
            case 0x3c: /* df/4 */
2681 367e86e8 bellard
                switch(rm) {
2682 367e86e8 bellard
                case 0:
2683 77f8dd5a bellard
                    gen_op_fnstsw_EAX();
2684 367e86e8 bellard
                    break;
2685 367e86e8 bellard
                default:
2686 1a9353d2 bellard
                    goto illegal_op;
2687 367e86e8 bellard
                }
2688 367e86e8 bellard
                break;
2689 367e86e8 bellard
            default:
2690 1a9353d2 bellard
                goto illegal_op;
2691 367e86e8 bellard
            }
2692 367e86e8 bellard
        }
2693 367e86e8 bellard
        break;
2694 367e86e8 bellard
        /************************/
2695 367e86e8 bellard
        /* string ops */
2696 9c605cb1 bellard
2697 367e86e8 bellard
    case 0xa4: /* movsS */
2698 367e86e8 bellard
    case 0xa5:
2699 367e86e8 bellard
        if ((b & 1) == 0)
2700 367e86e8 bellard
            ot = OT_BYTE;
2701 367e86e8 bellard
        else
2702 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2703 9c605cb1 bellard
2704 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2705 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_movs + 9);
2706 367e86e8 bellard
        } else {
2707 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_movs);
2708 367e86e8 bellard
        }
2709 367e86e8 bellard
        break;
2710 367e86e8 bellard
        
2711 367e86e8 bellard
    case 0xaa: /* stosS */
2712 367e86e8 bellard
    case 0xab:
2713 367e86e8 bellard
        if ((b & 1) == 0)
2714 367e86e8 bellard
            ot = OT_BYTE;
2715 367e86e8 bellard
        else
2716 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2717 9c605cb1 bellard
2718 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2719 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_stos + 9);
2720 367e86e8 bellard
        } else {
2721 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_stos);
2722 367e86e8 bellard
        }
2723 367e86e8 bellard
        break;
2724 367e86e8 bellard
    case 0xac: /* lodsS */
2725 367e86e8 bellard
    case 0xad:
2726 367e86e8 bellard
        if ((b & 1) == 0)
2727 367e86e8 bellard
            ot = OT_BYTE;
2728 367e86e8 bellard
        else
2729 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2730 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2731 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_lods + 9);
2732 367e86e8 bellard
        } else {
2733 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_lods);
2734 367e86e8 bellard
        }
2735 367e86e8 bellard
        break;
2736 367e86e8 bellard
    case 0xae: /* scasS */
2737 367e86e8 bellard
    case 0xaf:
2738 367e86e8 bellard
        if ((b & 1) == 0)
2739 367e86e8 bellard
            ot = OT_BYTE;
2740 367e86e8 bellard
        else
2741 9c605cb1 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2742 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2743 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2744 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2745 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2746 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2747 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2748 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2749 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2750 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas + 9);
2751 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2752 367e86e8 bellard
        } else {
2753 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas);
2754 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2755 367e86e8 bellard
        }
2756 367e86e8 bellard
        break;
2757 367e86e8 bellard
2758 367e86e8 bellard
    case 0xa6: /* cmpsS */
2759 367e86e8 bellard
    case 0xa7:
2760 367e86e8 bellard
        if ((b & 1) == 0)
2761 367e86e8 bellard
            ot = OT_BYTE;
2762 367e86e8 bellard
        else
2763 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2764 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2765 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2766 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2767 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2768 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2769 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2770 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2771 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2772 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps + 9);
2773 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2774 367e86e8 bellard
        } else {
2775 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps);
2776 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2777 367e86e8 bellard
        }
2778 367e86e8 bellard
        break;
2779 367e86e8 bellard
    case 0x6c: /* insS */
2780 367e86e8 bellard
    case 0x6d:
2781 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2782 982b4315 bellard
            /* NOTE: even for (E)CX = 0 the exception is raised */
2783 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2784 367e86e8 bellard
        } else {
2785 982b4315 bellard
            if ((b & 1) == 0)
2786 982b4315 bellard
                ot = OT_BYTE;
2787 982b4315 bellard
            else
2788 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2789 982b4315 bellard
            if (prefixes & PREFIX_REPZ) {
2790 982b4315 bellard
                gen_string_es(s, ot, gen_op_ins + 9);
2791 982b4315 bellard
            } else {
2792 982b4315 bellard
                gen_string_es(s, ot, gen_op_ins);
2793 982b4315 bellard
            }
2794 367e86e8 bellard
        }
2795 367e86e8 bellard
        break;
2796 367e86e8 bellard
    case 0x6e: /* outsS */
2797 367e86e8 bellard
    case 0x6f:
2798 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2799 982b4315 bellard
            /* NOTE: even for (E)CX = 0 the exception is raised */
2800 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2801 367e86e8 bellard
        } else {
2802 982b4315 bellard
            if ((b & 1) == 0)
2803 982b4315 bellard
                ot = OT_BYTE;
2804 982b4315 bellard
            else
2805 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2806 982b4315 bellard
            if (prefixes & PREFIX_REPZ) {
2807 982b4315 bellard
                gen_string_ds(s, ot, gen_op_outs + 9);
2808 982b4315 bellard
            } else {
2809 982b4315 bellard
                gen_string_ds(s, ot, gen_op_outs);
2810 982b4315 bellard
            }
2811 367e86e8 bellard
        }
2812 367e86e8 bellard
        break;
2813 9c605cb1 bellard
2814 9c605cb1 bellard
        /************************/
2815 9c605cb1 bellard
        /* port I/O */
2816 ba1c6e37 bellard
    case 0xe4:
2817 ba1c6e37 bellard
    case 0xe5:
2818 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2819 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2820 982b4315 bellard
        } else {
2821 982b4315 bellard
            if ((b & 1) == 0)
2822 982b4315 bellard
                ot = OT_BYTE;
2823 982b4315 bellard
            else
2824 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2825 982b4315 bellard
            val = ldub(s->pc++);
2826 982b4315 bellard
            gen_op_movl_T0_im(val);
2827 982b4315 bellard
            gen_op_in[ot]();
2828 982b4315 bellard
            gen_op_mov_reg_T1[ot][R_EAX]();
2829 982b4315 bellard
        }
2830 ba1c6e37 bellard
        break;
2831 ba1c6e37 bellard
    case 0xe6:
2832 ba1c6e37 bellard
    case 0xe7:
2833 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2834 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2835 982b4315 bellard
        } else {
2836 982b4315 bellard
            if ((b & 1) == 0)
2837 982b4315 bellard
                ot = OT_BYTE;
2838 982b4315 bellard
            else
2839 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2840 982b4315 bellard
            val = ldub(s->pc++);
2841 982b4315 bellard
            gen_op_movl_T0_im(val);
2842 982b4315 bellard
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2843 982b4315 bellard
            gen_op_out[ot]();
2844 982b4315 bellard
        }
2845 ba1c6e37 bellard
        break;
2846 ba1c6e37 bellard
    case 0xec:
2847 ba1c6e37 bellard
    case 0xed:
2848 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2849 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2850 982b4315 bellard
        } else {
2851 982b4315 bellard
            if ((b & 1) == 0)
2852 982b4315 bellard
                ot = OT_BYTE;
2853 982b4315 bellard
            else
2854 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2855 982b4315 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2856 982b4315 bellard
            gen_op_in[ot]();
2857 982b4315 bellard
            gen_op_mov_reg_T1[ot][R_EAX]();
2858 982b4315 bellard
        }
2859 ba1c6e37 bellard
        break;
2860 ba1c6e37 bellard
    case 0xee:
2861 ba1c6e37 bellard
    case 0xef:
2862 982b4315 bellard
        if (s->cpl > s->iopl || s->vm86) {
2863 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2864 982b4315 bellard
        } else {
2865 982b4315 bellard
            if ((b & 1) == 0)
2866 982b4315 bellard
                ot = OT_BYTE;
2867 982b4315 bellard
            else
2868 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2869 982b4315 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2870 982b4315 bellard
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2871 982b4315 bellard
            gen_op_out[ot]();
2872 982b4315 bellard
        }
2873 ba1c6e37 bellard
        break;
2874 367e86e8 bellard
2875 367e86e8 bellard
        /************************/
2876 367e86e8 bellard
        /* control */
2877 367e86e8 bellard
    case 0xc2: /* ret im */
2878 367e86e8 bellard
        val = ldsw(s->pc);
2879 367e86e8 bellard
        s->pc += 2;
2880 dab2ed99 bellard
        gen_pop_T0(s);
2881 dab2ed99 bellard
        if (s->ss32)
2882 dab2ed99 bellard
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2883 dab2ed99 bellard
        else
2884 dab2ed99 bellard
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2885 dab2ed99 bellard
        if (s->dflag == 0)
2886 dab2ed99 bellard
            gen_op_andl_T0_ffff();
2887 367e86e8 bellard
        gen_op_jmp_T0();
2888 6dbad63e bellard
        s->is_jmp = 1;
2889 367e86e8 bellard
        break;
2890 367e86e8 bellard
    case 0xc3: /* ret */
2891 dab2ed99 bellard
        gen_pop_T0(s);
2892 dab2ed99 bellard
        gen_pop_update(s);
2893 dab2ed99 bellard
        if (s->dflag == 0)
2894 dab2ed99 bellard
            gen_op_andl_T0_ffff();
2895 367e86e8 bellard
        gen_op_jmp_T0();
2896 6dbad63e bellard
        s->is_jmp = 1;
2897 367e86e8 bellard
        break;
2898 dab2ed99 bellard
    case 0xca: /* lret im */
2899 f631ef9b bellard
        /* XXX: not restartable */
2900 dab2ed99 bellard
        val = ldsw(s->pc);
2901 dab2ed99 bellard
        s->pc += 2;
2902 dab2ed99 bellard
        /* pop offset */
2903 dab2ed99 bellard
        gen_pop_T0(s);
2904 dab2ed99 bellard
        if (s->dflag == 0)
2905 dab2ed99 bellard
            gen_op_andl_T0_ffff();
2906 dab2ed99 bellard
        gen_op_jmp_T0();
2907 dab2ed99 bellard
        gen_pop_update(s);
2908 dab2ed99 bellard
        /* pop selector */
2909 dab2ed99 bellard
        gen_pop_T0(s);
2910 dab2ed99 bellard
        gen_movl_seg_T0(s, R_CS);
2911 dab2ed99 bellard
        gen_pop_update(s);
2912 dab2ed99 bellard
        /* add stack offset */
2913 dab2ed99 bellard
        if (s->ss32)
2914 148dfc2a bellard
            gen_op_addl_ESP_im(val);
2915 dab2ed99 bellard
        else
2916 148dfc2a bellard
            gen_op_addw_ESP_im(val);
2917 dab2ed99 bellard
        s->is_jmp = 1;
2918 dab2ed99 bellard
        break;
2919 dab2ed99 bellard
    case 0xcb: /* lret */
2920 f631ef9b bellard
        /* XXX: not restartable */
2921 dab2ed99 bellard
        /* pop offset */
2922 dab2ed99 bellard
        gen_pop_T0(s);
2923 dab2ed99 bellard
        if (s->dflag == 0)
2924 dab2ed99 bellard
            gen_op_andl_T0_ffff();
2925 dab2ed99 bellard
        gen_op_jmp_T0();
2926 dab2ed99 bellard
        gen_pop_update(s);
2927 dab2ed99 bellard
        /* pop selector */
2928 dab2ed99 bellard
        gen_pop_T0(s);
2929 dab2ed99 bellard
        gen_movl_seg_T0(s, R_CS);
2930 dab2ed99 bellard
        gen_pop_update(s);
2931 6dbad63e bellard
        s->is_jmp = 1;
2932 367e86e8 bellard
        break;
2933 f631ef9b bellard
    case 0xcf: /* iret */
2934 148dfc2a bellard
        if (s->vm86 && s->iopl != 3) {
2935 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2936 f631ef9b bellard
        } else {
2937 148dfc2a bellard
            /* XXX: not restartable */
2938 148dfc2a bellard
            /* pop offset */
2939 148dfc2a bellard
            gen_pop_T0(s);
2940 148dfc2a bellard
            if (s->dflag == 0)
2941 148dfc2a bellard
                gen_op_andl_T0_ffff();
2942 148dfc2a bellard
            gen_op_jmp_T0();
2943 148dfc2a bellard
            gen_pop_update(s);
2944 148dfc2a bellard
            /* pop selector */
2945 148dfc2a bellard
            gen_pop_T0(s);
2946 148dfc2a bellard
            gen_movl_seg_T0(s, R_CS);
2947 148dfc2a bellard
            gen_pop_update(s);
2948 148dfc2a bellard
            /* pop eflags */
2949 148dfc2a bellard
            gen_pop_T0(s);
2950 148dfc2a bellard
            if (s->dflag) {
2951 148dfc2a bellard
                gen_op_movl_eflags_T0();
2952 148dfc2a bellard
            } else {
2953 f631ef9b bellard
                gen_op_movw_eflags_T0();
2954 148dfc2a bellard
            }
2955 148dfc2a bellard
            gen_pop_update(s);
2956 148dfc2a bellard
            s->cc_op = CC_OP_EFLAGS;
2957 f631ef9b bellard
        }
2958 f631ef9b bellard
        s->is_jmp = 1;
2959 f631ef9b bellard
        break;
2960 dab2ed99 bellard
    case 0xe8: /* call im */
2961 dab2ed99 bellard
        {
2962 dab2ed99 bellard
            unsigned int next_eip;
2963 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2964 dab2ed99 bellard
            val = insn_get(s, ot);
2965 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
2966 dab2ed99 bellard
            val += next_eip;
2967 dab2ed99 bellard
            if (s->dflag == 0)
2968 dab2ed99 bellard
                val &= 0xffff;
2969 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
2970 dab2ed99 bellard
            gen_push_T0(s);
2971 dab2ed99 bellard
            gen_op_jmp_im(val);
2972 dab2ed99 bellard
            s->is_jmp = 1;
2973 dab2ed99 bellard
        }
2974 dab2ed99 bellard
        break;
2975 dab2ed99 bellard
    case 0x9a: /* lcall im */
2976 dab2ed99 bellard
        {
2977 dab2ed99 bellard
            unsigned int selector, offset;
2978 dab2ed99 bellard
2979 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2980 dab2ed99 bellard
            offset = insn_get(s, ot);
2981 dab2ed99 bellard
            selector = insn_get(s, OT_WORD);
2982 dab2ed99 bellard
            
2983 dab2ed99 bellard
            /* push return segment + offset */
2984 dab2ed99 bellard
            gen_op_movl_T0_seg(R_CS);
2985 dab2ed99 bellard
            gen_push_T0(s);
2986 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
2987 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
2988 dab2ed99 bellard
            gen_push_T0(s);
2989 dab2ed99 bellard
2990 dab2ed99 bellard
            /* change cs and pc */
2991 dab2ed99 bellard
            gen_op_movl_T0_im(selector);
2992 dab2ed99 bellard
            gen_movl_seg_T0(s, R_CS);
2993 dab2ed99 bellard
            gen_op_jmp_im((unsigned long)offset);
2994 dab2ed99 bellard
            s->is_jmp = 1;
2995 dab2ed99 bellard
        }
2996 dab2ed99 bellard
        break;
2997 367e86e8 bellard
    case 0xe9: /* jmp */
2998 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2999 dab2ed99 bellard
        val = insn_get(s, ot);
3000 dab2ed99 bellard
        val += s->pc - s->cs_base;
3001 dab2ed99 bellard
        if (s->dflag == 0)
3002 dab2ed99 bellard
            val = val & 0xffff;
3003 367e86e8 bellard
        gen_op_jmp_im(val);
3004 6dbad63e bellard
        s->is_jmp = 1;
3005 367e86e8 bellard
        break;
3006 dab2ed99 bellard
    case 0xea: /* ljmp im */
3007 dab2ed99 bellard
        {
3008 dab2ed99 bellard
            unsigned int selector, offset;
3009 dab2ed99 bellard
3010 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
3011 dab2ed99 bellard
            offset = insn_get(s, ot);
3012 dab2ed99 bellard
            selector = insn_get(s, OT_WORD);
3013 dab2ed99 bellard
            
3014 dab2ed99 bellard
            /* change cs and pc */
3015 dab2ed99 bellard
            gen_op_movl_T0_im(selector);
3016 dab2ed99 bellard
            gen_movl_seg_T0(s, R_CS);
3017 dab2ed99 bellard
            gen_op_jmp_im((unsigned long)offset);
3018 dab2ed99 bellard
            s->is_jmp = 1;
3019 dab2ed99 bellard
        }
3020 dab2ed99 bellard
        break;
3021 367e86e8 bellard
    case 0xeb: /* jmp Jb */
3022 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3023 dab2ed99 bellard
        val += s->pc - s->cs_base;
3024 dab2ed99 bellard
        if (s->dflag == 0)
3025 dab2ed99 bellard
            val = val & 0xffff;
3026 367e86e8 bellard
        gen_op_jmp_im(val);
3027 6dbad63e bellard
        s->is_jmp = 1;
3028 367e86e8 bellard
        break;
3029 367e86e8 bellard
    case 0x70 ... 0x7f: /* jcc Jb */
3030 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3031 367e86e8 bellard
        goto do_jcc;
3032 367e86e8 bellard
    case 0x180 ... 0x18f: /* jcc Jv */
3033 367e86e8 bellard
        if (dflag) {
3034 367e86e8 bellard
            val = insn_get(s, OT_LONG);
3035 367e86e8 bellard
        } else {
3036 367e86e8 bellard
            val = (int16_t)insn_get(s, OT_WORD); 
3037 367e86e8 bellard
        }
3038 367e86e8 bellard
    do_jcc:
3039 dab2ed99 bellard
        next_eip = s->pc - s->cs_base;
3040 dab2ed99 bellard
        val += next_eip;
3041 dab2ed99 bellard
        if (s->dflag == 0)
3042 dab2ed99 bellard
            val &= 0xffff;
3043 dab2ed99 bellard
        gen_jcc(s, b, val, next_eip);
3044 6dbad63e bellard
        s->is_jmp = 1;
3045 367e86e8 bellard
        break;
3046 367e86e8 bellard
3047 5dd9488c bellard
    case 0x190 ... 0x19f: /* setcc Gv */
3048 367e86e8 bellard
        modrm = ldub(s->pc++);
3049 367e86e8 bellard
        gen_setcc(s, b);
3050 367e86e8 bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3051 367e86e8 bellard
        break;
3052 5dd9488c bellard
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3053 5dd9488c bellard
        ot = dflag ? OT_LONG : OT_WORD;
3054 5dd9488c bellard
        modrm = ldub(s->pc++);
3055 5dd9488c bellard
        reg = (modrm >> 3) & 7;
3056 5dd9488c bellard
        mod = (modrm >> 6) & 3;
3057 5dd9488c bellard
        gen_setcc(s, b);
3058 5dd9488c bellard
        if (mod != 3) {
3059 5dd9488c bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3060 5dd9488c bellard
            gen_op_ld_T1_A0[ot]();
3061 5dd9488c bellard
        } else {
3062 5dd9488c bellard
            rm = modrm & 7;
3063 5dd9488c bellard
            gen_op_mov_TN_reg[ot][1][rm]();
3064 5dd9488c bellard
        }
3065 5dd9488c bellard
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3066 5dd9488c bellard
        break;
3067 5dd9488c bellard
        
3068 367e86e8 bellard
        /************************/
3069 367e86e8 bellard
        /* flags */
3070 367e86e8 bellard
    case 0x9c: /* pushf */
3071 148dfc2a bellard
        if (s->vm86 && s->iopl != 3) {
3072 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3073 148dfc2a bellard
        } else {
3074 148dfc2a bellard
            if (s->cc_op != CC_OP_DYNAMIC)
3075 148dfc2a bellard
                gen_op_set_cc_op(s->cc_op);
3076 f631ef9b bellard
            gen_op_movl_T0_eflags();
3077 148dfc2a bellard
            gen_push_T0(s);
3078 148dfc2a bellard
        }
3079 367e86e8 bellard
        break;
3080 367e86e8 bellard
    case 0x9d: /* popf */
3081 148dfc2a bellard
        if (s->vm86 && s->iopl != 3) {
3082 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3083 f631ef9b bellard
        } else {
3084 148dfc2a bellard
            gen_pop_T0(s);
3085 148dfc2a bellard
            if (s->dflag) {
3086 148dfc2a bellard
                gen_op_movl_eflags_T0();
3087 148dfc2a bellard
            } else {
3088 f631ef9b bellard
                gen_op_movw_eflags_T0();
3089 148dfc2a bellard
            }
3090 148dfc2a bellard
            gen_pop_update(s);
3091 148dfc2a bellard
            s->cc_op = CC_OP_EFLAGS;
3092 f631ef9b bellard
        }
3093 367e86e8 bellard
        break;
3094 367e86e8 bellard
    case 0x9e: /* sahf */
3095 367e86e8 bellard
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3096 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3097 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3098 367e86e8 bellard
        gen_op_movb_eflags_T0();
3099 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3100 367e86e8 bellard
        break;
3101 367e86e8 bellard
    case 0x9f: /* lahf */
3102 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3103 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3104 367e86e8 bellard
        gen_op_movl_T0_eflags();
3105 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3106 367e86e8 bellard
        break;
3107 367e86e8 bellard
    case 0xf5: /* cmc */
3108 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3109 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3110 367e86e8 bellard
        gen_op_cmc();
3111 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3112 367e86e8 bellard
        break;
3113 367e86e8 bellard
    case 0xf8: /* clc */
3114 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3115 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3116 367e86e8 bellard
        gen_op_clc();
3117 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3118 367e86e8 bellard
        break;
3119 367e86e8 bellard
    case 0xf9: /* stc */
3120 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3121 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3122 367e86e8 bellard
        gen_op_stc();
3123 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3124 367e86e8 bellard
        break;
3125 367e86e8 bellard
    case 0xfc: /* cld */
3126 367e86e8 bellard
        gen_op_cld();
3127 367e86e8 bellard
        break;
3128 367e86e8 bellard
    case 0xfd: /* std */
3129 367e86e8 bellard
        gen_op_std();
3130 367e86e8 bellard
        break;
3131 367e86e8 bellard
3132 367e86e8 bellard
        /************************/
3133 4b74fe1f bellard
        /* bit operations */
3134 4b74fe1f bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3135 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
3136 4b74fe1f bellard
        modrm = ldub(s->pc++);
3137 4b74fe1f bellard
        op = (modrm >> 3) & 7;
3138 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
3139 4b74fe1f bellard
        rm = modrm & 7;
3140 4b74fe1f bellard
        if (mod != 3) {
3141 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3142 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
3143 4b74fe1f bellard
        } else {
3144 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
3145 4b74fe1f bellard
        }
3146 4b74fe1f bellard
        /* load shift */
3147 4b74fe1f bellard
        val = ldub(s->pc++);
3148 4b74fe1f bellard
        gen_op_movl_T1_im(val);
3149 4b74fe1f bellard
        if (op < 4)
3150 1a9353d2 bellard
            goto illegal_op;
3151 4b74fe1f bellard
        op -= 4;
3152 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3153 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
3154 4b74fe1f bellard
        if (op != 0) {
3155 4b74fe1f bellard
            if (mod != 3)
3156 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
3157 4b74fe1f bellard
            else
3158 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
3159 4b74fe1f bellard
        }
3160 4b74fe1f bellard
        break;
3161 4b74fe1f bellard
    case 0x1a3: /* bt Gv, Ev */
3162 4b74fe1f bellard
        op = 0;
3163 4b74fe1f bellard
        goto do_btx;
3164 4b74fe1f bellard
    case 0x1ab: /* bts */
3165 4b74fe1f bellard
        op = 1;
3166 4b74fe1f bellard
        goto do_btx;
3167 4b74fe1f bellard
    case 0x1b3: /* btr */
3168 4b74fe1f bellard
        op = 2;
3169 4b74fe1f bellard
        goto do_btx;
3170 4b74fe1f bellard
    case 0x1bb: /* btc */
3171 4b74fe1f bellard
        op = 3;
3172 4b74fe1f bellard
    do_btx:
3173 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
3174 4b74fe1f bellard
        modrm = ldub(s->pc++);
3175 4b74fe1f bellard
        reg = (modrm >> 3) & 7;
3176 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
3177 4b74fe1f bellard
        rm = modrm & 7;
3178 4b74fe1f bellard
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3179 4b74fe1f bellard
        if (mod != 3) {
3180 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3181 4b74fe1f bellard
            /* specific case: we need to add a displacement */
3182 4b74fe1f bellard
            if (ot == OT_WORD)
3183 4b74fe1f bellard
                gen_op_add_bitw_A0_T1();
3184 4b74fe1f bellard
            else
3185 4b74fe1f bellard
                gen_op_add_bitl_A0_T1();
3186 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
3187 4b74fe1f bellard
        } else {
3188 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
3189 4b74fe1f bellard
        }
3190 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3191 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
3192 4b74fe1f bellard
        if (op != 0) {
3193 4b74fe1f bellard
            if (mod != 3)
3194 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
3195 4b74fe1f bellard
            else
3196 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
3197 4b74fe1f bellard
        }
3198 4b74fe1f bellard
        break;
3199 77f8dd5a bellard
    case 0x1bc: /* bsf */
3200 77f8dd5a bellard
    case 0x1bd: /* bsr */
3201 77f8dd5a bellard
        ot = dflag ? OT_LONG : OT_WORD;
3202 77f8dd5a bellard
        modrm = ldub(s->pc++);
3203 77f8dd5a bellard
        reg = (modrm >> 3) & 7;
3204 77f8dd5a bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3205 77f8dd5a bellard
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3206 77f8dd5a bellard
        /* NOTE: we always write back the result. Intel doc says it is
3207 77f8dd5a bellard
           undefined if T0 == 0 */
3208 77f8dd5a bellard
        gen_op_mov_reg_T0[ot][reg]();
3209 77f8dd5a bellard
        s->cc_op = CC_OP_LOGICB + ot;
3210 77f8dd5a bellard
        break;
3211 4b74fe1f bellard
        /************************/
3212 27362c82 bellard
        /* bcd */
3213 27362c82 bellard
    case 0x27: /* daa */
3214 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3215 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3216 27362c82 bellard
        gen_op_daa();
3217 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3218 27362c82 bellard
        break;
3219 27362c82 bellard
    case 0x2f: /* das */
3220 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3221 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3222 27362c82 bellard
        gen_op_das();
3223 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3224 27362c82 bellard
        break;
3225 27362c82 bellard
    case 0x37: /* aaa */
3226 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3227 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3228 27362c82 bellard
        gen_op_aaa();
3229 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3230 27362c82 bellard
        break;
3231 27362c82 bellard
    case 0x3f: /* aas */
3232 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3233 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3234 27362c82 bellard
        gen_op_aas();
3235 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3236 27362c82 bellard
        break;
3237 27362c82 bellard
    case 0xd4: /* aam */
3238 27362c82 bellard
        val = ldub(s->pc++);
3239 27362c82 bellard
        gen_op_aam(val);
3240 27362c82 bellard
        s->cc_op = CC_OP_LOGICB;
3241 27362c82 bellard
        break;
3242 27362c82 bellard
    case 0xd5: /* aad */
3243 27362c82 bellard
        val = ldub(s->pc++);
3244 27362c82 bellard
        gen_op_aad(val);
3245 27362c82 bellard
        s->cc_op = CC_OP_LOGICB;
3246 27362c82 bellard
        break;
3247 27362c82 bellard
        /************************/
3248 367e86e8 bellard
        /* misc */
3249 367e86e8 bellard
    case 0x90: /* nop */
3250 367e86e8 bellard
        break;
3251 0ecfa993 bellard
    case 0xcc: /* int3 */
3252 78c34e98 bellard
        gen_exception(s, EXCP03_INT3, s->pc - s->cs_base);
3253 0ecfa993 bellard
        break;
3254 0ecfa993 bellard
    case 0xcd: /* int N */
3255 0ecfa993 bellard
        val = ldub(s->pc++);
3256 c50c0c3f bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3257 c50c0c3f bellard
            gen_op_set_cc_op(s->cc_op);
3258 982b4315 bellard
        gen_op_int_im(val, pc_start - s->cs_base);
3259 6dbad63e bellard
        s->is_jmp = 1;
3260 0ecfa993 bellard
        break;
3261 0ecfa993 bellard
    case 0xce: /* into */
3262 0ecfa993 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3263 0ecfa993 bellard
            gen_op_set_cc_op(s->cc_op);
3264 78c34e98 bellard
        gen_op_into(s->pc - s->cs_base);
3265 9c605cb1 bellard
        break;
3266 f631ef9b bellard
    case 0xfa: /* cli */
3267 982b4315 bellard
        if (!s->vm86) {
3268 148dfc2a bellard
            if (s->cpl <= s->iopl) {
3269 982b4315 bellard
                gen_op_cli();
3270 148dfc2a bellard
            } else {
3271 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3272 148dfc2a bellard
            }
3273 982b4315 bellard
        } else {
3274 148dfc2a bellard
            if (s->iopl == 3) {
3275 982b4315 bellard
                gen_op_cli();
3276 148dfc2a bellard
            } else {
3277 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3278 148dfc2a bellard
            }
3279 982b4315 bellard
        }
3280 f631ef9b bellard
        break;
3281 f631ef9b bellard
    case 0xfb: /* sti */
3282 982b4315 bellard
        if (!s->vm86) {
3283 148dfc2a bellard
            if (s->cpl <= s->iopl) {
3284 982b4315 bellard
                gen_op_sti();
3285 148dfc2a bellard
            } else {
3286 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3287 148dfc2a bellard
            }
3288 982b4315 bellard
        } else {
3289 148dfc2a bellard
            if (s->iopl == 3) {
3290 982b4315 bellard
                gen_op_sti();
3291 148dfc2a bellard
            } else {
3292 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3293 148dfc2a bellard
            }
3294 982b4315 bellard
        }
3295 f631ef9b bellard
        break;
3296 9c605cb1 bellard
    case 0x62: /* bound */
3297 9c605cb1 bellard
        ot = dflag ? OT_LONG : OT_WORD;
3298 9c605cb1 bellard
        modrm = ldub(s->pc++);
3299 9c605cb1 bellard
        reg = (modrm >> 3) & 7;
3300 9c605cb1 bellard
        mod = (modrm >> 6) & 3;
3301 9c605cb1 bellard
        if (mod == 3)
3302 9c605cb1 bellard
            goto illegal_op;
3303 9c605cb1 bellard
        gen_op_mov_reg_T0[ot][reg]();
3304 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3305 9c605cb1 bellard
        if (ot == OT_WORD)
3306 9c605cb1 bellard
            gen_op_boundw();
3307 9c605cb1 bellard
        else
3308 9c605cb1 bellard
            gen_op_boundl();
3309 0ecfa993 bellard
        break;
3310 4b74fe1f bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
3311 27362c82 bellard
        reg = b & 7;
3312 27362c82 bellard
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3313 27362c82 bellard
        gen_op_bswapl_T0();
3314 27362c82 bellard
        gen_op_mov_reg_T0[OT_LONG][reg]();
3315 27362c82 bellard
        break;
3316 27362c82 bellard
    case 0xd6: /* salc */
3317 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3318 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3319 27362c82 bellard
        gen_op_salc();
3320 27362c82 bellard
        break;
3321 1a9353d2 bellard
    case 0xe0: /* loopnz */
3322 1a9353d2 bellard
    case 0xe1: /* loopz */
3323 1a9353d2 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3324 1a9353d2 bellard
            gen_op_set_cc_op(s->cc_op);
3325 1a9353d2 bellard
        /* FALL THRU */
3326 1a9353d2 bellard
    case 0xe2: /* loop */
3327 1a9353d2 bellard
    case 0xe3: /* jecxz */
3328 1a9353d2 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3329 dab2ed99 bellard
        next_eip = s->pc - s->cs_base;
3330 dab2ed99 bellard
        val += next_eip;
3331 dab2ed99 bellard
        if (s->dflag == 0)
3332 dab2ed99 bellard
            val &= 0xffff;
3333 dab2ed99 bellard
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3334 1a9353d2 bellard
        s->is_jmp = 1;
3335 1a9353d2 bellard
        break;
3336 5dd9488c bellard
    case 0x131: /* rdtsc */
3337 27362c82 bellard
        gen_op_rdtsc();
3338 27362c82 bellard
        break;
3339 367e86e8 bellard
    case 0x1a2: /* cpuid */
3340 9c605cb1 bellard
        gen_op_cpuid();
3341 367e86e8 bellard
        break;
3342 982b4315 bellard
    case 0xf4: /* hlt */
3343 148dfc2a bellard
        /* XXX: if cpl == 0, then should do something else */
3344 c50c0c3f bellard
        gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3345 982b4315 bellard
        break;
3346 78c34e98 bellard
    case 0x102: /* lar */
3347 78c34e98 bellard
    case 0x103: /* lsl */
3348 78c34e98 bellard
        if (s->vm86)
3349 78c34e98 bellard
            goto illegal_op;
3350 78c34e98 bellard
        ot = dflag ? OT_LONG : OT_WORD;
3351 78c34e98 bellard
        modrm = ldub(s->pc++);
3352 78c34e98 bellard
        reg = (modrm >> 3) & 7;
3353 78c34e98 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3354 78c34e98 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
3355 78c34e98 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3356 78c34e98 bellard
            gen_op_set_cc_op(s->cc_op);
3357 78c34e98 bellard
        if (b == 0x102)
3358 78c34e98 bellard
            gen_op_lar();
3359 78c34e98 bellard
        else
3360 78c34e98 bellard
            gen_op_lsl();
3361 78c34e98 bellard
        s->cc_op = CC_OP_EFLAGS;
3362 78c34e98 bellard
        gen_op_mov_reg_T1[ot][reg]();
3363 78c34e98 bellard
        break;
3364 367e86e8 bellard
    default:
3365 1a9353d2 bellard
        goto illegal_op;
3366 367e86e8 bellard
    }
3367 1b6b029e bellard
    /* lock generation */
3368 1b6b029e bellard
    if (s->prefix & PREFIX_LOCK)
3369 1b6b029e bellard
        gen_op_unlock();
3370 367e86e8 bellard
    return (long)s->pc;
3371 6dbad63e bellard
 illegal_op:
3372 1b6b029e bellard
    /* XXX: ensure that no lock was generated */
3373 6dbad63e bellard
    return -1;
3374 367e86e8 bellard
}
3375 367e86e8 bellard
3376 dc99065b bellard
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3377 dc99065b bellard
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3378 dc99065b bellard
3379 dc99065b bellard
/* flags read by an operation */
3380 dc99065b bellard
static uint16_t opc_read_flags[NB_OPS] = { 
3381 dc99065b bellard
    [INDEX_op_aas] = CC_A,
3382 dc99065b bellard
    [INDEX_op_aaa] = CC_A,
3383 dc99065b bellard
    [INDEX_op_das] = CC_A | CC_C,
3384 dc99065b bellard
    [INDEX_op_daa] = CC_A | CC_C,
3385 dc99065b bellard
3386 dc99065b bellard
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3387 dc99065b bellard
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3388 dc99065b bellard
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3389 dc99065b bellard
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3390 dc99065b bellard
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3391 dc99065b bellard
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3392 dc99065b bellard
3393 982b4315 bellard
    /* subtle: due to the incl/decl implementation, C is used */
3394 982b4315 bellard
    [INDEX_op_incl_T0_cc] = CC_C, 
3395 982b4315 bellard
    [INDEX_op_decl_T0_cc] = CC_C,
3396 982b4315 bellard
3397 dc99065b bellard
    [INDEX_op_into] = CC_O,
3398 dc99065b bellard
3399 dc99065b bellard
    [INDEX_op_jo_cc] = CC_O,
3400 dc99065b bellard
    [INDEX_op_jb_cc] = CC_C,
3401 dc99065b bellard
    [INDEX_op_jz_cc] = CC_Z,
3402 dc99065b bellard
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3403 dc99065b bellard
    [INDEX_op_js_cc] = CC_S,
3404 dc99065b bellard
    [INDEX_op_jp_cc] = CC_P,
3405 dc99065b bellard
    [INDEX_op_jl_cc] = CC_O | CC_S,
3406 dc99065b bellard
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3407 dc99065b bellard
3408 dc99065b bellard
    [INDEX_op_jb_subb] = CC_C,
3409 dc99065b bellard
    [INDEX_op_jb_subw] = CC_C,
3410 dc99065b bellard
    [INDEX_op_jb_subl] = CC_C,
3411 dc99065b bellard
3412 dc99065b bellard
    [INDEX_op_jz_subb] = CC_Z,
3413 dc99065b bellard
    [INDEX_op_jz_subw] = CC_Z,
3414 dc99065b bellard
    [INDEX_op_jz_subl] = CC_Z,
3415 dc99065b bellard
3416 dc99065b bellard
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3417 dc99065b bellard
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3418 dc99065b bellard
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3419 dc99065b bellard
3420 dc99065b bellard
    [INDEX_op_js_subb] = CC_S,
3421 dc99065b bellard
    [INDEX_op_js_subw] = CC_S,
3422 dc99065b bellard
    [INDEX_op_js_subl] = CC_S,
3423 dc99065b bellard
3424 dc99065b bellard
    [INDEX_op_jl_subb] = CC_O | CC_S,
3425 dc99065b bellard
    [INDEX_op_jl_subw] = CC_O | CC_S,
3426 dc99065b bellard
    [INDEX_op_jl_subl] = CC_O | CC_S,
3427 dc99065b bellard
3428 dc99065b bellard
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3429 dc99065b bellard
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3430 dc99065b bellard
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3431 dc99065b bellard
3432 dc99065b bellard
    [INDEX_op_loopnzw] = CC_Z,
3433 dc99065b bellard
    [INDEX_op_loopnzl] = CC_Z,
3434 dc99065b bellard
    [INDEX_op_loopzw] = CC_Z,
3435 dc99065b bellard
    [INDEX_op_loopzl] = CC_Z,
3436 dc99065b bellard
3437 dc99065b bellard
    [INDEX_op_seto_T0_cc] = CC_O,
3438 dc99065b bellard
    [INDEX_op_setb_T0_cc] = CC_C,
3439 dc99065b bellard
    [INDEX_op_setz_T0_cc] = CC_Z,
3440 dc99065b bellard
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3441 dc99065b bellard
    [INDEX_op_sets_T0_cc] = CC_S,
3442 dc99065b bellard
    [INDEX_op_setp_T0_cc] = CC_P,
3443 dc99065b bellard
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3444 dc99065b bellard
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3445 dc99065b bellard
3446 dc99065b bellard
    [INDEX_op_setb_T0_subb] = CC_C,
3447 dc99065b bellard
    [INDEX_op_setb_T0_subw] = CC_C,
3448 dc99065b bellard
    [INDEX_op_setb_T0_subl] = CC_C,
3449 dc99065b bellard
3450 dc99065b bellard
    [INDEX_op_setz_T0_subb] = CC_Z,
3451 dc99065b bellard
    [INDEX_op_setz_T0_subw] = CC_Z,
3452 dc99065b bellard
    [INDEX_op_setz_T0_subl] = CC_Z,
3453 dc99065b bellard
3454 dc99065b bellard
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3455 dc99065b bellard
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3456 dc99065b bellard
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3457 dc99065b bellard
3458 dc99065b bellard
    [INDEX_op_sets_T0_subb] = CC_S,
3459 dc99065b bellard
    [INDEX_op_sets_T0_subw] = CC_S,
3460 dc99065b bellard
    [INDEX_op_sets_T0_subl] = CC_S,
3461 dc99065b bellard
3462 dc99065b bellard
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3463 dc99065b bellard
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3464 dc99065b bellard
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3465 dc99065b bellard
3466 dc99065b bellard
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3467 dc99065b bellard
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3468 dc99065b bellard
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3469 dc99065b bellard
3470 dc99065b bellard
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3471 dc99065b bellard
    [INDEX_op_cmc] = CC_C,
3472 dc99065b bellard
    [INDEX_op_salc] = CC_C,
3473 dc99065b bellard
3474 dc99065b bellard
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3475 dc99065b bellard
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3476 dc99065b bellard
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3477 dc99065b bellard
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3478 dc99065b bellard
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3479 dc99065b bellard
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3480 dc99065b bellard
};
3481 dc99065b bellard
3482 dc99065b bellard
/* flags written by an operation */
3483 dc99065b bellard
static uint16_t opc_write_flags[NB_OPS] = { 
3484 dc99065b bellard
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3485 dc99065b bellard
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3486 dc99065b bellard
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3487 dc99065b bellard
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3488 dc99065b bellard
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3489 dc99065b bellard
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3490 dc99065b bellard
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3491 dc99065b bellard
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3492 dc99065b bellard
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3493 dc99065b bellard
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3494 dc99065b bellard
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3495 dc99065b bellard
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3496 dc99065b bellard
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3497 982b4315 bellard
    /* subtle: due to the incl/decl implementation, C is used */
3498 982b4315 bellard
    [INDEX_op_incl_T0_cc] = CC_OSZAPC, 
3499 982b4315 bellard
    [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3500 dc99065b bellard
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3501 dc99065b bellard
3502 dc99065b bellard
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3503 dc99065b bellard
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3504 dc99065b bellard
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3505 dc99065b bellard
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3506 dc99065b bellard
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3507 dc99065b bellard
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3508 dc99065b bellard
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3509 dc99065b bellard
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3510 dc99065b bellard
    
3511 dc99065b bellard
    /* bcd */
3512 dc99065b bellard
    [INDEX_op_aam] = CC_OSZAPC,
3513 dc99065b bellard
    [INDEX_op_aad] = CC_OSZAPC,
3514 dc99065b bellard
    [INDEX_op_aas] = CC_OSZAPC,
3515 dc99065b bellard
    [INDEX_op_aaa] = CC_OSZAPC,
3516 dc99065b bellard
    [INDEX_op_das] = CC_OSZAPC,
3517 dc99065b bellard
    [INDEX_op_daa] = CC_OSZAPC,
3518 dc99065b bellard
3519 dc99065b bellard
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3520 f631ef9b bellard
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3521 dc99065b bellard
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3522 dc99065b bellard
    [INDEX_op_clc] = CC_C,
3523 dc99065b bellard
    [INDEX_op_stc] = CC_C,
3524 dc99065b bellard
    [INDEX_op_cmc] = CC_C,
3525 dc99065b bellard
3526 dc99065b bellard
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3527 dc99065b bellard
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3528 dc99065b bellard
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3529 dc99065b bellard
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3530 dc99065b bellard
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3531 dc99065b bellard
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3532 dc99065b bellard
3533 dc99065b bellard
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3534 dc99065b bellard
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3535 dc99065b bellard
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3536 dc99065b bellard
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3537 dc99065b bellard
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3538 dc99065b bellard
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3539 dc99065b bellard
3540 dc99065b bellard
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3541 dc99065b bellard
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3542 dc99065b bellard
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3543 dc99065b bellard
3544 dc99065b bellard
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3545 dc99065b bellard
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3546 dc99065b bellard
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3547 dc99065b bellard
3548 dc99065b bellard
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3549 dc99065b bellard
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3550 dc99065b bellard
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3551 dc99065b bellard
3552 dc99065b bellard
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3553 dc99065b bellard
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3554 dc99065b bellard
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3555 dc99065b bellard
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3556 dc99065b bellard
3557 dc99065b bellard
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3558 dc99065b bellard
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3559 dc99065b bellard
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3560 dc99065b bellard
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3561 dc99065b bellard
3562 dc99065b bellard
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3563 dc99065b bellard
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3564 dc99065b bellard
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3565 dc99065b bellard
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3566 dc99065b bellard
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3567 dc99065b bellard
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3568 dc99065b bellard
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3569 dc99065b bellard
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3570 dc99065b bellard
3571 dc99065b bellard
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3572 dc99065b bellard
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3573 dc99065b bellard
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3574 dc99065b bellard
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3575 dc99065b bellard
3576 9c605cb1 bellard
#undef STRINGOP
3577 9c605cb1 bellard
#define STRINGOP(x) \
3578 9c605cb1 bellard
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3579 9c605cb1 bellard
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3580 9c605cb1 bellard
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3581 9c605cb1 bellard
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3582 9c605cb1 bellard
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3583 9c605cb1 bellard
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3584 9c605cb1 bellard
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3585 9c605cb1 bellard
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3586 9c605cb1 bellard
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3587 9c605cb1 bellard
3588 9c605cb1 bellard
    STRINGOP(scas)
3589 9c605cb1 bellard
    STRINGOP(repz_scas)
3590 9c605cb1 bellard
    STRINGOP(repnz_scas)
3591 9c605cb1 bellard
    STRINGOP(cmps)
3592 9c605cb1 bellard
    STRINGOP(repz_cmps)
3593 9c605cb1 bellard
    STRINGOP(repnz_cmps)
3594 9c605cb1 bellard
3595 9c605cb1 bellard
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3596 dc99065b bellard
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3597 dc99065b bellard
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3598 9c605cb1 bellard
3599 9c605cb1 bellard
    [INDEX_op_cmpxchg8b] = CC_Z,
3600 78c34e98 bellard
    [INDEX_op_lar] = CC_Z,
3601 78c34e98 bellard
    [INDEX_op_lsl] = CC_Z,
3602 dc99065b bellard
};
3603 dc99065b bellard
3604 dc99065b bellard
/* simpler form of an operation if no flags need to be generated */
3605 dc99065b bellard
static uint16_t opc_simpler[NB_OPS] = { 
3606 dc99065b bellard
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3607 dc99065b bellard
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3608 dc99065b bellard
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3609 dc99065b bellard
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3610 dc99065b bellard
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3611 dc99065b bellard
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3612 dc99065b bellard
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3613 dc99065b bellard
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3614 dc99065b bellard
3615 dc99065b bellard
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3616 dc99065b bellard
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3617 dc99065b bellard
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3618 dc99065b bellard
3619 dc99065b bellard
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3620 dc99065b bellard
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3621 dc99065b bellard
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3622 dc99065b bellard
3623 dc99065b bellard
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3624 dc99065b bellard
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3625 dc99065b bellard
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3626 dc99065b bellard
3627 dc99065b bellard
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3628 dc99065b bellard
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3629 dc99065b bellard
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3630 dc99065b bellard
3631 dc99065b bellard
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3632 dc99065b bellard
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3633 dc99065b bellard
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3634 dc99065b bellard
};
3635 dc99065b bellard
3636 dc99065b bellard
static void optimize_flags_init(void)
3637 dc99065b bellard
{
3638 dc99065b bellard
    int i;
3639 dc99065b bellard
    /* put default values in arrays */
3640 dc99065b bellard
    for(i = 0; i < NB_OPS; i++) {
3641 dc99065b bellard
        if (opc_simpler[i] == 0)
3642 dc99065b bellard
            opc_simpler[i] = i;
3643 dc99065b bellard
    }
3644 dc99065b bellard
}
3645 dc99065b bellard
3646 dc99065b bellard
/* CPU flags computation optimization: we move backward thru the
3647 dc99065b bellard
   generated code to see which flags are needed. The operation is
3648 dc99065b bellard
   modified if suitable */
3649 dc99065b bellard
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3650 dc99065b bellard
{
3651 dc99065b bellard
    uint16_t *opc_ptr;
3652 dc99065b bellard
    int live_flags, write_flags, op;
3653 dc99065b bellard
3654 dc99065b bellard
    opc_ptr = opc_buf + opc_buf_len;
3655 dc99065b bellard
    /* live_flags contains the flags needed by the next instructions
3656 dc99065b bellard
       in the code. At the end of the bloc, we consider that all the
3657 dc99065b bellard
       flags are live. */
3658 dc99065b bellard
    live_flags = CC_OSZAPC;
3659 dc99065b bellard
    while (opc_ptr > opc_buf) {
3660 dc99065b bellard
        op = *--opc_ptr;
3661 dc99065b bellard
        /* if none of the flags written by the instruction is used,
3662 dc99065b bellard
           then we can try to find a simpler instruction */
3663 dc99065b bellard
        write_flags = opc_write_flags[op];
3664 dc99065b bellard
        if ((live_flags & write_flags) == 0) {
3665 dc99065b bellard
            *opc_ptr = opc_simpler[op];
3666 dc99065b bellard
        }
3667 dc99065b bellard
        /* compute the live flags before the instruction */
3668 dc99065b bellard
        live_flags &= ~write_flags;
3669 dc99065b bellard
        live_flags |= opc_read_flags[op];
3670 dc99065b bellard
    }
3671 dc99065b bellard
}
3672 dc99065b bellard
3673 dc99065b bellard
3674 dc99065b bellard
#ifdef DEBUG_DISAS
3675 dc99065b bellard
static const char *op_str[] = {
3676 9c605cb1 bellard
#define DEF(s, n) #s,
3677 9c605cb1 bellard
#include "opc-i386.h"
3678 9c605cb1 bellard
#undef DEF
3679 9c605cb1 bellard
};
3680 9c605cb1 bellard
3681 9c605cb1 bellard
static uint8_t op_nb_args[] = {
3682 9c605cb1 bellard
#define DEF(s, n) n,
3683 dc99065b bellard
#include "opc-i386.h"
3684 dc99065b bellard
#undef DEF
3685 dc99065b bellard
};
3686 dc99065b bellard
3687 9c605cb1 bellard
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3688 dc99065b bellard
{
3689 dc99065b bellard
    const uint16_t *opc_ptr;
3690 9c605cb1 bellard
    const uint32_t *opparam_ptr;
3691 9c605cb1 bellard
    int c, n, i;
3692 9c605cb1 bellard
3693 dc99065b bellard
    opc_ptr = opc_buf;
3694 9c605cb1 bellard
    opparam_ptr = opparam_buf;
3695 dc99065b bellard
    for(;;) {
3696 dc99065b bellard
        c = *opc_ptr++;
3697 9c605cb1 bellard
        n = op_nb_args[c];
3698 366c1b8b bellard
        fprintf(logfile, "0x%04x: %s", 
3699 366c1b8b bellard
                (int)(opc_ptr - opc_buf - 1), op_str[c]);
3700 9c605cb1 bellard
        for(i = 0; i < n; i++) {
3701 9c605cb1 bellard
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3702 9c605cb1 bellard
        }
3703 9c605cb1 bellard
        fprintf(logfile, "\n");
3704 dc99065b bellard
        if (c == INDEX_op_end)
3705 dc99065b bellard
            break;
3706 9c605cb1 bellard
        opparam_ptr += n;
3707 dc99065b bellard
    }
3708 dc99065b bellard
}
3709 dc99065b bellard
3710 dc99065b bellard
#endif
3711 dc99065b bellard
3712 dc99065b bellard
/* XXX: make this buffer thread safe */
3713 dc99065b bellard
/* XXX: make safe guess about sizes */
3714 dc99065b bellard
#define MAX_OP_PER_INSTR 32
3715 dc99065b bellard
#define OPC_BUF_SIZE 512
3716 dc99065b bellard
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3717 dc99065b bellard
3718 dc99065b bellard
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3719 dc99065b bellard
3720 dc99065b bellard
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3721 dc99065b bellard
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3722 dc99065b bellard
3723 9de5e440 bellard
/* return non zero if the very first instruction is invalid so that
3724 9de5e440 bellard
   the virtual CPU can trigger an exception. */
3725 1017ebe9 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3726 dab2ed99 bellard
                     int *gen_code_size_ptr,
3727 dab2ed99 bellard
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3728 ba1c6e37 bellard
{
3729 ba1c6e37 bellard
    DisasContext dc1, *dc = &dc1;
3730 dc99065b bellard
    uint8_t *pc_ptr;
3731 dc99065b bellard
    uint16_t *gen_opc_end;
3732 04369ff2 bellard
    int gen_code_size;
3733 ba1c6e37 bellard
    long ret;
3734 dc99065b bellard
    
3735 dc99065b bellard
    /* generate intermediate code */
3736 dc99065b bellard
3737 6dbad63e bellard
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3738 dab2ed99 bellard
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3739 6dbad63e bellard
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3740 6dbad63e bellard
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3741 9c605cb1 bellard
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3742 982b4315 bellard
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3743 982b4315 bellard
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3744 c50c0c3f bellard
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3745 ba1c6e37 bellard
    dc->cc_op = CC_OP_DYNAMIC;
3746 dab2ed99 bellard
    dc->cs_base = cs_base;
3747 dc99065b bellard
3748 dc99065b bellard
    gen_opc_ptr = gen_opc_buf;
3749 dc99065b bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3750 dc99065b bellard
    gen_opparam_ptr = gen_opparam_buf;
3751 0ecfa993 bellard
3752 6dbad63e bellard
    dc->is_jmp = 0;
3753 1017ebe9 bellard
    pc_ptr = pc_start;
3754 1017ebe9 bellard
    do {
3755 6dbad63e bellard
        ret = disas_insn(dc, pc_ptr);
3756 1a9353d2 bellard
        if (ret == -1) {
3757 9de5e440 bellard
            /* we trigger an illegal instruction operation only if it
3758 9de5e440 bellard
               is the first instruction. Otherwise, we simply stop
3759 9de5e440 bellard
               generating the code just before it */
3760 9de5e440 bellard
            if (pc_ptr == pc_start)
3761 9de5e440 bellard
                return -1;
3762 9de5e440 bellard
            else
3763 9de5e440 bellard
                break;
3764 1a9353d2 bellard
        }
3765 1017ebe9 bellard
        pc_ptr = (void *)ret;
3766 c50c0c3f bellard
        /* if single step mode, we generate only one instruction and
3767 c50c0c3f bellard
           generate an exception */
3768 c50c0c3f bellard
        if (dc->tf)
3769 c50c0c3f bellard
            break;
3770 dc99065b bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3771 0ecfa993 bellard
    /* we must store the eflags state if it is not already done */
3772 0ecfa993 bellard
    if (dc->cc_op != CC_OP_DYNAMIC)
3773 0ecfa993 bellard
        gen_op_set_cc_op(dc->cc_op);
3774 6dbad63e bellard
    if (dc->is_jmp != 1) {
3775 0ecfa993 bellard
        /* we add an additionnal jmp to update the simulated PC */
3776 dab2ed99 bellard
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3777 0ecfa993 bellard
    }
3778 c50c0c3f bellard
    if (dc->tf) {
3779 c50c0c3f bellard
        gen_op_raise_exception(EXCP01_SSTP);
3780 c50c0c3f bellard
    }
3781 c50c0c3f bellard
3782 dc99065b bellard
    *gen_opc_ptr = INDEX_op_end;
3783 0ecfa993 bellard
3784 0ecfa993 bellard
#ifdef DEBUG_DISAS
3785 586314f2 bellard
    if (loglevel) {
3786 dc99065b bellard
        fprintf(logfile, "----------------\n");
3787 b9adb4a6 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3788 b9adb4a6 bellard
        disas(logfile, pc_start, pc_ptr - pc_start,
3789 b9adb4a6 bellard
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3790 1017ebe9 bellard
        fprintf(logfile, "\n");
3791 982b4315 bellard
3792 dc99065b bellard
        fprintf(logfile, "OP:\n");
3793 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
3794 dc99065b bellard
        fprintf(logfile, "\n");
3795 dc99065b bellard
    }
3796 dc99065b bellard
#endif
3797 dc99065b bellard
3798 dc99065b bellard
    /* optimize flag computations */
3799 dc99065b bellard
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3800 dc99065b bellard
3801 dc99065b bellard
#ifdef DEBUG_DISAS
3802 dc99065b bellard
    if (loglevel) {
3803 dc99065b bellard
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3804 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
3805 dc99065b bellard
        fprintf(logfile, "\n");
3806 dc99065b bellard
    }
3807 dc99065b bellard
#endif
3808 dc99065b bellard
3809 dc99065b bellard
    /* generate machine code */
3810 04369ff2 bellard
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3811 04369ff2 bellard
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3812 04369ff2 bellard
    *gen_code_size_ptr = gen_code_size;
3813 dc99065b bellard
3814 dc99065b bellard
#ifdef DEBUG_DISAS
3815 dc99065b bellard
    if (loglevel) {
3816 0ecfa993 bellard
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3817 b9adb4a6 bellard
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3818 0ecfa993 bellard
        fprintf(logfile, "\n");
3819 1b6b029e bellard
        fflush(logfile);
3820 0ecfa993 bellard
    }
3821 0ecfa993 bellard
#endif
3822 ba1c6e37 bellard
    return 0;
3823 ba1c6e37 bellard
}
3824 ba1c6e37 bellard
3825 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
3826 ba1c6e37 bellard
{
3827 ba1c6e37 bellard
    CPUX86State *env;
3828 ba1c6e37 bellard
    int i;
3829 dc99065b bellard
    static int inited;
3830 ba1c6e37 bellard
3831 7d13299d bellard
    cpu_x86_tblocks_init();
3832 7d13299d bellard
3833 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
3834 ba1c6e37 bellard
    if (!env)
3835 ba1c6e37 bellard
        return NULL;
3836 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
3837 ba1c6e37 bellard
    /* basic FPU init */
3838 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
3839 ba1c6e37 bellard
        env->fptags[i] = 1;
3840 ba1c6e37 bellard
    env->fpuc = 0x37f;
3841 9c605cb1 bellard
    /* flags setup : we activate the IRQs by default as in user mode */
3842 9c605cb1 bellard
    env->eflags = 0x2 | IF_MASK;
3843 dc99065b bellard
3844 dc99065b bellard
    /* init various static tables */
3845 dc99065b bellard
    if (!inited) {
3846 dc99065b bellard
        inited = 1;
3847 dc99065b bellard
        optimize_flags_init();
3848 dc99065b bellard
    }
3849 ba1c6e37 bellard
    return env;
3850 ba1c6e37 bellard
}
3851 ba1c6e37 bellard
3852 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
3853 ba1c6e37 bellard
{
3854 ba1c6e37 bellard
    free(env);
3855 ba1c6e37 bellard
}
3856 148dfc2a bellard
3857 148dfc2a bellard
static const char *cc_op_str[] = {
3858 148dfc2a bellard
    "DYNAMIC",
3859 148dfc2a bellard
    "EFLAGS",
3860 148dfc2a bellard
    "MUL",
3861 148dfc2a bellard
    "ADDB",
3862 148dfc2a bellard
    "ADDW",
3863 148dfc2a bellard
    "ADDL",
3864 148dfc2a bellard
    "ADCB",
3865 148dfc2a bellard
    "ADCW",
3866 148dfc2a bellard
    "ADCL",
3867 148dfc2a bellard
    "SUBB",
3868 148dfc2a bellard
    "SUBW",
3869 148dfc2a bellard
    "SUBL",
3870 148dfc2a bellard
    "SBBB",
3871 148dfc2a bellard
    "SBBW",
3872 148dfc2a bellard
    "SBBL",
3873 148dfc2a bellard
    "LOGICB",
3874 148dfc2a bellard
    "LOGICW",
3875 148dfc2a bellard
    "LOGICL",
3876 148dfc2a bellard
    "INCB",
3877 148dfc2a bellard
    "INCW",
3878 148dfc2a bellard
    "INCL",
3879 148dfc2a bellard
    "DECB",
3880 148dfc2a bellard
    "DECW",
3881 148dfc2a bellard
    "DECL",
3882 148dfc2a bellard
    "SHLB",
3883 148dfc2a bellard
    "SHLW",
3884 148dfc2a bellard
    "SHLL",
3885 148dfc2a bellard
    "SARB",
3886 148dfc2a bellard
    "SARW",
3887 148dfc2a bellard
    "SARL",
3888 148dfc2a bellard
};
3889 148dfc2a bellard
3890 148dfc2a bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3891 148dfc2a bellard
{
3892 148dfc2a bellard
    int eflags;
3893 148dfc2a bellard
    char cc_op_name[32];
3894 148dfc2a bellard
3895 148dfc2a bellard
    eflags = env->eflags;
3896 148dfc2a bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3897 148dfc2a bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3898 148dfc2a bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3899 148dfc2a bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
3900 148dfc2a bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
3901 148dfc2a bellard
            env->eip, eflags,
3902 148dfc2a bellard
            eflags & DF_MASK ? 'D' : '-',
3903 148dfc2a bellard
            eflags & CC_O ? 'O' : '-',
3904 148dfc2a bellard
            eflags & CC_S ? 'S' : '-',
3905 148dfc2a bellard
            eflags & CC_Z ? 'Z' : '-',
3906 148dfc2a bellard
            eflags & CC_A ? 'A' : '-',
3907 148dfc2a bellard
            eflags & CC_P ? 'P' : '-',
3908 148dfc2a bellard
            eflags & CC_C ? 'C' : '-');
3909 148dfc2a bellard
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3910 148dfc2a bellard
            env->segs[R_CS],
3911 148dfc2a bellard
            env->segs[R_SS],
3912 148dfc2a bellard
            env->segs[R_DS],
3913 148dfc2a bellard
            env->segs[R_ES],
3914 148dfc2a bellard
            env->segs[R_FS],
3915 148dfc2a bellard
            env->segs[R_GS]);
3916 148dfc2a bellard
    if (flags & X86_DUMP_CCOP) {
3917 148dfc2a bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
3918 148dfc2a bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
3919 148dfc2a bellard
        else
3920 148dfc2a bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
3921 148dfc2a bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
3922 148dfc2a bellard
                env->cc_src, env->cc_dst, cc_op_name);
3923 148dfc2a bellard
    }
3924 148dfc2a bellard
    if (flags & X86_DUMP_FPU) {
3925 148dfc2a bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
3926 148dfc2a bellard
                (double)env->fpregs[0], 
3927 148dfc2a bellard
                (double)env->fpregs[1], 
3928 148dfc2a bellard
                (double)env->fpregs[2], 
3929 148dfc2a bellard
                (double)env->fpregs[3]);
3930 148dfc2a bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
3931 148dfc2a bellard
                (double)env->fpregs[4], 
3932 148dfc2a bellard
                (double)env->fpregs[5], 
3933 148dfc2a bellard
                (double)env->fpregs[7], 
3934 148dfc2a bellard
                (double)env->fpregs[8]);
3935 148dfc2a bellard
    }
3936 148dfc2a bellard
}