Statistics
| Branch: | Revision:

root / translate-i386.c @ d57c4e01

History | View | Annotate | Download (64.9 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 4b74fe1f bellard
    fprintf(stderr, "\n");
31 367e86e8 bellard
    vfprintf(stderr, fmt, ap);
32 4b74fe1f bellard
    fprintf(stderr, "\n");
33 367e86e8 bellard
    va_end(ap);
34 367e86e8 bellard
    exit(1);
35 367e86e8 bellard
}
36 367e86e8 bellard
37 367e86e8 bellard
#define PREFIX_REPZ 1
38 367e86e8 bellard
#define PREFIX_REPNZ 2
39 367e86e8 bellard
#define PREFIX_LOCK 4
40 367e86e8 bellard
#define PREFIX_CS 8
41 367e86e8 bellard
#define PREFIX_SS 0x10
42 367e86e8 bellard
#define PREFIX_DS 0x20
43 367e86e8 bellard
#define PREFIX_ES 0x40
44 367e86e8 bellard
#define PREFIX_FS 0x80
45 367e86e8 bellard
#define PREFIX_GS 0x100
46 367e86e8 bellard
#define PREFIX_DATA 0x200
47 367e86e8 bellard
#define PREFIX_ADR 0x400
48 367e86e8 bellard
#define PREFIX_FWAIT 0x800
49 367e86e8 bellard
50 367e86e8 bellard
typedef struct DisasContext {
51 367e86e8 bellard
    /* current insn context */
52 367e86e8 bellard
    int prefix;
53 367e86e8 bellard
    int aflag, dflag;
54 367e86e8 bellard
    uint8_t *pc; /* current pc */
55 367e86e8 bellard
    int cc_op; /* current CC operation */
56 367e86e8 bellard
    int f_st;
57 367e86e8 bellard
} DisasContext;
58 367e86e8 bellard
59 367e86e8 bellard
/* i386 arith/logic operations */
60 367e86e8 bellard
enum {
61 367e86e8 bellard
    OP_ADDL, 
62 367e86e8 bellard
    OP_ORL, 
63 367e86e8 bellard
    OP_ADCL, 
64 367e86e8 bellard
    OP_SBBL,
65 367e86e8 bellard
    OP_ANDL, 
66 367e86e8 bellard
    OP_SUBL, 
67 367e86e8 bellard
    OP_XORL, 
68 367e86e8 bellard
    OP_CMPL,
69 367e86e8 bellard
};
70 367e86e8 bellard
71 367e86e8 bellard
/* i386 shift ops */
72 367e86e8 bellard
enum {
73 367e86e8 bellard
    OP_ROL, 
74 367e86e8 bellard
    OP_ROR, 
75 367e86e8 bellard
    OP_RCL, 
76 367e86e8 bellard
    OP_RCR, 
77 367e86e8 bellard
    OP_SHL, 
78 367e86e8 bellard
    OP_SHR, 
79 367e86e8 bellard
    OP_SHL1, /* undocumented */
80 367e86e8 bellard
    OP_SAR = 7,
81 367e86e8 bellard
};
82 367e86e8 bellard
83 367e86e8 bellard
#include "op-i386.h"
84 367e86e8 bellard
85 367e86e8 bellard
/* operand size */
86 367e86e8 bellard
enum {
87 367e86e8 bellard
    OT_BYTE = 0,
88 367e86e8 bellard
    OT_WORD,
89 367e86e8 bellard
    OT_LONG, 
90 367e86e8 bellard
    OT_QUAD,
91 367e86e8 bellard
};
92 367e86e8 bellard
93 367e86e8 bellard
enum {
94 367e86e8 bellard
    /* I386 int registers */
95 367e86e8 bellard
    OR_EAX,   /* MUST be even numbered */
96 367e86e8 bellard
    OR_ECX,
97 367e86e8 bellard
    OR_EDX,
98 367e86e8 bellard
    OR_EBX,
99 367e86e8 bellard
    OR_ESP,
100 367e86e8 bellard
    OR_EBP,
101 367e86e8 bellard
    OR_ESI,
102 367e86e8 bellard
    OR_EDI,
103 367e86e8 bellard
    OR_TMP0,    /* temporary operand register */
104 367e86e8 bellard
    OR_TMP1,
105 367e86e8 bellard
    OR_A0, /* temporary register used when doing address evaluation */
106 367e86e8 bellard
    OR_ZERO, /* fixed zero register */
107 367e86e8 bellard
    NB_OREGS,
108 367e86e8 bellard
};
109 367e86e8 bellard
110 367e86e8 bellard
typedef void (GenOpFunc)(void);
111 367e86e8 bellard
typedef void (GenOpFunc1)(long);
112 367e86e8 bellard
typedef void (GenOpFunc2)(long, long);
113 367e86e8 bellard
                    
114 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
115 367e86e8 bellard
    [OT_BYTE] = {
116 367e86e8 bellard
        gen_op_movb_EAX_T0,
117 367e86e8 bellard
        gen_op_movb_ECX_T0,
118 367e86e8 bellard
        gen_op_movb_EDX_T0,
119 367e86e8 bellard
        gen_op_movb_EBX_T0,
120 367e86e8 bellard
        gen_op_movh_EAX_T0,
121 367e86e8 bellard
        gen_op_movh_ECX_T0,
122 367e86e8 bellard
        gen_op_movh_EDX_T0,
123 367e86e8 bellard
        gen_op_movh_EBX_T0,
124 367e86e8 bellard
    },
125 367e86e8 bellard
    [OT_WORD] = {
126 367e86e8 bellard
        gen_op_movw_EAX_T0,
127 367e86e8 bellard
        gen_op_movw_ECX_T0,
128 367e86e8 bellard
        gen_op_movw_EDX_T0,
129 367e86e8 bellard
        gen_op_movw_EBX_T0,
130 367e86e8 bellard
        gen_op_movw_ESP_T0,
131 367e86e8 bellard
        gen_op_movw_EBP_T0,
132 367e86e8 bellard
        gen_op_movw_ESI_T0,
133 367e86e8 bellard
        gen_op_movw_EDI_T0,
134 367e86e8 bellard
    },
135 367e86e8 bellard
    [OT_LONG] = {
136 367e86e8 bellard
        gen_op_movl_EAX_T0,
137 367e86e8 bellard
        gen_op_movl_ECX_T0,
138 367e86e8 bellard
        gen_op_movl_EDX_T0,
139 367e86e8 bellard
        gen_op_movl_EBX_T0,
140 367e86e8 bellard
        gen_op_movl_ESP_T0,
141 367e86e8 bellard
        gen_op_movl_EBP_T0,
142 367e86e8 bellard
        gen_op_movl_ESI_T0,
143 367e86e8 bellard
        gen_op_movl_EDI_T0,
144 367e86e8 bellard
    },
145 367e86e8 bellard
};
146 367e86e8 bellard
147 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
148 367e86e8 bellard
    [OT_BYTE] = {
149 367e86e8 bellard
        gen_op_movb_EAX_T1,
150 367e86e8 bellard
        gen_op_movb_ECX_T1,
151 367e86e8 bellard
        gen_op_movb_EDX_T1,
152 367e86e8 bellard
        gen_op_movb_EBX_T1,
153 367e86e8 bellard
        gen_op_movh_EAX_T1,
154 367e86e8 bellard
        gen_op_movh_ECX_T1,
155 367e86e8 bellard
        gen_op_movh_EDX_T1,
156 367e86e8 bellard
        gen_op_movh_EBX_T1,
157 367e86e8 bellard
    },
158 367e86e8 bellard
    [OT_WORD] = {
159 367e86e8 bellard
        gen_op_movw_EAX_T1,
160 367e86e8 bellard
        gen_op_movw_ECX_T1,
161 367e86e8 bellard
        gen_op_movw_EDX_T1,
162 367e86e8 bellard
        gen_op_movw_EBX_T1,
163 367e86e8 bellard
        gen_op_movw_ESP_T1,
164 367e86e8 bellard
        gen_op_movw_EBP_T1,
165 367e86e8 bellard
        gen_op_movw_ESI_T1,
166 367e86e8 bellard
        gen_op_movw_EDI_T1,
167 367e86e8 bellard
    },
168 367e86e8 bellard
    [OT_LONG] = {
169 367e86e8 bellard
        gen_op_movl_EAX_T1,
170 367e86e8 bellard
        gen_op_movl_ECX_T1,
171 367e86e8 bellard
        gen_op_movl_EDX_T1,
172 367e86e8 bellard
        gen_op_movl_EBX_T1,
173 367e86e8 bellard
        gen_op_movl_ESP_T1,
174 367e86e8 bellard
        gen_op_movl_EBP_T1,
175 367e86e8 bellard
        gen_op_movl_ESI_T1,
176 367e86e8 bellard
        gen_op_movl_EDI_T1,
177 367e86e8 bellard
    },
178 367e86e8 bellard
};
179 367e86e8 bellard
180 367e86e8 bellard
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
181 367e86e8 bellard
    [0] = {
182 367e86e8 bellard
        gen_op_movw_EAX_A0,
183 367e86e8 bellard
        gen_op_movw_ECX_A0,
184 367e86e8 bellard
        gen_op_movw_EDX_A0,
185 367e86e8 bellard
        gen_op_movw_EBX_A0,
186 367e86e8 bellard
        gen_op_movw_ESP_A0,
187 367e86e8 bellard
        gen_op_movw_EBP_A0,
188 367e86e8 bellard
        gen_op_movw_ESI_A0,
189 367e86e8 bellard
        gen_op_movw_EDI_A0,
190 367e86e8 bellard
    },
191 367e86e8 bellard
    [1] = {
192 367e86e8 bellard
        gen_op_movl_EAX_A0,
193 367e86e8 bellard
        gen_op_movl_ECX_A0,
194 367e86e8 bellard
        gen_op_movl_EDX_A0,
195 367e86e8 bellard
        gen_op_movl_EBX_A0,
196 367e86e8 bellard
        gen_op_movl_ESP_A0,
197 367e86e8 bellard
        gen_op_movl_EBP_A0,
198 367e86e8 bellard
        gen_op_movl_ESI_A0,
199 367e86e8 bellard
        gen_op_movl_EDI_A0,
200 367e86e8 bellard
    },
201 367e86e8 bellard
};
202 367e86e8 bellard
203 367e86e8 bellard
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
204 367e86e8 bellard
{
205 367e86e8 bellard
    [OT_BYTE] = {
206 367e86e8 bellard
        {
207 367e86e8 bellard
            gen_op_movl_T0_EAX,
208 367e86e8 bellard
            gen_op_movl_T0_ECX,
209 367e86e8 bellard
            gen_op_movl_T0_EDX,
210 367e86e8 bellard
            gen_op_movl_T0_EBX,
211 367e86e8 bellard
            gen_op_movh_T0_EAX,
212 367e86e8 bellard
            gen_op_movh_T0_ECX,
213 367e86e8 bellard
            gen_op_movh_T0_EDX,
214 367e86e8 bellard
            gen_op_movh_T0_EBX,
215 367e86e8 bellard
        },
216 367e86e8 bellard
        {
217 367e86e8 bellard
            gen_op_movl_T1_EAX,
218 367e86e8 bellard
            gen_op_movl_T1_ECX,
219 367e86e8 bellard
            gen_op_movl_T1_EDX,
220 367e86e8 bellard
            gen_op_movl_T1_EBX,
221 367e86e8 bellard
            gen_op_movh_T1_EAX,
222 367e86e8 bellard
            gen_op_movh_T1_ECX,
223 367e86e8 bellard
            gen_op_movh_T1_EDX,
224 367e86e8 bellard
            gen_op_movh_T1_EBX,
225 367e86e8 bellard
        },
226 367e86e8 bellard
    },
227 367e86e8 bellard
    [OT_WORD] = {
228 367e86e8 bellard
        {
229 367e86e8 bellard
            gen_op_movl_T0_EAX,
230 367e86e8 bellard
            gen_op_movl_T0_ECX,
231 367e86e8 bellard
            gen_op_movl_T0_EDX,
232 367e86e8 bellard
            gen_op_movl_T0_EBX,
233 367e86e8 bellard
            gen_op_movl_T0_ESP,
234 367e86e8 bellard
            gen_op_movl_T0_EBP,
235 367e86e8 bellard
            gen_op_movl_T0_ESI,
236 367e86e8 bellard
            gen_op_movl_T0_EDI,
237 367e86e8 bellard
        },
238 367e86e8 bellard
        {
239 367e86e8 bellard
            gen_op_movl_T1_EAX,
240 367e86e8 bellard
            gen_op_movl_T1_ECX,
241 367e86e8 bellard
            gen_op_movl_T1_EDX,
242 367e86e8 bellard
            gen_op_movl_T1_EBX,
243 367e86e8 bellard
            gen_op_movl_T1_ESP,
244 367e86e8 bellard
            gen_op_movl_T1_EBP,
245 367e86e8 bellard
            gen_op_movl_T1_ESI,
246 367e86e8 bellard
            gen_op_movl_T1_EDI,
247 367e86e8 bellard
        },
248 367e86e8 bellard
    },
249 367e86e8 bellard
    [OT_LONG] = {
250 367e86e8 bellard
        {
251 367e86e8 bellard
            gen_op_movl_T0_EAX,
252 367e86e8 bellard
            gen_op_movl_T0_ECX,
253 367e86e8 bellard
            gen_op_movl_T0_EDX,
254 367e86e8 bellard
            gen_op_movl_T0_EBX,
255 367e86e8 bellard
            gen_op_movl_T0_ESP,
256 367e86e8 bellard
            gen_op_movl_T0_EBP,
257 367e86e8 bellard
            gen_op_movl_T0_ESI,
258 367e86e8 bellard
            gen_op_movl_T0_EDI,
259 367e86e8 bellard
        },
260 367e86e8 bellard
        {
261 367e86e8 bellard
            gen_op_movl_T1_EAX,
262 367e86e8 bellard
            gen_op_movl_T1_ECX,
263 367e86e8 bellard
            gen_op_movl_T1_EDX,
264 367e86e8 bellard
            gen_op_movl_T1_EBX,
265 367e86e8 bellard
            gen_op_movl_T1_ESP,
266 367e86e8 bellard
            gen_op_movl_T1_EBP,
267 367e86e8 bellard
            gen_op_movl_T1_ESI,
268 367e86e8 bellard
            gen_op_movl_T1_EDI,
269 367e86e8 bellard
        },
270 367e86e8 bellard
    },
271 367e86e8 bellard
};
272 367e86e8 bellard
273 367e86e8 bellard
static GenOpFunc *gen_op_movl_A0_reg[8] = {
274 367e86e8 bellard
    gen_op_movl_A0_EAX,
275 367e86e8 bellard
    gen_op_movl_A0_ECX,
276 367e86e8 bellard
    gen_op_movl_A0_EDX,
277 367e86e8 bellard
    gen_op_movl_A0_EBX,
278 367e86e8 bellard
    gen_op_movl_A0_ESP,
279 367e86e8 bellard
    gen_op_movl_A0_EBP,
280 367e86e8 bellard
    gen_op_movl_A0_ESI,
281 367e86e8 bellard
    gen_op_movl_A0_EDI,
282 367e86e8 bellard
};
283 367e86e8 bellard
284 367e86e8 bellard
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
285 367e86e8 bellard
    [0] = {
286 367e86e8 bellard
        gen_op_addl_A0_EAX,
287 367e86e8 bellard
        gen_op_addl_A0_ECX,
288 367e86e8 bellard
        gen_op_addl_A0_EDX,
289 367e86e8 bellard
        gen_op_addl_A0_EBX,
290 367e86e8 bellard
        gen_op_addl_A0_ESP,
291 367e86e8 bellard
        gen_op_addl_A0_EBP,
292 367e86e8 bellard
        gen_op_addl_A0_ESI,
293 367e86e8 bellard
        gen_op_addl_A0_EDI,
294 367e86e8 bellard
    },
295 367e86e8 bellard
    [1] = {
296 367e86e8 bellard
        gen_op_addl_A0_EAX_s1,
297 367e86e8 bellard
        gen_op_addl_A0_ECX_s1,
298 367e86e8 bellard
        gen_op_addl_A0_EDX_s1,
299 367e86e8 bellard
        gen_op_addl_A0_EBX_s1,
300 367e86e8 bellard
        gen_op_addl_A0_ESP_s1,
301 367e86e8 bellard
        gen_op_addl_A0_EBP_s1,
302 367e86e8 bellard
        gen_op_addl_A0_ESI_s1,
303 367e86e8 bellard
        gen_op_addl_A0_EDI_s1,
304 367e86e8 bellard
    },
