Statistics
| Branch: | Revision:

root / translate-i386.c @ 586314f2

History | View | Annotate | Download (58.3 kB)

1 367e86e8 bellard
#include <stdarg.h>
2 367e86e8 bellard
#include <stdlib.h>
3 367e86e8 bellard
#include <stdio.h>
4 367e86e8 bellard
#include <string.h>
5 367e86e8 bellard
#include <inttypes.h>
6 367e86e8 bellard
#include <assert.h>
7 367e86e8 bellard
8 0ecfa993 bellard
#define DEBUG_DISAS
9 0ecfa993 bellard
10 586314f2 bellard
#define IN_OP_I386
11 586314f2 bellard
#include "cpu-i386.h"
12 586314f2 bellard
13 586314f2 bellard
/* dump all code */
14 0ecfa993 bellard
#ifdef DEBUG_DISAS
15 0ecfa993 bellard
#include "dis-asm.h"
16 0ecfa993 bellard
#endif
17 0ecfa993 bellard
18 367e86e8 bellard
static uint8_t *gen_code_ptr;
19 367e86e8 bellard
int __op_param1, __op_param2, __op_param3;
20 367e86e8 bellard
21 586314f2 bellard
extern FILE *logfile;
22 586314f2 bellard
extern int loglevel;
23 0ecfa993 bellard
24 367e86e8 bellard
/* supress that */
25 367e86e8 bellard
static void error(const char *fmt, ...)
26 367e86e8 bellard
{
27 367e86e8 bellard
    va_list ap;
28 367e86e8 bellard
29 367e86e8 bellard
    va_start(ap, fmt);
30 367e86e8 bellard
    vfprintf(stderr, fmt, ap);
31 367e86e8 bellard
    va_end(ap);
32 367e86e8 bellard
    exit(1);
33 367e86e8 bellard
}
34 367e86e8 bellard
35 367e86e8 bellard
#define PREFIX_REPZ 1
36 367e86e8 bellard
#define PREFIX_REPNZ 2
37 367e86e8 bellard
#define PREFIX_LOCK 4
38 367e86e8 bellard
#define PREFIX_CS 8
39 367e86e8 bellard
#define PREFIX_SS 0x10
40 367e86e8 bellard
#define PREFIX_DS 0x20
41 367e86e8 bellard
#define PREFIX_ES 0x40
42 367e86e8 bellard
#define PREFIX_FS 0x80
43 367e86e8 bellard
#define PREFIX_GS 0x100
44 367e86e8 bellard
#define PREFIX_DATA 0x200
45 367e86e8 bellard
#define PREFIX_ADR 0x400
46 367e86e8 bellard
#define PREFIX_FWAIT 0x800
47 367e86e8 bellard
48 367e86e8 bellard
typedef struct DisasContext {
49 367e86e8 bellard
    /* current insn context */
50 367e86e8 bellard
    int prefix;
51 367e86e8 bellard
    int aflag, dflag;
52 367e86e8 bellard
    uint8_t *pc; /* current pc */
53 367e86e8 bellard
    int cc_op; /* current CC operation */
54 367e86e8 bellard
    int f_st;
55 367e86e8 bellard
} DisasContext;
56 367e86e8 bellard
57 367e86e8 bellard
/* i386 arith/logic operations */
58 367e86e8 bellard
enum {
59 367e86e8 bellard
    OP_ADDL, 
60 367e86e8 bellard
    OP_ORL, 
61 367e86e8 bellard
    OP_ADCL, 
62 367e86e8 bellard
    OP_SBBL,
63 367e86e8 bellard
    OP_ANDL, 
64 367e86e8 bellard
    OP_SUBL, 
65 367e86e8 bellard
    OP_XORL, 
66 367e86e8 bellard
    OP_CMPL,
67 367e86e8 bellard
};
68 367e86e8 bellard
69 367e86e8 bellard
/* i386 shift ops */
70 367e86e8 bellard
enum {
71 367e86e8 bellard
    OP_ROL, 
72 367e86e8 bellard
    OP_ROR, 
73 367e86e8 bellard
    OP_RCL, 
74 367e86e8 bellard
    OP_RCR, 
75 367e86e8 bellard
    OP_SHL, 
76 367e86e8 bellard
    OP_SHR, 
77 367e86e8 bellard
    OP_SHL1, /* undocumented */
78 367e86e8 bellard
    OP_SAR = 7,
79 367e86e8 bellard
};
80 367e86e8 bellard
81 367e86e8 bellard
#include "op-i386.h"
82 367e86e8 bellard
83 367e86e8 bellard
/* operand size */
84 367e86e8 bellard
enum {
85 367e86e8 bellard
    OT_BYTE = 0,
86 367e86e8 bellard
    OT_WORD,
87 367e86e8 bellard
    OT_LONG, 
88 367e86e8 bellard
    OT_QUAD,
89 367e86e8 bellard
};
90 367e86e8 bellard
91 367e86e8 bellard
enum {
92 367e86e8 bellard
    /* I386 int registers */
93 367e86e8 bellard
    OR_EAX,   /* MUST be even numbered */
94 367e86e8 bellard
    OR_ECX,
95 367e86e8 bellard
    OR_EDX,
96 367e86e8 bellard
    OR_EBX,
97 367e86e8 bellard
    OR_ESP,
98 367e86e8 bellard
    OR_EBP,
99 367e86e8 bellard
    OR_ESI,
100 367e86e8 bellard
    OR_EDI,
101 367e86e8 bellard
102 367e86e8 bellard
    /* I386 float registers */
103 367e86e8 bellard
    OR_ST0,
104 367e86e8 bellard
    OR_ST1,
105 367e86e8 bellard
    OR_ST2,
106 367e86e8 bellard
    OR_ST3,
107 367e86e8 bellard
    OR_ST4,
108 367e86e8 bellard
    OR_ST5,
109 367e86e8 bellard
    OR_ST6,
110 367e86e8 bellard
    OR_ST7,
111 367e86e8 bellard
    OR_TMP0,    /* temporary operand register */
112 367e86e8 bellard
    OR_TMP1,
113 367e86e8 bellard
    OR_A0, /* temporary register used when doing address evaluation */
114 367e86e8 bellard
    OR_EFLAGS,  /* cpu flags */
115 367e86e8 bellard
    OR_ITMP0, /* used for byte/word insertion */
116 367e86e8 bellard
    OR_ITMP1, /* used for byte/word insertion */
117 367e86e8 bellard
    OR_ITMP2, /* used for byte/word insertion */
118 367e86e8 bellard
    OR_FTMP0, /* float temporary */
119 367e86e8 bellard
    OR_DF,    /* D flag, for string ops */
120 367e86e8 bellard
    OR_ZERO, /* fixed zero register */
121 367e86e8 bellard
    OR_IM, /* dummy immediate value register */
122 367e86e8 bellard
    NB_OREGS,
123 367e86e8 bellard
};
124 367e86e8 bellard
125 367e86e8 bellard
#if 0
126 367e86e8 bellard
static const double tab_const[7] = {
127 367e86e8 bellard
    1.0, 
128 367e86e8 bellard
    3.32192809488736234789, /* log2(10) */
129 367e86e8 bellard
    M_LOG2E,
130 367e86e8 bellard
    M_PI,
131 367e86e8 bellard
    0.30102999566398119521, /* log10(2) */
132 367e86e8 bellard
    M_LN2,
133 367e86e8 bellard
    0.0
134 367e86e8 bellard
};
135 367e86e8 bellard
#endif
136 367e86e8 bellard
137 367e86e8 bellard
typedef void (GenOpFunc)(void);
138 367e86e8 bellard
typedef void (GenOpFunc1)(long);
139 367e86e8 bellard
typedef void (GenOpFunc2)(long, long);
140 367e86e8 bellard
                    
141 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
142 367e86e8 bellard
    [OT_BYTE] = {
143 367e86e8 bellard
        gen_op_movb_EAX_T0,
144 367e86e8 bellard
        gen_op_movb_ECX_T0,
145 367e86e8 bellard
        gen_op_movb_EDX_T0,
146 367e86e8 bellard
        gen_op_movb_EBX_T0,
147 367e86e8 bellard
        gen_op_movh_EAX_T0,
148 367e86e8 bellard
        gen_op_movh_ECX_T0,
149 367e86e8 bellard
        gen_op_movh_EDX_T0,
150 367e86e8 bellard
        gen_op_movh_EBX_T0,
151 367e86e8 bellard
    },
152 367e86e8 bellard
    [OT_WORD] = {
153 367e86e8 bellard
        gen_op_movw_EAX_T0,
154 367e86e8 bellard
        gen_op_movw_ECX_T0,
155 367e86e8 bellard
        gen_op_movw_EDX_T0,
156 367e86e8 bellard
        gen_op_movw_EBX_T0,
157 367e86e8 bellard
        gen_op_movw_ESP_T0,
158 367e86e8 bellard
        gen_op_movw_EBP_T0,
159 367e86e8 bellard
        gen_op_movw_ESI_T0,
160 367e86e8 bellard
        gen_op_movw_EDI_T0,
161 367e86e8 bellard
    },
162 367e86e8 bellard
    [OT_LONG] = {
163 367e86e8 bellard
        gen_op_movl_EAX_T0,
164 367e86e8 bellard
        gen_op_movl_ECX_T0,
165 367e86e8 bellard
        gen_op_movl_EDX_T0,
166 367e86e8 bellard
        gen_op_movl_EBX_T0,
167 367e86e8 bellard
        gen_op_movl_ESP_T0,
168 367e86e8 bellard
        gen_op_movl_EBP_T0,
169 367e86e8 bellard
        gen_op_movl_ESI_T0,
170 367e86e8 bellard
        gen_op_movl_EDI_T0,
171 367e86e8 bellard
    },
172 367e86e8 bellard
};
173 367e86e8 bellard
174 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
175 367e86e8 bellard
    [OT_BYTE] = {
176 367e86e8 bellard
        gen_op_movb_EAX_T1,
177 367e86e8 bellard
        gen_op_movb_ECX_T1,
178 367e86e8 bellard
        gen_op_movb_EDX_T1,
179 367e86e8 bellard
        gen_op_movb_EBX_T1,
180 367e86e8 bellard
        gen_op_movh_EAX_T1,
181 367e86e8 bellard
        gen_op_movh_ECX_T1,
182 367e86e8 bellard
        gen_op_movh_EDX_T1,
183 367e86e8 bellard
        gen_op_movh_EBX_T1,
184 367e86e8 bellard
    },
185 367e86e8 bellard
    [OT_WORD] = {
186 367e86e8 bellard
        gen_op_movw_EAX_T1,
187 367e86e8 bellard
        gen_op_movw_ECX_T1,
188 367e86e8 bellard
        gen_op_movw_EDX_T1,
189 367e86e8 bellard
        gen_op_movw_EBX_T1,
190 367e86e8 bellard
        gen_op_movw_ESP_T1,
191 367e86e8 bellard
        gen_op_movw_EBP_T1,
192 367e86e8 bellard
        gen_op_movw_ESI_T1,
193 367e86e8 bellard
        gen_op_movw_EDI_T1,
194 367e86e8 bellard
    },
195 367e86e8 bellard
    [OT_LONG] = {
196 367e86e8 bellard
        gen_op_movl_EAX_T1,
197 367e86e8 bellard
        gen_op_movl_ECX_T1,
198 367e86e8 bellard
        gen_op_movl_EDX_T1,
199 367e86e8 bellard
        gen_op_movl_EBX_T1,
200 367e86e8 bellard
        gen_op_movl_ESP_T1,
201 367e86e8 bellard
        gen_op_movl_EBP_T1,
202 367e86e8 bellard
        gen_op_movl_ESI_T1,
203 367e86e8 bellard
        gen_op_movl_EDI_T1,
204 367e86e8 bellard
    },
205 367e86e8 bellard
};
206 367e86e8 bellard
207 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
208 367e86e8 bellard
    [0] = {
209 367e86e8 bellard
        gen_op_movw_EAX_A0,
210 367e86e8 bellard
        gen_op_movw_ECX_A0,
211 367e86e8 bellard
        gen_op_movw_EDX_A0,
212 367e86e8 bellard
        gen_op_movw_EBX_A0,
213 367e86e8 bellard
        gen_op_movw_ESP_A0,
214 367e86e8 bellard
        gen_op_movw_EBP_A0,
215 367e86e8 bellard
        gen_op_movw_ESI_A0,
216 367e86e8 bellard
        gen_op_movw_EDI_A0,
217 367e86e8 bellard
    },
218 367e86e8 bellard
    [1] = {
219 367e86e8 bellard
        gen_op_movl_EAX_A0,
220 367e86e8 bellard
        gen_op_movl_ECX_A0,
221 367e86e8 bellard
        gen_op_movl_EDX_A0,
222 367e86e8 bellard
        gen_op_movl_EBX_A0,
223 367e86e8 bellard
        gen_op_movl_ESP_A0,
224 367e86e8 bellard
        gen_op_movl_EBP_A0,
225 367e86e8 bellard
        gen_op_movl_ESI_A0,
226 367e86e8 bellard
        gen_op_movl_EDI_A0,
227 367e86e8 bellard
    },
