Statistics
| Branch: | Revision:

root / translate-i386.c @ 3ef693a0

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