305 367e86e8 bellard
    [2] = {
306 367e86e8 bellard
        gen_op_addl_A0_EAX_s2,
307 367e86e8 bellard
        gen_op_addl_A0_ECX_s2,
308 367e86e8 bellard
        gen_op_addl_A0_EDX_s2,
309 367e86e8 bellard
        gen_op_addl_A0_EBX_s2,
310 367e86e8 bellard
        gen_op_addl_A0_ESP_s2,
311 367e86e8 bellard
        gen_op_addl_A0_EBP_s2,
312 367e86e8 bellard
        gen_op_addl_A0_ESI_s2,
313 367e86e8 bellard
        gen_op_addl_A0_EDI_s2,
314 367e86e8 bellard
    },
315 367e86e8 bellard
    [3] = {
316 367e86e8 bellard
        gen_op_addl_A0_EAX_s3,
317 367e86e8 bellard
        gen_op_addl_A0_ECX_s3,
318 367e86e8 bellard
        gen_op_addl_A0_EDX_s3,
319 367e86e8 bellard
        gen_op_addl_A0_EBX_s3,
320 367e86e8 bellard
        gen_op_addl_A0_ESP_s3,
321 367e86e8 bellard
        gen_op_addl_A0_EBP_s3,
322 367e86e8 bellard
        gen_op_addl_A0_ESI_s3,
323 367e86e8 bellard
        gen_op_addl_A0_EDI_s3,
324 367e86e8 bellard
    },
325 367e86e8 bellard
};
326 367e86e8 bellard
327 367e86e8 bellard
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
328 367e86e8 bellard
    gen_op_addl_T0_T1_cc,
329 367e86e8 bellard
    gen_op_orl_T0_T1_cc,
330 4b74fe1f bellard
    NULL,
331 4b74fe1f bellard
    NULL,
332 367e86e8 bellard
    gen_op_andl_T0_T1_cc,
333 367e86e8 bellard
    gen_op_subl_T0_T1_cc,
334 367e86e8 bellard
    gen_op_xorl_T0_T1_cc,
335 367e86e8 bellard
    gen_op_cmpl_T0_T1_cc,
336 367e86e8 bellard
};
337 367e86e8 bellard
338 4b74fe1f bellard
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
339 4b74fe1f bellard
    [OT_BYTE] = {
340 4b74fe1f bellard
        gen_op_adcb_T0_T1_cc,
341 4b74fe1f bellard
        gen_op_sbbb_T0_T1_cc,
342 4b74fe1f bellard
    },
343 4b74fe1f bellard
    [OT_WORD] = {
344 4b74fe1f bellard
        gen_op_adcw_T0_T1_cc,
345 4b74fe1f bellard
        gen_op_sbbw_T0_T1_cc,
346 4b74fe1f bellard
    },
347 4b74fe1f bellard
    [OT_LONG] = {
348 4b74fe1f bellard
        gen_op_adcl_T0_T1_cc,
349 4b74fe1f bellard
        gen_op_sbbl_T0_T1_cc,
350 4b74fe1f bellard
    },
351 4b74fe1f bellard
};
352 4b74fe1f bellard
353 367e86e8 bellard
static const int cc_op_arithb[8] = {
354 367e86e8 bellard
    CC_OP_ADDB,
355 367e86e8 bellard
    CC_OP_LOGICB,
356 367e86e8 bellard
    CC_OP_ADDB,
357 367e86e8 bellard
    CC_OP_SUBB,
358 367e86e8 bellard
    CC_OP_LOGICB,
359 367e86e8 bellard
    CC_OP_SUBB,
360 367e86e8 bellard
    CC_OP_LOGICB,
361 367e86e8 bellard
    CC_OP_SUBB,
362 367e86e8 bellard
};
363 367e86e8 bellard
364 367e86e8 bellard
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
365 367e86e8 bellard
    [OT_BYTE] = {
366 367e86e8 bellard
        gen_op_rolb_T0_T1_cc,
367 367e86e8 bellard
        gen_op_rorb_T0_T1_cc,
368 367e86e8 bellard
        gen_op_rclb_T0_T1_cc,
369 367e86e8 bellard
        gen_op_rcrb_T0_T1_cc,
370 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
371 367e86e8 bellard
        gen_op_shrb_T0_T1_cc,
372 367e86e8 bellard
        gen_op_shlb_T0_T1_cc,
373 367e86e8 bellard
        gen_op_sarb_T0_T1_cc,
374 367e86e8 bellard
    },
375 367e86e8 bellard
    [OT_WORD] = {
376 367e86e8 bellard
        gen_op_rolw_T0_T1_cc,
377 367e86e8 bellard
        gen_op_rorw_T0_T1_cc,
378 367e86e8 bellard
        gen_op_rclw_T0_T1_cc,
379 367e86e8 bellard
        gen_op_rcrw_T0_T1_cc,
380 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
381 367e86e8 bellard
        gen_op_shrw_T0_T1_cc,
382 367e86e8 bellard
        gen_op_shlw_T0_T1_cc,
383 367e86e8 bellard
        gen_op_sarw_T0_T1_cc,
384 367e86e8 bellard
    },
385 367e86e8 bellard
    [OT_LONG] = {
386 367e86e8 bellard
        gen_op_roll_T0_T1_cc,
387 367e86e8 bellard
        gen_op_rorl_T0_T1_cc,
388 367e86e8 bellard
        gen_op_rcll_T0_T1_cc,
389 367e86e8 bellard
        gen_op_rcrl_T0_T1_cc,
390 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
391 367e86e8 bellard
        gen_op_shrl_T0_T1_cc,
392 367e86e8 bellard
        gen_op_shll_T0_T1_cc,
393 367e86e8 bellard
        gen_op_sarl_T0_T1_cc,
394 367e86e8 bellard
    },
395 367e86e8 bellard
};
396 367e86e8 bellard
397 d57c4e01 bellard
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
398 d57c4e01 bellard
    [0] = {
399 d57c4e01 bellard
        gen_op_shldw_T0_T1_im_cc,
400 d57c4e01 bellard
        gen_op_shrdw_T0_T1_im_cc,
401 d57c4e01 bellard
    },
402 d57c4e01 bellard
    [1] = {
403 d57c4e01 bellard
        gen_op_shldl_T0_T1_im_cc,
404 d57c4e01 bellard
        gen_op_shrdl_T0_T1_im_cc,
405 d57c4e01 bellard
    },
406 d57c4e01 bellard
};
407 d57c4e01 bellard
408 d57c4e01 bellard
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
409 d57c4e01 bellard
    [0] = {
410 d57c4e01 bellard
        gen_op_shldw_T0_T1_ECX_cc,
411 d57c4e01 bellard
        gen_op_shrdw_T0_T1_ECX_cc,
412 d57c4e01 bellard
    },
413 d57c4e01 bellard
    [1] = {
414 d57c4e01 bellard
        gen_op_shldl_T0_T1_ECX_cc,
415 d57c4e01 bellard
        gen_op_shrdl_T0_T1_ECX_cc,
416 d57c4e01 bellard
    },
417 d57c4e01 bellard
};
418 d57c4e01 bellard
419 4b74fe1f bellard
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
420 4b74fe1f bellard
    [0] = {
421 4b74fe1f bellard
        gen_op_btw_T0_T1_cc,
422 4b74fe1f bellard
        gen_op_btsw_T0_T1_cc,
423 4b74fe1f bellard
        gen_op_btrw_T0_T1_cc,
424 4b74fe1f bellard
        gen_op_btcw_T0_T1_cc,
425 4b74fe1f bellard
    },
426 4b74fe1f bellard
    [1] = {
427 4b74fe1f bellard
        gen_op_btl_T0_T1_cc,
428 4b74fe1f bellard
        gen_op_btsl_T0_T1_cc,
429 4b74fe1f bellard
        gen_op_btrl_T0_T1_cc,
430 4b74fe1f bellard
        gen_op_btcl_T0_T1_cc,
431 4b74fe1f bellard
    },
432 4b74fe1f bellard
};
433 4b74fe1f bellard
434 367e86e8 bellard
static GenOpFunc *gen_op_lds_T0_A0[3] = {
435 367e86e8 bellard
    gen_op_ldsb_T0_A0,
436 367e86e8 bellard
    gen_op_ldsw_T0_A0,
437 367e86e8 bellard
};
438 367e86e8 bellard
439 367e86e8 bellard
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
440 367e86e8 bellard
    gen_op_ldub_T0_A0,
441 367e86e8 bellard
    gen_op_lduw_T0_A0,
442 367e86e8 bellard
};
443 367e86e8 bellard
444 367e86e8 bellard
/* sign does not matter */
445 367e86e8 bellard
static GenOpFunc *gen_op_ld_T0_A0[3] = {
446 367e86e8 bellard
    gen_op_ldub_T0_A0,
447 367e86e8 bellard
    gen_op_lduw_T0_A0,
448 367e86e8 bellard
    gen_op_ldl_T0_A0,
449 367e86e8 bellard
};
450 367e86e8 bellard
451 367e86e8 bellard
static GenOpFunc *gen_op_ld_T1_A0[3] = {
452 367e86e8 bellard
    gen_op_ldub_T1_A0,
453 367e86e8 bellard
    gen_op_lduw_T1_A0,
454 367e86e8 bellard
    gen_op_ldl_T1_A0,
455 367e86e8 bellard
};
456 367e86e8 bellard
457 367e86e8 bellard
static GenOpFunc *gen_op_st_T0_A0[3] = {
458 367e86e8 bellard
    gen_op_stb_T0_A0,
459 367e86e8 bellard
    gen_op_stw_T0_A0,
460 367e86e8 bellard
    gen_op_stl_T0_A0,
461 367e86e8 bellard
};
462 367e86e8 bellard
463 367e86e8 bellard
static GenOpFunc *gen_op_movs[6] = {
464 367e86e8 bellard
    gen_op_movsb,
465 367e86e8 bellard
    gen_op_movsw,
466 367e86e8 bellard
    gen_op_movsl,
467 367e86e8 bellard
    gen_op_rep_movsb,
468 367e86e8 bellard
    gen_op_rep_movsw,
469 367e86e8 bellard
    gen_op_rep_movsl,
470 367e86e8 bellard
};
471 367e86e8 bellard
472 367e86e8 bellard
static GenOpFunc *gen_op_stos[6] = {
473 367e86e8 bellard
    gen_op_stosb,
474 367e86e8 bellard
    gen_op_stosw,
475 367e86e8 bellard
    gen_op_stosl,
476 367e86e8 bellard
    gen_op_rep_stosb,
477 367e86e8 bellard
    gen_op_rep_stosw,
478 367e86e8 bellard
    gen_op_rep_stosl,
479 367e86e8 bellard
};
480 367e86e8 bellard
481 367e86e8 bellard
static GenOpFunc *gen_op_lods[6] = {
482 367e86e8 bellard
    gen_op_lodsb,
483 367e86e8 bellard
    gen_op_lodsw,
484 367e86e8 bellard
    gen_op_lodsl,
485 367e86e8 bellard
    gen_op_rep_lodsb,
486 367e86e8 bellard
    gen_op_rep_lodsw,
487 367e86e8 bellard
    gen_op_rep_lodsl,
488 367e86e8 bellard
};
489 367e86e8 bellard
490 367e86e8 bellard
static GenOpFunc *gen_op_scas[9] = {
491 367e86e8 bellard
    gen_op_scasb,
492 367e86e8 bellard
    gen_op_scasw,
493 367e86e8 bellard
    gen_op_scasl,
494 367e86e8 bellard
    gen_op_repz_scasb,
495 367e86e8 bellard
    gen_op_repz_scasw,
496 367e86e8 bellard
    gen_op_repz_scasl,
497 367e86e8 bellard
    gen_op_repnz_scasb,
498 367e86e8 bellard
    gen_op_repnz_scasw,
499 367e86e8 bellard
    gen_op_repnz_scasl,
500 367e86e8 bellard
};
501 367e86e8 bellard
502 367e86e8 bellard
static GenOpFunc *gen_op_cmps[9] = {
503 367e86e8 bellard
    gen_op_cmpsb,
504 367e86e8 bellard
    gen_op_cmpsw,
505 367e86e8 bellard
    gen_op_cmpsl,
506 367e86e8 bellard
    gen_op_repz_cmpsb,
507 367e86e8 bellard
    gen_op_repz_cmpsw,
508 367e86e8 bellard
    gen_op_repz_cmpsl,
509 367e86e8 bellard
    gen_op_repnz_cmpsb,
510 367e86e8 bellard
    gen_op_repnz_cmpsw,
511 367e86e8 bellard
    gen_op_repnz_cmpsl,
512 367e86e8 bellard
};
513 367e86e8 bellard
514 367e86e8 bellard
static GenOpFunc *gen_op_ins[6] = {
515 367e86e8 bellard
    gen_op_insb,
516 367e86e8 bellard
    gen_op_insw,
517 367e86e8 bellard
    gen_op_insl,
518 367e86e8 bellard
    gen_op_rep_insb,
519 367e86e8 bellard
    gen_op_rep_insw,
520 367e86e8 bellard
    gen_op_rep_insl,
521 367e86e8 bellard
};
522 367e86e8 bellard
523 367e86e8 bellard
524 367e86e8 bellard
static GenOpFunc *gen_op_outs[6] = {
525 367e86e8 bellard
    gen_op_outsb,
526 367e86e8 bellard
    gen_op_outsw,
527 367e86e8 bellard
    gen_op_outsl,
528 367e86e8 bellard
    gen_op_rep_outsb,
529 367e86e8 bellard
    gen_op_rep_outsw,
530 367e86e8 bellard
    gen_op_rep_outsl,
531 367e86e8 bellard
};
532 367e86e8 bellard
533 ba1c6e37 bellard
static GenOpFunc *gen_op_in[3] = {
534 ba1c6e37 bellard
    gen_op_inb_T0_T1,
535 ba1c6e37 bellard
    gen_op_inw_T0_T1,
536 ba1c6e37 bellard
    gen_op_inl_T0_T1,
537 ba1c6e37 bellard
};
538 ba1c6e37 bellard
539 ba1c6e37 bellard
static GenOpFunc *gen_op_out[3] = {
540 ba1c6e37 bellard
    gen_op_outb_T0_T1,
541 ba1c6e37 bellard
    gen_op_outw_T0_T1,
542 ba1c6e37 bellard
    gen_op_outl_T0_T1,
543 ba1c6e37 bellard
};
544 ba1c6e37 bellard
545 367e86e8 bellard
enum {
546 367e86e8 bellard
    JCC_O,
547 367e86e8 bellard
    JCC_B,
548 367e86e8 bellard
    JCC_Z,
549 367e86e8 bellard
    JCC_BE,
550 367e86e8 bellard
    JCC_S,
551 367e86e8 bellard
    JCC_P,
552 367e86e8 bellard
    JCC_L,
553 367e86e8 bellard
    JCC_LE,
554 367e86e8 bellard
};
555 367e86e8 bellard
556 367e86e8 bellard
static GenOpFunc2 *gen_jcc_slow[8] = {
557 367e86e8 bellard
    gen_op_jo_cc,
558 367e86e8 bellard
    gen_op_jb_cc,
559 367e86e8 bellard
    gen_op_jz_cc,
560 367e86e8 bellard
    gen_op_jbe_cc,
561 367e86e8 bellard
    gen_op_js_cc,
562 367e86e8 bellard
    gen_op_jp_cc,
563 367e86e8 bellard
    gen_op_jl_cc,
564 367e86e8 bellard
    gen_op_jle_cc,
565 367e86e8 bellard
};
566 367e86e8 bellard
    