228 367e86e8 bellard
};
229 367e86e8 bellard
230 367e86e8 bellard
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
231 367e86e8 bellard
{
232 367e86e8 bellard
    [OT_BYTE] = {
233 367e86e8 bellard
        {
234 367e86e8 bellard
            gen_op_movl_T0_EAX,
235 367e86e8 bellard
            gen_op_movl_T0_ECX,
236 367e86e8 bellard
            gen_op_movl_T0_EDX,
237 367e86e8 bellard
            gen_op_movl_T0_EBX,
238 367e86e8 bellard
            gen_op_movh_T0_EAX,
239 367e86e8 bellard
            gen_op_movh_T0_ECX,
240 367e86e8 bellard
            gen_op_movh_T0_EDX,
241 367e86e8 bellard
            gen_op_movh_T0_EBX,
242 367e86e8 bellard
        },
243 367e86e8 bellard
        {
244 367e86e8 bellard
            gen_op_movl_T1_EAX,
245 367e86e8 bellard
            gen_op_movl_T1_ECX,
246 367e86e8 bellard
            gen_op_movl_T1_EDX,
247 367e86e8 bellard
            gen_op_movl_T1_EBX,
248 367e86e8 bellard
            gen_op_movh_T1_EAX,
249 367e86e8 bellard
            gen_op_movh_T1_ECX,
250 367e86e8 bellard
            gen_op_movh_T1_EDX,
251 367e86e8 bellard
            gen_op_movh_T1_EBX,
252 367e86e8 bellard
        },
253 367e86e8 bellard
    },
254 367e86e8 bellard
    [OT_WORD] = {
255 367e86e8 bellard
        {
256 367e86e8 bellard
            gen_op_movl_T0_EAX,
257 367e86e8 bellard
            gen_op_movl_T0_ECX,
258 367e86e8 bellard
            gen_op_movl_T0_EDX,
259 367e86e8 bellard
            gen_op_movl_T0_EBX,
260 367e86e8 bellard
            gen_op_movl_T0_ESP,
261 367e86e8 bellard
            gen_op_movl_T0_EBP,
262 367e86e8 bellard
            gen_op_movl_T0_ESI,
263 367e86e8 bellard
            gen_op_movl_T0_EDI,
264 367e86e8 bellard
        },
265 367e86e8 bellard
        {
266 367e86e8 bellard
            gen_op_movl_T1_EAX,
267 367e86e8 bellard
            gen_op_movl_T1_ECX,
268 367e86e8 bellard
            gen_op_movl_T1_EDX,
269 367e86e8 bellard
            gen_op_movl_T1_EBX,
270 367e86e8 bellard
            gen_op_movl_T1_ESP,
271 367e86e8 bellard
            gen_op_movl_T1_EBP,
272 367e86e8 bellard
            gen_op_movl_T1_ESI,
273 367e86e8 bellard
            gen_op_movl_T1_EDI,
274 367e86e8 bellard
        },
275 367e86e8 bellard
    },
276 367e86e8 bellard
    [OT_LONG] = {
277 367e86e8 bellard
        {
278 367e86e8 bellard
            gen_op_movl_T0_EAX,
279 367e86e8 bellard
            gen_op_movl_T0_ECX,
280 367e86e8 bellard
            gen_op_movl_T0_EDX,
281 367e86e8 bellard
            gen_op_movl_T0_EBX,
282 367e86e8 bellard
            gen_op_movl_T0_ESP,
283 367e86e8 bellard
            gen_op_movl_T0_EBP,
284 367e86e8 bellard
            gen_op_movl_T0_ESI,
285 367e86e8 bellard
            gen_op_movl_T0_EDI,
286 367e86e8 bellard
        },
287 367e86e8 bellard
        {
288 367e86e8 bellard
            gen_op_movl_T1_EAX,
289 367e86e8 bellard
            gen_op_movl_T1_ECX,
290 367e86e8 bellard
            gen_op_movl_T1_EDX,
291 367e86e8 bellard
            gen_op_movl_T1_EBX,
292 367e86e8 bellard
            gen_op_movl_T1_ESP,
293 367e86e8 bellard
            gen_op_movl_T1_EBP,
294 367e86e8 bellard
            gen_op_movl_T1_ESI,
295 367e86e8 bellard
            gen_op_movl_T1_EDI,
296 367e86e8 bellard
        },
297 367e86e8 bellard
    },
298 367e86e8 bellard
};
299 367e86e8 bellard
300 367e86e8 bellard
static GenOpFunc *gen_op_movl_A0_reg[8] = {
301 367e86e8 bellard
    gen_op_movl_A0_EAX,
302 367e86e8 bellard
    gen_op_movl_A0_ECX,
303 367e86e8 bellard
    gen_op_movl_A0_EDX,
304 367e86e8 bellard
    gen_op_movl_A0_EBX,
305 367e86e8 bellard
    gen_op_movl_A0_ESP,
306 367e86e8 bellard
    gen_op_movl_A0_EBP,
307 367e86e8 bellard
    gen_op_movl_A0_ESI,
308 367e86e8 bellard
    gen_op_movl_A0_EDI,
309 367e86e8 bellard
};
310 367e86e8 bellard
311 367e86e8 bellard
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
312 367e86e8 bellard
    [0] = {
313 367e86e8 bellard
        gen_op_addl_A0_EAX,
314 367e86e8 bellard
        gen_op_addl_A0_ECX,
315 367e86e8 bellard
        gen_op_addl_A0_EDX,
316 367e86e8 bellard
        gen_op_addl_A0_EBX,
317 367e86e8 bellard
        gen_op_addl_A0_ESP,
318 367e86e8 bellard
        gen_op_addl_A0_EBP,
319 367e86e8 bellard
        gen_op_addl_A0_ESI,
320 367e86e8 bellard
        gen_op_addl_A0_EDI,
321 367e86e8 bellard
    },
322 367e86e8 bellard
    [1] = {
323 367e86e8 bellard
        gen_op_addl_A0_EAX_s1,
324 367e86e8 bellard
        gen_op_addl_A0_ECX_s1,
325 367e86e8 bellard
        gen_op_addl_A0_EDX_s1,
326 367e86e8 bellard
        gen_op_addl_A0_EBX_s1,
327 367e86e8 bellard
        gen_op_addl_A0_ESP_s1,
328 367e86e8 bellard
        gen_op_addl_A0_EBP_s1,
329 367e86e8 bellard
        gen_op_addl_A0_ESI_s1,
330 367e86e8 bellard
        gen_op_addl_A0_EDI_s1,
331 367e86e8 bellard
    },
332 367e86e8 bellard
    [2] = {
333 367e86e8 bellard
        gen_op_addl_A0_EAX_s2,
334 367e86e8 bellard
        gen_op_addl_A0_ECX_s2,
335 367e86e8 bellard
        gen_op_addl_A0_EDX_s2,
336 367e86e8 bellard
        gen_op_addl_A0_EBX_s2,
337 367e86e8 bellard
        gen_op_addl_A0_ESP_s2,
338 367e86e8 bellard
        gen_op_addl_A0_EBP_s2,
339 367e86e8 bellard
        gen_op_addl_A0_ESI_s2,
340 367e86e8 bellard
        gen_op_addl_A0_EDI_s2,
341 367e86e8 bellard
    },
342 367e86e8 bellard
    [3] = {
343 367e86e8 bellard
        gen_op_addl_A0_EAX_s3,
344 367e86e8 bellard
        gen_op_addl_A0_ECX_s3,
345 367e86e8 bellard
        gen_op_addl_A0_EDX_s3,
346 367e86e8 bellard
        gen_op_addl_A0_EBX_s3,
347 367e86e8 bellard
        gen_op_addl_A0_ESP_s3,
348 367e86e8 bellard
        gen_op_addl_A0_EBP_s3,
349 367e86e8 bellard
        gen_op_addl_A0_ESI_s3,
350 367e86e8 bellard
        gen_op_addl_A0_EDI_s3,
351 367e86e8 bellard
    },
352 367e86e8 bellard
};
353 367e86e8 bellard
354 367e86e8 bellard
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
355 367e86e8 bellard
    gen_op_addl_T0_T1_cc,
356 367e86e8 bellard
    gen_op_orl_T0_T1_cc,
357 367e86e8 bellard
    gen_op_adcl_T0_T1_cc,
358 367e86e8 bellard
    gen_op_sbbl_T0_T1_cc,
359 367e86e8 bellard
    gen_op_andl_T0_T1_cc,
360 367e86e8 bellard
    gen_op_subl_T0_T1_cc,
361 367e86e8 bellard
    gen_op_xorl_T0_T1_cc,
362 367e86e8 bellard
    gen_op_cmpl_T0_T1_cc,
363 367e86e8 bellard
};
364 367e86e8 bellard
365 367e86e8 bellard
static const int cc_op_arithb[8] = {
366 367e86e8 bellard
    CC_OP_ADDB,
367 367e86e8 bellard
    CC_OP_LOGICB,
368 367e86e8 bellard
    CC_OP_ADDB,
369 367e86e8 bellard
    CC_OP_SUBB,
370 367e86e8 bellard
    CC_OP_LOGICB,
371 367e86e8 bellard
    CC_OP_SUBB,
372 367e86e8 bellard
    CC_OP_LOGICB,
373 367e86e8 bellard
    CC_OP_SUBB,
374 367e86e8 bellard
};
375 367e86e8 bellard
376 367e86e8 bellard
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
377 367e86e8 bellard
    [OT_BYTE] = {
378 367e86e8 bellard
        gen_op_rolb_T0_T1_cc,
379 367e86e8 bellard
        gen_op_rorb_T0_T1_cc,
380 367e86e8 bellard
        gen_op_rclb_T0_T1_cc,
381 367e86e8 bellard
        gen_op_rcrb_T0_T1_cc,
382 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
383 367e86e8 bellard
        gen_op_shrb_T0_T1_cc,
384 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
385 367e86e8 bellard
        gen_op_sarb_T0_T1_cc,
386 367e86e8 bellard
    },
387 367e86e8 bellard
    [OT_WORD] = {
388 367e86e8 bellard
        gen_op_rolw_T0_T1_cc,
389 367e86e8 bellard
        gen_op_rorw_T0_T1_cc,
390 367e86e8 bellard
        gen_op_rclw_T0_T1_cc,
391 367e86e8 bellard
        gen_op_rcrw_T0_T1_cc,
392 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
393 367e86e8 bellard
        gen_op_shrw_T0_T1_cc,
394 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
395 367e86e8 bellard
        gen_op_sarw_T0_T1_cc,
396 367e86e8 bellard
    },
397 367e86e8 bellard
    [OT_LONG] = {
398 367e86e8 bellard
        gen_op_roll_T0_T1_cc,
399 367e86e8 bellard
        gen_op_rorl_T0_T1_cc,
400 367e86e8 bellard
        gen_op_rcll_T0_T1_cc,
401 367e86e8 bellard
        gen_op_rcrl_T0_T1_cc,
402 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
403 367e86e8 bellard
        gen_op_shrl_T0_T1_cc,
404 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
405 367e86e8 bellard
        gen_op_sarl_T0_T1_cc,
406 367e86e8 bellard
    },
407 367e86e8 bellard
};
408 367e86e8 bellard
409 367e86e8 bellard
static GenOpFunc *gen_op_lds_T0_A0[3] = {
410 367e86e8 bellard
    gen_op_ldsb_T0_A0,
411 367e86e8 bellard
    gen_op_ldsw_T0_A0,
412 367e86e8 bellard
};
413 367e86e8 bellard
414 367e86e8 bellard
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
415 367e86e8 bellard
    gen_op_ldub_T0_A0,
416 367e86e8 bellard
    gen_op_lduw_T0_A0,
417 367e86e8 bellard
};
418 367e86e8 bellard
419 367e86e8 bellard
/* sign does not matter */
420 367e86e8 bellard
static GenOpFunc *gen_op_ld_T0_A0[3] = {
421 367e86e8 bellard
    gen_op_ldub_T0_A0,
422 367e86e8 bellard
    gen_op_lduw_T0_A0,
423 367e86e8 bellard
    gen_op_ldl_T0_A0,
424 367e86e8 bellard
};
425 367e86e8 bellard
426 367e86e8 bellard
static GenOpFunc *gen_op_ld_T1_A0[3] = {
427 367e86e8 bellard
    gen_op_ldub_T1_A0,
428 367e86e8 bellard
    gen_op_lduw_T1_A0,
429 367e86e8 bellard
    gen_op_ldl_T1_A0,
430 367e86e8 bellard
};
431 367e86e8 bellard
432 367e86e8 bellard
static GenOpFunc *gen_op_st_T0_A0[3] = {
433 367e86e8 bellard
    gen_op_stb_T0_A0,
434 367e86e8 bellard
    gen_op_stw_T0_A0,
435 367e86e8 bellard
    gen_op_stl_T0_A0,
436 367e86e8 bellard
};
437 367e86e8 bellard
438 367e86e8 bellard
static GenOpFunc *gen_op_movs[6] = {
439 367e86e8 bellard
    gen_op_movsb,
440 367e86e8 bellard
    gen_op_movsw,
441 367e86e8 bellard
    gen_op_movsl,
442 367e86e8 bellard
    gen_op_rep_movsb,
443 367e86e8 bellard
    gen_op_rep_movsw,
444 367e86e8 bellard
    gen_op_rep_movsl,
445 367e86e8 bellard
};
446 367e86e8 bellard
447 367e86e8 bellard
static GenOpFunc *gen_op_stos[6] = {
448 367e86e8 bellard
    gen_op_stosb,
449 367e86e8 bellard
    gen_op_stosw,
450 367e86e8 bellard
    gen_op_stosl,
451 367e86e8 bellard
    gen_op_rep_stosb,
452 367e86e8 bellard
    gen_op_rep_stosw,
453 367e86e8 bellard
    gen_op_rep_stosl,
454 367e86e8 bellard
};
455 367e86e8 bellard
456 367e86e8 bellard
static GenOpFunc *gen_op_lods[6] = {
457 367e86e8 bellard
    gen_op_lodsb,
458 367e86e8 bellard
    gen_op_lodsw,
459 367e86e8 bellard
    gen_op_lodsl,
460 367e86e8 bellard
    gen_op_rep_lodsb,
461 367e86e8 bellard
    gen_op_rep_lodsw,
462 367e86e8 bellard
    gen_op_rep_lodsl,
463 367e86e8 bellard
};
464 367e86e8 bellard
465 367e86e8 bellard
static GenOpFunc *gen_op_scas[9] = {
466 367e86e8 bellard
    gen_op_scasb,
467 367e86e8 bellard
    gen_op_scasw,
468 367e86e8 bellard
    gen_op_scasl,
469 367e86e8 bellard
    gen_op_repz_scasb,
470 367e86e8 bellard
    gen_op_repz_scasw,
471 367e86e8 bellard
    gen_op_repz_scasl,
472 367e86e8 bellard
    gen_op_repnz_scasb,
473 367e86e8 bellard
    gen_op_repnz_scasw,
474 367e86e8 bellard
    gen_op_repnz_scasl,
475 367e86e8 bellard
};
476 367e86e8 bellard
477 367e86e8 bellard
static GenOpFunc *gen_op_cmps[9] = {
478 367e86e8 bellard
    gen_op_cmpsb,
479 367e86e8 bellard
    gen_op_cmpsw,
480 367e86e8 bellard
    gen_op_cmpsl,
481 367e86e8 bellard
    gen_op_repz_cmpsb,
482 367e86e8 bellard
    gen_op_repz_cmpsw,
483 367e86e8 bellard
    gen_op_repz_cmpsl,
484 367e86e8 bellard
    gen_op_repnz_cmpsb,
485 367e86e8 bellard
    gen_op_repnz_cmpsw,
486 367e86e8 bellard
    gen_op_repnz_cmpsl,
487 367e86e8 bellard
};
488 367e86e8 bellard
489 367e86e8 bellard
static GenOpFunc *gen_op_ins[6] = {
490 367e86e8 bellard
    gen_op_insb,
491 367e86e8 bellard
    gen_op_insw,
492 367e86e8 bellard
    gen_op_insl,
493 367e86e8 bellard
    gen_op_rep_insb,
494 367e86e8 bellard
    gen_op_rep_insw,
495 367e86e8 bellard
    gen_op_rep_insl,
496 367e86e8 bellard
};
497 367e86e8 bellard
498 367e86e8 bellard
499 367e86e8 bellard
static GenOpFunc *gen_op_outs[6] = {
500 367e86e8 bellard
    gen_op_outsb,
501 367e86e8 bellard
    gen_op_outsw,
502 367e86e8 bellard
    gen_op_outsl,
503 367e86e8 bellard
    gen_op_rep_outsb,
504 367e86e8 bellard
    gen_op_rep_outsw,
505 367e86e8 bellard
    gen_op_rep_outsl,
506 367e86e8 bellard
};
507 367e86e8 bellard
508 ba1c6e37 bellard
static GenOpFunc *gen_op_in[3] = {
509 ba1c6e37 bellard
    gen_op_inb_T0_T1,
510 ba1c6e37 bellard
    gen_op_inw_T0_T1,
511 ba1c6e37 bellard
    gen_op_inl_T0_T1,
512 ba1c6e37 bellard
};
513 ba1c6e37 bellard
514 ba1c6e37 bellard
static GenOpFunc *gen_op_out[3] = {
515 ba1c6e37 bellard
    gen_op_outb_T0_T1,
516 ba1c6e37 bellard
    gen_op_outw_T0_T1,
517 ba1c6e37 bellard
    gen_op_outl_T0_T1,
518 ba1c6e37 bellard
};
519 ba1c6e37 bellard
520 367e86e8 bellard
enum {
521 367e86e8 bellard
    JCC_O,
522 367e86e8 bellard
    JCC_B,
523 367e86e8 bellard
    JCC_Z,
524 367e86e8 bellard
    JCC_BE,
525 367e86e8 bellard
    JCC_S,
526 367e86e8 bellard
    JCC_P,
527 367e86e8 bellard
    JCC_L,
528 367e86e8 bellard
    JCC_LE,
529 367e86e8 bellard
};
530 367e86e8 bellard
531 367e86e8 bellard
static GenOpFunc2 *gen_jcc_slow[8] = {
532 367e86e8 bellard
    gen_op_jo_cc,
533 367e86e8 bellard
    gen_op_jb_cc,
534 367e86e8 bellard
    gen_op_jz_cc,
535 367e86e8 bellard
    gen_op_jbe_cc,
536 367e86e8 bellard
    gen_op_js_cc,
537 367e86e8 bellard
    gen_op_jp_cc,
538 367e86e8 bellard
    gen_op_jl_cc,
539 367e86e8 bellard
    gen_op_jle_cc,
540 367e86e8 bellard
};
541 367e86e8 bellard
    
