Statistics
| Branch: | Revision:

root / translate-i386.c @ ae48a073

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