567 367e86e8 bellard
static GenOpFunc2 *gen_jcc_sub[3][8] = {
568 367e86e8 bellard
    [OT_BYTE] = {
569 367e86e8 bellard
        NULL,
570 367e86e8 bellard
        gen_op_jb_subb,
571 367e86e8 bellard
        gen_op_jz_subb,
572 367e86e8 bellard
        gen_op_jbe_subb,
573 367e86e8 bellard
        gen_op_js_subb,
574 367e86e8 bellard
        NULL,
575 367e86e8 bellard
        gen_op_jl_subb,
576 367e86e8 bellard
        gen_op_jle_subb,
577 367e86e8 bellard
    },
578 367e86e8 bellard
    [OT_WORD] = {
579 367e86e8 bellard
        NULL,
580 367e86e8 bellard
        gen_op_jb_subw,
581 367e86e8 bellard
        gen_op_jz_subw,
582 367e86e8 bellard
        gen_op_jbe_subw,
583 367e86e8 bellard
        gen_op_js_subw,
584 367e86e8 bellard
        NULL,
585 367e86e8 bellard
        gen_op_jl_subw,
586 367e86e8 bellard
        gen_op_jle_subw,
587 367e86e8 bellard
    },
588 367e86e8 bellard
    [OT_LONG] = {
589 367e86e8 bellard
        NULL,
590 367e86e8 bellard
        gen_op_jb_subl,
591 367e86e8 bellard
        gen_op_jz_subl,
592 367e86e8 bellard
        gen_op_jbe_subl,
593 367e86e8 bellard
        gen_op_js_subl,
594 367e86e8 bellard
        NULL,
595 367e86e8 bellard
        gen_op_jl_subl,
596 367e86e8 bellard
        gen_op_jle_subl,
597 367e86e8 bellard
    },
598 367e86e8 bellard
};
599 367e86e8 bellard
600 367e86e8 bellard
static GenOpFunc *gen_setcc_slow[8] = {
601 367e86e8 bellard
    gen_op_seto_T0_cc,
602 367e86e8 bellard
    gen_op_setb_T0_cc,
603 367e86e8 bellard
    gen_op_setz_T0_cc,
604 367e86e8 bellard
    gen_op_setbe_T0_cc,
605 367e86e8 bellard
    gen_op_sets_T0_cc,
606 367e86e8 bellard
    gen_op_setp_T0_cc,
607 367e86e8 bellard
    gen_op_setl_T0_cc,
608 367e86e8 bellard
    gen_op_setle_T0_cc,
609 367e86e8 bellard
};
610 367e86e8 bellard
611 367e86e8 bellard
static GenOpFunc *gen_setcc_sub[3][8] = {
612 367e86e8 bellard
    [OT_BYTE] = {
613 367e86e8 bellard
        NULL,
614 367e86e8 bellard
        gen_op_setb_T0_subb,
615 367e86e8 bellard
        gen_op_setz_T0_subb,
616 367e86e8 bellard
        gen_op_setbe_T0_subb,
617 367e86e8 bellard
        gen_op_sets_T0_subb,
618 367e86e8 bellard
        NULL,
619 367e86e8 bellard
        gen_op_setl_T0_subb,
620 367e86e8 bellard
        gen_op_setle_T0_subb,
621 367e86e8 bellard
    },
622 367e86e8 bellard
    [OT_WORD] = {
623 367e86e8 bellard
        NULL,
624 367e86e8 bellard
        gen_op_setb_T0_subw,
625 367e86e8 bellard
        gen_op_setz_T0_subw,
626 367e86e8 bellard
        gen_op_setbe_T0_subw,
627 367e86e8 bellard
        gen_op_sets_T0_subw,
628 367e86e8 bellard
        NULL,
629 367e86e8 bellard
        gen_op_setl_T0_subw,
630 367e86e8 bellard
        gen_op_setle_T0_subw,
631 367e86e8 bellard
    },
632 367e86e8 bellard
    [OT_LONG] = {
633 367e86e8 bellard
        NULL,
634 367e86e8 bellard
        gen_op_setb_T0_subl,
635 367e86e8 bellard
        gen_op_setz_T0_subl,
636 367e86e8 bellard
        gen_op_setbe_T0_subl,
637 367e86e8 bellard
        gen_op_sets_T0_subl,
638 367e86e8 bellard
        NULL,
639 367e86e8 bellard
        gen_op_setl_T0_subl,
640 367e86e8 bellard
        gen_op_setle_T0_subl,
641 367e86e8 bellard
    },
642 367e86e8 bellard
};
643 367e86e8 bellard
644 927f621e bellard
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
645 927f621e bellard
    gen_op_fadd_ST0_FT0,
646 927f621e bellard
    gen_op_fmul_ST0_FT0,
647 927f621e bellard
    gen_op_fcom_ST0_FT0,
648 927f621e bellard
    gen_op_fcom_ST0_FT0,
649 927f621e bellard
    gen_op_fsub_ST0_FT0,
650 927f621e bellard
    gen_op_fsubr_ST0_FT0,
651 927f621e bellard
    gen_op_fdiv_ST0_FT0,
652 927f621e bellard
    gen_op_fdivr_ST0_FT0,
653 927f621e bellard
};
654 927f621e bellard
655 927f621e bellard
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
656 927f621e bellard
    gen_op_fadd_STN_ST0,
657 927f621e bellard
    gen_op_fmul_STN_ST0,
658 927f621e bellard
    NULL,
659 927f621e bellard
    NULL,
660 927f621e bellard
    gen_op_fsub_STN_ST0,
661 927f621e bellard
    gen_op_fsubr_STN_ST0,
662 927f621e bellard
    gen_op_fdiv_STN_ST0,
663 927f621e bellard
    gen_op_fdivr_STN_ST0,
664 927f621e bellard
};
665 927f621e bellard
666 367e86e8 bellard
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
667 367e86e8 bellard
{
668 367e86e8 bellard
    if (d != OR_TMP0)
669 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
670 367e86e8 bellard
    if (s != OR_TMP1)
671 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
672 4b74fe1f bellard
    if (op == OP_ADCL || op == OP_SBBL) {
673 4b74fe1f bellard
        if (s1->cc_op != CC_OP_DYNAMIC)
674 4b74fe1f bellard
            gen_op_set_cc_op(s1->cc_op);
675 4b74fe1f bellard
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
676 4b74fe1f bellard
        s1->cc_op = CC_OP_DYNAMIC;
677 4b74fe1f bellard
    } else {
678 4b74fe1f bellard
        gen_op_arith_T0_T1_cc[op]();
679 4b74fe1f bellard
        s1->cc_op = cc_op_arithb[op] + ot;
680 4b74fe1f bellard
    }
681 367e86e8 bellard
    if (d != OR_TMP0 && op != OP_CMPL)
682 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
683 367e86e8 bellard
}
684 367e86e8 bellard
685 367e86e8 bellard
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
686 367e86e8 bellard
{
687 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
688 4b74fe1f bellard
    gen_op(s1, op, ot, d, OR_TMP1);
689 367e86e8 bellard
}
690 367e86e8 bellard
691 367e86e8 bellard
static void gen_inc(DisasContext *s1, int ot, int d, int c)
692 367e86e8 bellard
{
693 367e86e8 bellard
    if (d != OR_TMP0)
694 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
695 367e86e8 bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
696 367e86e8 bellard
        gen_op_set_cc_op(s1->cc_op);
697 4b74fe1f bellard
    if (c > 0) {
698 367e86e8 bellard
        gen_op_incl_T0_cc();
699 4b74fe1f bellard
        s1->cc_op = CC_OP_INCB + ot;
700 4b74fe1f bellard
    } else {
701 367e86e8 bellard
        gen_op_decl_T0_cc();
702 4b74fe1f bellard
        s1->cc_op = CC_OP_DECB + ot;
703 4b74fe1f bellard
    }
704 367e86e8 bellard
    if (d != OR_TMP0)
705 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
706 367e86e8 bellard
}
707 367e86e8 bellard
708 367e86e8 bellard
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
709 367e86e8 bellard
{
710 367e86e8 bellard
    if (d != OR_TMP0)
711 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][d]();
712 367e86e8 bellard
    if (s != OR_TMP1)
713 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][s]();
714 4b74fe1f bellard
    /* for zero counts, flags are not updated, so must do it dynamically */
715 4b74fe1f bellard
    if (s1->cc_op != CC_OP_DYNAMIC)
716 4b74fe1f bellard
        gen_op_set_cc_op(s1->cc_op);
717 4b74fe1f bellard
718 4b74fe1f bellard
    gen_op_shift_T0_T1_cc[ot][op]();
719 4b74fe1f bellard
720 367e86e8 bellard
    if (d != OR_TMP0)
721 367e86e8 bellard
        gen_op_mov_reg_T0[ot][d]();
722 367e86e8 bellard
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
723 367e86e8 bellard
}
724 367e86e8 bellard
725 367e86e8 bellard
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
726 367e86e8 bellard
{
727 367e86e8 bellard
    /* currently not optimized */
728 ba1c6e37 bellard
    gen_op_movl_T1_im(c);
729 367e86e8 bellard
    gen_shift(s1, op, ot, d, OR_TMP1);
730 367e86e8 bellard
}
731 367e86e8 bellard
732 367e86e8 bellard
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
733 367e86e8 bellard
{
734 367e86e8 bellard
    int havesib;
735 367e86e8 bellard
    int havebase;
736 367e86e8 bellard
    int base, disp;
737 367e86e8 bellard
    int index = 0;
738 367e86e8 bellard
    int scale = 0;
739 367e86e8 bellard
    int reg1, reg2, opreg;
740 367e86e8 bellard
    int mod, rm, code;
741 367e86e8 bellard
742 367e86e8 bellard
    mod = (modrm >> 6) & 3;
743 367e86e8 bellard
    rm = modrm & 7;
744 367e86e8 bellard
745 367e86e8 bellard
    if (s->aflag) {
746 367e86e8 bellard
747 367e86e8 bellard
        havesib = 0;
748 367e86e8 bellard
        havebase = 1;
749 367e86e8 bellard
        base = rm;
750 367e86e8 bellard
        
751 367e86e8 bellard
        if (base == 4) {
752 367e86e8 bellard
            havesib = 1;
753 367e86e8 bellard
            code = ldub(s->pc++);
754 367e86e8 bellard
            scale = (code >> 6) & 3;
755 367e86e8 bellard
            index = (code >> 3) & 7;
756 367e86e8 bellard
            base = code & 7;
757 367e86e8 bellard
        }
758 367e86e8 bellard
759 367e86e8 bellard
        switch (mod) {
760 367e86e8 bellard
        case 0:
761 367e86e8 bellard
            if (base == 5) {
762 367e86e8 bellard
                havebase = 0;
763 367e86e8 bellard
                disp = ldl(s->pc);
764 367e86e8 bellard
                s->pc += 4;
765 367e86e8 bellard
            } else {
766 367e86e8 bellard
                disp = 0;
767 367e86e8 bellard
            }
768 367e86e8 bellard
            break;
769 367e86e8 bellard
        case 1:
770 367e86e8 bellard
            disp = (int8_t)ldub(s->pc++);
771 367e86e8 bellard
            break;
772 367e86e8 bellard
        default:
773 367e86e8 bellard
        case 2:
774 367e86e8 bellard
            disp = ldl(s->pc);
775 367e86e8 bellard
            s->pc += 4;
776 367e86e8 bellard
            break;
777 367e86e8 bellard
        }
778 367e86e8 bellard
779 367e86e8 bellard
        reg1 = OR_ZERO;
780 367e86e8 bellard
        reg2 = OR_ZERO;
781 367e86e8 bellard
          
782 367e86e8 bellard
        if (havebase || (havesib && (index != 4 || scale != 0))) {
783 367e86e8 bellard
            if (havebase)
784 367e86e8 bellard
                reg1 = OR_EAX + base;
785 367e86e8 bellard
            if (havesib && index != 4) {
786 367e86e8 bellard
                if (havebase)
787 367e86e8 bellard
                    reg2 = index + OR_EAX;
788 367e86e8 bellard
                else
789 367e86e8 bellard
                    reg1 = index + OR_EAX;
790 367e86e8 bellard
            }
791 367e86e8 bellard
        }
792 367e86e8 bellard
        /* XXX: disp only ? */
793 367e86e8 bellard
        if (reg2 == OR_ZERO) {
794 367e86e8 bellard
            /* op: disp + (reg1 << scale) */
795 367e86e8 bellard
            if (reg1 == OR_ZERO) {
796 ba1c6e37 bellard
                gen_op_movl_A0_im(disp);
797 367e86e8 bellard
            } else if (scale == 0 && disp == 0) {
798 367e86e8 bellard
                gen_op_movl_A0_reg[reg1]();
799 367e86e8 bellard
            } else {
800 0ecfa993 bellard
                gen_op_movl_A0_im(disp);
801 367e86e8 bellard
                gen_op_addl_A0_reg_sN[scale][reg1]();
802 367e86e8 bellard
            }
803 367e86e8 bellard
        } else {
804 367e86e8 bellard
            /* op: disp + reg1 + (reg2 << scale) */
805 367e86e8 bellard
            if (disp != 0) {
806 ba1c6e37 bellard
                gen_op_movl_A0_im(disp);
807 367e86e8 bellard
                gen_op_addl_A0_reg_sN[0][reg1]();
808 367e86e8 bellard
            } else {
809 367e86e8 bellard
                gen_op_movl_A0_reg[reg1]();
810 367e86e8 bellard
            }
811 367e86e8 bellard
            gen_op_addl_A0_reg_sN[scale][reg2]();
812 367e86e8 bellard
        }
813 367e86e8 bellard
    } else {
814 4b74fe1f bellard
        switch (mod) {
815 4b74fe1f bellard
        case 0:
816 4b74fe1f bellard
            if (rm == 6) {
817 4b74fe1f bellard
                disp = lduw(s->pc);
818 4b74fe1f bellard
                s->pc += 2;
819 4b74fe1f bellard
                gen_op_movl_A0_im(disp);
820 4b74fe1f bellard
                goto no_rm;
821 4b74fe1f bellard
            } else {
822 4b74fe1f bellard
                disp = 0;
823 4b74fe1f bellard
            }
824 4b74fe1f bellard
            break;
825 4b74fe1f bellard
        case 1:
826 4b74fe1f bellard
            disp = (int8_t)ldub(s->pc++);
827 4b74fe1f bellard
            break;
828 4b74fe1f bellard
        default:
829 4b74fe1f bellard
        case 2:
830 4b74fe1f bellard
            disp = lduw(s->pc);
831 4b74fe1f bellard
            s->pc += 2;
832 4b74fe1f bellard
            break;
833 4b74fe1f bellard
        }
834 4b74fe1f bellard
        switch(rm) {
835 4b74fe1f bellard
        case 0:
836 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
837 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_ESI]();
838 4b74fe1f bellard
            break;
839 4b74fe1f bellard
        case 1:
840 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
841 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_EDI]();
842 4b74fe1f bellard
            break;
843 4b74fe1f bellard
        case 2:
844 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
845 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_ESI]();
846 4b74fe1f bellard
            break;
847 4b74fe1f bellard
        case 3:
848 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
849 4b74fe1f bellard
            gen_op_addl_A0_reg_sN[0][R_EDI]();
850 4b74fe1f bellard
            break;
851 4b74fe1f bellard
        case 4:
852 4b74fe1f bellard
            gen_op_movl_A0_reg[R_ESI]();
853 4b74fe1f bellard
            break;
854 4b74fe1f bellard
        case 5:
855 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EDI]();
856 4b74fe1f bellard
            break;
857 4b74fe1f bellard
        case 6:
858 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBP]();
859 4b74fe1f bellard
            break;
860 4b74fe1f bellard
        default:
861 4b74fe1f bellard
        case 7:
862 4b74fe1f bellard
            gen_op_movl_A0_reg[R_EBX]();
863 4b74fe1f bellard
            break;
864 4b74fe1f bellard
        }
865 4b74fe1f bellard
        if (disp != 0)
866 4b74fe1f bellard
            gen_op_addl_A0_im(disp);
867 4b74fe1f bellard
        gen_op_andl_A0_ffff();
868 4b74fe1f bellard
    no_rm: ;
869 367e86e8 bellard
    }
870 4b74fe1f bellard
    opreg = OR_A0;
871 4b74fe1f bellard
    disp = 0;
872 367e86e8 bellard
    *reg_ptr = opreg;
873 367e86e8 bellard
    *offset_ptr = disp;
874 367e86e8 bellard
}
875 367e86e8 bellard
876 367e86e8 bellard
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
877 367e86e8 bellard
   OR_TMP0 */
878 367e86e8 bellard
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
879 367e86e8 bellard
{
880 367e86e8 bellard
    int mod, rm, opreg, disp;
881 367e86e8 bellard
882 367e86e8 bellard
    mod = (modrm >> 6) & 3;
883 367e86e8 bellard
    rm = modrm & 7;
884 367e86e8 bellard
    if (mod == 3) {
885 367e86e8 bellard
        if (is_store) {
886 367e86e8 bellard
            if (reg != OR_TMP0)
887 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
888 367e86e8 bellard
            gen_op_mov_reg_T0[ot][rm]();
889 367e86e8 bellard
        } else {
890 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
891 367e86e8 bellard
            if (reg != OR_TMP0)
892 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
893 367e86e8 bellard
        }
894 367e86e8 bellard
    } else {
895 367e86e8 bellard
        gen_lea_modrm(s, modrm, &opreg, &disp);
896 367e86e8 bellard
        if (is_store) {
897 367e86e8 bellard
            if (reg != OR_TMP0)
898 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][reg]();
899 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
900 367e86e8 bellard
        } else {
901 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
902 367e86e8 bellard
            if (reg != OR_TMP0)
903 367e86e8 bellard
                gen_op_mov_reg_T0[ot][reg]();
904 367e86e8 bellard
        }
905 367e86e8 bellard
    }