542 367e86e8 bellard
static GenOpFunc2 *gen_jcc_sub[3][8] = {
543 367e86e8 bellard
    [OT_BYTE] = {
544 367e86e8 bellard
        NULL,
545 367e86e8 bellard
        gen_op_jb_subb,
546 367e86e8 bellard
        gen_op_jz_subb,
547 367e86e8 bellard
        gen_op_jbe_subb,
548 367e86e8 bellard
        gen_op_js_subb,
549 367e86e8 bellard
        NULL,
550 367e86e8 bellard
        gen_op_jl_subb,
551 367e86e8 bellard
        gen_op_jle_subb,
552 367e86e8 bellard
    },
553 367e86e8 bellard
    [OT_WORD] = {
554 367e86e8 bellard
        NULL,
555 367e86e8 bellard
        gen_op_jb_subw,
556 367e86e8 bellard
        gen_op_jz_subw,
557 367e86e8 bellard
        gen_op_jbe_subw,
558 367e86e8 bellard
        gen_op_js_subw,
559 367e86e8 bellard
        NULL,
560 367e86e8 bellard
        gen_op_jl_subw,
561 367e86e8 bellard
        gen_op_jle_subw,
562 367e86e8 bellard
    },
563 367e86e8 bellard
    [OT_LONG] = {
564 367e86e8 bellard
        NULL,
565 367e86e8 bellard
        gen_op_jb_subl,
566 367e86e8 bellard
        gen_op_jz_subl,
567 367e86e8 bellard
        gen_op_jbe_subl,
568 367e86e8 bellard
        gen_op_js_subl,
569 367e86e8 bellard
        NULL,
570 367e86e8 bellard
        gen_op_jl_subl,
571 367e86e8 bellard
        gen_op_jle_subl,
572 367e86e8 bellard
    },
573 367e86e8 bellard
};
574 367e86e8 bellard
575 367e86e8 bellard
static GenOpFunc *gen_setcc_slow[8] = {
576 367e86e8 bellard
    gen_op_seto_T0_cc,
577 367e86e8 bellard
    gen_op_setb_T0_cc,
578 367e86e8 bellard
    gen_op_setz_T0_cc,
579 367e86e8 bellard
    gen_op_setbe_T0_cc,
580 367e86e8 bellard
    gen_op_sets_T0_cc,
581 367e86e8 bellard
    gen_op_setp_T0_cc,
582 367e86e8 bellard
    gen_op_setl_T0_cc,
583 367e86e8 bellard
    gen_op_setle_T0_cc,
584 367e86e8 bellard
};
585 367e86e8 bellard
586 367e86e8 bellard
static GenOpFunc *gen_setcc_sub[3][8] = {
587 367e86e8 bellard
    [OT_BYTE] = {
588 367e86e8 bellard
        NULL,
589 367e86e8 bellard
        gen_op_setb_T0_subb,
590 367e86e8 bellard
        gen_op_setz_T0_subb,
591 367e86e8 bellard
        gen_op_setbe_T0_subb,
592 367e86e8 bellard
        gen_op_sets_T0_subb,
593 367e86e8 bellard
        NULL,
594 367e86e8 bellard
        gen_op_setl_T0_subb,
595 367e86e8 bellard
        gen_op_setle_T0_subb,
596 367e86e8 bellard
    },
597 367e86e8 bellard
    [OT_WORD] = {
598 367e86e8 bellard
        NULL,
599 367e86e8 bellard
        gen_op_setb_T0_subw,
600 367e86e8 bellard
        gen_op_setz_T0_subw,
601 367e86e8 bellard
        gen_op_setbe_T0_subw,
602 367e86e8 bellard
        gen_op_sets_T0_subw,
603 367e86e8 bellard
        NULL,
604 367e86e8 bellard
        gen_op_setl_T0_subw,
605 367e86e8 bellard
        gen_op_setle_T0_subw,
606 367e86e8 bellard
    },
607 367e86e8 bellard
    [OT_LONG] = {
608 367e86e8 bellard
        NULL,
609 367e86e8 bellard
        gen_op_setb_T0_subl,
610 367e86e8 bellard
        gen_op_setz_T0_subl,
611 367e86e8 bellard
        gen_op_setbe_T0_subl,
612 367e86e8 bellard
        gen_op_sets_T0_subl,
613 367e86e8 bellard
        NULL,
614 367e86e8 bellard
        gen_op_setl_T0_subl,
615 367e86e8 bellard
        gen_op_setle_T0_subl,
616 367e86e8 bellard
    },
617 367e86e8 bellard
};
618 367e86e8 bellard
619 927f621e bellard
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
620 927f621e bellard
    gen_op_fadd_ST0_FT0,
621 927f621e bellard
    gen_op_fmul_ST0_FT0,
622 927f621e bellard
    gen_op_fcom_ST0_FT0,
623 927f621e bellard
    gen_op_fcom_ST0_FT0,
624 927f621e bellard
    gen_op_fsub_ST0_FT0,
625 927f621e bellard
    gen_op_fsubr_ST0_FT0,
626 927f621e bellard
    gen_op_fdiv_ST0_FT0,
627 927f621e bellard
    gen_op_fdivr_ST0_FT0,
628 927f621e bellard
};
629 927f621e bellard
630 927f621e bellard
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
631 927f621e bellard
    gen_op_fadd_STN_ST0,
632 927f621e bellard
    gen_op_fmul_STN_ST0,
633 927f621e bellard
    NULL,
634 927f621e bellard
    NULL,
635 927f621e bellard
    gen_op_fsub_STN_ST0,
636 927f621e bellard
    gen_op_fsubr_STN_ST0,
637 927f621e bellard
    gen_op_fdiv_STN_ST0,
638 927f621e bellard
    gen_op_fdivr_STN_ST0,
639 927f621e bellard
};
640 927f621e bellard
641 367e86e8 bellard
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
642 367e86e8 bellard
{
643 367e86e8 bellard
    if (d != OR_TMP0)
644 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
645 367e86e8 bellard
    if (s != OR_TMP1)
646 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
647 367e86e8 bellard
    if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC)
648 367e86e8 bellard
        gen_op_set_cc_op(s1->cc_op);
649 367e86e8 bellard
    gen_op_arith_T0_T1_cc[op]();
650 367e86e8 bellard
    if (d != OR_TMP0 && op != OP_CMPL)
651 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
652 367e86e8 bellard
    s1->cc_op = cc_op_arithb[op] + ot;
653 367e86e8 bellard
}
654 367e86e8 bellard
655 367e86e8 bellard
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
656 367e86e8 bellard
{
657 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
658 367e86e8 bellard
    gen_op(s1, op, ot, d, OR_TMP0);
659 367e86e8 bellard
}
660 367e86e8 bellard
661 367e86e8 bellard
static void gen_inc(DisasContext *s1, int ot, int d, int c)
662 367e86e8 bellard
{
663 367e86e8 bellard
    if (d != OR_TMP0)
664 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
665 367e86e8 bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
666 367e86e8 bellard
        gen_op_set_cc_op(s1->cc_op);
667 367e86e8 bellard
    if (c > 0)
668 367e86e8 bellard
        gen_op_incl_T0_cc();
669 367e86e8 bellard
    else
670 367e86e8 bellard
        gen_op_decl_T0_cc();
671 367e86e8 bellard
    if (d != OR_TMP0)
672 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
673 367e86e8 bellard
}
674 367e86e8 bellard
675 367e86e8 bellard
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
676 367e86e8 bellard
{
677 367e86e8 bellard
    if (d != OR_TMP0)
678 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
679 367e86e8 bellard
    if (s != OR_TMP1)
680 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
681 367e86e8 bellard
    switch(op) {
682 367e86e8 bellard
    case OP_ROL:
683 367e86e8 bellard
    case OP_ROR:
684 367e86e8 bellard
    case OP_RCL:
685 367e86e8 bellard
    case OP_RCR:
686 367e86e8 bellard
        /* only C and O are modified, so we must update flags dynamically */
687 367e86e8 bellard
        if (s1->cc_op != CC_OP_DYNAMIC)
688 367e86e8 bellard
            gen_op_set_cc_op(s1->cc_op);
689 367e86e8 bellard
        gen_op_shift_T0_T1_cc[ot][op]();
690 367e86e8 bellard
        break;
691 367e86e8 bellard
    default:
692 367e86e8 bellard
        gen_op_shift_T0_T1_cc[ot][op]();
693 367e86e8 bellard
        break;
694 367e86e8 bellard
    }
695 367e86e8 bellard
    if (d != OR_TMP0)
696 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
697 367e86e8 bellard
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
698 367e86e8 bellard
}
699 367e86e8 bellard
700 367e86e8 bellard
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
701 367e86e8 bellard
{
702 367e86e8 bellard
    /* currently not optimized */
703 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
704 367e86e8 bellard
    gen_shift(s1, op, ot, d, OR_TMP1);
705 367e86e8 bellard
}
706 367e86e8 bellard
707 367e86e8 bellard
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
708 367e86e8 bellard
{
709 367e86e8 bellard
    int havesib;
710 367e86e8 bellard
    int havebase;
711 367e86e8 bellard
    int base, disp;
712 367e86e8 bellard
    int index = 0;
713 367e86e8 bellard
    int scale = 0;
714 367e86e8 bellard
    int reg1, reg2, opreg;
715 367e86e8 bellard
    int mod, rm, code;
716 367e86e8 bellard
717 367e86e8 bellard
    mod = (modrm >> 6) & 3;
718 367e86e8 bellard
    rm = modrm & 7;
719 367e86e8 bellard
720 367e86e8 bellard
    if (s->aflag) {
721 367e86e8 bellard
722 367e86e8 bellard
        havesib = 0;
723 367e86e8 bellard
        havebase = 1;
724 367e86e8 bellard
        base = rm;
725 367e86e8 bellard
        
726 367e86e8 bellard
        if (base == 4) {
727 367e86e8 bellard
            havesib = 1;
728 367e86e8 bellard
            code = ldub(s->pc++);
729 367e86e8 bellard
            scale = (code >> 6) & 3;
730 367e86e8 bellard
            index = (code >> 3) & 7;
731 367e86e8 bellard
            base = code & 7;
732 367e86e8 bellard
        }
733 367e86e8 bellard
734 367e86e8 bellard
        switch (mod) {
735 367e86e8 bellard
        case 0:
736 367e86e8 bellard
            if (base == 5) {
737 367e86e8 bellard
                havebase = 0;
738 367e86e8 bellard
                disp = ldl(s->pc);
739 367e86e8 bellard
                s->pc += 4;
740 367e86e8 bellard
            } else {
741 367e86e8 bellard
                disp = 0;
742 367e86e8 bellard
            }
743 367e86e8 bellard
            break;
744 367e86e8 bellard
        case 1:
745 367e86e8 bellard
            disp = (int8_t)ldub(s->pc++);
746 367e86e8 bellard
            break;
747 367e86e8 bellard
        default:
748 367e86e8 bellard
        case 2:
749 367e86e8 bellard
            disp = ldl(s->pc);
750 367e86e8 bellard
            s->pc += 4;
751 367e86e8 bellard
            break;
752 367e86e8 bellard
        }
753 367e86e8 bellard
754 367e86e8 bellard
        reg1 = OR_ZERO;
755 367e86e8 bellard
        reg2 = OR_ZERO;
756 367e86e8 bellard
          
757 367e86e8 bellard
        if (havebase || (havesib && (index != 4 || scale != 0))) {
758 367e86e8 bellard
            if (havebase)
759 367e86e8 bellard
                reg1 = OR_EAX + base;
760 367e86e8 bellard
            if (havesib && index != 4) {
761 367e86e8 bellard
                if (havebase)
762 367e86e8 bellard
                    reg2 = index + OR_EAX;
763 367e86e8 bellard
                else
764 367e86e8 bellard
                    reg1 = index + OR_EAX;
765 367e86e8 bellard
            }
766 367e86e8 bellard
        }
767 367e86e8 bellard
        /* XXX: disp only ? */
768 367e86e8 bellard
        if (reg2 == OR_ZERO) {
769 367e86e8 bellard
            /* op: disp + (reg1 << scale) */
770 367e86e8 bellard
            if (reg1 == OR_ZERO) {
771 ba1c6e37 bellard
                gen_op_movl_A0_im(disp);
772 367e86e8 bellard
            } else if (scale == 0 && disp == 0) {
773 367e86e8 bellard
                gen_op_movl_A0_reg[reg1]();
774 367e86e8 bellard
            } else {
775 0ecfa993 bellard
                gen_op_movl_A0_im(disp);
776 367e86e8 bellard
                gen_op_addl_A0_reg_sN[scale][reg1]();
777 367e86e8 bellard
            }
778 367e86e8 bellard
        } else {
779 367e86e8 bellard
            /* op: disp + reg1 + (reg2 << scale) */
780 367e86e8 bellard
            if (disp != 0) {
781 ba1c6e37 bellard
                gen_op_movl_A0_im(disp);
782 367e86e8 bellard
                gen_op_addl_A0_reg_sN[0][reg1]();
783 367e86e8 bellard
            } else {
784 367e86e8 bellard
                gen_op_movl_A0_reg[reg1]();
785 367e86e8 bellard
            }
786 367e86e8 bellard
            gen_op_addl_A0_reg_sN[scale][reg2]();
787 367e86e8 bellard
        }
788 367e86e8 bellard
        opreg = OR_A0;
789 367e86e8 bellard
    } else {
790 367e86e8 bellard
        fprintf(stderr, "16 bit addressing not supported\n");
791 367e86e8 bellard
        disp = 0;
792 367e86e8 bellard
        opreg = 0;
793 367e86e8 bellard
    }
794 367e86e8 bellard
    *reg_ptr = opreg;
795 367e86e8 bellard
    *offset_ptr = disp;
796 367e86e8 bellard
}
797 367e86e8 bellard
798 367e86e8 bellard
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
799 367e86e8 bellard
   OR_TMP0 */
