Statistics
| Branch: | Revision:

root / translate-i386.c @ a69d83b6

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