906 367e86e8 bellard
}
907 367e86e8 bellard
908 367e86e8 bellard
static inline uint32_t insn_get(DisasContext *s, int ot)
909 367e86e8 bellard
{
910 367e86e8 bellard
    uint32_t ret;
911 367e86e8 bellard
912 367e86e8 bellard
    switch(ot) {
913 367e86e8 bellard
    case OT_BYTE:
914 367e86e8 bellard
        ret = ldub(s->pc);
915 367e86e8 bellard
        s->pc++;
916 367e86e8 bellard
        break;
917 367e86e8 bellard
    case OT_WORD:
918 367e86e8 bellard
        ret = lduw(s->pc);
919 367e86e8 bellard
        s->pc += 2;
920 367e86e8 bellard
        break;
921 367e86e8 bellard
    default:
922 367e86e8 bellard
    case OT_LONG:
923 367e86e8 bellard
        ret = ldl(s->pc);
924 367e86e8 bellard
        s->pc += 4;
925 367e86e8 bellard
        break;
926 367e86e8 bellard
    }
927 367e86e8 bellard
    return ret;
928 367e86e8 bellard
}
929 367e86e8 bellard
930 367e86e8 bellard
static void gen_jcc(DisasContext *s, int b, int val)
931 367e86e8 bellard
{
932 367e86e8 bellard
    int inv, jcc_op;
933 367e86e8 bellard
    GenOpFunc2 *func;
934 367e86e8 bellard
935 367e86e8 bellard
    inv = b & 1;
936 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
937 367e86e8 bellard
    switch(s->cc_op) {
938 367e86e8 bellard
        /* we optimize the cmp/jcc case */
939 367e86e8 bellard
    case CC_OP_SUBB:
940 367e86e8 bellard
    case CC_OP_SUBW:
941 367e86e8 bellard
    case CC_OP_SUBL:
942 367e86e8 bellard
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
943 367e86e8 bellard
        if (!func)
944 367e86e8 bellard
            goto slow_jcc;
945 367e86e8 bellard
        break;
946 367e86e8 bellard
        
947 367e86e8 bellard
        /* some jumps are easy to compute */
948 367e86e8 bellard
    case CC_OP_ADDB:
949 367e86e8 bellard
    case CC_OP_ADDW:
950 367e86e8 bellard
    case CC_OP_ADDL:
951 4b74fe1f bellard
    case CC_OP_ADCB:
952 4b74fe1f bellard
    case CC_OP_ADCW:
953 4b74fe1f bellard
    case CC_OP_ADCL:
954 4b74fe1f bellard
    case CC_OP_SBBB:
955 4b74fe1f bellard
    case CC_OP_SBBW:
956 4b74fe1f bellard
    case CC_OP_SBBL:
957 367e86e8 bellard
    case CC_OP_LOGICB:
958 367e86e8 bellard
    case CC_OP_LOGICW:
959 367e86e8 bellard
    case CC_OP_LOGICL:
960 367e86e8 bellard
    case CC_OP_INCB:
961 367e86e8 bellard
    case CC_OP_INCW:
962 367e86e8 bellard
    case CC_OP_INCL:
963 367e86e8 bellard
    case CC_OP_DECB:
964 367e86e8 bellard
    case CC_OP_DECW:
965 367e86e8 bellard
    case CC_OP_DECL:
966 367e86e8 bellard
    case CC_OP_SHLB:
967 367e86e8 bellard
    case CC_OP_SHLW:
968 367e86e8 bellard
    case CC_OP_SHLL:
969 4b74fe1f bellard
    case CC_OP_SARB:
970 4b74fe1f bellard
    case CC_OP_SARW:
971 4b74fe1f bellard
    case CC_OP_SARL:
972 367e86e8 bellard
        switch(jcc_op) {
973 367e86e8 bellard
        case JCC_Z:
974 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
975 367e86e8 bellard
            break;
976 367e86e8 bellard
        case JCC_S:
977 367e86e8 bellard
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
978 367e86e8 bellard
            break;
979 367e86e8 bellard
        default:
980 367e86e8 bellard
            goto slow_jcc;
981 367e86e8 bellard
        }
982 367e86e8 bellard
        break;
983 367e86e8 bellard
    default:
984 367e86e8 bellard
    slow_jcc:
985 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
986 367e86e8 bellard
            op_set_cc_op(s->cc_op);
987 367e86e8 bellard
        func = gen_jcc_slow[jcc_op];
988 367e86e8 bellard
        break;
989 367e86e8 bellard
    }
990 367e86e8 bellard
    if (!inv) {
991 367e86e8 bellard
        func(val, (long)s->pc);
992 367e86e8 bellard
    } else {
993 367e86e8 bellard
        func((long)s->pc, val);
994 367e86e8 bellard
    }
995 367e86e8 bellard
}
996 367e86e8 bellard
997 367e86e8 bellard
static void gen_setcc(DisasContext *s, int b)
998 367e86e8 bellard
{
999 367e86e8 bellard
    int inv, jcc_op;
1000 367e86e8 bellard
    GenOpFunc *func;
1001 367e86e8 bellard
1002 367e86e8 bellard
    inv = b & 1;
1003 367e86e8 bellard
    jcc_op = (b >> 1) & 7;
1004 367e86e8 bellard
    switch(s->cc_op) {
1005 367e86e8 bellard
        /* we optimize the cmp/jcc case */
1006 367e86e8 bellard
    case CC_OP_SUBB:
1007 367e86e8 bellard
    case CC_OP_SUBW:
1008 367e86e8 bellard
    case CC_OP_SUBL:
1009 367e86e8 bellard
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1010 367e86e8 bellard
        if (!func)
1011 367e86e8 bellard
            goto slow_jcc;
1012 367e86e8 bellard
        break;
1013 367e86e8 bellard
        
1014 367e86e8 bellard
        /* some jumps are easy to compute */
1015 367e86e8 bellard
    case CC_OP_ADDB:
1016 367e86e8 bellard
    case CC_OP_ADDW:
1017 367e86e8 bellard
    case CC_OP_ADDL:
1018 367e86e8 bellard
    case CC_OP_LOGICB:
1019 367e86e8 bellard
    case CC_OP_LOGICW:
1020 367e86e8 bellard
    case CC_OP_LOGICL:
1021 367e86e8 bellard
    case CC_OP_INCB:
1022 367e86e8 bellard
    case CC_OP_INCW:
1023 367e86e8 bellard
    case CC_OP_INCL:
1024 367e86e8 bellard
    case CC_OP_DECB:
1025 367e86e8 bellard
    case CC_OP_DECW:
1026 367e86e8 bellard
    case CC_OP_DECL:
1027 367e86e8 bellard
    case CC_OP_SHLB:
1028 367e86e8 bellard
    case CC_OP_SHLW:
1029 367e86e8 bellard
    case CC_OP_SHLL:
1030 367e86e8 bellard
        switch(jcc_op) {
1031 367e86e8 bellard
        case JCC_Z:
1032 367e86e8 bellard
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
1033 367e86e8 bellard
            break;
1034 367e86e8 bellard
        case JCC_S:
1035 367e86e8 bellard
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
1036 367e86e8 bellard
            break;
1037 367e86e8 bellard
        default:
1038 367e86e8 bellard
            goto slow_jcc;
1039 367e86e8 bellard
        }
1040 367e86e8 bellard
        break;
1041 367e86e8 bellard
    default:
1042 367e86e8 bellard
    slow_jcc:
1043 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
1044 367e86e8 bellard
            op_set_cc_op(s->cc_op);
1045 367e86e8 bellard
        func = gen_setcc_slow[jcc_op];
1046 367e86e8 bellard
        break;
1047 367e86e8 bellard
    }
1048 367e86e8 bellard
    func();
1049 367e86e8 bellard
    if (inv) {
1050 367e86e8 bellard
        gen_op_xor_T0_1();
1051 367e86e8 bellard
    }
1052 367e86e8 bellard
}
1053 367e86e8 bellard
1054 0ecfa993 bellard
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1055 0ecfa993 bellard
   is set to true if the instruction sets the PC (last instruction of
1056 0ecfa993 bellard
   a basic block) */