800 367e86e8 bellard
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
801 367e86e8 bellard
{
802 367e86e8 bellard
    int mod, rm, opreg, disp;
803 367e86e8 bellard
804 367e86e8 bellard
    mod = (modrm >> 6) & 3;
805 367e86e8 bellard
    rm = modrm & 7;
806 367e86e8 bellard
    if (mod == 3) {
807 367e86e8 bellard
        if (is_store) {
808 367e86e8 bellard
            if (reg != OR_TMP0)
809 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
810 367e86e8 bellard
            gen_op_mov_reg_T0[ot][rm]();
811 367e86e8 bellard
        } else {
812 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
813 367e86e8 bellard
            if (reg != OR_TMP0)
814 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
815 367e86e8 bellard
        }
816 367e86e8 bellard
    } else {
817 367e86e8 bellard
        gen_lea_modrm(s, modrm, &opreg, &disp);
818 367e86e8 bellard
        if (is_store) {
819 367e86e8 bellard
            if (reg != OR_TMP0)
820 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
821 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
822 367e86e8 bellard
        } else {
823 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
824 367e86e8 bellard
            if (reg != OR_TMP0)
825 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
826 367e86e8 bellard
        }
827 367e86e8 bellard
    }
828 367e86e8 bellard
}
829 367e86e8 bellard
830 367e86e8 bellard
static inline uint32_t insn_get(DisasContext *s, int ot)
831 367e86e8 bellard
{
832 367e86e8 bellard
    uint32_t ret;
833 367e86e8 bellard
834 367e86e8 bellard
    switch(ot) {
835 367e86e8 bellard
    case OT_BYTE:
836 367e86e8 bellard
        ret = ldub(s->pc);
837 367e86e8 bellard
        s->pc++;
838 367e86e8 bellard
        break;
839 367e86e8 bellard
    case OT_WORD:
840 367e86e8 bellard
        ret = lduw(s->pc);
841 367e86e8 bellard
        s->pc += 2;
842 367e86e8 bellard
        break;
843 367e86e8 bellard
    default:
844 367e86e8 bellard
    case OT_LONG:
845 367e86e8 bellard
        ret = ldl(s->pc);
846 367e86e8 bellard
        s->pc += 4;
847 367e86e8 bellard
        break;
848 367e86e8 bellard
    }
849 367e86e8 bellard
    return ret;
850 367e86e8 bellard
}
851 367e86e8 bellard
852 367e86e8 bellard
static void gen_jcc(DisasContext *s, int b, int val)
853 367e86e8 bellard
{
854 367e86e8 bellard
    int inv, jcc_op;
855 367e86e8 bellard
    GenOpFunc2 *func;
856 367e86e8 bellard
857 367e86e8 bellard
    inv = b & 1;
858 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
859 367e86e8 bellard
    switch(s->cc_op) {
860 367e86e8 bellard
        /* we optimize the cmp/jcc case */
861 367e86e8 bellard
    case CC_OP_SUBB:
862 367e86e8 bellard
    case CC_OP_SUBW:
863 367e86e8 bellard
    case CC_OP_SUBL:
864 367e86e8 bellard
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
865 367e86e8 bellard
        if (!func)
866 367e86e8 bellard
            goto slow_jcc;
867 367e86e8 bellard
        break;
868 367e86e8 bellard
        
869 367e86e8 bellard
        /* some jumps are easy to compute */
870 367e86e8 bellard
    case CC_OP_ADDB:
871 367e86e8 bellard
    case CC_OP_ADDW:
872 367e86e8 bellard
    case CC_OP_ADDL:
873 367e86e8 bellard
    case CC_OP_LOGICB:
874 367e86e8 bellard
    case CC_OP_LOGICW:
875 367e86e8 bellard
    case CC_OP_LOGICL:
876 367e86e8 bellard
    case CC_OP_INCB:
877 367e86e8 bellard
    case CC_OP_INCW:
878 367e86e8 bellard
    case CC_OP_INCL:
879 367e86e8 bellard
    case CC_OP_DECB:
880 367e86e8 bellard
    case CC_OP_DECW:
881 367e86e8 bellard
    case CC_OP_DECL:
882 367e86e8 bellard
    case CC_OP_SHLB:
883 367e86e8 bellard
    case CC_OP_SHLW:
884 367e86e8 bellard
    case CC_OP_SHLL:
885 367e86e8 bellard
        switch(jcc_op) {
886 367e86e8 bellard
        case JCC_Z:
887 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
888 367e86e8 bellard
            break;
889 367e86e8 bellard
        case JCC_S:
890 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
891 367e86e8 bellard
            break;
892 367e86e8 bellard
        default:
893 367e86e8 bellard
            goto slow_jcc;
894 367e86e8 bellard
        }
895 367e86e8 bellard
        break;
896 367e86e8 bellard
    default:
897 367e86e8 bellard
    slow_jcc:
898 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
899 367e86e8 bellard
            op_set_cc_op(s->cc_op);
900 367e86e8 bellard
        func = gen_jcc_slow[jcc_op];
901 367e86e8 bellard
        break;
902 367e86e8 bellard
    }
903 367e86e8 bellard
    if (!inv) {
904 367e86e8 bellard
        func(val, (long)s->pc);
905 367e86e8 bellard
    } else {
906 367e86e8 bellard
        func((long)s->pc, val);
907 367e86e8 bellard
    }
908 367e86e8 bellard
}
909 367e86e8 bellard
910 367e86e8 bellard
static void gen_setcc(DisasContext *s, int b)
911 367e86e8 bellard
{
912 367e86e8 bellard
    int inv, jcc_op;
913 367e86e8 bellard
    GenOpFunc *func;
914 367e86e8 bellard
915 367e86e8 bellard
    inv = b & 1;
916 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
917 367e86e8 bellard
    switch(s->cc_op) {
918 367e86e8 bellard
        /* we optimize the cmp/jcc case */
919 367e86e8 bellard
    case CC_OP_SUBB:
920 367e86e8 bellard
    case CC_OP_SUBW:
921 367e86e8 bellard
    case CC_OP_SUBL:
922 367e86e8 bellard
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
923 367e86e8 bellard
        if (!func)
924 367e86e8 bellard
            goto slow_jcc;
925 367e86e8 bellard
        break;
926 367e86e8 bellard
        
927 367e86e8 bellard
        /* some jumps are easy to compute */
928 367e86e8 bellard
    case CC_OP_ADDB:
929 367e86e8 bellard
    case CC_OP_ADDW:
930 367e86e8 bellard
    case CC_OP_ADDL:
931 367e86e8 bellard
    case CC_OP_LOGICB:
932 367e86e8 bellard
    case CC_OP_LOGICW:
933 367e86e8 bellard
    case CC_OP_LOGICL:
934 367e86e8 bellard
    case CC_OP_INCB:
935 367e86e8 bellard
    case CC_OP_INCW:
936 367e86e8 bellard
    case CC_OP_INCL:
937 367e86e8 bellard
    case CC_OP_DECB:
938 367e86e8 bellard
    case CC_OP_DECW:
939 367e86e8 bellard
    case CC_OP_DECL:
940 367e86e8 bellard
    case CC_OP_SHLB:
941 367e86e8 bellard
    case CC_OP_SHLW:
942 367e86e8 bellard
    case CC_OP_SHLL:
943 367e86e8 bellard
        switch(jcc_op) {
944 367e86e8 bellard
        case JCC_Z:
945 367e86e8 bellard
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
946 367e86e8 bellard
            break;
947 367e86e8 bellard
        case JCC_S:
948 367e86e8 bellard
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
949 367e86e8 bellard
            break;
950 367e86e8 bellard
        default:
951 367e86e8 bellard
            goto slow_jcc;
952 367e86e8 bellard
        }
953 367e86e8 bellard
        break;
954 367e86e8 bellard
    default:
955 367e86e8 bellard
    slow_jcc:
956 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
957 367e86e8 bellard
            op_set_cc_op(s->cc_op);
958 367e86e8 bellard
        func = gen_setcc_slow[jcc_op];
959 367e86e8 bellard
        break;
960 367e86e8 bellard
    }
961 367e86e8 bellard
    func();
962 367e86e8 bellard
    if (inv) {
963 367e86e8 bellard
        gen_op_xor_T0_1();
964 367e86e8 bellard
    }
965 367e86e8 bellard
}
966 367e86e8 bellard
967 0ecfa993 bellard
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
968 0ecfa993 bellard
   is set to true if the instruction sets the PC (last instruction of
969 0ecfa993 bellard
   a basic block) */
