Statistics
| Branch: | Revision:

root / translate-i386.c @ 982b4315

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