1057 0ecfa993 bellard
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1058 367e86e8 bellard
{
1059 367e86e8 bellard
    int b, prefixes, aflag, dflag;
1060 367e86e8 bellard
    int shift, ot;
1061 367e86e8 bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1062 367e86e8 bellard
1063 367e86e8 bellard
    s->pc = pc_start;
1064 367e86e8 bellard
    prefixes = 0;
1065 367e86e8 bellard
    aflag = 1;
1066 367e86e8 bellard
    dflag = 1;
1067 367e86e8 bellard
    //    cur_pc = s->pc; /* for insn generation */
1068 367e86e8 bellard
 next_byte:
1069 367e86e8 bellard
    b = ldub(s->pc);
1070 367e86e8 bellard
    s->pc++;
1071 367e86e8 bellard
    /* check prefixes */
1072 367e86e8 bellard
    switch (b) {
1073 367e86e8 bellard
    case 0xf3:
1074 367e86e8 bellard
        prefixes |= PREFIX_REPZ;
1075 367e86e8 bellard
        goto next_byte;
1076 367e86e8 bellard
    case 0xf2:
1077 367e86e8 bellard
        prefixes |= PREFIX_REPNZ;
1078 367e86e8 bellard
        goto next_byte;
1079 367e86e8 bellard
    case 0xf0:
1080 367e86e8 bellard
        prefixes |= PREFIX_LOCK;
1081 367e86e8 bellard
        goto next_byte;
1082 367e86e8 bellard
    case 0x2e:
1083 367e86e8 bellard
        prefixes |= PREFIX_CS;
1084 367e86e8 bellard
        goto next_byte;
1085 367e86e8 bellard
    case 0x36:
1086 367e86e8 bellard
        prefixes |= PREFIX_SS;
1087 367e86e8 bellard
        goto next_byte;
1088 367e86e8 bellard
    case 0x3e:
1089 367e86e8 bellard
        prefixes |= PREFIX_DS;
1090 367e86e8 bellard
        goto next_byte;
1091 367e86e8 bellard
    case 0x26:
1092 367e86e8 bellard
        prefixes |= PREFIX_ES;
1093 367e86e8 bellard
        goto next_byte;
1094 367e86e8 bellard
    case 0x64:
1095 367e86e8 bellard
        prefixes |= PREFIX_FS;
1096 367e86e8 bellard
        goto next_byte;
1097 367e86e8 bellard
    case 0x65:
1098 367e86e8 bellard
        prefixes |= PREFIX_GS;
1099 367e86e8 bellard
        goto next_byte;
1100 367e86e8 bellard
    case 0x66:
1101 367e86e8 bellard
        prefixes |= PREFIX_DATA;
1102 367e86e8 bellard
        goto next_byte;
1103 367e86e8 bellard
    case 0x67:
1104 367e86e8 bellard
        prefixes |= PREFIX_ADR;
1105 367e86e8 bellard
        goto next_byte;
1106 367e86e8 bellard
    case 0x9b:
1107 367e86e8 bellard
        prefixes |= PREFIX_FWAIT;
1108 367e86e8 bellard
        goto next_byte;
1109 367e86e8 bellard
    }
1110 367e86e8 bellard
1111 367e86e8 bellard
    if (prefixes & PREFIX_DATA)
1112 367e86e8 bellard
        dflag ^= 1;
1113 367e86e8 bellard
    if (prefixes & PREFIX_ADR)
1114 367e86e8 bellard
        aflag ^= 1;
1115 367e86e8 bellard
1116 367e86e8 bellard
    s->prefix = prefixes;
1117 367e86e8 bellard
    s->aflag = aflag;
1118 367e86e8 bellard
    s->dflag = dflag;
1119 367e86e8 bellard
1120 367e86e8 bellard
    /* now check op code */
1121 367e86e8 bellard
 reswitch:
1122 367e86e8 bellard
    switch(b) {
1123 367e86e8 bellard
    case 0x0f:
1124 367e86e8 bellard
        /**************************/
1125 367e86e8 bellard
        /* extended op code */
1126 367e86e8 bellard
        b = ldub(s->pc++) | 0x100;
1127 367e86e8 bellard
        goto reswitch;
1128 367e86e8 bellard
        
1129 367e86e8 bellard
        /**************************/
1130 367e86e8 bellard
        /* arith & logic */
1131 367e86e8 bellard
    case 0x00 ... 0x05:
1132 367e86e8 bellard
    case 0x08 ... 0x0d:
1133 367e86e8 bellard
    case 0x10 ... 0x15:
1134 367e86e8 bellard
    case 0x18 ... 0x1d:
1135 367e86e8 bellard
    case 0x20 ... 0x25:
1136 367e86e8 bellard
    case 0x28 ... 0x2d:
1137 367e86e8 bellard
    case 0x30 ... 0x35:
1138 367e86e8 bellard
    case 0x38 ... 0x3d:
1139 367e86e8 bellard
        {
1140 367e86e8 bellard
            int op, f, val;
1141 367e86e8 bellard
            op = (b >> 3) & 7;
1142 367e86e8 bellard
            f = (b >> 1) & 3;
1143 367e86e8 bellard
1144 367e86e8 bellard
            if ((b & 1) == 0)
1145 367e86e8 bellard
                ot = OT_BYTE;
1146 367e86e8 bellard
            else
1147 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1148 367e86e8 bellard
            
1149 367e86e8 bellard
            switch(f) {
1150 367e86e8 bellard
            case 0: /* OP Ev, Gv */
1151 367e86e8 bellard
                modrm = ldub(s->pc++);
1152 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1153 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1154 367e86e8 bellard
                rm = modrm & 7;
1155 367e86e8 bellard
                if (mod != 3) {
1156 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1157 367e86e8 bellard
                    gen_op_ld_T0_A0[ot]();
1158 367e86e8 bellard
                    opreg = OR_TMP0;
1159 367e86e8 bellard
                } else {
1160 367e86e8 bellard
                    opreg = OR_EAX + rm;
1161 367e86e8 bellard
                }
1162 367e86e8 bellard
                gen_op(s, op, ot, opreg, reg);
1163 367e86e8 bellard
                if (mod != 3 && op != 7) {
1164 367e86e8 bellard
                    gen_op_st_T0_A0[ot]();
1165 367e86e8 bellard
                }
1166 367e86e8 bellard
                break;
1167 367e86e8 bellard
            case 1: /* OP Gv, Ev */
1168 367e86e8 bellard
                modrm = ldub(s->pc++);
1169 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1170 367e86e8 bellard
                reg = ((modrm >> 3) & 7) + OR_EAX;
1171 367e86e8 bellard
                rm = modrm & 7;
1172 367e86e8 bellard
                if (mod != 3) {
1173 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1174 367e86e8 bellard
                    gen_op_ld_T1_A0[ot]();
1175 367e86e8 bellard
                    opreg = OR_TMP1;
1176 367e86e8 bellard
                } else {
1177 367e86e8 bellard
                    opreg = OR_EAX + rm;
1178 367e86e8 bellard
                }
1179 367e86e8 bellard
                gen_op(s, op, ot, reg, opreg);
1180 367e86e8 bellard
                break;
1181 367e86e8 bellard
            case 2: /* OP A, Iv */
1182 367e86e8 bellard
                val = insn_get(s, ot);
1183 367e86e8 bellard
                gen_opi(s, op, ot, OR_EAX, val);
1184 367e86e8 bellard
                break;
1185 367e86e8 bellard
            }
1186 367e86e8 bellard
        }
1187 367e86e8 bellard
        break;
1188 367e86e8 bellard
1189 367e86e8 bellard
    case 0x80: /* GRP1 */
1190 367e86e8 bellard
    case 0x81:
1191 367e86e8 bellard
    case 0x83:
1192 367e86e8 bellard
        {
1193 367e86e8 bellard
            int val;
1194 367e86e8 bellard
1195 367e86e8 bellard
            if ((b & 1) == 0)
1196 367e86e8 bellard
                ot = OT_BYTE;
1197 367e86e8 bellard
            else
1198 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1199 367e86e8 bellard
            
1200 367e86e8 bellard
            modrm = ldub(s->pc++);
1201 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1202 367e86e8 bellard
            rm = modrm & 7;
1203 367e86e8 bellard
            op = (modrm >> 3) & 7;
1204 367e86e8 bellard
            
1205 367e86e8 bellard
            if (mod != 3) {
1206 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1207 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
1208 367e86e8 bellard
                opreg = OR_TMP0;
1209 367e86e8 bellard
            } else {
1210 367e86e8 bellard
                opreg = rm + OR_EAX;
1211 367e86e8 bellard
            }
1212 367e86e8 bellard
1213 367e86e8 bellard
            switch(b) {
1214 367e86e8 bellard
            default:
1215 367e86e8 bellard
            case 0x80:
1216 367e86e8 bellard
            case 0x81:
1217 367e86e8 bellard
                val = insn_get(s, ot);
1218 367e86e8 bellard
                break;
1219 367e86e8 bellard
            case 0x83:
1220 367e86e8 bellard
                val = (int8_t)insn_get(s, OT_BYTE);
1221 367e86e8 bellard
                break;
1222 367e86e8 bellard
            }
1223 367e86e8 bellard
1224 367e86e8 bellard
            gen_opi(s, op, ot, opreg, val);
1225 367e86e8 bellard
            if (op != 7 && mod != 3) {
1226 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1227 367e86e8 bellard
            }
1228 367e86e8 bellard
        }
1229 367e86e8 bellard
        break;
1230 367e86e8 bellard
1231 367e86e8 bellard
        /**************************/
1232 367e86e8 bellard
        /* inc, dec, and other misc arith */
1233 367e86e8 bellard
    case 0x40 ... 0x47: /* inc Gv */
1234 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1235 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1236 367e86e8 bellard
        break;
1237 367e86e8 bellard
    case 0x48 ... 0x4f: /* dec Gv */
1238 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1239 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1240 367e86e8 bellard
        break;
1241 367e86e8 bellard
    case 0xf6: /* GRP3 */
1242 367e86e8 bellard
    case 0xf7:
1243 367e86e8 bellard
        if ((b & 1) == 0)
1244 367e86e8 bellard
            ot = OT_BYTE;
1245 367e86e8 bellard
        else
1246 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1247 367e86e8 bellard
1248 367e86e8 bellard
        modrm = ldub(s->pc++);
1249 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1250 367e86e8 bellard
        rm = modrm & 7;
1251 367e86e8 bellard
        op = (modrm >> 3) & 7;
1252 367e86e8 bellard
        if (mod != 3) {
1253 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1254 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1255 367e86e8 bellard
        } else {
1256 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1257 367e86e8 bellard
        }
1258 367e86e8 bellard
1259 367e86e8 bellard
        switch(op) {
1260 367e86e8 bellard
        case 0: /* test */
1261 367e86e8 bellard
            val = insn_get(s, ot);
1262 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1263 367e86e8 bellard
            gen_op_testl_T0_T1_cc();
1264 367e86e8 bellard
            s->cc_op = CC_OP_LOGICB + ot;
1265 367e86e8 bellard
            break;
1266 367e86e8 bellard
        case 2: /* not */
1267 367e86e8 bellard
            gen_op_notl_T0();
1268 367e86e8 bellard
            if (mod != 3) {
1269 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1270 367e86e8 bellard
            } else {
1271 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1272 367e86e8 bellard
            }
1273 367e86e8 bellard
            break;
1274 367e86e8 bellard
        case 3: /* neg */
1275 367e86e8 bellard
            gen_op_negl_T0_cc();
1276 367e86e8 bellard
            if (mod != 3) {
1277 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1278 367e86e8 bellard
            } else {
1279 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1280 367e86e8 bellard
            }
1281 367e86e8 bellard
            s->cc_op = CC_OP_SUBB + ot;
1282 367e86e8 bellard
            break;
1283 367e86e8 bellard
        case 4: /* mul */
1284 367e86e8 bellard
            switch(ot) {
1285 367e86e8 bellard
            case OT_BYTE:
1286 367e86e8 bellard
                gen_op_mulb_AL_T0();
1287 367e86e8 bellard
                break;
1288 367e86e8 bellard
            case OT_WORD:
1289 367e86e8 bellard
                gen_op_mulw_AX_T0();
1290 367e86e8 bellard
                break;
1291 367e86e8 bellard
            default:
1292 367e86e8 bellard
            case OT_LONG:
1293 367e86e8 bellard
                gen_op_mull_EAX_T0();
1294 367e86e8 bellard
                break;
1295 367e86e8 bellard
            }
1296 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1297 367e86e8 bellard
            break;
1298 367e86e8 bellard
        case 5: /* imul */
1299 367e86e8 bellard
            switch(ot) {
1300 367e86e8 bellard
            case OT_BYTE:
1301 367e86e8 bellard
                gen_op_imulb_AL_T0();
1302 367e86e8 bellard
                break;
1303 367e86e8 bellard
            case OT_WORD:
1304 367e86e8 bellard
                gen_op_imulw_AX_T0();
1305 367e86e8 bellard
                break;
1306 367e86e8 bellard
            default:
1307 367e86e8 bellard
            case OT_LONG:
1308 367e86e8 bellard
                gen_op_imull_EAX_T0();
1309 367e86e8 bellard
                break;
1310 367e86e8 bellard
            }
1311 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1312 367e86e8 bellard
            break;
1313 367e86e8 bellard
        case 6: /* div */
1314 367e86e8 bellard
            switch(ot) {
1315 367e86e8 bellard
            case OT_BYTE:
1316 367e86e8 bellard
                gen_op_divb_AL_T0();
1317 367e86e8 bellard
                break;
1318 367e86e8 bellard
            case OT_WORD:
1319 367e86e8 bellard
                gen_op_divw_AX_T0();
1320 367e86e8 bellard
                break;
1321 367e86e8 bellard
            default:
1322 367e86e8 bellard
            case OT_LONG:
1323 367e86e8 bellard
                gen_op_divl_EAX_T0();
1324 367e86e8 bellard
                break;
1325 367e86e8 bellard
            }
1326 367e86e8 bellard
            break;
1327 367e86e8 bellard
        case 7: /* idiv */
1328 367e86e8 bellard
            switch(ot) {
1329 367e86e8 bellard
            case OT_BYTE:
1330 367e86e8 bellard
                gen_op_idivb_AL_T0();
1331 367e86e8 bellard
                break;
1332 367e86e8 bellard
            case OT_WORD:
1333 367e86e8 bellard
                gen_op_idivw_AX_T0();
1334 367e86e8 bellard
                break;
1335 367e86e8 bellard
            default:
1336 367e86e8 bellard
            case OT_LONG:
1337 367e86e8 bellard
                gen_op_idivl_EAX_T0();
1338 367e86e8 bellard
                break;
1339 367e86e8 bellard
            }
1340 367e86e8 bellard
            break;
1341 367e86e8 bellard
        default:
1342 367e86e8 bellard
            error("GRP3: bad instruction");
1343 367e86e8 bellard
            return -1;
1344 367e86e8 bellard
        }
1345 367e86e8 bellard
        break;
1346 367e86e8 bellard
1347 367e86e8 bellard
    case 0xfe: /* GRP4 */
1348 367e86e8 bellard
    case 0xff: /* GRP5 */
1349 367e86e8 bellard
        if ((b & 1) == 0)
1350 367e86e8 bellard
            ot = OT_BYTE;
1351 367e86e8 bellard
        else
1352 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1353 367e86e8 bellard
1354 367e86e8 bellard
        modrm = ldub(s->pc++);
1355 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1356 367e86e8 bellard
        rm = modrm & 7;
1357 367e86e8 bellard
        op = (modrm >> 3) & 7;
1358 367e86e8 bellard
        if (op >= 2 && b == 0xfe) {
1359 367e86e8 bellard
            error("GRP4: bad instruction");
1360 367e86e8 bellard
            return -1;
1361 367e86e8 bellard
        }
1362 367e86e8 bellard
        if (mod != 3) {
1363 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1364 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1365 367e86e8 bellard
        } else {
1366 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1367 367e86e8 bellard
        }
1368 367e86e8 bellard
1369 367e86e8 bellard
        switch(op) {
1370 367e86e8 bellard
        case 0: /* inc Ev */
1371 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, 1);
1372 367e86e8 bellard
            if (mod != 3)
1373 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1374 4b74fe1f bellard
            else
1375 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
1376 367e86e8 bellard
            break;
1377 367e86e8 bellard
        case 1: /* dec Ev */
1378 367e86e8 bellard
            gen_inc(s, ot, OR_TMP0, -1);
1379 367e86e8 bellard
            if (mod != 3)
1380 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1381 4b74fe1f bellard
            else
1382 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
1383 367e86e8 bellard
            break;
1384 367e86e8 bellard
        case 2: /* call Ev */
1385 ba1c6e37 bellard
            gen_op_movl_T1_im((long)s->pc);
1386 367e86e8 bellard
            gen_op_pushl_T1();
1387 367e86e8 bellard
            gen_op_jmp_T0();
1388 0ecfa993 bellard
            *is_jmp_ptr = 1;
1389 367e86e8 bellard
            break;
1390 367e86e8 bellard
        case 4: /* jmp Ev */
1391 367e86e8 bellard
            gen_op_jmp_T0();
1392 0ecfa993 bellard
            *is_jmp_ptr = 1;
1393 367e86e8 bellard
            break;
1394 367e86e8 bellard
        case 6: /* push Ev */
1395 367e86e8 bellard
            gen_op_pushl_T0();
1396 367e86e8 bellard
            break;
1397 367e86e8 bellard
        default:
1398 367e86e8 bellard
            error("GRP5: bad instruction");
1399 367e86e8 bellard
            return -1;
1400 367e86e8 bellard
        }
1401 367e86e8 bellard
        break;
1402 367e86e8 bellard
1403 367e86e8 bellard
    case 0x84: /* test Ev, Gv */
1404 367e86e8 bellard
    case 0x85: 
1405 367e86e8 bellard
        if ((b & 1) == 0)
1406 367e86e8 bellard
            ot = OT_BYTE;
1407 367e86e8 bellard
        else
1408 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1409 367e86e8 bellard
1410 367e86e8 bellard
        modrm = ldub(s->pc++);
1411 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1412 367e86e8 bellard
        rm = modrm & 7;
1413 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1414 367e86e8 bellard
        
1415 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1416 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1417 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1418 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1419 367e86e8 bellard
        break;
1420 367e86e8 bellard
        
1421 367e86e8 bellard
    case 0xa8: /* test eAX, Iv */
1422 367e86e8 bellard
    case 0xa9:
1423 367e86e8 bellard
        if ((b & 1) == 0)
1424 367e86e8 bellard
            ot = OT_BYTE;
1425 367e86e8 bellard
        else
1426 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1427 367e86e8 bellard
        val = insn_get(s, ot);
1428 367e86e8 bellard
1429 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1430 ba1c6e37 bellard
        gen_op_movl_T1_im(val);
1431 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1432 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1433 367e86e8 bellard
        break;
1434 367e86e8 bellard
        
1435 367e86e8 bellard
    case 0x98: /* CWDE/CBW */
1436 367e86e8 bellard
        if (dflag)
1437 367e86e8 bellard
            gen_op_movswl_EAX_AX();
1438 367e86e8 bellard
        else
1439 367e86e8 bellard
            gen_op_movsbw_AX_AL();
1440 367e86e8 bellard
        break;
1441 367e86e8 bellard
    case 0x99: /* CDQ/CWD */
1442 367e86e8 bellard
        if (dflag)
1443 367e86e8 bellard
            gen_op_movslq_EDX_EAX();
1444 367e86e8 bellard
        else
1445 367e86e8 bellard
            gen_op_movswl_DX_AX();
1446 367e86e8 bellard
        break;
1447 367e86e8 bellard
    case 0x1af: /* imul Gv, Ev */
1448 367e86e8 bellard
    case 0x69: /* imul Gv, Ev, I */
1449 367e86e8 bellard
    case 0x6b:
1450 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1451 367e86e8 bellard
        modrm = ldub(s->pc++);
1452 367e86e8 bellard
        reg = ((modrm >> 3) & 7) + OR_EAX;
1453 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1454 367e86e8 bellard
        if (b == 0x69) {
1455 367e86e8 bellard
            val = insn_get(s, ot);
1456 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1457 367e86e8 bellard
        } else if (b == 0x6b) {
1458 367e86e8 bellard
            val = insn_get(s, OT_BYTE);
1459 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1460 367e86e8 bellard
        } else {
1461 367e86e8 bellard
            gen_op_mov_TN_reg[ot][1][reg]();
1462 367e86e8 bellard
        }
1463 367e86e8 bellard
1464 367e86e8 bellard
        if (ot == OT_LONG) {
1465 4b74fe1f bellard
            gen_op_imull_T0_T1();
1466 367e86e8 bellard
        } else {
1467 4b74fe1f bellard
            gen_op_imulw_T0_T1();
1468 367e86e8 bellard
        }
1469 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1470 0ecfa993 bellard
        s->cc_op = CC_OP_MUL;
1471 367e86e8 bellard
        break;
1472 367e86e8 bellard
        
1473 367e86e8 bellard
        /**************************/
1474 367e86e8 bellard
        /* push/pop */
1475 367e86e8 bellard
    case 0x50 ... 0x57: /* push */
1476 927f621e bellard
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1477 367e86e8 bellard
        gen_op_pushl_T0();
1478 367e86e8 bellard
        break;
1479 367e86e8 bellard
    case 0x58 ... 0x5f: /* pop */
1480 367e86e8 bellard
        gen_op_popl_T0();
1481 927f621e bellard
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1482 367e86e8 bellard
        break;
1483 367e86e8 bellard
    case 0x68: /* push Iv */
1484 367e86e8 bellard
    case 0x6a:
1485 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1486 367e86e8 bellard
        if (b == 0x68)
1487 367e86e8 bellard
            val = insn_get(s, ot);
1488 367e86e8 bellard
        else
1489 367e86e8 bellard
            val = (int8_t)insn_get(s, OT_BYTE);
1490 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1491 367e86e8 bellard
        gen_op_pushl_T0();
1492 367e86e8 bellard
        break;
1493 367e86e8 bellard
    case 0x8f: /* pop Ev */
1494 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1495 367e86e8 bellard
        modrm = ldub(s->pc++);
1496 367e86e8 bellard
        gen_op_popl_T0();
1497 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1498 367e86e8 bellard
        break;
1499 367e86e8 bellard
    case 0xc9: /* leave */
1500 367e86e8 bellard
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1501 367e86e8 bellard
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1502 367e86e8 bellard
        gen_op_popl_T0();
1503 367e86e8 bellard
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1504 367e86e8 bellard
        break;
1505 367e86e8 bellard
        /**************************/
1506 367e86e8 bellard
        /* mov */
1507 367e86e8 bellard
    case 0x88:
1508 367e86e8 bellard
    case 0x89: /* mov Gv, Ev */
1509 367e86e8 bellard
        if ((b & 1) == 0)
1510 367e86e8 bellard
            ot = OT_BYTE;
1511 367e86e8 bellard
        else
1512 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1513 367e86e8 bellard
        modrm = ldub(s->pc++);
1514 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1515 367e86e8 bellard
        
1516 367e86e8 bellard
        /* generate a generic store */
1517 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1518 367e86e8 bellard
        break;
1519 367e86e8 bellard
    case 0xc6:
1520 367e86e8 bellard
    case 0xc7: /* mov Ev, Iv */
1521 367e86e8 bellard
        if ((b & 1) == 0)
1522 367e86e8 bellard
            ot = OT_BYTE;
1523 367e86e8 bellard
        else
1524 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1525 367e86e8 bellard
        modrm = ldub(s->pc++);
1526 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1527 0ecfa993 bellard
        if (mod != 3)
1528 0ecfa993 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1529 367e86e8 bellard
        val = insn_get(s, ot);
1530 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1531 0ecfa993 bellard
        if (mod != 3)
1532 0ecfa993 bellard
            gen_op_st_T0_A0[ot]();
1533 0ecfa993 bellard
        else
1534 0ecfa993 bellard
            gen_op_mov_reg_T0[ot][modrm & 7]();
1535 367e86e8 bellard
        break;
1536 367e86e8 bellard
    case 0x8a:
1537 367e86e8 bellard
    case 0x8b: /* mov Ev, Gv */
1538 367e86e8 bellard
        if ((b & 1) == 0)
1539 367e86e8 bellard
            ot = OT_BYTE;
1540 367e86e8 bellard
        else
1541 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1542 367e86e8 bellard
        modrm = ldub(s->pc++);
1543 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1544 367e86e8 bellard
        
1545 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1546 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1547 367e86e8 bellard
        break;
1548 367e86e8 bellard
1549 367e86e8 bellard
    case 0x1b6: /* movzbS Gv, Eb */
1550 367e86e8 bellard
    case 0x1b7: /* movzwS Gv, Eb */
1551 367e86e8 bellard
    case 0x1be: /* movsbS Gv, Eb */
1552 367e86e8 bellard
    case 0x1bf: /* movswS Gv, Eb */
1553 367e86e8 bellard
        {
1554 367e86e8 bellard
            int d_ot;
1555 367e86e8 bellard
            /* d_ot is the size of destination */
1556 367e86e8 bellard
            d_ot = dflag + OT_WORD;
1557 367e86e8 bellard
            /* ot is the size of source */
1558 367e86e8 bellard
            ot = (b & 1) + OT_BYTE;
1559 367e86e8 bellard
            modrm = ldub(s->pc++);
1560 367e86e8 bellard
            reg = ((modrm >> 3) & 7) + OR_EAX;
1561 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1562 367e86e8 bellard
            rm = modrm & 7;
1563 367e86e8 bellard
            
1564 367e86e8 bellard
            if (mod == 3) {
1565 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][rm]();
1566 367e86e8 bellard
                switch(ot | (b & 8)) {
1567 367e86e8 bellard
                case OT_BYTE:
1568 367e86e8 bellard
                    gen_op_movzbl_T0_T0();
1569 367e86e8 bellard
                    break;
1570 367e86e8 bellard
                case OT_BYTE | 8:
1571 367e86e8 bellard
                    gen_op_movsbl_T0_T0();
1572 367e86e8 bellard
                    break;
1573 367e86e8 bellard
                case OT_WORD:
1574 367e86e8 bellard
                    gen_op_movzwl_T0_T0();
1575 367e86e8 bellard
                    break;
1576 367e86e8 bellard
                default:
1577 367e86e8 bellard
                case OT_WORD | 8:
1578 367e86e8 bellard
                    gen_op_movswl_T0_T0();
1579 367e86e8 bellard
                    break;
1580 367e86e8 bellard
                }
1581 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
1582 367e86e8 bellard
            } else {
1583 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1584 367e86e8 bellard
                if (b & 8) {
1585 367e86e8 bellard
                    gen_op_lds_T0_A0[ot]();
1586 367e86e8 bellard
                } else {
1587 367e86e8 bellard
                    gen_op_ldu_T0_A0[ot]();
1588 367e86e8 bellard
                }
1589 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
1590 367e86e8 bellard
            }
1591 367e86e8 bellard
        }