970 0ecfa993 bellard
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
971 367e86e8 bellard
{
972 367e86e8 bellard
    int b, prefixes, aflag, dflag;
973 367e86e8 bellard
    int shift, ot;
974 367e86e8 bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
975 367e86e8 bellard
976 367e86e8 bellard
    s->pc = pc_start;
977 367e86e8 bellard
    prefixes = 0;
978 367e86e8 bellard
    aflag = 1;
979 367e86e8 bellard
    dflag = 1;
980 367e86e8 bellard
    //    cur_pc = s->pc; /* for insn generation */
981 367e86e8 bellard
 next_byte:
982 367e86e8 bellard
    b = ldub(s->pc);
983 367e86e8 bellard
    s->pc++;
984 367e86e8 bellard
    /* check prefixes */
985 367e86e8 bellard
    switch (b) {
986 367e86e8 bellard
    case 0xf3:
987 367e86e8 bellard
        prefixes |= PREFIX_REPZ;
988 367e86e8 bellard
        goto next_byte;
989 367e86e8 bellard
    case 0xf2:
990 367e86e8 bellard
        prefixes |= PREFIX_REPNZ;
991 367e86e8 bellard
        goto next_byte;
992 367e86e8 bellard
    case 0xf0:
993 367e86e8 bellard
        prefixes |= PREFIX_LOCK;
994 367e86e8 bellard
        goto next_byte;
995 367e86e8 bellard
    case 0x2e:
996 367e86e8 bellard
        prefixes |= PREFIX_CS;
997 367e86e8 bellard
        goto next_byte;
998 367e86e8 bellard
    case 0x36:
999 367e86e8 bellard
        prefixes |= PREFIX_SS;
1000 367e86e8 bellard
        goto next_byte;
1001 367e86e8 bellard
    case 0x3e:
1002 367e86e8 bellard
        prefixes |= PREFIX_DS;
1003 367e86e8 bellard
        goto next_byte;
1004 367e86e8 bellard
    case 0x26:
1005 367e86e8 bellard
        prefixes |= PREFIX_ES;
1006 367e86e8 bellard
        goto next_byte;
1007 367e86e8 bellard
    case 0x64:
1008 367e86e8 bellard
        prefixes |= PREFIX_FS;
1009 367e86e8 bellard
        goto next_byte;
1010 367e86e8 bellard
    case 0x65:
1011 367e86e8 bellard
        prefixes |= PREFIX_GS;
1012 367e86e8 bellard
        goto next_byte;
1013 367e86e8 bellard
    case 0x66:
1014 367e86e8 bellard
        prefixes |= PREFIX_DATA;
1015 367e86e8 bellard
        goto next_byte;
1016 367e86e8 bellard
    case 0x67:
1017 367e86e8 bellard
        prefixes |= PREFIX_ADR;
1018 367e86e8 bellard
        goto next_byte;
1019 367e86e8 bellard
    case 0x9b:
1020 367e86e8 bellard
        prefixes |= PREFIX_FWAIT;
1021 367e86e8 bellard
        goto next_byte;
1022 367e86e8 bellard
    }
1023 367e86e8 bellard
1024 367e86e8 bellard
    if (prefixes & PREFIX_DATA)
1025 367e86e8 bellard
        dflag ^= 1;
1026 367e86e8 bellard
    if (prefixes & PREFIX_ADR)
1027 367e86e8 bellard
        aflag ^= 1;
1028 367e86e8 bellard
1029 367e86e8 bellard
    s->prefix = prefixes;
1030 367e86e8 bellard
    s->aflag = aflag;
1031 367e86e8 bellard
    s->dflag = dflag;
1032 367e86e8 bellard
1033 367e86e8 bellard
    /* now check op code */
1034 367e86e8 bellard
 reswitch:
1035 367e86e8 bellard
    switch(b) {
1036 367e86e8 bellard
    case 0x0f:
1037 367e86e8 bellard
        /**************************/
1038 367e86e8 bellard
        /* extended op code */
1039 367e86e8 bellard
        b = ldub(s->pc++) | 0x100;
1040 367e86e8 bellard
        goto reswitch;
1041 367e86e8 bellard
        
1042 367e86e8 bellard
        /**************************/
1043 367e86e8 bellard
        /* arith & logic */
1044 367e86e8 bellard
    case 0x00 ... 0x05:
1045 367e86e8 bellard
    case 0x08 ... 0x0d:
1046 367e86e8 bellard
    case 0x10 ... 0x15:
1047 367e86e8 bellard
    case 0x18 ... 0x1d:
1048 367e86e8 bellard
    case 0x20 ... 0x25:
1049 367e86e8 bellard
    case 0x28 ... 0x2d:
1050 367e86e8 bellard
    case 0x30 ... 0x35:
1051 367e86e8 bellard
    case 0x38 ... 0x3d:
1052 367e86e8 bellard
        {
1053 367e86e8 bellard
            int op, f, val;
1054 367e86e8 bellard
            op = (b >> 3) & 7;
1055 367e86e8 bellard
            f = (b >> 1) & 3;
1056 367e86e8 bellard
1057 367e86e8 bellard
            if ((b & 1) == 0)
1058 367e86e8 bellard
                ot = OT_BYTE;
1059 367e86e8 bellard
            else
1060 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1061 367e86e8 bellard
            
1062 367e86e8 bellard
            switch(f) {
1063 367e86e8 bellard
            case 0: /* OP Ev, Gv */
1064 367e86e8 bellard
                modrm = ldub(s->pc++);
1065 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1066 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1067 367e86e8 bellard
                rm = modrm & 7;
1068 367e86e8 bellard
                if (mod != 3) {
1069 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1070 367e86e8 bellard
                    gen_op_ld_T0_A0[ot]();
1071 367e86e8 bellard
                    opreg = OR_TMP0;
1072 367e86e8 bellard
                } else {
1073 367e86e8 bellard
                    opreg = OR_EAX + rm;
1074 367e86e8 bellard
                }
1075 367e86e8 bellard
                gen_op(s, op, ot, opreg, reg);
1076 367e86e8 bellard
                if (mod != 3 && op != 7) {
1077 367e86e8 bellard
                    gen_op_st_T0_A0[ot]();
1078 367e86e8 bellard
                }
1079 367e86e8 bellard
                break;
1080 367e86e8 bellard
            case 1: /* OP Gv, Ev */
1081 367e86e8 bellard
                modrm = ldub(s->pc++);
1082 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1083 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1084 367e86e8 bellard
                rm = modrm & 7;
1085 367e86e8 bellard
                if (mod != 3) {
1086 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1087 367e86e8 bellard
                    gen_op_ld_T1_A0[ot]();
1088 367e86e8 bellard
                    opreg = OR_TMP1;
1089 367e86e8 bellard
                } else {
1090 367e86e8 bellard
                    opreg = OR_EAX + rm;
1091 367e86e8 bellard
                }
1092 367e86e8 bellard
                gen_op(s, op, ot, reg, opreg);
1093 367e86e8 bellard
                break;
1094 367e86e8 bellard
            case 2: /* OP A, Iv */
1095 367e86e8 bellard
                val = insn_get(s, ot);
1096 367e86e8 bellard
                gen_opi(s, op, ot, OR_EAX, val);
1097 367e86e8 bellard
                break;
1098 367e86e8 bellard
            }
1099 367e86e8 bellard
        }
1100 367e86e8 bellard
        break;
1101 367e86e8 bellard
1102 367e86e8 bellard
    case 0x80: /* GRP1 */
1103 367e86e8 bellard
    case 0x81:
1104 367e86e8 bellard
    case 0x83:
1105 367e86e8 bellard
        {
1106 367e86e8 bellard
            int val;
1107 367e86e8 bellard
1108 367e86e8 bellard
            if ((b & 1) == 0)
1109 367e86e8 bellard
                ot = OT_BYTE;
1110 367e86e8 bellard
            else
1111 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1112 367e86e8 bellard
            
1113 367e86e8 bellard
            modrm = ldub(s->pc++);
1114 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1115 367e86e8 bellard
            rm = modrm & 7;
1116 367e86e8 bellard
            op = (modrm >> 3) & 7;
1117 367e86e8 bellard
            
1118 367e86e8 bellard
            if (mod != 3) {
1119 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1120 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
1121 367e86e8 bellard
                opreg = OR_TMP0;
1122 367e86e8 bellard
            } else {
1123 367e86e8 bellard
                opreg = rm + OR_EAX;
1124 367e86e8 bellard
            }
1125 367e86e8 bellard
1126 367e86e8 bellard
            switch(b) {
1127 367e86e8 bellard
            default:
1128 367e86e8 bellard
            case 0x80:
1129 367e86e8 bellard
            case 0x81:
1130 367e86e8 bellard
                val = insn_get(s, ot);
1131 367e86e8 bellard
                break;
1132 367e86e8 bellard
            case 0x83:
1133 367e86e8 bellard
                val = (int8_t)insn_get(s, OT_BYTE);
1134 367e86e8 bellard
                break;
1135 367e86e8 bellard
            }
1136 367e86e8 bellard
1137 367e86e8 bellard
            gen_opi(s, op, ot, opreg, val);
1138 367e86e8 bellard
            if (op != 7 && mod != 3) {
1139 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1140 367e86e8 bellard
            }
1141 367e86e8 bellard
        }
1142 367e86e8 bellard
        break;
1143 367e86e8 bellard
1144 367e86e8 bellard
        /**************************/
1145 367e86e8 bellard
        /* inc, dec, and other misc arith */
1146 367e86e8 bellard
    case 0x40 ... 0x47: /* inc Gv */
1147 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1148 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1149 367e86e8 bellard
        break;
1150 367e86e8 bellard
    case 0x48 ... 0x4f: /* dec Gv */
1151 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1152 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1153 367e86e8 bellard
        break;
1154 367e86e8 bellard
    case 0xf6: /* GRP3 */
1155 367e86e8 bellard
    case 0xf7:
1156 367e86e8 bellard
        if ((b & 1) == 0)
1157 367e86e8 bellard
            ot = OT_BYTE;
1158 367e86e8 bellard
        else
1159 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1160 367e86e8 bellard
1161 367e86e8 bellard
        modrm = ldub(s->pc++);
1162 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1163 367e86e8 bellard
        rm = modrm & 7;
1164 367e86e8 bellard
        op = (modrm >> 3) & 7;
1165 367e86e8 bellard
        if (mod != 3) {
1166 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1167 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1168 367e86e8 bellard
        } else {
1169 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1170 367e86e8 bellard
        }
1171 367e86e8 bellard
1172 367e86e8 bellard
        switch(op) {
1173 367e86e8 bellard
        case 0: /* test */
1174 367e86e8 bellard
            val = insn_get(s, ot);
1175 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1176 367e86e8 bellard
            gen_op_testl_T0_T1_cc();
1177 367e86e8 bellard
            s->cc_op = CC_OP_LOGICB + ot;
1178 367e86e8 bellard
            break;
1179 367e86e8 bellard
        case 2: /* not */
1180 367e86e8 bellard
            gen_op_notl_T0();
1181 367e86e8 bellard
            if (mod != 3) {
1182 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1183 367e86e8 bellard
            } else {
1184 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1185 367e86e8 bellard
            }
1186 367e86e8 bellard
            break;
1187 367e86e8 bellard
        case 3: /* neg */
1188 367e86e8 bellard
            gen_op_negl_T0_cc();
1189 367e86e8 bellard
            if (mod != 3) {
1190 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1191 367e86e8 bellard
            } else {
1192 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1193 367e86e8 bellard
            }
1194 367e86e8 bellard
            s->cc_op = CC_OP_SUBB + ot;
1195 367e86e8 bellard
            break;
1196 367e86e8 bellard
        case 4: /* mul */
1197 367e86e8 bellard
            switch(ot) {
1198 367e86e8 bellard
            case OT_BYTE:
1199 367e86e8 bellard
                gen_op_mulb_AL_T0();
1200 367e86e8 bellard
                break;
1201 367e86e8 bellard
            case OT_WORD:
1202 367e86e8 bellard
                gen_op_mulw_AX_T0();
1203 367e86e8 bellard
                break;
1204 367e86e8 bellard
            default:
1205 367e86e8 bellard
            case OT_LONG:
1206 367e86e8 bellard
                gen_op_mull_EAX_T0();
1207 367e86e8 bellard
                break;
1208 367e86e8 bellard
            }
1209 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1210 367e86e8 bellard
            break;
1211 367e86e8 bellard
        case 5: /* imul */
1212 367e86e8 bellard
            switch(ot) {
1213 367e86e8 bellard
            case OT_BYTE:
1214 367e86e8 bellard
                gen_op_imulb_AL_T0();
1215 367e86e8 bellard
                break;
1216 367e86e8 bellard
            case OT_WORD:
1217 367e86e8 bellard
                gen_op_imulw_AX_T0();
1218 367e86e8 bellard
                break;
1219 367e86e8 bellard
            default:
1220 367e86e8 bellard
            case OT_LONG:
1221 367e86e8 bellard
                gen_op_imull_EAX_T0();
1222 367e86e8 bellard
                break;
1223 367e86e8 bellard
            }
1224 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1225 367e86e8 bellard
            break;
1226 367e86e8 bellard
        case 6: /* div */
1227 367e86e8 bellard
            switch(ot) {
1228 367e86e8 bellard
            case OT_BYTE:
1229 367e86e8 bellard
                gen_op_divb_AL_T0();
1230 367e86e8 bellard
                break;
1231 367e86e8 bellard
            case OT_WORD:
1232 367e86e8 bellard
                gen_op_divw_AX_T0();
1233 367e86e8 bellard
                break;
1234 367e86e8 bellard
            default:
1235 367e86e8 bellard
            case OT_LONG:
1236 367e86e8 bellard
                gen_op_divl_EAX_T0();
1237 367e86e8 bellard
                break;
1238 367e86e8 bellard
            }
1239 367e86e8 bellard
            break;
1240 367e86e8 bellard
        case 7: /* idiv */
1241 367e86e8 bellard
            switch(ot) {
1242 367e86e8 bellard
            case OT_BYTE:
1243 367e86e8 bellard
                gen_op_idivb_AL_T0();
1244 367e86e8 bellard
                break;
1245 367e86e8 bellard
            case OT_WORD:
1246 367e86e8 bellard
                gen_op_idivw_AX_T0();
1247 367e86e8 bellard
                break;
1248 367e86e8 bellard
            default:
1249 367e86e8 bellard
            case OT_LONG:
1250 367e86e8 bellard
                gen_op_idivl_EAX_T0();
1251 367e86e8 bellard
                break;
1252 367e86e8 bellard
            }
1253 367e86e8 bellard
            break;
1254 367e86e8 bellard
        default:
1255 367e86e8 bellard
            error("GRP3: bad instruction");
1256 367e86e8 bellard
            return -1;
1257 367e86e8 bellard
        }
1258 367e86e8 bellard
        break;
1259 367e86e8 bellard
1260 367e86e8 bellard
    case 0xfe: /* GRP4 */
1261 367e86e8 bellard
    case 0xff: /* GRP5 */
1262 367e86e8 bellard
        if ((b & 1) == 0)
1263 367e86e8 bellard
            ot = OT_BYTE;
1264 367e86e8 bellard
        else
1265 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1266 367e86e8 bellard
1267 367e86e8 bellard
        modrm = ldub(s->pc++);
1268 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1269 367e86e8 bellard
        rm = modrm & 7;
1270 367e86e8 bellard
        op = (modrm >> 3) & 7;
1271 367e86e8 bellard
        if (op >= 2 && b == 0xfe) {
1272 367e86e8 bellard
            error("GRP4: bad instruction");
1273 367e86e8 bellard
            return -1;
1274 367e86e8 bellard
        }
1275 367e86e8 bellard
        if (mod != 3) {
1276 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1277 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1278 367e86e8 bellard
        } else {
1279 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1280 367e86e8 bellard
        }
1281 367e86e8 bellard
1282 367e86e8 bellard
        switch(op) {
1283 367e86e8 bellard
        case 0: /* inc Ev */
1284 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, 1);
1285 367e86e8 bellard
            if (mod != 3)
1286 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1287 367e86e8 bellard
            break;
1288 367e86e8 bellard
        case 1: /* dec Ev */
1289 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, -1);
1290 367e86e8 bellard
            if (mod != 3)
1291 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1292 367e86e8 bellard
            break;
1293 367e86e8 bellard
        case 2: /* call Ev */
1294 ba1c6e37 bellard
            gen_op_movl_T1_im((long)s->pc);
1295 367e86e8 bellard
            gen_op_pushl_T1();
1296 367e86e8 bellard
            gen_op_jmp_T0();
1297 0ecfa993 bellard
            *is_jmp_ptr = 1;
1298 367e86e8 bellard
            break;
1299 367e86e8 bellard
        case 4: /* jmp Ev */
1300 367e86e8 bellard
            gen_op_jmp_T0();
1301 0ecfa993 bellard
            *is_jmp_ptr = 1;
1302 367e86e8 bellard
            break;
1303 367e86e8 bellard
        case 6: /* push Ev */
1304 367e86e8 bellard
            gen_op_pushl_T0();
1305 367e86e8 bellard
            break;
1306 367e86e8 bellard
        default:
1307 367e86e8 bellard
            error("GRP5: bad instruction");
1308 367e86e8 bellard
            return -1;
1309 367e86e8 bellard
        }
1310 367e86e8 bellard
        break;
1311 367e86e8 bellard
1312 367e86e8 bellard
    case 0x84: /* test Ev, Gv */
1313 367e86e8 bellard
    case 0x85: 
1314 367e86e8 bellard
        if ((b & 1) == 0)
1315 367e86e8 bellard
            ot = OT_BYTE;
1316 367e86e8 bellard
        else
1317 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1318 367e86e8 bellard
1319 367e86e8 bellard
        modrm = ldub(s->pc++);
1320 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1321 367e86e8 bellard
        rm = modrm & 7;
1322 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1323 367e86e8 bellard
        
1324 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1325 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1326 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1327 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1328 367e86e8 bellard
        break;
1329 367e86e8 bellard
        
1330 367e86e8 bellard
    case 0xa8: /* test eAX, Iv */
1331 367e86e8 bellard
    case 0xa9:
1332 367e86e8 bellard
        if ((b & 1) == 0)
1333 367e86e8 bellard
            ot = OT_BYTE;
1334 367e86e8 bellard
        else
1335 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1336 367e86e8 bellard
        val = insn_get(s, ot);
1337 367e86e8 bellard
1338 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1339 ba1c6e37 bellard
        gen_op_movl_T1_im(val);
1340 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1341 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1342 367e86e8 bellard
        break;
1343 367e86e8 bellard
        
1344 367e86e8 bellard
    case 0x98: /* CWDE/CBW */
1345 367e86e8 bellard
        if (dflag)
1346 367e86e8 bellard
            gen_op_movswl_EAX_AX();
1347 367e86e8 bellard
        else
1348 367e86e8 bellard
            gen_op_movsbw_AX_AL();
1349 367e86e8 bellard
        break;
1350 367e86e8 bellard
    case 0x99: /* CDQ/CWD */
1351 367e86e8 bellard
        if (dflag)
1352 367e86e8 bellard
            gen_op_movslq_EDX_EAX();
1353 367e86e8 bellard
        else
1354 367e86e8 bellard
            gen_op_movswl_DX_AX();
1355 367e86e8 bellard
        break;
1356 367e86e8 bellard
    case 0x1af: /* imul Gv, Ev */
1357 367e86e8 bellard
    case 0x69: /* imul Gv, Ev, I */
1358 367e86e8 bellard
    case 0x6b:
1359 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1360 367e86e8 bellard
        modrm = ldub(s->pc++);
1361 367e86e8 bellard
        reg = ((modrm >> 3) & 7) + OR_EAX;
1362 367e86e8 bellard
        
1363 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1364 367e86e8 bellard
        if (b == 0x69) {
1365 367e86e8 bellard
            val = insn_get(s, ot);
1366 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1367 367e86e8 bellard
        } else if (b == 0x6b) {
1368 367e86e8 bellard
            val = insn_get(s, OT_BYTE);
1369 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1370 367e86e8 bellard
        } else {
1371 367e86e8 bellard
            gen_op_mov_TN_reg[ot][1][reg]();
1372 367e86e8 bellard
        }
1373 367e86e8 bellard
1374 367e86e8 bellard
        if (ot == OT_LONG) {
1375 367e86e8 bellard
            op_imull_T0_T1();
1376 367e86e8 bellard
        } else {
1377 367e86e8 bellard
            op_imulw_T0_T1();
1378 367e86e8 bellard
        }
1379 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1380 0ecfa993 bellard
        s->cc_op = CC_OP_MUL;
1381 367e86e8 bellard
        break;
1382 367e86e8 bellard
        
1383 367e86e8 bellard
        /**************************/
1384 367e86e8 bellard
        /* push/pop */
1385 367e86e8 bellard
    case 0x50 ... 0x57: /* push */
1386 927f621e bellard
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1387 367e86e8 bellard
        gen_op_pushl_T0();
1388 367e86e8 bellard
        break;
1389 367e86e8 bellard
    case 0x58 ... 0x5f: /* pop */
1390 367e86e8 bellard
        gen_op_popl_T0();
1391 927f621e bellard
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1392 367e86e8 bellard
        break;
1393 367e86e8 bellard
    case 0x68: /* push Iv */
1394 367e86e8 bellard
    case 0x6a:
1395 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1396 367e86e8 bellard
        if (b == 0x68)
1397 367e86e8 bellard
            val = insn_get(s, ot);
1398 367e86e8 bellard
        else
1399 367e86e8 bellard
            val = (int8_t)insn_get(s, OT_BYTE);
1400 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1401 367e86e8 bellard
        gen_op_pushl_T0();
1402 367e86e8 bellard
        break;
1403 367e86e8 bellard
    case 0x8f: /* pop Ev */
1404 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1405 367e86e8 bellard
        modrm = ldub(s->pc++);
1406 367e86e8 bellard
        gen_op_popl_T0();
1407 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1408 367e86e8 bellard
        break;
1409 367e86e8 bellard
    case 0xc9: /* leave */
1410 367e86e8 bellard
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1411 367e86e8 bellard
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1412 367e86e8 bellard
        gen_op_popl_T0();
1413 367e86e8 bellard
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1414 367e86e8 bellard
        break;
1415 367e86e8 bellard
        /**************************/
1416 367e86e8 bellard
        /* mov */
1417 367e86e8 bellard
    case 0x88:
1418 367e86e8 bellard
    case 0x89: /* mov Gv, Ev */
1419 367e86e8 bellard
        if ((b & 1) == 0)
1420 367e86e8 bellard
            ot = OT_BYTE;
1421 367e86e8 bellard
        else
