Statistics
| Branch: | Revision:

root / translate-i386.c @ 7d13299d

History | View | Annotate | Download (67.7 kB)

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