1592 367e86e8 bellard
        break;
1593 367e86e8 bellard
1594 367e86e8 bellard
    case 0x8d: /* lea */
1595 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1596 367e86e8 bellard
        modrm = ldub(s->pc++);
1597 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1598 367e86e8 bellard
1599 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1600 367e86e8 bellard
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1601 367e86e8 bellard
        break;
1602 367e86e8 bellard
        
1603 367e86e8 bellard
    case 0xa0: /* mov EAX, Ov */
1604 367e86e8 bellard
    case 0xa1:
1605 367e86e8 bellard
    case 0xa2: /* mov Ov, EAX */
1606 367e86e8 bellard
    case 0xa3:
1607 367e86e8 bellard
        if ((b & 1) == 0)
1608 367e86e8 bellard
            ot = OT_BYTE;
1609 367e86e8 bellard
        else
1610 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1611 367e86e8 bellard
        if (s->aflag)
1612 367e86e8 bellard
            offset_addr = insn_get(s, OT_LONG);
1613 367e86e8 bellard
        else
1614 367e86e8 bellard
            offset_addr = insn_get(s, OT_WORD);
1615 4b74fe1f bellard
        gen_op_movl_A0_im(offset_addr);
1616 367e86e8 bellard
        if ((b & 2) == 0) {
1617 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1618 367e86e8 bellard
            gen_op_mov_reg_T0[ot][R_EAX]();
1619 367e86e8 bellard
        } else {
1620 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1621 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
1622 367e86e8 bellard
        }
1623 367e86e8 bellard
        break;
1624 367e86e8 bellard
1625 367e86e8 bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
1626 367e86e8 bellard
        val = insn_get(s, OT_BYTE);
1627 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1628 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1629 367e86e8 bellard
        break;
1630 367e86e8 bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
1631 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1632 367e86e8 bellard
        val = insn_get(s, ot);
1633 367e86e8 bellard
        reg = OR_EAX + (b & 7);
1634 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
1635 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1636 367e86e8 bellard
        break;
1637 367e86e8 bellard
1638 367e86e8 bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
1639 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1640 367e86e8 bellard
        reg = b & 7;
1641 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][reg]();
1642 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1643 367e86e8 bellard
        gen_op_mov_reg_T0[ot][R_EAX]();
1644 367e86e8 bellard
        gen_op_mov_reg_T1[ot][reg]();
1645 367e86e8 bellard
        break;
1646 367e86e8 bellard
    case 0x86:
1647 367e86e8 bellard
    case 0x87: /* xchg Ev, Gv */
1648 367e86e8 bellard
        if ((b & 1) == 0)
1649 367e86e8 bellard
            ot = OT_BYTE;
1650 367e86e8 bellard
        else
1651 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1652 367e86e8 bellard
        modrm = ldub(s->pc++);
1653 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1654 367e86e8 bellard
1655 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1656 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][reg]();
1657 367e86e8 bellard
        gen_op_ld_T1_A0[ot]();
1658 367e86e8 bellard
        gen_op_st_T0_A0[ot]();
1659 367e86e8 bellard
        gen_op_mov_reg_T1[ot][reg]();
1660 367e86e8 bellard
        break;
1661 367e86e8 bellard
        
1662 367e86e8 bellard
        /************************/
1663 367e86e8 bellard
        /* shifts */
1664 367e86e8 bellard
    case 0xc0:
1665 367e86e8 bellard
    case 0xc1:
1666 367e86e8 bellard
        /* shift Ev,Ib */
1667 367e86e8 bellard
        shift = 2;
1668 367e86e8 bellard
    grp2:
1669 367e86e8 bellard
        {
1670 367e86e8 bellard
            if ((b & 1) == 0)
1671 367e86e8 bellard
                ot = OT_BYTE;
1672 367e86e8 bellard
            else
1673 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1674 367e86e8 bellard
            
1675 367e86e8 bellard
            modrm = ldub(s->pc++);
1676 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1677 367e86e8 bellard
            rm = modrm & 7;
1678 367e86e8 bellard
            op = (modrm >> 3) & 7;
1679 367e86e8 bellard
            
1680 367e86e8 bellard
            if (mod != 3) {
1681 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1682 367e86e8 bellard
                gen_op_ld_T0_A0[ot]();
1683 367e86e8 bellard
                opreg = OR_TMP0;
1684 367e86e8 bellard
            } else {
1685 367e86e8 bellard
                opreg = rm + OR_EAX;
1686 367e86e8 bellard
            }
1687 367e86e8 bellard
1688 367e86e8 bellard
            /* simpler op */
1689 367e86e8 bellard
            if (shift == 0) {
1690 367e86e8 bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
1691 367e86e8 bellard
            } else {
1692 367e86e8 bellard
                if (shift == 2) {
1693 367e86e8 bellard
                    shift = ldub(s->pc++);
1694 367e86e8 bellard
                }
1695 367e86e8 bellard
                gen_shifti(s, op, ot, opreg, shift);
1696 367e86e8 bellard
            }
1697 367e86e8 bellard
1698 367e86e8 bellard
            if (mod != 3) {
1699 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1700 367e86e8 bellard
            }
1701 367e86e8 bellard
        }
1702 367e86e8 bellard
        break;
1703 367e86e8 bellard
    case 0xd0:
1704 367e86e8 bellard
    case 0xd1:
1705 367e86e8 bellard
        /* shift Ev,1 */
1706 367e86e8 bellard
        shift = 1;
1707 367e86e8 bellard
        goto grp2;
1708 367e86e8 bellard
    case 0xd2:
1709 367e86e8 bellard
    case 0xd3:
1710 367e86e8 bellard
        /* shift Ev,cl */
1711 367e86e8 bellard
        shift = 0;
1712 367e86e8 bellard
        goto grp2;
1713 367e86e8 bellard
1714 d57c4e01 bellard
    case 0x1a4: /* shld imm */
1715 d57c4e01 bellard
        op = 0;
1716 d57c4e01 bellard
        shift = 1;
1717 d57c4e01 bellard
        goto do_shiftd;
1718 d57c4e01 bellard
    case 0x1a5: /* shld cl */
1719 d57c4e01 bellard
        op = 0;
1720 d57c4e01 bellard
        shift = 0;
1721 d57c4e01 bellard
        goto do_shiftd;
1722 d57c4e01 bellard
    case 0x1ac: /* shrd imm */
1723 d57c4e01 bellard
        op = 1;
1724 d57c4e01 bellard
        shift = 1;
1725 d57c4e01 bellard
        goto do_shiftd;
1726 d57c4e01 bellard
    case 0x1ad: /* shrd cl */
1727 d57c4e01 bellard
        op = 1;
1728 d57c4e01 bellard
        shift = 0;
1729 d57c4e01 bellard
    do_shiftd:
1730 d57c4e01 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1731 d57c4e01 bellard
        modrm = ldub(s->pc++);
1732 d57c4e01 bellard
        mod = (modrm >> 6) & 3;
1733 d57c4e01 bellard
        rm = modrm & 7;
1734 d57c4e01 bellard
        reg = (modrm >> 3) & 7;
1735 d57c4e01 bellard
        
1736 d57c4e01 bellard
        if (mod != 3) {
1737 d57c4e01 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1738 d57c4e01 bellard
            gen_op_ld_T0_A0[ot]();
1739 d57c4e01 bellard
        } else {
1740 d57c4e01 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1741 d57c4e01 bellard
        }
1742 d57c4e01 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
1743 d57c4e01 bellard
        
1744 d57c4e01 bellard
        if (shift) {
1745 d57c4e01 bellard
            val = ldub(s->pc++);
1746 d57c4e01 bellard
            val &= 0x1f;
1747 d57c4e01 bellard
            if (val) {
1748 d57c4e01 bellard
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1749 d57c4e01 bellard
                if (op == 0 && ot != OT_WORD)
1750 d57c4e01 bellard
                    s->cc_op = CC_OP_SHLB + ot;
1751 d57c4e01 bellard
                else
1752 d57c4e01 bellard
                    s->cc_op = CC_OP_SARB + ot;
1753 d57c4e01 bellard
            }
1754 d57c4e01 bellard
        } else {
1755 d57c4e01 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
1756 d57c4e01 bellard
                gen_op_set_cc_op(s->cc_op);
1757 d57c4e01 bellard
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1758 d57c4e01 bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1759 d57c4e01 bellard
        }
1760 d57c4e01 bellard
        if (mod != 3) {
1761 d57c4e01 bellard
            gen_op_st_T0_A0[ot]();
1762 d57c4e01 bellard
        } else {
1763 d57c4e01 bellard
            gen_op_mov_reg_T0[ot][rm]();
1764 d57c4e01 bellard
        }
1765 d57c4e01 bellard
        break;
1766 d57c4e01 bellard
1767 367e86e8 bellard
        /************************/
1768 367e86e8 bellard
        /* floats */
1769 367e86e8 bellard
    case 0xd8 ... 0xdf: 
1770 367e86e8 bellard
        modrm = ldub(s->pc++);
1771 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1772 367e86e8 bellard
        rm = modrm & 7;
1773 367e86e8 bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1774 367e86e8 bellard
        