1422 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1423 367e86e8 bellard
        modrm = ldub(s->pc++);
1424 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1425 367e86e8 bellard
        
1426 367e86e8 bellard
        /* generate a generic store */
1427 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1428 367e86e8 bellard
        break;
1429 367e86e8 bellard
    case 0xc6:
1430 367e86e8 bellard
    case 0xc7: /* mov Ev, Iv */
1431 367e86e8 bellard
        if ((b & 1) == 0)
1432 367e86e8 bellard
            ot = OT_BYTE;
1433 367e86e8 bellard
        else
1434 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1435 367e86e8 bellard
        modrm = ldub(s->pc++);
1436 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1437 0ecfa993 bellard
        if (mod != 3)
1438 0ecfa993 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1439 367e86e8 bellard
        val = insn_get(s, ot);
1440 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1441 0ecfa993 bellard
        if (mod != 3)
1442 0ecfa993 bellard
            gen_op_st_T0_A0[ot]();
1443 0ecfa993 bellard
        else
1444 0ecfa993 bellard
            gen_op_mov_reg_T0[ot][modrm & 7]();
1445 367e86e8 bellard
        break;
1446 367e86e8 bellard
    case 0x8a:
1447 367e86e8 bellard
    case 0x8b: /* mov Ev, Gv */
1448 367e86e8 bellard
        if ((b & 1) == 0)
1449 367e86e8 bellard
            ot = OT_BYTE;
1450 367e86e8 bellard
        else
1451 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1452 367e86e8 bellard
        modrm = ldub(s->pc++);
1453 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1454 367e86e8 bellard
        
1455 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1456 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1457 367e86e8 bellard
        break;
1458 367e86e8 bellard
1459 367e86e8 bellard
    case 0x1b6: /* movzbS Gv, Eb */
1460 367e86e8 bellard
    case 0x1b7: /* movzwS Gv, Eb */
1461 367e86e8 bellard
    case 0x1be: /* movsbS Gv, Eb */
1462 367e86e8 bellard
    case 0x1bf: /* movswS Gv, Eb */
1463 367e86e8 bellard
        {
1464 367e86e8 bellard
            int d_ot;
1465 367e86e8 bellard
            /* d_ot is the size of destination */
1466 367e86e8 bellard
            d_ot = dflag + OT_WORD;
1467 367e86e8 bellard
            /* ot is the size of source */
1468 367e86e8 bellard
            ot = (b & 1) + OT_BYTE;
1469 367e86e8 bellard
            modrm = ldub(s->pc++);
1470 367e86e8 bellard
            reg = ((modrm >> 3) & 7) + OR_EAX;
1471 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1472 367e86e8 bellard
            rm = modrm & 7;
1473 367e86e8 bellard
            
1474 367e86e8 bellard
            if (mod == 3) {
1475 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][rm]();
1476 367e86e8 bellard
                switch(ot | (b & 8)) {
1477 367e86e8 bellard
                case OT_BYTE:
1478 367e86e8 bellard
                    gen_op_movzbl_T0_T0();
1479 367e86e8 bellard
                    break;
1480 367e86e8 bellard
                case OT_BYTE | 8:
1481 367e86e8 bellard
                    gen_op_movsbl_T0_T0();
1482 367e86e8 bellard
                    break;
1483 367e86e8 bellard
                case OT_WORD:
1484 367e86e8 bellard
                    gen_op_movzwl_T0_T0();
1485 367e86e8 bellard
                    break;
1486 367e86e8 bellard
                default:
1487 367e86e8 bellard
                case OT_WORD | 8:
1488 367e86e8 bellard
                    gen_op_movswl_T0_T0();
1489 367e86e8 bellard
                    break;
1490 367e86e8 bellard
                }
1491 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
1492 367e86e8 bellard
            } else {
1493 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1494 367e86e8 bellard
                if (b & 8) {
1495 367e86e8 bellard
                    gen_op_lds_T0_A0[ot]();
1496 367e86e8 bellard
                } else {
1497 367e86e8 bellard
                    gen_op_ldu_T0_A0[ot]();
1498 367e86e8 bellard
                }
1499 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
1500 367e86e8 bellard
            }
1501 367e86e8 bellard
        }
1502 367e86e8 bellard
        break;
1503 367e86e8 bellard
1504 367e86e8 bellard
    case 0x8d: /* lea */
1505 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1506 367e86e8 bellard
        modrm = ldub(s->pc++);
1507 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1508 367e86e8 bellard
1509 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1510 367e86e8 bellard
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1511 367e86e8 bellard
        break;
1512 367e86e8 bellard
        
1513 367e86e8 bellard
    case 0xa0: /* mov EAX, Ov */
1514 367e86e8 bellard
    case 0xa1:
1515 367e86e8 bellard
    case 0xa2: /* mov Ov, EAX */
1516 367e86e8 bellard
    case 0xa3:
1517 367e86e8 bellard
        if ((b & 1) == 0)
1518 367e86e8 bellard
            ot = OT_BYTE;
1519 367e86e8 bellard
        else
1520 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1521 367e86e8 bellard
        if (s->aflag)
1522 367e86e8 bellard
            offset_addr = insn_get(s, OT_LONG);
1523 367e86e8 bellard
        else
1524 367e86e8 bellard
            offset_addr = insn_get(s, OT_WORD);
1525 367e86e8 bellard
            
1526 367e86e8 bellard
        if ((b & 2) == 0) {
1527 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1528 367e86e8 bellard
            gen_op_mov_reg_T0[ot][R_EAX]();
1529 367e86e8 bellard
        } else {
1530 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1531 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
1532 367e86e8 bellard
        }
1533 367e86e8 bellard
        break;
1534 367e86e8 bellard
1535 367e86e8 bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
1536 367e86e8 bellard
        val = insn_get(s, OT_BYTE);
1537 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1538 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1539 367e86e8 bellard
        break;
1540 367e86e8 bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
1541 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1542 367e86e8 bellard
        val = insn_get(s, ot);
1543 367e86e8 bellard
        reg = OR_EAX + (b & 7);
1544 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1545 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1546 367e86e8 bellard
        break;
1547 367e86e8 bellard
1548 367e86e8 bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
1549 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1550 367e86e8 bellard
        reg = b & 7;
1551 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][reg]();
1552 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1553 367e86e8 bellard
        gen_op_mov_reg_T0[ot][R_EAX]();
1554 367e86e8 bellard
        gen_op_mov_reg_T1[ot][reg]();
1555 367e86e8 bellard
        break;
1556 367e86e8 bellard
    case 0x86:
1557 367e86e8 bellard
    case 0x87: /* xchg Ev, Gv */
1558 367e86e8 bellard
        if ((b & 1) == 0)
1559 367e86e8 bellard
            ot = OT_BYTE;
1560 367e86e8 bellard
        else
1561 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1562 367e86e8 bellard
        modrm = ldub(s->pc++);
1563 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1564 367e86e8 bellard
1565 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1566 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][reg]();
1567 367e86e8 bellard
        gen_op_ld_T1_A0[ot]();
1568 367e86e8 bellard
        gen_op_st_T0_A0[ot]();
1569 367e86e8 bellard
        gen_op_mov_reg_T1[ot][reg]();
1570 367e86e8 bellard
        break;
1571 367e86e8 bellard
        
1572 367e86e8 bellard
        /************************/
1573 367e86e8 bellard
        /* shifts */
1574 367e86e8 bellard
    case 0xc0:
1575 367e86e8 bellard
    case 0xc1:
1576 367e86e8 bellard
        /* shift Ev,Ib */
1577 367e86e8 bellard
        shift = 2;
1578 367e86e8 bellard
    grp2:
1579 367e86e8 bellard
        {
1580 367e86e8 bellard
            if ((b & 1) == 0)
1581 367e86e8 bellard
                ot = OT_BYTE;
1582 367e86e8 bellard
            else
1583 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1584 367e86e8 bellard
            
1585 367e86e8 bellard
            modrm = ldub(s->pc++);
1586 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1587 367e86e8 bellard
            rm = modrm & 7;
1588 367e86e8 bellard
            op = (modrm >> 3) & 7;
1589 367e86e8 bellard
            
1590 367e86e8 bellard
            if (mod != 3) {
1591 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1592 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
1593 367e86e8 bellard
                opreg = OR_TMP0;
1594 367e86e8 bellard
            } else {
1595 367e86e8 bellard
                opreg = rm + OR_EAX;
1596 367e86e8 bellard
            }
1597 367e86e8 bellard
1598 367e86e8 bellard
            /* simpler op */
1599 367e86e8 bellard
            if (shift == 0) {
1600 367e86e8 bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
1601 367e86e8 bellard
            } else {
1602 367e86e8 bellard
                if (shift == 2) {
1603 367e86e8 bellard
                    shift = ldub(s->pc++);
1604 367e86e8 bellard
                }
1605 367e86e8 bellard
                gen_shifti(s, op, ot, opreg, shift);
1606 367e86e8 bellard
            }
1607 367e86e8 bellard
1608 367e86e8 bellard
            if (mod != 3) {
1609 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1610 367e86e8 bellard
            }
1611 367e86e8 bellard
        }
1612 367e86e8 bellard
        break;
1613 367e86e8 bellard
    case 0xd0:
1614 367e86e8 bellard
    case 0xd1:
1615 367e86e8 bellard
        /* shift Ev,1 */
1616 367e86e8 bellard
        shift = 1;
1617 367e86e8 bellard
        goto grp2;
1618 367e86e8 bellard
    case 0xd2:
1619 367e86e8 bellard
    case 0xd3:
1620 367e86e8 bellard
        /* shift Ev,cl */
1621 367e86e8 bellard
        shift = 0;
1622 367e86e8 bellard
        goto grp2;
1623 367e86e8 bellard
1624 367e86e8 bellard
        /************************/
1625 367e86e8 bellard
        /* floats */
1626 367e86e8 bellard
    case 0xd8 ... 0xdf: 
1627 367e86e8 bellard
        modrm = ldub(s->pc++);
1628 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1629 367e86e8 bellard
        rm = modrm & 7;
1630 367e86e8 bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1631 367e86e8 bellard
        
