Statistics
| Branch: | Revision:

root / translate-i386.c @ 5132455e

History | View | Annotate | Download (106.3 kB)

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

3723 727d01d4 bellard
   '*code_size_ptr' contains the target code size including the
3724 727d01d4 bellard
   instruction which triggered an exception, except in case of invalid
3725 727d01d4 bellard
   illegal opcode. It must never exceed one target page. 
3726 727d01d4 bellard
   
3727 727d01d4 bellard
   '*gen_code_size_ptr' contains the size of the generated code (host
3728 727d01d4 bellard
   code).
3729 727d01d4 bellard
*/
3730 1017ebe9 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3731 dab2ed99 bellard
                     int *gen_code_size_ptr,
3732 727d01d4 bellard
                     uint8_t *pc_start,  uint8_t *cs_base, int flags,
3733 727d01d4 bellard
                     int *code_size_ptr)
3734 ba1c6e37 bellard
{
3735 ba1c6e37 bellard
    DisasContext dc1, *dc = &dc1;
3736 dc99065b bellard
    uint8_t *pc_ptr;
3737 dc99065b bellard
    uint16_t *gen_opc_end;
3738 04369ff2 bellard
    int gen_code_size;
3739 ba1c6e37 bellard
    long ret;
3740 dc99065b bellard
    
3741 dc99065b bellard
    /* generate intermediate code */
3742 dc99065b bellard
3743 6dbad63e bellard
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3744 dab2ed99 bellard
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3745 6dbad63e bellard
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3746 6dbad63e bellard
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3747 9c605cb1 bellard
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3748 982b4315 bellard
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3749 982b4315 bellard
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3750 c50c0c3f bellard
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3751 ba1c6e37 bellard
    dc->cc_op = CC_OP_DYNAMIC;
3752 dab2ed99 bellard
    dc->cs_base = cs_base;
3753 dc99065b bellard
3754 dc99065b bellard
    gen_opc_ptr = gen_opc_buf;
3755 dc99065b bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3756 dc99065b bellard
    gen_opparam_ptr = gen_opparam_buf;
3757 0ecfa993 bellard
3758 6dbad63e bellard
    dc->is_jmp = 0;
3759 1017ebe9 bellard
    pc_ptr = pc_start;
3760 1017ebe9 bellard
    do {
3761 6dbad63e bellard
        ret = disas_insn(dc, pc_ptr);
3762 1a9353d2 bellard
        if (ret == -1) {
3763 9de5e440 bellard
            /* we trigger an illegal instruction operation only if it
3764 9de5e440 bellard
               is the first instruction. Otherwise, we simply stop
3765 9de5e440 bellard
               generating the code just before it */
3766 9de5e440 bellard
            if (pc_ptr == pc_start)
3767 9de5e440 bellard
                return -1;
3768 9de5e440 bellard
            else
3769 9de5e440 bellard
                break;
3770 1a9353d2 bellard
        }
3771 1017ebe9 bellard
        pc_ptr = (void *)ret;
3772 c50c0c3f bellard
        /* if single step mode, we generate only one instruction and
3773 c50c0c3f bellard
           generate an exception */
3774 c50c0c3f bellard
        if (dc->tf)
3775 c50c0c3f bellard
            break;
3776 727d01d4 bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
3777 727d01d4 bellard
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3778 0ecfa993 bellard
    /* we must store the eflags state if it is not already done */
3779 0ecfa993 bellard
    if (dc->cc_op != CC_OP_DYNAMIC)
3780 0ecfa993 bellard
        gen_op_set_cc_op(dc->cc_op);
3781 6dbad63e bellard
    if (dc->is_jmp != 1) {
3782 0ecfa993 bellard
        /* we add an additionnal jmp to update the simulated PC */
3783 dab2ed99 bellard
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3784 0ecfa993 bellard
    }
3785 c50c0c3f bellard
    if (dc->tf) {
3786 c50c0c3f bellard
        gen_op_raise_exception(EXCP01_SSTP);
3787 c50c0c3f bellard
    }
3788 c50c0c3f bellard
3789 dc99065b bellard
    *gen_opc_ptr = INDEX_op_end;
3790 0ecfa993 bellard
3791 0ecfa993 bellard
#ifdef DEBUG_DISAS
3792 586314f2 bellard
    if (loglevel) {
3793 dc99065b bellard
        fprintf(logfile, "----------------\n");
3794 b9adb4a6 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3795 b9adb4a6 bellard
        disas(logfile, pc_start, pc_ptr - pc_start,
3796 b9adb4a6 bellard
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3797 1017ebe9 bellard
        fprintf(logfile, "\n");
3798 982b4315 bellard
3799 dc99065b bellard
        fprintf(logfile, "OP:\n");
3800 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
3801 dc99065b bellard
        fprintf(logfile, "\n");
3802 dc99065b bellard
    }
3803 dc99065b bellard
#endif
3804 dc99065b bellard
3805 dc99065b bellard
    /* optimize flag computations */
3806 dc99065b bellard
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3807 dc99065b bellard
3808 dc99065b bellard
#ifdef DEBUG_DISAS
3809 dc99065b bellard
    if (loglevel) {
3810 dc99065b bellard
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3811 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
3812 dc99065b bellard
        fprintf(logfile, "\n");
3813 dc99065b bellard
    }
3814 dc99065b bellard
#endif
3815 dc99065b bellard
3816 dc99065b bellard
    /* generate machine code */
3817 04369ff2 bellard
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3818 04369ff2 bellard
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3819 04369ff2 bellard
    *gen_code_size_ptr = gen_code_size;
3820 727d01d4 bellard
    *code_size_ptr = pc_ptr - pc_start;
3821 dc99065b bellard
#ifdef DEBUG_DISAS
3822 dc99065b bellard
    if (loglevel) {
3823 0ecfa993 bellard
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3824 b9adb4a6 bellard
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3825 0ecfa993 bellard
        fprintf(logfile, "\n");
3826 1b6b029e bellard
        fflush(logfile);
3827 0ecfa993 bellard
    }
3828 0ecfa993 bellard
#endif
3829 ba1c6e37 bellard
    return 0;
3830 ba1c6e37 bellard
}
3831 ba1c6e37 bellard
3832 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
3833 ba1c6e37 bellard
{
3834 ba1c6e37 bellard
    CPUX86State *env;
3835 ba1c6e37 bellard
    int i;
3836 dc99065b bellard
    static int inited;
3837 ba1c6e37 bellard
3838 7d13299d bellard
    cpu_x86_tblocks_init();
3839 7d13299d bellard
3840 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
3841 ba1c6e37 bellard
    if (!env)
3842 ba1c6e37 bellard
        return NULL;
3843 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
3844 ba1c6e37 bellard
    /* basic FPU init */
3845 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
3846 ba1c6e37 bellard
        env->fptags[i] = 1;
3847 ba1c6e37 bellard
    env->fpuc = 0x37f;
3848 9c605cb1 bellard
    /* flags setup : we activate the IRQs by default as in user mode */
3849 9c605cb1 bellard
    env->eflags = 0x2 | IF_MASK;
3850 dc99065b bellard
3851 dc99065b bellard
    /* init various static tables */
3852 dc99065b bellard
    if (!inited) {
3853 dc99065b bellard
        inited = 1;
3854 dc99065b bellard
        optimize_flags_init();
3855 54936004 bellard
        page_init();
3856 dc99065b bellard
    }
3857 ba1c6e37 bellard
    return env;
3858 ba1c6e37 bellard
}
3859 ba1c6e37 bellard
3860 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
3861 ba1c6e37 bellard
{
3862 ba1c6e37 bellard
    free(env);
3863 ba1c6e37 bellard
}
3864 148dfc2a bellard
3865 148dfc2a bellard
static const char *cc_op_str[] = {
3866 148dfc2a bellard
    "DYNAMIC",
3867 148dfc2a bellard
    "EFLAGS",
3868 148dfc2a bellard
    "MUL",
3869 148dfc2a bellard
    "ADDB",
3870 148dfc2a bellard
    "ADDW",
3871 148dfc2a bellard
    "ADDL",
3872 148dfc2a bellard
    "ADCB",
3873 148dfc2a bellard
    "ADCW",
3874 148dfc2a bellard
    "ADCL",
3875 148dfc2a bellard
    "SUBB",
3876 148dfc2a bellard
    "SUBW",
3877 148dfc2a bellard
    "SUBL",
3878 148dfc2a bellard
    "SBBB",
3879 148dfc2a bellard
    "SBBW",
3880 148dfc2a bellard
    "SBBL",
3881 148dfc2a bellard
    "LOGICB",
3882 148dfc2a bellard
    "LOGICW",
3883 148dfc2a bellard
    "LOGICL",
3884 148dfc2a bellard
    "INCB",
3885 148dfc2a bellard
    "INCW",
3886 148dfc2a bellard
    "INCL",
3887 148dfc2a bellard
    "DECB",
3888 148dfc2a bellard
    "DECW",
3889 148dfc2a bellard
    "DECL",
3890 148dfc2a bellard
    "SHLB",
3891 148dfc2a bellard
    "SHLW",
3892 148dfc2a bellard
    "SHLL",
3893 148dfc2a bellard
    "SARB",
3894 148dfc2a bellard
    "SARW",
3895 148dfc2a bellard
    "SARL",
3896 148dfc2a bellard
};
3897 148dfc2a bellard
3898 148dfc2a bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3899 148dfc2a bellard
{
3900 148dfc2a bellard
    int eflags;
3901 148dfc2a bellard
    char cc_op_name[32];
3902 148dfc2a bellard
3903 148dfc2a bellard
    eflags = env->eflags;
3904 148dfc2a bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3905 148dfc2a bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3906 148dfc2a bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3907 148dfc2a bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
3908 148dfc2a bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
3909 148dfc2a bellard
            env->eip, eflags,
3910 148dfc2a bellard
            eflags & DF_MASK ? 'D' : '-',
3911 148dfc2a bellard
            eflags & CC_O ? 'O' : '-',
3912 148dfc2a bellard
            eflags & CC_S ? 'S' : '-',
3913 148dfc2a bellard
            eflags & CC_Z ? 'Z' : '-',
3914 148dfc2a bellard
            eflags & CC_A ? 'A' : '-',
3915 148dfc2a bellard
            eflags & CC_P ? 'P' : '-',
3916 148dfc2a bellard
            eflags & CC_C ? 'C' : '-');
3917 148dfc2a bellard
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3918 148dfc2a bellard
            env->segs[R_CS],
3919 148dfc2a bellard
            env->segs[R_SS],
3920 148dfc2a bellard
            env->segs[R_DS],
3921 148dfc2a bellard
            env->segs[R_ES],
3922 148dfc2a bellard
            env->segs[R_FS],
3923 148dfc2a bellard
            env->segs[R_GS]);
3924 148dfc2a bellard
    if (flags & X86_DUMP_CCOP) {
3925 148dfc2a bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
3926 148dfc2a bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
3927 148dfc2a bellard
        else
3928 148dfc2a bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
3929 148dfc2a bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
3930 148dfc2a bellard
                env->cc_src, env->cc_dst, cc_op_name);
3931 148dfc2a bellard
    }
3932 148dfc2a bellard
    if (flags & X86_DUMP_FPU) {
3933 148dfc2a bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
3934 148dfc2a bellard
                (double)env->fpregs[0], 
3935 148dfc2a bellard
                (double)env->fpregs[1], 
3936 148dfc2a bellard
                (double)env->fpregs[2], 
3937 148dfc2a bellard
                (double)env->fpregs[3]);
3938 148dfc2a bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
3939 148dfc2a bellard
                (double)env->fpregs[4], 
3940 148dfc2a bellard
                (double)env->fpregs[5], 
3941 148dfc2a bellard
                (double)env->fpregs[7], 
3942 148dfc2a bellard
                (double)env->fpregs[8]);
3943 148dfc2a bellard
    }
3944 148dfc2a bellard
}