1775 367e86e8 bellard
        if (mod != 3) {
1776 367e86e8 bellard
            /* memory op */
1777 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1778 367e86e8 bellard
            switch(op) {
1779 367e86e8 bellard
            case 0x00 ... 0x07: /* fxxxs */
1780 367e86e8 bellard
            case 0x10 ... 0x17: /* fixxxl */
1781 367e86e8 bellard
            case 0x20 ... 0x27: /* fxxxl */
1782 367e86e8 bellard
            case 0x30 ... 0x37: /* fixxx */
1783 367e86e8 bellard
                {
1784 927f621e bellard
                    int op1;
1785 927f621e bellard
                    op1 = op & 7;
1786 367e86e8 bellard
1787 367e86e8 bellard
                    switch(op >> 4) {
1788 367e86e8 bellard
                    case 0:
1789 927f621e bellard
                        gen_op_flds_FT0_A0();
1790 367e86e8 bellard
                        break;
1791 367e86e8 bellard
                    case 1:
1792 927f621e bellard
                        gen_op_fildl_FT0_A0();
1793 367e86e8 bellard
                        break;
1794 367e86e8 bellard
                    case 2:
1795 927f621e bellard
                        gen_op_fldl_FT0_A0();
1796 367e86e8 bellard
                        break;
1797 367e86e8 bellard
                    case 3:
1798 367e86e8 bellard
                    default:
1799 927f621e bellard
                        gen_op_fild_FT0_A0();
1800 367e86e8 bellard
                        break;
1801 367e86e8 bellard
                    }
1802 367e86e8 bellard
                    
1803 927f621e bellard
                    gen_op_fp_arith_ST0_FT0[op1]();
1804 927f621e bellard
                    if (op1 == 3) {
1805 367e86e8 bellard
                        /* fcomp needs pop */
1806 927f621e bellard
                        gen_op_fpop();
1807 367e86e8 bellard
                    }
1808 367e86e8 bellard
                }
1809 367e86e8 bellard
                break;
1810 367e86e8 bellard
            case 0x08: /* flds */
1811 367e86e8 bellard
            case 0x0a: /* fsts */
1812 367e86e8 bellard
            case 0x0b: /* fstps */
1813 367e86e8 bellard
            case 0x18: /* fildl */
1814 367e86e8 bellard
            case 0x1a: /* fistl */
1815 367e86e8 bellard
            case 0x1b: /* fistpl */
1816 367e86e8 bellard
            case 0x28: /* fldl */
1817 367e86e8 bellard
            case 0x2a: /* fstl */
1818 367e86e8 bellard
            case 0x2b: /* fstpl */
1819 367e86e8 bellard
            case 0x38: /* filds */
1820 367e86e8 bellard
            case 0x3a: /* fists */
1821 367e86e8 bellard
            case 0x3b: /* fistps */
1822 367e86e8 bellard
                
1823 367e86e8 bellard
                switch(op & 7) {
1824 367e86e8 bellard
                case 0:
1825 927f621e bellard
                    gen_op_fpush();
1826 927f621e bellard
                    switch(op >> 4) {
1827 927f621e bellard
                    case 0:
1828 927f621e bellard
                        gen_op_flds_ST0_A0();
1829 927f621e bellard
                        break;
1830 927f621e bellard
                    case 1:
1831 927f621e bellard
                        gen_op_fildl_ST0_A0();
1832 927f621e bellard
                        break;
1833 927f621e bellard
                    case 2:
1834 927f621e bellard
                        gen_op_fldl_ST0_A0();
1835 927f621e bellard
                        break;
1836 927f621e bellard
                    case 3:
1837 927f621e bellard
                    default:
1838 927f621e bellard
                        gen_op_fild_ST0_A0();
1839 927f621e bellard
                        break;
1840 367e86e8 bellard
                    }
1841 367e86e8 bellard
                    break;
1842 367e86e8 bellard
                default:
1843 927f621e bellard
                    switch(op >> 4) {
1844 927f621e bellard
                    case 0:
1845 927f621e bellard
                        gen_op_fsts_ST0_A0();
1846 927f621e bellard
                        break;
1847 927f621e bellard
                    case 1:
1848 927f621e bellard
                        gen_op_fistl_ST0_A0();
1849 927f621e bellard
                        break;
1850 927f621e bellard
                    case 2:
1851 927f621e bellard
                        gen_op_fstl_ST0_A0();
1852 927f621e bellard
                        break;
1853 927f621e bellard
                    case 3:
1854 927f621e bellard
                    default:
1855 927f621e bellard
                        gen_op_fist_ST0_A0();
1856 927f621e bellard
                        break;
1857 367e86e8 bellard
                    }
1858 367e86e8 bellard
                    if ((op & 7) == 3)
1859 927f621e bellard
                        gen_op_fpop();
1860 367e86e8 bellard
                    break;
1861 367e86e8 bellard
                }
1862 367e86e8 bellard
                break;
1863 4b74fe1f bellard
            case 0x0d: /* fldcw mem */
1864 4b74fe1f bellard
                gen_op_fldcw_A0();
1865 4b74fe1f bellard
                break;
1866 4b74fe1f bellard
            case 0x0f: /* fnstcw mem */
1867 4b74fe1f bellard
                gen_op_fnstcw_A0();
1868 4b74fe1f bellard
                break;
1869 367e86e8 bellard
            case 0x2f: /* fnstsw mem */
1870 4b74fe1f bellard
                gen_op_fnstsw_A0();
1871 367e86e8 bellard
                break;
1872 367e86e8 bellard
            case 0x3c: /* fbld */
1873 367e86e8 bellard
            case 0x3e: /* fbstp */
1874 367e86e8 bellard
                error("float BCD not hanlded");
1875 367e86e8 bellard
                return -1;
1876 367e86e8 bellard
            case 0x3d: /* fildll */
1877 927f621e bellard
                gen_op_fpush();
1878 927f621e bellard
                gen_op_fildll_ST0_A0();
1879 367e86e8 bellard
                break;
1880 367e86e8 bellard
            case 0x3f: /* fistpll */
1881 927f621e bellard
                gen_op_fistll_ST0_A0();
1882 927f621e bellard
                gen_op_fpop();
1883 367e86e8 bellard
                break;
1884 367e86e8 bellard
            default:
1885 4b74fe1f bellard
                error("unhandled memory FP [op=0x%02x]\n", op);
1886 367e86e8 bellard
                return -1;
1887 367e86e8 bellard
            }
1888 367e86e8 bellard
        } else {
1889 367e86e8 bellard
            /* register float ops */
1890 927f621e bellard
            opreg = rm;
1891 367e86e8 bellard
1892 367e86e8 bellard
            switch(op) {
1893 367e86e8 bellard
            case 0x08: /* fld sti */
1894 927f621e bellard
                gen_op_fpush();
1895 927f621e bellard
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1896 367e86e8 bellard
                break;
1897 367e86e8 bellard
            case 0x09: /* fxchg sti */
1898 927f621e bellard
                gen_op_fxchg_ST0_STN((opreg + 1) & 7);
1899 367e86e8 bellard
                break;
1900 367e86e8 bellard
            case 0x0a: /* grp d9/2 */
1901 367e86e8 bellard
                switch(rm) {
1902 367e86e8 bellard
                case 0: /* fnop */
1903 367e86e8 bellard
                    break;
1904 367e86e8 bellard
                default:
1905 367e86e8 bellard
                    error("unhandled FP GRP d9/2\n");
1906 367e86e8 bellard
                    return -1;
1907 367e86e8 bellard
                }
1908 367e86e8 bellard
                break;
1909 367e86e8 bellard
            case 0x0c: /* grp d9/4 */
1910 367e86e8 bellard
                switch(rm) {
1911 367e86e8 bellard
                case 0: /* fchs */
1912 927f621e bellard
                    gen_op_fchs_ST0();
1913 367e86e8 bellard
                    break;
1914 367e86e8 bellard
                case 1: /* fabs */
1915 927f621e bellard
                    gen_op_fabs_ST0();
1916 367e86e8 bellard
                    break;
1917 367e86e8 bellard
                case 4: /* ftst */
1918 927f621e bellard
                    gen_op_fldz_FT0();
1919 927f621e bellard
                    gen_op_fcom_ST0_FT0();
1920 367e86e8 bellard
                    break;
1921 367e86e8 bellard
                case 5: /* fxam */
1922 927f621e bellard
                    gen_op_fxam_ST0();
1923 367e86e8 bellard
                    break;
1924 367e86e8 bellard
                default:
1925 367e86e8 bellard
                    return -1;
1926 367e86e8 bellard
                }
1927 367e86e8 bellard
                break;
1928 367e86e8 bellard
            case 0x0d: /* grp d9/5 */
1929 367e86e8 bellard
                {
1930 927f621e bellard
                    switch(rm) {
1931 927f621e bellard
                    case 0:
1932 927f621e bellard
                        gen_op_fld1_ST0();
1933 927f621e bellard
                        break;
1934 927f621e bellard
                    case 1:
1935 927f621e bellard
                        gen_op_fld2t_ST0();
1936 927f621e bellard
                        break;
1937 927f621e bellard
                    case 2:
1938 927f621e bellard
                        gen_op_fld2e_ST0();
1939 927f621e bellard
                        break;
1940 927f621e bellard
                    case 3:
1941 927f621e bellard
                        gen_op_fldpi_ST0();
1942 927f621e bellard
                        break;
1943 927f621e bellard
                    case 4:
1944 927f621e bellard
                        gen_op_fldlg2_ST0();
1945 927f621e bellard
                        break;
1946 927f621e bellard
                    case 5:
1947 927f621e bellard
                        gen_op_fldln2_ST0();
1948 927f621e bellard
                        break;
1949 927f621e bellard
                    case 6:
1950 927f621e bellard
                        gen_op_fldz_ST0();
1951 927f621e bellard
                        break;
1952 927f621e bellard
                    default:
1953 367e86e8 bellard
                        return -1;
1954 367e86e8 bellard
                    }
1955 367e86e8 bellard
                }
1956 367e86e8 bellard
                break;
1957 367e86e8 bellard
            case 0x0e: /* grp d9/6 */
1958 367e86e8 bellard
                switch(rm) {
1959 367e86e8 bellard
                case 0: /* f2xm1 */
1960 927f621e bellard
                    gen_op_f2xm1();
1961 367e86e8 bellard
                    break;
1962 367e86e8 bellard
                case 1: /* fyl2x */
1963 927f621e bellard
                    gen_op_fyl2x();
1964 367e86e8 bellard
                    break;
1965 367e86e8 bellard
                case 2: /* fptan */
1966 927f621e bellard
                    gen_op_fptan();
1967 367e86e8 bellard
                    break;
1968 367e86e8 bellard
                case 3: /* fpatan */
1969 927f621e bellard
                    gen_op_fpatan();
1970 367e86e8 bellard
                    break;
1971 367e86e8 bellard
                case 4: /* fxtract */
1972 927f621e bellard
                    gen_op_fxtract();
1973 367e86e8 bellard
                    break;
1974 367e86e8 bellard
                case 5: /* fprem1 */
1975 927f621e bellard
                    gen_op_fprem1();
1976 367e86e8 bellard
                    break;
1977 367e86e8 bellard
                case 6: /* fdecstp */
1978 927f621e bellard
                    gen_op_fdecstp();
1979 367e86e8 bellard
                    break;
1980 367e86e8 bellard
                default:
1981 927f621e bellard
                case 7: /* fincstp */
1982 927f621e bellard
                    gen_op_fincstp();
1983 367e86e8 bellard
                    break;
1984 367e86e8 bellard
                }
1985 367e86e8 bellard
                break;
1986 367e86e8 bellard
            case 0x0f: /* grp d9/7 */
1987 367e86e8 bellard
                switch(rm) {
1988 367e86e8 bellard
                case 0: /* fprem */
1989 927f621e bellard
                    gen_op_fprem();
1990 367e86e8 bellard
                    break;
1991 367e86e8 bellard
                case 1: /* fyl2xp1 */
1992 927f621e bellard
                    gen_op_fyl2xp1();
1993 927f621e bellard
                    break;
1994 927f621e bellard
                case 2: /* fsqrt */
1995 927f621e bellard
                    gen_op_fsqrt();
1996 367e86e8 bellard
                    break;
1997 367e86e8 bellard
                case 3: /* fsincos */
1998 927f621e bellard
                    gen_op_fsincos();
1999 367e86e8 bellard
                    break;
2000 367e86e8 bellard
                case 5: /* fscale */
2001 927f621e bellard
                    gen_op_fscale();
2002 367e86e8 bellard
                    break;
2003 367e86e8 bellard
                case 4: /* frndint */
2004 927f621e bellard
                    gen_op_frndint();
2005 927f621e bellard
                    break;
2006 367e86e8 bellard
                case 6: /* fsin */
2007 927f621e bellard
                    gen_op_fsin();
2008 927f621e bellard
                    break;
2009 367e86e8 bellard
                default:
2010 367e86e8 bellard
                case 7: /* fcos */
2011 927f621e bellard
                    gen_op_fcos();
2012 367e86e8 bellard
                    break;
2013 367e86e8 bellard
                }
2014 367e86e8 bellard
                break;
2015 367e86e8 bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2016 367e86e8 bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2017 367e86e8 bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2018 367e86e8 bellard
                {
2019 927f621e bellard
                    int op1;
2020 367e86e8 bellard
                    
2021 927f621e bellard
                    op1 = op & 7;
2022 367e86e8 bellard
                    if (op >= 0x20) {
2023 927f621e bellard
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2024 367e86e8 bellard
                    } else {
2025 927f621e bellard
                        gen_op_fmov_FT0_STN(opreg);
2026 927f621e bellard
                        gen_op_fp_arith_ST0_FT0[op1]();
2027 367e86e8 bellard
                    }
2028 367e86e8 bellard
                    if (op >= 0x30)
2029 927f621e bellard
                        gen_op_fpop();
2030 367e86e8 bellard
                }
2031 367e86e8 bellard
                break;
2032 367e86e8 bellard
            case 0x02: /* fcom */
2033 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2034 927f621e bellard
                gen_op_fcom_ST0_FT0();
2035 367e86e8 bellard
                break;
2036 367e86e8 bellard
            case 0x03: /* fcomp */
2037 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2038 927f621e bellard
                gen_op_fcom_ST0_FT0();
2039 927f621e bellard
                gen_op_fpop();
2040 367e86e8 bellard
                break;
2041 367e86e8 bellard
            case 0x15: /* da/5 */
2042 367e86e8 bellard
                switch(rm) {
2043 367e86e8 bellard
                case 1: /* fucompp */
2044 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2045 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2046 927f621e bellard
                    gen_op_fpop();
2047 927f621e bellard
                    gen_op_fpop();
2048 367e86e8 bellard
                    break;
2049 367e86e8 bellard
                default:
2050 367e86e8 bellard
                    return -1;
2051 367e86e8 bellard
                }
2052 367e86e8 bellard
                break;
2053 367e86e8 bellard
            case 0x2a: /* fst sti */
2054 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2055 367e86e8 bellard
                break;
2056 367e86e8 bellard
            case 0x2b: /* fstp sti */
2057 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2058 927f621e bellard
                gen_op_fpop();
2059 367e86e8 bellard
                break;
2060 367e86e8 bellard
            case 0x33: /* de/3 */
2061 367e86e8 bellard
                switch(rm) {
2062 367e86e8 bellard
                case 1: /* fcompp */
2063 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2064 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2065 927f621e bellard
                    gen_op_fpop();
2066 927f621e bellard
                    gen_op_fpop();
2067 367e86e8 bellard
                    break;
2068 367e86e8 bellard
                default:
2069 367e86e8 bellard
                    return -1;
2070 367e86e8 bellard
                }
2071 367e86e8 bellard
                break;
2072 367e86e8 bellard
            case 0x3c: /* df/4 */
2073 367e86e8 bellard
                switch(rm) {
2074 927f621e bellard
#if 0
2075 367e86e8 bellard
                case 0:
2076 367e86e8 bellard
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
2077 367e86e8 bellard
                    break;
2078 927f621e bellard
#endif
2079 367e86e8 bellard
                default:
2080 d57c4e01 bellard
                    error("unhandled FP df/4\n");
2081 367e86e8 bellard
                    return -1;
2082 367e86e8 bellard
                }
2083 367e86e8 bellard
                break;
2084 367e86e8 bellard
            default:
2085 367e86e8 bellard
                error("unhandled FP\n");
2086 367e86e8 bellard
                return -1;
2087 367e86e8 bellard
            }
2088 367e86e8 bellard
        }
2089 367e86e8 bellard
        break;
2090 367e86e8 bellard
        /************************/
2091 367e86e8 bellard
        /* string ops */
2092 367e86e8 bellard
    case 0xa4: /* movsS */
2093 367e86e8 bellard
    case 0xa5:
2094 367e86e8 bellard
        if ((b & 1) == 0)
2095 367e86e8 bellard
            ot = OT_BYTE;
2096 367e86e8 bellard
        else
2097 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2098 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2099 367e86e8 bellard
            gen_op_movs[3 + ot]();
2100 367e86e8 bellard
        } else {
2101 367e86e8 bellard
            gen_op_movs[ot]();
2102 367e86e8 bellard
        }
2103 367e86e8 bellard
        break;
2104 367e86e8 bellard
        
2105 367e86e8 bellard
    case 0xaa: /* stosS */
2106 367e86e8 bellard
    case 0xab:
2107 367e86e8 bellard
        if ((b & 1) == 0)
2108 367e86e8 bellard
            ot = OT_BYTE;
2109 367e86e8 bellard
        else
2110 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2111 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2112 367e86e8 bellard
            gen_op_stos[3 + ot]();
2113 367e86e8 bellard
        } else {
2114 367e86e8 bellard
            gen_op_stos[ot]();
2115 367e86e8 bellard
        }
2116 367e86e8 bellard
        break;
2117 367e86e8 bellard
    case 0xac: /* lodsS */
2118 367e86e8 bellard
    case 0xad:
2119 367e86e8 bellard
        if ((b & 1) == 0)
2120 367e86e8 bellard
            ot = OT_BYTE;
2121 367e86e8 bellard
        else
2122 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2123 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2124 367e86e8 bellard
            gen_op_lods[3 + ot]();
2125 367e86e8 bellard
        } else {
2126 367e86e8 bellard
            gen_op_lods[ot]();
2127 367e86e8 bellard
        }
2128 367e86e8 bellard
        break;
2129 367e86e8 bellard
    case 0xae: /* scasS */
2130 367e86e8 bellard
    case 0xaf:
2131 367e86e8 bellard
        if ((b & 1) == 0)
2132 367e86e8 bellard
            ot = OT_BYTE;
2133 367e86e8 bellard
        else
2134 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2135 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2136 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2137 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2138 367e86e8 bellard
            gen_op_scas[6 + ot]();
2139 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2140 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2141 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2142 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2143 367e86e8 bellard
            gen_op_scas[3 + ot]();
2144 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2145 367e86e8 bellard
        } else {
2146 367e86e8 bellard
            gen_op_scas[ot]();
2147 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2148 367e86e8 bellard
        }
2149 367e86e8 bellard
        break;
2150 367e86e8 bellard
2151 367e86e8 bellard
    case 0xa6: /* cmpsS */
2152 367e86e8 bellard
    case 0xa7:
2153 367e86e8 bellard
        if ((b & 1) == 0)
2154 367e86e8 bellard
            ot = OT_BYTE;
2155 367e86e8 bellard
        else
2156 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2157 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2158 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2159 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2160 367e86e8 bellard
            gen_op_cmps[6 + ot]();
2161 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2162 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2163 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2164 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2165 367e86e8 bellard
            gen_op_cmps[3 + ot]();
2166 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2167 367e86e8 bellard
        } else {
2168 367e86e8 bellard
            gen_op_cmps[ot]();
2169 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2170 367e86e8 bellard
        }
2171 367e86e8 bellard
        break;
2172 367e86e8 bellard
        
2173 ba1c6e37 bellard
        /************************/
2174 ba1c6e37 bellard
        /* port I/O */
2175 367e86e8 bellard
    case 0x6c: /* insS */
2176 367e86e8 bellard
    case 0x6d:
2177 367e86e8 bellard
        if ((b & 1) == 0)
2178 367e86e8 bellard
            ot = OT_BYTE;
2179 367e86e8 bellard
        else
2180 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2181 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2182 367e86e8 bellard
            gen_op_ins[3 + ot]();
2183 367e86e8 bellard
        } else {
2184 367e86e8 bellard
            gen_op_ins[ot]();
2185 367e86e8 bellard
        }
2186 367e86e8 bellard
        break;
2187 367e86e8 bellard
    case 0x6e: /* outsS */
2188 367e86e8 bellard
    case 0x6f:
2189 367e86e8 bellard
        if ((b & 1) == 0)
2190 367e86e8 bellard
            ot = OT_BYTE;
2191 367e86e8 bellard
        else
2192 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2193 367e86e8 bellard
        if (prefixes & PREFIX_REPZ) {
2194 367e86e8 bellard
            gen_op_outs[3 + ot]();
2195 367e86e8 bellard
        } else {
2196 367e86e8 bellard
            gen_op_outs[ot]();
2197 367e86e8 bellard
        }
2198 367e86e8 bellard
        break;
2199 ba1c6e37 bellard
    case 0xe4:
2200 ba1c6e37 bellard
    case 0xe5:
2201 ba1c6e37 bellard
        if ((b & 1) == 0)
2202 ba1c6e37 bellard
            ot = OT_BYTE;
2203 ba1c6e37 bellard
        else
2204 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2205 ba1c6e37 bellard
        val = ldub(s->pc++);
2206 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2207 ba1c6e37 bellard
        gen_op_in[ot]();
2208 ba1c6e37 bellard
        gen_op_mov_reg_T1[ot][R_EAX]();
2209 ba1c6e37 bellard
        break;
2210 ba1c6e37 bellard
    case 0xe6:
2211 ba1c6e37 bellard
    case 0xe7:
2212 ba1c6e37 bellard
        if ((b & 1) == 0)
2213 ba1c6e37 bellard
            ot = OT_BYTE;
2214 ba1c6e37 bellard
        else
2215 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2216 ba1c6e37 bellard
        val = ldub(s->pc++);
2217 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2218 ba1c6e37 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2219 ba1c6e37 bellard
        gen_op_out[ot]();
2220 ba1c6e37 bellard
        break;
2221 ba1c6e37 bellard
    case 0xec:
2222 ba1c6e37 bellard
    case 0xed:
2223 ba1c6e37 bellard
        if ((b & 1) == 0)
2224 ba1c6e37 bellard
            ot = OT_BYTE;
2225 ba1c6e37 bellard
        else
2226 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2227 ba1c6e37 bellard
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2228 ba1c6e37 bellard
        gen_op_in[ot]();
2229 ba1c6e37 bellard
        gen_op_mov_reg_T1[ot][R_EAX]();
2230 ba1c6e37 bellard
        break;
2231 ba1c6e37 bellard
    case 0xee:
2232 ba1c6e37 bellard
    case 0xef:
2233 ba1c6e37 bellard
        if ((b & 1) == 0)
2234 ba1c6e37 bellard
            ot = OT_BYTE;
2235 ba1c6e37 bellard
        else