1632 367e86e8 bellard
        if (mod != 3) {
1633 367e86e8 bellard
            /* memory op */
1634 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1635 367e86e8 bellard
            switch(op) {
1636 367e86e8 bellard
            case 0x00 ... 0x07: /* fxxxs */
1637 367e86e8 bellard
            case 0x10 ... 0x17: /* fixxxl */
1638 367e86e8 bellard
            case 0x20 ... 0x27: /* fxxxl */
1639 367e86e8 bellard
            case 0x30 ... 0x37: /* fixxx */
1640 367e86e8 bellard
                {
1641 927f621e bellard
                    int op1;
1642 927f621e bellard
                    op1 = op & 7;
1643 367e86e8 bellard
1644 367e86e8 bellard
                    switch(op >> 4) {
1645 367e86e8 bellard
                    case 0:
1646 927f621e bellard
                        gen_op_flds_FT0_A0();
1647 367e86e8 bellard
                        break;
1648 367e86e8 bellard
                    case 1:
1649 927f621e bellard
                        gen_op_fildl_FT0_A0();
1650 367e86e8 bellard
                        break;
1651 367e86e8 bellard
                    case 2:
1652 927f621e bellard
                        gen_op_fldl_FT0_A0();
1653 367e86e8 bellard
                        break;
1654 367e86e8 bellard
                    case 3:
1655 367e86e8 bellard
                    default:
1656 927f621e bellard
                        gen_op_fild_FT0_A0();
1657 367e86e8 bellard
                        break;
1658 367e86e8 bellard
                    }
1659 367e86e8 bellard
                    
1660 927f621e bellard
                    gen_op_fp_arith_ST0_FT0[op1]();
1661 927f621e bellard
                    if (op1 == 3) {
1662 367e86e8 bellard
                        /* fcomp needs pop */
1663 927f621e bellard
                        gen_op_fpop();
1664 367e86e8 bellard
                    }
1665 367e86e8 bellard
                }
1666 367e86e8 bellard
                break;
1667 367e86e8 bellard
            case 0x08: /* flds */
1668 367e86e8 bellard
            case 0x0a: /* fsts */
1669 367e86e8 bellard
            case 0x0b: /* fstps */
1670 367e86e8 bellard
            case 0x18: /* fildl */
1671 367e86e8 bellard
            case 0x1a: /* fistl */
1672 367e86e8 bellard
            case 0x1b: /* fistpl */
1673 367e86e8 bellard
            case 0x28: /* fldl */
1674 367e86e8 bellard
            case 0x2a: /* fstl */
1675 367e86e8 bellard
            case 0x2b: /* fstpl */
1676 367e86e8 bellard
            case 0x38: /* filds */
1677 367e86e8 bellard
            case 0x3a: /* fists */
1678 367e86e8 bellard
            case 0x3b: /* fistps */
1679 367e86e8 bellard
                
1680 367e86e8 bellard
                switch(op & 7) {
1681 367e86e8 bellard
                case 0:
1682 927f621e bellard
                    gen_op_fpush();
1683 927f621e bellard
                    switch(op >> 4) {
1684 927f621e bellard
                    case 0:
1685 927f621e bellard
                        gen_op_flds_ST0_A0();
1686 927f621e bellard
                        break;
1687 927f621e bellard
                    case 1:
1688 927f621e bellard
                        gen_op_fildl_ST0_A0();
1689 927f621e bellard
                        break;
1690 927f621e bellard
                    case 2:
1691 927f621e bellard
                        gen_op_fldl_ST0_A0();
1692 927f621e bellard
                        break;
1693 927f621e bellard
                    case 3:
1694 927f621e bellard
                    default:
1695 927f621e bellard
                        gen_op_fild_ST0_A0();
1696 927f621e bellard
                        break;
1697 367e86e8 bellard
                    }
1698 367e86e8 bellard
                    break;
1699 367e86e8 bellard
                default:
1700 927f621e bellard
                    switch(op >> 4) {
1701 927f621e bellard
                    case 0:
1702 927f621e bellard
                        gen_op_fsts_ST0_A0();
1703 927f621e bellard
                        break;
1704 927f621e bellard
                    case 1:
1705 927f621e bellard
                        gen_op_fistl_ST0_A0();
1706 927f621e bellard
                        break;
1707 927f621e bellard
                    case 2:
1708 927f621e bellard
                        gen_op_fstl_ST0_A0();
1709 927f621e bellard
                        break;
1710 927f621e bellard
                    case 3:
1711 927f621e bellard
                    default:
1712 927f621e bellard
                        gen_op_fist_ST0_A0();
1713 927f621e bellard
                        break;
1714 367e86e8 bellard
                    }
1715 367e86e8 bellard
                    if ((op & 7) == 3)
1716 927f621e bellard
                        gen_op_fpop();
1717 367e86e8 bellard
                    break;
1718 367e86e8 bellard
                }
1719 367e86e8 bellard
                break;
1720 927f621e bellard
#if 0
1721 367e86e8 bellard
            case 0x2f: /* fnstsw mem */
1722 367e86e8 bellard
                gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1723 367e86e8 bellard
                gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
1724 367e86e8 bellard
                break;
1725 367e86e8 bellard

1726 367e86e8 bellard
            case 0x3c: /* fbld */
1727 367e86e8 bellard
            case 0x3e: /* fbstp */
1728 367e86e8 bellard
                error("float BCD not hanlded");
1729 367e86e8 bellard
                return -1;
1730 927f621e bellard
#endif
1731 367e86e8 bellard
            case 0x3d: /* fildll */
1732 927f621e bellard
                gen_op_fpush();
1733 927f621e bellard
                gen_op_fildll_ST0_A0();
1734 367e86e8 bellard
                break;
1735 367e86e8 bellard
            case 0x3f: /* fistpll */
1736 927f621e bellard
                gen_op_fistll_ST0_A0();
1737 927f621e bellard
                gen_op_fpop();
1738 367e86e8 bellard
                break;
1739 367e86e8 bellard
            default:
1740 367e86e8 bellard
                error("unhandled memory FP\n");
1741 367e86e8 bellard
                return -1;
1742 367e86e8 bellard
            }
1743 367e86e8 bellard
        } else {
1744 367e86e8 bellard
            /* register float ops */
1745 927f621e bellard
            opreg = rm;
1746 367e86e8 bellard
1747 367e86e8 bellard
            switch(op) {
1748 367e86e8 bellard
            case 0x08: /* fld sti */
1749 927f621e bellard
                gen_op_fpush();
1750 927f621e bellard
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1751 367e86e8 bellard
                break;
1752 367e86e8 bellard
            case 0x09: /* fxchg sti */
1753 927f621e bellard
                gen_op_fxchg_ST0_STN((opreg + 1) & 7);
1754 367e86e8 bellard
                break;
1755 367e86e8 bellard
            case 0x0a: /* grp d9/2 */
1756 367e86e8 bellard
                switch(rm) {
1757 367e86e8 bellard
                case 0: /* fnop */
1758 367e86e8 bellard
                    break;
1759 367e86e8 bellard
                default:
1760 367e86e8 bellard
                    error("unhandled FP GRP d9/2\n");
1761 367e86e8 bellard
                    return -1;
1762 367e86e8 bellard
                }
1763 367e86e8 bellard
                break;
1764 367e86e8 bellard
            case 0x0c: /* grp d9/4 */
1765 367e86e8 bellard
                switch(rm) {
1766 367e86e8 bellard
                case 0: /* fchs */
1767 927f621e bellard
                    gen_op_fchs_ST0();
1768 367e86e8 bellard
                    break;
1769 367e86e8 bellard
                case 1: /* fabs */
1770 927f621e bellard
                    gen_op_fabs_ST0();
1771 367e86e8 bellard
                    break;
1772 367e86e8 bellard
                case 4: /* ftst */
1773 927f621e bellard
                    gen_op_fldz_FT0();
1774 927f621e bellard
                    gen_op_fcom_ST0_FT0();
1775 367e86e8 bellard
                    break;
1776 367e86e8 bellard
                case 5: /* fxam */
1777 927f621e bellard
                    gen_op_fxam_ST0();
1778 367e86e8 bellard
                    break;
1779 367e86e8 bellard
                default:
1780 367e86e8 bellard
                    return -1;
1781 367e86e8 bellard
                }
1782 367e86e8 bellard
                break;
1783 367e86e8 bellard
            case 0x0d: /* grp d9/5 */
1784 367e86e8 bellard
                {
1785 927f621e bellard
                    switch(rm) {
1786 927f621e bellard
                    case 0:
1787 927f621e bellard
                        gen_op_fld1_ST0();
1788 927f621e bellard
                        break;
1789 927f621e bellard
                    case 1:
1790 927f621e bellard
                        gen_op_fld2t_ST0();
1791 927f621e bellard
                        break;
1792 927f621e bellard
                    case 2:
1793 927f621e bellard
                        gen_op_fld2e_ST0();
1794 927f621e bellard
                        break;
1795 927f621e bellard
                    case 3:
1796 927f621e bellard
                        gen_op_fldpi_ST0();
1797 927f621e bellard
                        break;
1798 927f621e bellard
                    case 4:
1799 927f621e bellard
                        gen_op_fldlg2_ST0();
1800 927f621e bellard
                        break;
1801 927f621e bellard
                    case 5:
1802 927f621e bellard
                        gen_op_fldln2_ST0();
1803 927f621e bellard
                        break;
1804 927f621e bellard
                    case 6:
1805 927f621e bellard
                        gen_op_fldz_ST0();
1806 927f621e bellard
                        break;
1807 927f621e bellard
                    default:
1808 367e86e8 bellard
                        return -1;
1809 367e86e8 bellard
                    }
1810 367e86e8 bellard
                }
1811 367e86e8 bellard
                break;
1812 367e86e8 bellard
            case 0x0e: /* grp d9/6 */
1813 367e86e8 bellard
                switch(rm) {
1814 367e86e8 bellard
                case 0: /* f2xm1 */
1815 927f621e bellard
                    gen_op_f2xm1();
1816 367e86e8 bellard
                    break;
1817 367e86e8 bellard
                case 1: /* fyl2x */
1818 927f621e bellard
                    gen_op_fyl2x();
1819 367e86e8 bellard
                    break;
1820 367e86e8 bellard
                case 2: /* fptan */
1821 927f621e bellard
                    gen_op_fptan();
1822 367e86e8 bellard
                    break;
1823 367e86e8 bellard
                case 3: /* fpatan */
1824 927f621e bellard
                    gen_op_fpatan();
1825 367e86e8 bellard
                    break;
1826 367e86e8 bellard
                case 4: /* fxtract */
1827 927f621e bellard
                    gen_op_fxtract();
1828 367e86e8 bellard
                    break;
1829 367e86e8 bellard
                case 5: /* fprem1 */
1830 927f621e bellard
                    gen_op_fprem1();
1831 367e86e8 bellard
                    break;
1832 367e86e8 bellard
                case 6: /* fdecstp */
1833 927f621e bellard
                    gen_op_fdecstp();
1834 367e86e8 bellard
                    break;
1835 367e86e8 bellard
                default:
1836 927f621e bellard
                case 7: /* fincstp */
1837 927f621e bellard
                    gen_op_fincstp();
1838 367e86e8 bellard
                    break;
1839 367e86e8 bellard
                }
1840 367e86e8 bellard
                break;
1841 367e86e8 bellard
            case 0x0f: /* grp d9/7 */
1842 367e86e8 bellard
                switch(rm) {
1843 367e86e8 bellard
                case 0: /* fprem */
1844 927f621e bellard
                    gen_op_fprem();
1845 367e86e8 bellard
                    break;
1846 367e86e8 bellard
                case 1: /* fyl2xp1 */
1847 927f621e bellard
                    gen_op_fyl2xp1();
1848 927f621e bellard
                    break;
1849 927f621e bellard
                case 2: /* fsqrt */
1850 927f621e bellard
                    gen_op_fsqrt();
1851 367e86e8 bellard
                    break;
1852 367e86e8 bellard
                case 3: /* fsincos */
1853 927f621e bellard
                    gen_op_fsincos();
1854 367e86e8 bellard
                    break;
1855 367e86e8 bellard
                case 5: /* fscale */
1856 927f621e bellard
                    gen_op_fscale();
1857 367e86e8 bellard
                    break;
1858 367e86e8 bellard
                case 4: /* frndint */
1859 927f621e bellard
                    gen_op_frndint();
1860 927f621e bellard
                    break;
1861 367e86e8 bellard
                case 6: /* fsin */
1862 927f621e bellard
                    gen_op_fsin();
1863 927f621e bellard
                    break;
1864 367e86e8 bellard
                default:
1865 367e86e8 bellard
                case 7: /* fcos */
1866 927f621e bellard
                    gen_op_fcos();
1867 367e86e8 bellard
                    break;
1868 367e86e8 bellard
                }
1869 367e86e8 bellard
                break;
1870 367e86e8 bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
1871 367e86e8 bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
1872 367e86e8 bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
1873 367e86e8 bellard
                {
1874 927f621e bellard
                    int op1;
1875 367e86e8 bellard
                    
1876 927f621e bellard
                    op1 = op & 7;
1877 367e86e8 bellard
                    if (op >= 0x20) {
1878 927f621e bellard
                        gen_op_fp_arith_STN_ST0[op1](opreg);
1879 367e86e8 bellard
                    } else {
1880 927f621e bellard
                        gen_op_fmov_FT0_STN(opreg);
1881 927f621e bellard
                        gen_op_fp_arith_ST0_FT0[op1]();
1882 367e86e8 bellard
                    }
1883 367e86e8 bellard
                    if (op >= 0x30)
1884 927f621e bellard
                        gen_op_fpop();
1885 367e86e8 bellard
                }
1886 367e86e8 bellard
                break;
1887 367e86e8 bellard
            case 0x02: /* fcom */
1888 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
1889 927f621e bellard
                gen_op_fcom_ST0_FT0();
1890 367e86e8 bellard
                break;
1891 367e86e8 bellard
            case 0x03: /* fcomp */
1892 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
1893 927f621e bellard
                gen_op_fcom_ST0_FT0();
1894 927f621e bellard
                gen_op_fpop();
1895 367e86e8 bellard
                break;
1896 367e86e8 bellard
            case 0x15: /* da/5 */
1897 367e86e8 bellard
                switch(rm) {
1898 367e86e8 bellard
                case 1: /* fucompp */
1899 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
1900 927f621e bellard
                    gen_op_fcom_ST0_FT0();
1901 927f621e bellard
                    gen_op_fpop();
1902 927f621e bellard
                    gen_op_fpop();
1903 367e86e8 bellard
                    break;
1904 367e86e8 bellard
                default:
1905 367e86e8 bellard
                    return -1;
1906 367e86e8 bellard
                }
1907 367e86e8 bellard
                break;
1908 367e86e8 bellard
            case 0x2a: /* fst sti */
1909 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
1910 367e86e8 bellard
                break;
1911 367e86e8 bellard
            case 0x2b: /* fstp sti */
1912 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
1913 927f621e bellard
                gen_op_fpop();
1914 367e86e8 bellard
                break;
1915 367e86e8 bellard
            case 0x33: /* de/3 */
1916 367e86e8 bellard
                switch(rm) {
1917 367e86e8 bellard
                case 1: /* fcompp */
1918 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
1919 927f621e bellard
                    gen_op_fcom_ST0_FT0();
1920 927f621e bellard
                    gen_op_fpop();
1921 927f621e bellard
                    gen_op_fpop();
1922 367e86e8 bellard
                    break;
1923 367e86e8 bellard
                default:
1924 367e86e8 bellard
                    return -1;
1925 367e86e8 bellard
                }
1926 367e86e8 bellard
                break;
1927 367e86e8 bellard
            case 0x3c: /* df/4 */
1928 367e86e8 bellard
                switch(rm) {
1929 927f621e bellard
#if 0
1930 367e86e8 bellard
                case 0:
1931 367e86e8 bellard
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
1932 367e86e8 bellard
                    break;
1933 927f621e bellard
#endif
1934 367e86e8 bellard
                default:
1935 367e86e8 bellard
                    return -1;
1936 367e86e8 bellard
                }
1937 367e86e8 bellard
                break;
1938 367e86e8 bellard
            default:
1939 367e86e8 bellard
                error("unhandled FP\n");
1940 367e86e8 bellard
                return -1;
1941 367e86e8 bellard
            }
1942 367e86e8 bellard
        }
1943 367e86e8 bellard
        break;
1944 367e86e8 bellard
        /************************/
1945 367e86e8 bellard
        /* string ops */
1946 367e86e8 bellard
    case 0xa4: /* movsS */
1947 367e86e8 bellard
    case 0xa5:
1948 367e86e8 bellard
        if ((b & 1) == 0)
1949 367e86e8 bellard
            ot = OT_BYTE;
1950 367e86e8 bellard
        else
1951 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1952 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
1953 367e86e8 bellard
            gen_op_movs[3 + ot]();
1954 367e86e8 bellard
        } else {
1955 367e86e8 bellard
            gen_op_movs[ot]();
1956 367e86e8 bellard
        }
1957 367e86e8 bellard
        break;
1958 367e86e8 bellard
        
1959 367e86e8 bellard
    case 0xaa: /* stosS */
1960 367e86e8 bellard
    case 0xab:
1961 367e86e8 bellard
        if ((b & 1) == 0)
1962 367e86e8 bellard
            ot = OT_BYTE;
1963 367e86e8 bellard
        else
1964 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1965 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
1966 367e86e8 bellard
            gen_op_stos[3 + ot]();
1967 367e86e8 bellard
        } else {
1968 367e86e8 bellard
            gen_op_stos[ot]();
1969 367e86e8 bellard
        }
1970 367e86e8 bellard
        break;
1971 367e86e8 bellard
    case 0xac: /* lodsS */
1972 367e86e8 bellard
    case 0xad:
1973 367e86e8 bellard
        if ((b & 1) == 0)
1974 367e86e8 bellard
            ot = OT_BYTE;
1975 367e86e8 bellard
        else
1976 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1977 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
1978 367e86e8 bellard
            gen_op_lods[3 + ot]();
1979 367e86e8 bellard
        } else {
1980 367e86e8 bellard
            gen_op_lods[ot]();
1981 367e86e8 bellard
        }
1982 367e86e8 bellard
        break;
1983 367e86e8 bellard
    case 0xae: /* scasS */
1984 367e86e8 bellard
    case 0xaf:
1985 367e86e8 bellard
        if ((b & 1) == 0)
1986 367e86e8 bellard
            ot = OT_BYTE;
1987 367e86e8 bellard
        else
1988 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1989 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
1990 367e86e8 bellard
            gen_op_scas[6 + ot]();
1991 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
1992 367e86e8 bellard
            gen_op_scas[3 + ot]();
1993 367e86e8 bellard
        } else {
1994 367e86e8 bellard
            gen_op_scas[ot]();
1995 367e86e8 bellard
        }
1996 367e86e8 bellard
        break;
1997 367e86e8 bellard
1998 367e86e8 bellard
    case 0xa6: /* cmpsS */
1999 367e86e8 bellard
    case 0xa7:
2000 367e86e8 bellard
        if ((b & 1) == 0)
2001 367e86e8 bellard
            ot = OT_BYTE;
2002 367e86e8 bellard
        else
2003 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2004 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2005 367e86e8 bellard
            gen_op_cmps[6 + ot]();
2006 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2007 367e86e8 bellard
            gen_op_cmps[3 + ot]();
2008 367e86e8 bellard
        } else {
2009 367e86e8 bellard
            gen_op_cmps[ot]();
2010 367e86e8 bellard
        }
2011 367e86e8 bellard
        break;
2012 367e86e8 bellard
        
2013 ba1c6e37 bellard
        /************************/
2014 ba1c6e37 bellard
        /* port I/O */
2015 367e86e8 bellard
    case 0x6c: /* insS */
2016 367e86e8 bellard
    case 0x6d:
2017 367e86e8 bellard
        if ((b & 1) == 0)
2018 367e86e8 bellard
            ot = OT_BYTE;
2019 367e86e8 bellard
        else
2020 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2021 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2022 367e86e8 bellard
            gen_op_ins[3 + ot]();
2023 367e86e8 bellard
        } else {
2024 367e86e8 bellard
            gen_op_ins[ot]();
2025 367e86e8 bellard
        }
2026 367e86e8 bellard
        break;
2027 367e86e8 bellard
    case 0x6e: /* outsS */
2028 367e86e8 bellard
    case 0x6f:
2029 367e86e8 bellard
        if ((b & 1) == 0)
2030 367e86e8 bellard
            ot = OT_BYTE;
2031 367e86e8 bellard
        else
2032 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2033 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2034 367e86e8 bellard
            gen_op_outs[3 + ot]();