2236 ba1c6e37 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2237 ba1c6e37 bellard
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2238 ba1c6e37 bellard
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2239 ba1c6e37 bellard
        gen_op_out[ot]();
2240 ba1c6e37 bellard
        break;
2241 367e86e8 bellard
2242 367e86e8 bellard
        /************************/
2243 367e86e8 bellard
        /* control */
2244 367e86e8 bellard
    case 0xc2: /* ret im */
2245 367e86e8 bellard
        /* XXX: handle stack pop ? */
2246 367e86e8 bellard
        val = ldsw(s->pc);
2247 367e86e8 bellard
        s->pc += 2;
2248 367e86e8 bellard
        gen_op_popl_T0();
2249 367e86e8 bellard
        gen_op_addl_ESP_im(val);
2250 367e86e8 bellard
        gen_op_jmp_T0();
2251 0ecfa993 bellard
        *is_jmp_ptr = 1;
2252 367e86e8 bellard
        break;
2253 367e86e8 bellard
    case 0xc3: /* ret */
2254 367e86e8 bellard
        gen_op_popl_T0();
2255 367e86e8 bellard
        gen_op_jmp_T0();
2256 0ecfa993 bellard
        *is_jmp_ptr = 1;
2257 367e86e8 bellard
        break;
2258 367e86e8 bellard
    case 0xe8: /* call */
2259 367e86e8 bellard
        val = insn_get(s, OT_LONG);
2260 367e86e8 bellard
        val += (long)s->pc;
2261 ba1c6e37 bellard
        gen_op_movl_T1_im((long)s->pc);
2262 367e86e8 bellard
        gen_op_pushl_T1();
2263 367e86e8 bellard
        gen_op_jmp_im(val);
2264 0ecfa993 bellard
        *is_jmp_ptr = 1;
2265 367e86e8 bellard
        break;
2266 367e86e8 bellard
    case 0xe9: /* jmp */
2267 367e86e8 bellard
        val = insn_get(s, OT_LONG);
2268 367e86e8 bellard
        val += (long)s->pc;
2269 367e86e8 bellard
        gen_op_jmp_im(val);
2270 0ecfa993 bellard
        *is_jmp_ptr = 1;
2271 367e86e8 bellard
        break;
2272 367e86e8 bellard
    case 0xeb: /* jmp Jb */
2273 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
2274 367e86e8 bellard
        val += (long)s->pc;
2275 367e86e8 bellard
        gen_op_jmp_im(val);
2276 0ecfa993 bellard
        *is_jmp_ptr = 1;
2277 367e86e8 bellard
        break;
2278 367e86e8 bellard
    case 0x70 ... 0x7f: /* jcc Jb */
2279 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
2280 367e86e8 bellard
        val += (long)s->pc;
2281 367e86e8 bellard
        goto do_jcc;
2282 367e86e8 bellard
    case 0x180 ... 0x18f: /* jcc Jv */
2283 367e86e8 bellard
        if (dflag) {
2284 367e86e8 bellard
            val = insn_get(s, OT_LONG);
2285 367e86e8 bellard
        } else {
2286 367e86e8 bellard
            val = (int16_t)insn_get(s, OT_WORD); 
2287 367e86e8 bellard
        }
2288 367e86e8 bellard
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2289 367e86e8 bellard
    do_jcc:
2290 367e86e8 bellard
        gen_jcc(s, b, val);
2291 0ecfa993 bellard
        *is_jmp_ptr = 1;
2292 367e86e8 bellard
        break;
2293 367e86e8 bellard
2294 367e86e8 bellard
    case 0x190 ... 0x19f:
2295 367e86e8 bellard
        modrm = ldub(s->pc++);
2296 367e86e8 bellard
        gen_setcc(s, b);
2297 367e86e8 bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2298 367e86e8 bellard
        break;
2299 367e86e8 bellard
2300 367e86e8 bellard
        /************************/
2301 367e86e8 bellard
        /* flags */
2302 367e86e8 bellard
    case 0x9c: /* pushf */
2303 367e86e8 bellard
        gen_op_movl_T0_eflags();
2304 367e86e8 bellard
        gen_op_pushl_T0();
2305 367e86e8 bellard
        break;
2306 367e86e8 bellard
    case 0x9d: /* popf */
2307 367e86e8 bellard
        gen_op_popl_T0();
2308 367e86e8 bellard
        gen_op_movl_eflags_T0();
2309 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2310 367e86e8 bellard
        break;
2311 367e86e8 bellard
    case 0x9e: /* sahf */
2312 367e86e8 bellard
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2313 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2314 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2315 367e86e8 bellard
        gen_op_movb_eflags_T0();
2316 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2317 367e86e8 bellard
        break;
2318 367e86e8 bellard
    case 0x9f: /* lahf */
2319 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2320 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2321 367e86e8 bellard
        gen_op_movl_T0_eflags();
2322 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2323 367e86e8 bellard
        break;
2324 367e86e8 bellard
    case 0xf5: /* cmc */
2325 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2326 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2327 367e86e8 bellard
        gen_op_cmc();
2328 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2329 367e86e8 bellard
        break;
2330 367e86e8 bellard
    case 0xf8: /* clc */
2331 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2332 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2333 367e86e8 bellard
        gen_op_clc();
2334 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2335 367e86e8 bellard
        break;
2336 367e86e8 bellard
    case 0xf9: /* stc */
2337 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2338 367e86e8 bellard
            op_set_cc_op(s->cc_op);
2339 367e86e8 bellard
        gen_op_stc();
2340 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
2341 367e86e8 bellard
        break;
2342 367e86e8 bellard
    case 0xfc: /* cld */
2343 367e86e8 bellard
        gen_op_cld();
2344 367e86e8 bellard
        break;
2345 367e86e8 bellard
    case 0xfd: /* std */
2346 367e86e8 bellard
        gen_op_std();
2347 367e86e8 bellard
        break;
2348 367e86e8 bellard
2349 367e86e8 bellard
        /************************/
2350 4b74fe1f bellard
        /* bit operations */
2351 4b74fe1f bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
2352 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
2353 4b74fe1f bellard
        modrm = ldub(s->pc++);
2354 4b74fe1f bellard
        op = (modrm >> 3) & 7;
2355 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
2356 4b74fe1f bellard
        rm = modrm & 7;
2357 4b74fe1f bellard
        if (mod != 3) {
2358 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2359 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
2360 4b74fe1f bellard
        } else {
2361 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
2362 4b74fe1f bellard
        }
2363 4b74fe1f bellard
        /* load shift */
2364 4b74fe1f bellard
        val = ldub(s->pc++);
2365 4b74fe1f bellard
        gen_op_movl_T1_im(val);
2366 4b74fe1f bellard
        if (op < 4)
2367 4b74fe1f bellard
            return -1;
2368 4b74fe1f bellard
        op -= 4;
2369 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2370 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
2371 4b74fe1f bellard
        if (op != 0) {
2372 4b74fe1f bellard
            if (mod != 3)
2373 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
2374 4b74fe1f bellard
            else
2375 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
2376 4b74fe1f bellard
        }
2377 4b74fe1f bellard
        break;
2378 4b74fe1f bellard
    case 0x1a3: /* bt Gv, Ev */
2379 4b74fe1f bellard
        op = 0;
2380 4b74fe1f bellard
        goto do_btx;
2381 4b74fe1f bellard
    case 0x1ab: /* bts */
2382 4b74fe1f bellard
        op = 1;
2383 4b74fe1f bellard
        goto do_btx;
2384 4b74fe1f bellard
    case 0x1b3: /* btr */
2385 4b74fe1f bellard
        op = 2;
2386 4b74fe1f bellard
        goto do_btx;
2387 4b74fe1f bellard
    case 0x1bb: /* btc */
2388 4b74fe1f bellard
        op = 3;
2389 4b74fe1f bellard
    do_btx:
2390 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
2391 4b74fe1f bellard
        modrm = ldub(s->pc++);
2392 4b74fe1f bellard
        reg = (modrm >> 3) & 7;
2393 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
2394 4b74fe1f bellard
        rm = modrm & 7;
2395 4b74fe1f bellard
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
2396 4b74fe1f bellard
        if (mod != 3) {
2397 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2398 4b74fe1f bellard
            /* specific case: we need to add a displacement */
2399 4b74fe1f bellard
            if (ot == OT_WORD)
2400 4b74fe1f bellard
                gen_op_add_bitw_A0_T1();
2401 4b74fe1f bellard
            else
2402 4b74fe1f bellard
                gen_op_add_bitl_A0_T1();
2403 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
2404 4b74fe1f bellard
        } else {
2405 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
2406 4b74fe1f bellard
        }
2407 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2408 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
2409 4b74fe1f bellard
        if (op != 0) {
2410 4b74fe1f bellard
            if (mod != 3)
2411 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
2412 4b74fe1f bellard
            else
2413 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
2414 4b74fe1f bellard
        }
2415 4b74fe1f bellard
        break;
2416 4b74fe1f bellard
2417 4b74fe1f bellard
        /************************/
2418 367e86e8 bellard
        /* misc */
2419 367e86e8 bellard
    case 0x90: /* nop */
2420 367e86e8 bellard
        break;
2421 0ecfa993 bellard
    case 0xcc: /* int3 */
2422 0ecfa993 bellard
        gen_op_int3((long)pc_start);
2423 0ecfa993 bellard
        *is_jmp_ptr = 1;
2424 0ecfa993 bellard
        break;
2425 0ecfa993 bellard
    case 0xcd: /* int N */
2426 0ecfa993 bellard
        val = ldub(s->pc++);
2427 0ecfa993 bellard
        /* XXX: currently we ignore the interrupt number */
2428 0ecfa993 bellard
        gen_op_int_im((long)pc_start);
2429 0ecfa993 bellard
        *is_jmp_ptr = 1;
2430 0ecfa993 bellard
        break;
2431 0ecfa993 bellard
    case 0xce: /* into */
2432 0ecfa993 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2433 0ecfa993 bellard
            gen_op_set_cc_op(s->cc_op);
2434 0ecfa993 bellard
        gen_op_into((long)pc_start, (long)s->pc);
2435 0ecfa993 bellard
        *is_jmp_ptr = 1;
2436 0ecfa993 bellard
        break;
2437 4b74fe1f bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
2438 4b74fe1f bellard
      reg = b & 7;
2439 4b74fe1f bellard
      gen_op_mov_TN_reg[OT_LONG][0][reg]();
2440 4b74fe1f bellard
      gen_op_bswapl_T0();
2441 4b74fe1f bellard
      gen_op_mov_reg_T0[OT_LONG][reg]();
2442 4b74fe1f bellard
      break;
2443 4b74fe1f bellard
      
2444 0ecfa993 bellard
#if 0
2445 367e86e8 bellard
    case 0x1a2: /* cpuid */
2446 367e86e8 bellard
        gen_insn0(OP_ASM);
2447 367e86e8 bellard
        break;
2448 367e86e8 bellard
#endif
2449 367e86e8 bellard
    default:
2450 367e86e8 bellard
        error("unknown opcode %x", b);
2451 367e86e8 bellard
        return -1;
2452 367e86e8 bellard
    }
2453 367e86e8 bellard
    return (long)s->pc;
2454 367e86e8 bellard
}
2455 367e86e8 bellard
2456 ba1c6e37 bellard
/* return the next pc */
2457 ba1c6e37 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
2458 ba1c6e37 bellard
                     uint8_t *pc_start)
2459 ba1c6e37 bellard
{
2460 ba1c6e37 bellard
    DisasContext dc1, *dc = &dc1;
2461 0ecfa993 bellard
    int is_jmp;
2462 ba1c6e37 bellard
    long ret;
2463 0ecfa993 bellard
#ifdef DEBUG_DISAS
2464 0ecfa993 bellard
    struct disassemble_info disasm_info;
2465 0ecfa993 bellard
#endif
2466 0ecfa993 bellard
2467 ba1c6e37 bellard
    dc->cc_op = CC_OP_DYNAMIC;
2468 ba1c6e37 bellard
    gen_code_ptr = gen_code_buf;
2469 ba1c6e37 bellard
    gen_start();
2470 0ecfa993 bellard
2471 0ecfa993 bellard
#ifdef DEBUG_DISAS
2472 586314f2 bellard
    if (loglevel) {
2473 586314f2 bellard
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2474 586314f2 bellard
        disasm_info.buffer = pc_start;
2475 586314f2 bellard
        disasm_info.buffer_vma = (unsigned long)pc_start;
2476 586314f2 bellard
        disasm_info.buffer_length = 15;
2477 0ecfa993 bellard
#if 0        
2478 586314f2 bellard
        disasm_info.flavour = bfd_get_flavour (abfd);
2479 586314f2 bellard
        disasm_info.arch = bfd_get_arch (abfd);
2480 586314f2 bellard
        disasm_info.mach = bfd_get_mach (abfd);
2481 0ecfa993 bellard
#endif
2482 0ecfa993 bellard
#ifdef WORDS_BIGENDIAN
2483 586314f2 bellard
        disasm_info.endian = BFD_ENDIAN_BIG;
2484 0ecfa993 bellard
#else
2485 586314f2 bellard
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2486 0ecfa993 bellard
#endif        
2487 586314f2 bellard
        fprintf(logfile, "IN:\n");
2488 586314f2 bellard
        fprintf(logfile, "0x%08lx:  ", (long)pc_start);
2489 586314f2 bellard
        print_insn_i386((unsigned long)pc_start, &disasm_info);
2490 586314f2 bellard
        fprintf(logfile, "\n\n");
2491 586314f2 bellard
    }
2492 0ecfa993 bellard
#endif
2493 0ecfa993 bellard
    is_jmp = 0;
2494 0ecfa993 bellard
    ret = disas_insn(dc, pc_start, &is_jmp);
2495 ba1c6e37 bellard
    if (ret == -1) 
2496 d57c4e01 bellard
        error("unknown instruction at PC=0x%x B=%02x %02x", 
2497 d57c4e01 bellard
              pc_start, pc_start[0], pc_start[1]);
2498 0ecfa993 bellard
    /* we must store the eflags state if it is not already done */
2499 0ecfa993 bellard
    if (dc->cc_op != CC_OP_DYNAMIC)
2500 0ecfa993 bellard
        gen_op_set_cc_op(dc->cc_op);
2501 0ecfa993 bellard
    if (!is_jmp) {
2502 0ecfa993 bellard
        /* we add an additionnal jmp to update the simulated PC */
2503 0ecfa993 bellard
        gen_op_jmp_im(ret);
2504 0ecfa993 bellard
    }
2505 ba1c6e37 bellard
    gen_end();
2506 ba1c6e37 bellard
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2507 0ecfa993 bellard
2508 0ecfa993 bellard
#ifdef DEBUG_DISAS
2509 586314f2 bellard
    if (loglevel) {
2510 0ecfa993 bellard
        uint8_t *pc;
2511 0ecfa993 bellard
        int count;
2512 0ecfa993 bellard
2513 0ecfa993 bellard
        pc = gen_code_buf;
2514 0ecfa993 bellard
        disasm_info.buffer = pc;
2515 0ecfa993 bellard
        disasm_info.buffer_vma = (unsigned long)pc;
2516 0ecfa993 bellard
        disasm_info.buffer_length = *gen_code_size_ptr;
2517 0ecfa993 bellard
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2518 0ecfa993 bellard
        while (pc < gen_code_ptr) {
2519 0ecfa993 bellard
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2520 0ecfa993 bellard
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2521 0ecfa993 bellard
            fprintf(logfile, "\n");
2522 0ecfa993 bellard
            pc += count;
2523 0ecfa993 bellard
        }
2524 0ecfa993 bellard
        fprintf(logfile, "\n");
2525 0ecfa993 bellard
    }
2526 0ecfa993 bellard
#endif
2527 ba1c6e37 bellard
    return 0;
2528 ba1c6e37 bellard
}
2529 ba1c6e37 bellard
2530 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
2531 ba1c6e37 bellard
{
2532 ba1c6e37 bellard
    CPUX86State *env;
2533 ba1c6e37 bellard
    int i;
2534 ba1c6e37 bellard
2535 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
2536 ba1c6e37 bellard
    if (!env)
2537 ba1c6e37 bellard
        return NULL;
2538 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
2539 ba1c6e37 bellard
    /* basic FPU init */
2540 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
2541 ba1c6e37 bellard
        env->fptags[i] = 1;
2542 ba1c6e37 bellard
    env->fpuc = 0x37f;
2543 ba1c6e37 bellard
    /* flags setup */
2544 ba1c6e37 bellard
    env->cc_op = CC_OP_EFLAGS;
2545 ba1c6e37 bellard
    env->df = 1;
2546 ba1c6e37 bellard
    return env;
2547 ba1c6e37 bellard
}
2548 ba1c6e37 bellard
2549 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
2550 ba1c6e37 bellard
{
2551 ba1c6e37 bellard
    free(env);
2552 ba1c6e37 bellard
}