2035 367e86e8 bellard
        } else {
2036 367e86e8 bellard
            gen_op_outs[ot]();
2037 367e86e8 bellard
        }
2038 367e86e8 bellard
        break;
2039 ba1c6e37 bellard
    case 0xe4:
2040 ba1c6e37 bellard
    case 0xe5:
2041 ba1c6e37 bellard
        if ((b & 1) == 0)
2042 ba1c6e37 bellard
            ot = OT_BYTE;
2043 ba1c6e37 bellard
        else
2044 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2045 ba1c6e37 bellard
        val = ldub(s->pc++);
2046 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2047 ba1c6e37 bellard
        gen_op_in[ot]();
2048 ba1c6e37 bellard
        gen_op_mov_reg_T1[ot][R_EAX]();
2049 ba1c6e37 bellard
        break;
2050 ba1c6e37 bellard
    case 0xe6:
2051 ba1c6e37 bellard
    case 0xe7:
2052 ba1c6e37 bellard
        if ((b & 1) == 0)
2053 ba1c6e37 bellard
            ot = OT_BYTE;
2054 ba1c6e37 bellard
        else
2055 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2056 ba1c6e37 bellard
        val = ldub(s->pc++);
2057 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2058 ba1c6e37 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2059 ba1c6e37 bellard
        gen_op_out[ot]();
2060 ba1c6e37 bellard
        break;
2061 ba1c6e37 bellard
    case 0xec:
2062 ba1c6e37 bellard
    case 0xed:
2063 ba1c6e37 bellard
        if ((b & 1) == 0)
2064 ba1c6e37 bellard
            ot = OT_BYTE;
2065 ba1c6e37 bellard
        else
2066 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2067 ba1c6e37 bellard
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2068 ba1c6e37 bellard
        gen_op_in[ot]();
2069 ba1c6e37 bellard
        gen_op_mov_reg_T1[ot][R_EAX]();
2070 ba1c6e37 bellard
        break;
2071 ba1c6e37 bellard
    case 0xee:
2072 ba1c6e37 bellard
    case 0xef:
2073 ba1c6e37 bellard
        if ((b & 1) == 0)
2074 ba1c6e37 bellard
            ot = OT_BYTE;
2075 ba1c6e37 bellard
        else
2076 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2077 ba1c6e37 bellard
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2078 ba1c6e37 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2079 ba1c6e37 bellard
        gen_op_out[ot]();
2080 ba1c6e37 bellard
        break;
2081 367e86e8 bellard
2082 367e86e8 bellard
        /************************/
2083 367e86e8 bellard
        /* control */
2084 367e86e8 bellard
    case 0xc2: /* ret im */
2085 367e86e8 bellard
        /* XXX: handle stack pop ? */
2086 367e86e8 bellard
        val = ldsw(s->pc);
2087 367e86e8 bellard
        s->pc += 2;
2088 367e86e8 bellard
        gen_op_popl_T0();
2089 367e86e8 bellard
        gen_op_addl_ESP_im(val);
2090 367e86e8 bellard
        gen_op_jmp_T0();
2091 0ecfa993 bellard
        *is_jmp_ptr = 1;
2092 367e86e8 bellard
        break;
2093 367e86e8 bellard
    case 0xc3: /* ret */
2094 367e86e8 bellard
        gen_op_popl_T0();
2095 367e86e8 bellard
        gen_op_jmp_T0();
2096 0ecfa993 bellard
        *is_jmp_ptr = 1;
2097 367e86e8 bellard
        break;
2098 367e86e8 bellard
    case 0xe8: /* call */
2099 367e86e8 bellard
        val = insn_get(s, OT_LONG);
2100 367e86e8 bellard
        val += (long)s->pc;
2101 ba1c6e37 bellard
        gen_op_movl_T1_im((long)s->pc);
2102 367e86e8 bellard
        gen_op_pushl_T1();
2103 367e86e8 bellard
        gen_op_jmp_im(val);
2104 0ecfa993 bellard
        *is_jmp_ptr = 1;
2105 367e86e8 bellard
        break;
2106 367e86e8 bellard
    case 0xe9: /* jmp */
2107 367e86e8 bellard
        val = insn_get(s, OT_LONG);
2108 367e86e8 bellard
        val += (long)s->pc;
2109 367e86e8 bellard
        gen_op_jmp_im(val);
2110 0ecfa993 bellard
        *is_jmp_ptr = 1;
2111 367e86e8 bellard
        break;
2112 367e86e8 bellard
    case 0xeb: /* jmp Jb */
2113 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
2114 367e86e8 bellard
        val += (long)s->pc;
2115 367e86e8 bellard
        gen_op_jmp_im(val);
2116 0ecfa993 bellard
        *is_jmp_ptr = 1;
2117 367e86e8 bellard
        break;
2118 367e86e8 bellard
    case 0x70 ... 0x7f: /* jcc Jb */
2119 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
2120 367e86e8 bellard
        val += (long)s->pc;
2121 367e86e8 bellard
        goto do_jcc;
2122 367e86e8 bellard
    case 0x180 ... 0x18f: /* jcc Jv */
2123 367e86e8 bellard
        if (dflag) {
2124 367e86e8 bellard
            val = insn_get(s, OT_LONG);
2125 367e86e8 bellard
        } else {
2126 367e86e8 bellard
            val = (int16_t)insn_get(s, OT_WORD); 
2127 367e86e8 bellard
        }
2128 367e86e8 bellard
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2129 367e86e8 bellard
    do_jcc:
2130 367e86e8 bellard
        gen_jcc(s, b, val);
2131 0ecfa993 bellard
        *is_jmp_ptr = 1;
2132 367e86e8 bellard
        break;
2133 367e86e8 bellard
2134 367e86e8 bellard
    case 0x190 ... 0x19f:
2135 367e86e8 bellard
        modrm = ldub(s->pc++);
2136 367e86e8 bellard
        gen_setcc(s, b);
2137 367e86e8 bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2138 367e86e8 bellard
        break;
2139 367e86e8 bellard
2140 367e86e8 bellard
        /************************/
2141 367e86e8 bellard
        /* flags */
2142 367e86e8 bellard
    case 0x9c: /* pushf */
2143 367e86e8 bellard
        gen_op_movl_T0_eflags();
2144 367e86e8 bellard
        gen_op_pushl_T0();
2145 367e86e8 bellard
        break;
2146 367e86e8 bellard
    case 0x9d: /* popf */
2147 367e86e8 bellard
        gen_op_popl_T0();
2148 367e86e8 bellard
        gen_op_movl_eflags_T0();
2149 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2150 367e86e8 bellard
        break;
2151 367e86e8 bellard
    case 0x9e: /* sahf */
2152 367e86e8 bellard
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2153 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2154 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2155 367e86e8 bellard
        gen_op_movb_eflags_T0();
2156 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2157 367e86e8 bellard
        break;
2158 367e86e8 bellard
    case 0x9f: /* lahf */
2159 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2160 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2161 367e86e8 bellard
        gen_op_movl_T0_eflags();
2162 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2163 367e86e8 bellard
        break;
2164 367e86e8 bellard
    case 0xf5: /* cmc */
2165 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2166 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2167 367e86e8 bellard
        gen_op_cmc();
2168 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2169 367e86e8 bellard
        break;
2170 367e86e8 bellard
    case 0xf8: /* clc */
2171 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2172 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2173 367e86e8 bellard
        gen_op_clc();
2174 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2175 367e86e8 bellard
        break;
2176 367e86e8 bellard
    case 0xf9: /* stc */
2177 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2178 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2179 367e86e8 bellard
        gen_op_stc();
2180 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2181 367e86e8 bellard
        break;
2182 367e86e8 bellard
    case 0xfc: /* cld */
2183 367e86e8 bellard
        gen_op_cld();
2184 367e86e8 bellard
        break;
2185 367e86e8 bellard
    case 0xfd: /* std */
2186 367e86e8 bellard
        gen_op_std();
2187 367e86e8 bellard
        break;
2188 367e86e8 bellard
2189 367e86e8 bellard
        /************************/
2190 367e86e8 bellard
        /* misc */
2191 367e86e8 bellard
    case 0x90: /* nop */
2192 367e86e8 bellard
        break;
2193 0ecfa993 bellard
    case 0xcc: /* int3 */
2194 0ecfa993 bellard
        gen_op_int3((long)pc_start);
2195 0ecfa993 bellard
        *is_jmp_ptr = 1;
2196 0ecfa993 bellard
        break;
2197 0ecfa993 bellard
    case 0xcd: /* int N */
2198 0ecfa993 bellard
        val = ldub(s->pc++);
2199 0ecfa993 bellard
        /* XXX: currently we ignore the interrupt number */
2200 0ecfa993 bellard
        gen_op_int_im((long)pc_start);
2201 0ecfa993 bellard
        *is_jmp_ptr = 1;
2202 0ecfa993 bellard
        break;
2203 0ecfa993 bellard
    case 0xce: /* into */
2204 0ecfa993 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2205 0ecfa993 bellard
            gen_op_set_cc_op(s->cc_op);
2206 0ecfa993 bellard
        gen_op_into((long)pc_start, (long)s->pc);
2207 0ecfa993 bellard
        *is_jmp_ptr = 1;
2208 0ecfa993 bellard
        break;
2209 0ecfa993 bellard
#if 0
2210 367e86e8 bellard
    case 0x1a2: /* cpuid */
2211 367e86e8 bellard
        gen_insn0(OP_ASM);
2212 367e86e8 bellard
        break;
2213 367e86e8 bellard
#endif
2214 367e86e8 bellard
    default:
2215 367e86e8 bellard
        error("unknown opcode %x", b);
2216 367e86e8 bellard
        return -1;
2217 367e86e8 bellard
    }
2218 367e86e8 bellard
    return (long)s->pc;
2219 367e86e8 bellard
}
2220 367e86e8 bellard
2221 ba1c6e37 bellard
/* return the next pc */
2222 ba1c6e37 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
2223 ba1c6e37 bellard
                     uint8_t *pc_start)
2224 ba1c6e37 bellard
{
2225 ba1c6e37 bellard
    DisasContext dc1, *dc = &dc1;
2226 0ecfa993 bellard
    int is_jmp;
2227 ba1c6e37 bellard
    long ret;
2228 0ecfa993 bellard
#ifdef DEBUG_DISAS
2229 0ecfa993 bellard
    struct disassemble_info disasm_info;
2230 0ecfa993 bellard
#endif
2231 0ecfa993 bellard
2232 ba1c6e37 bellard
    dc->cc_op = CC_OP_DYNAMIC;
2233 ba1c6e37 bellard
    gen_code_ptr = gen_code_buf;
2234 ba1c6e37 bellard
    gen_start();
2235 0ecfa993 bellard
2236 0ecfa993 bellard
#ifdef DEBUG_DISAS
2237 586314f2 bellard
    if (loglevel) {
2238 586314f2 bellard
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2239 586314f2 bellard
        disasm_info.buffer = pc_start;
2240 586314f2 bellard
        disasm_info.buffer_vma = (unsigned long)pc_start;
2241 586314f2 bellard
        disasm_info.buffer_length = 15;
2242 0ecfa993 bellard
#if 0        
2243 586314f2 bellard
        disasm_info.flavour = bfd_get_flavour (abfd);
2244 586314f2 bellard
        disasm_info.arch = bfd_get_arch (abfd);
2245 586314f2 bellard
        disasm_info.mach = bfd_get_mach (abfd);
2246 0ecfa993 bellard
#endif
2247 0ecfa993 bellard
#ifdef WORDS_BIGENDIAN
2248 586314f2 bellard
        disasm_info.endian = BFD_ENDIAN_BIG;
2249 0ecfa993 bellard
#else
2250 586314f2 bellard
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2251 0ecfa993 bellard
#endif        
2252 586314f2 bellard
        fprintf(logfile, "IN:\n");
2253 586314f2 bellard
        fprintf(logfile, "0x%08lx:  ", (long)pc_start);
2254 586314f2 bellard
        print_insn_i386((unsigned long)pc_start, &disasm_info);
2255 586314f2 bellard
        fprintf(logfile, "\n\n");
2256 586314f2 bellard
    }
2257 0ecfa993 bellard
#endif
2258 0ecfa993 bellard
    is_jmp = 0;
2259 0ecfa993 bellard
    ret = disas_insn(dc, pc_start, &is_jmp);
2260 ba1c6e37 bellard
    if (ret == -1) 
2261 ba1c6e37 bellard
        error("unknown instruction at PC=0x%x", pc_start);
2262 0ecfa993 bellard
    /* we must store the eflags state if it is not already done */
2263 0ecfa993 bellard
    if (dc->cc_op != CC_OP_DYNAMIC)
2264 0ecfa993 bellard
        gen_op_set_cc_op(dc->cc_op);
2265 0ecfa993 bellard
    if (!is_jmp) {
2266 0ecfa993 bellard
        /* we add an additionnal jmp to update the simulated PC */
2267 0ecfa993 bellard
        gen_op_jmp_im(ret);
2268 0ecfa993 bellard
    }
2269 ba1c6e37 bellard
    gen_end();
2270 ba1c6e37 bellard
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2271 0ecfa993 bellard
2272 0ecfa993 bellard
#ifdef DEBUG_DISAS
2273 586314f2 bellard
    if (loglevel) {
2274 0ecfa993 bellard
        uint8_t *pc;
2275 0ecfa993 bellard
        int count;
2276 0ecfa993 bellard
2277 0ecfa993 bellard
        pc = gen_code_buf;
2278 0ecfa993 bellard
        disasm_info.buffer = pc;
2279 0ecfa993 bellard
        disasm_info.buffer_vma = (unsigned long)pc;
2280 0ecfa993 bellard
        disasm_info.buffer_length = *gen_code_size_ptr;
2281 0ecfa993 bellard
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2282 0ecfa993 bellard
        while (pc < gen_code_ptr) {
2283 0ecfa993 bellard
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2284 0ecfa993 bellard
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2285 0ecfa993 bellard
            fprintf(logfile, "\n");
2286 0ecfa993 bellard
            pc += count;
2287 0ecfa993 bellard
        }
2288 0ecfa993 bellard
        fprintf(logfile, "\n");
2289 0ecfa993 bellard
    }
2290 0ecfa993 bellard
#endif
2291 ba1c6e37 bellard
    return 0;
2292 ba1c6e37 bellard
}
2293 ba1c6e37 bellard
2294 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
2295 ba1c6e37 bellard
{
2296 ba1c6e37 bellard
    CPUX86State *env;
2297 ba1c6e37 bellard
    int i;
2298 ba1c6e37 bellard
2299 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
2300 ba1c6e37 bellard
    if (!env)
2301 ba1c6e37 bellard
        return NULL;
2302 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
2303 ba1c6e37 bellard
    /* basic FPU init */
2304 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
2305 ba1c6e37 bellard
        env->fptags[i] = 1;
2306 ba1c6e37 bellard
    env->fpuc = 0x37f;
2307 ba1c6e37 bellard
    /* flags setup */
2308 ba1c6e37 bellard
    env->cc_op = CC_OP_EFLAGS;
2309 ba1c6e37 bellard
    env->df = 1;
2310 ba1c6e37 bellard
    return env;
2311 ba1c6e37 bellard
}
2312 ba1c6e37 bellard
2313 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
2314 ba1c6e37 bellard
{
2315 ba1c6e37 bellard
    free(env);
2316 ba1c6e37 bellard
}