Statistics
| Branch: | Revision:

root / translate-i386.c @ 5a91de8c

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

3855 5a91de8c bellard
   '*gen_code_size_ptr' contains the size of the generated code (host
3856 5a91de8c bellard
   code).
3857 5a91de8c bellard
*/
3858 5a91de8c bellard
int cpu_x86_gen_code(TranslationBlock *tb,
3859 5a91de8c bellard
                     int max_code_size, int *gen_code_size_ptr)
3860 5a91de8c bellard
{
3861 5a91de8c bellard
    uint8_t *gen_code_buf;
3862 5a91de8c bellard
    int gen_code_size;
3863 5a91de8c bellard
3864 5a91de8c bellard
    if (gen_intermediate_code(tb, 0) < 0)
3865 5a91de8c bellard
        return -1;
3866 dc99065b bellard
3867 dc99065b bellard
    /* generate machine code */
3868 d4e8164f bellard
    tb->tb_next_offset[0] = 0xffff;
3869 d4e8164f bellard
    tb->tb_next_offset[1] = 0xffff;
3870 5a91de8c bellard
    gen_code_buf = tb->tc_ptr;
3871 d4e8164f bellard
    gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3872 d4e8164f bellard
#ifdef USE_DIRECT_JUMP
3873 d4e8164f bellard
                                tb->tb_jmp_offset,
3874 d4e8164f bellard
#else
3875 d4e8164f bellard
                                NULL,
3876 d4e8164f bellard
#endif
3877 d4e8164f bellard
                                gen_opc_buf, gen_opparam_buf);
3878 04369ff2 bellard
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3879 5a91de8c bellard
    
3880 04369ff2 bellard
    *gen_code_size_ptr = gen_code_size;
3881 dc99065b bellard
#ifdef DEBUG_DISAS
3882 dc99065b bellard
    if (loglevel) {
3883 0ecfa993 bellard
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3884 5a91de8c bellard
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3885 0ecfa993 bellard
        fprintf(logfile, "\n");
3886 1b6b029e bellard
        fflush(logfile);
3887 0ecfa993 bellard
    }
3888 0ecfa993 bellard
#endif
3889 ba1c6e37 bellard
    return 0;
3890 ba1c6e37 bellard
}
3891 ba1c6e37 bellard
3892 5a91de8c bellard
static const unsigned short opc_copy_size[] = {
3893 5a91de8c bellard
#define DEF(s, n, copy_size) copy_size,
3894 5a91de8c bellard
#include "opc-i386.h"
3895 5a91de8c bellard
#undef DEF
3896 5a91de8c bellard
};
3897 5a91de8c bellard
3898 5a91de8c bellard
/* The simulated PC corresponding to
3899 5a91de8c bellard
   'searched_pc' in the generated code is searched. 0 is returned if
3900 5a91de8c bellard
   found. *found_pc contains the found PC. 
3901 5a91de8c bellard
 */
3902 5a91de8c bellard
int cpu_x86_search_pc(TranslationBlock *tb, 
3903 5a91de8c bellard
                      uint32_t *found_pc, unsigned long searched_pc)
3904 5a91de8c bellard
{
3905 5a91de8c bellard
    int j, c;
3906 5a91de8c bellard
    unsigned long tc_ptr;
3907 5a91de8c bellard
    uint16_t *opc_ptr;
3908 5a91de8c bellard
3909 5a91de8c bellard
    if (gen_intermediate_code(tb, 1) < 0)
3910 5a91de8c bellard
        return -1;
3911 5a91de8c bellard
    
3912 5a91de8c bellard
    /* find opc index corresponding to search_pc */
3913 5a91de8c bellard
    tc_ptr = (unsigned long)tb->tc_ptr;
3914 5a91de8c bellard
    if (searched_pc < tc_ptr)
3915 5a91de8c bellard
        return -1;
3916 5a91de8c bellard
    j = 0;
3917 5a91de8c bellard
    opc_ptr = gen_opc_buf;
3918 5a91de8c bellard
    for(;;) {
3919 5a91de8c bellard
        c = *opc_ptr;
3920 5a91de8c bellard
        if (c == INDEX_op_end)
3921 5a91de8c bellard
            return -1;
3922 5a91de8c bellard
        tc_ptr += opc_copy_size[c];
3923 5a91de8c bellard
        if (searched_pc < tc_ptr)
3924 5a91de8c bellard
            break;
3925 5a91de8c bellard
        opc_ptr++;
3926 5a91de8c bellard
    }
3927 5a91de8c bellard
    j = opc_ptr - gen_opc_buf;
3928 5a91de8c bellard
    /* now find start of instruction before */
3929 5a91de8c bellard
    while (gen_opc_instr_start[j] == 0)
3930 5a91de8c bellard
        j--;
3931 5a91de8c bellard
    *found_pc = gen_opc_pc[j];
3932 5a91de8c bellard
    return 0;
3933 5a91de8c bellard
}
3934 5a91de8c bellard
3935 5a91de8c bellard
3936 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
3937 ba1c6e37 bellard
{
3938 ba1c6e37 bellard
    CPUX86State *env;
3939 ba1c6e37 bellard
    int i;
3940 dc99065b bellard
    static int inited;
3941 ba1c6e37 bellard
3942 7d13299d bellard
    cpu_x86_tblocks_init();
3943 7d13299d bellard
3944 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
3945 ba1c6e37 bellard
    if (!env)
3946 ba1c6e37 bellard
        return NULL;
3947 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
3948 ba1c6e37 bellard
    /* basic FPU init */
3949 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
3950 ba1c6e37 bellard
        env->fptags[i] = 1;
3951 ba1c6e37 bellard
    env->fpuc = 0x37f;
3952 9c605cb1 bellard
    /* flags setup : we activate the IRQs by default as in user mode */
3953 9c605cb1 bellard
    env->eflags = 0x2 | IF_MASK;
3954 dc99065b bellard
3955 dc99065b bellard
    /* init various static tables */
3956 dc99065b bellard
    if (!inited) {
3957 dc99065b bellard
        inited = 1;
3958 dc99065b bellard
        optimize_flags_init();
3959 54936004 bellard
        page_init();
3960 dc99065b bellard
    }
3961 ba1c6e37 bellard
    return env;
3962 ba1c6e37 bellard
}
3963 ba1c6e37 bellard
3964 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
3965 ba1c6e37 bellard
{
3966 ba1c6e37 bellard
    free(env);
3967 ba1c6e37 bellard
}
3968 148dfc2a bellard
3969 148dfc2a bellard
static const char *cc_op_str[] = {
3970 148dfc2a bellard
    "DYNAMIC",
3971 148dfc2a bellard
    "EFLAGS",
3972 148dfc2a bellard
    "MUL",
3973 148dfc2a bellard
    "ADDB",
3974 148dfc2a bellard
    "ADDW",
3975 148dfc2a bellard
    "ADDL",
3976 148dfc2a bellard
    "ADCB",
3977 148dfc2a bellard
    "ADCW",
3978 148dfc2a bellard
    "ADCL",
3979 148dfc2a bellard
    "SUBB",
3980 148dfc2a bellard
    "SUBW",
3981 148dfc2a bellard
    "SUBL",
3982 148dfc2a bellard
    "SBBB",
3983 148dfc2a bellard
    "SBBW",
3984 148dfc2a bellard
    "SBBL",
3985 148dfc2a bellard
    "LOGICB",
3986 148dfc2a bellard
    "LOGICW",
3987 148dfc2a bellard
    "LOGICL",
3988 148dfc2a bellard
    "INCB",
3989 148dfc2a bellard
    "INCW",
3990 148dfc2a bellard
    "INCL",
3991 148dfc2a bellard
    "DECB",
3992 148dfc2a bellard
    "DECW",
3993 148dfc2a bellard
    "DECL",
3994 148dfc2a bellard
    "SHLB",
3995 148dfc2a bellard
    "SHLW",
3996 148dfc2a bellard
    "SHLL",
3997 148dfc2a bellard
    "SARB",
3998 148dfc2a bellard
    "SARW",
3999 148dfc2a bellard
    "SARL",
4000 148dfc2a bellard
};
4001 148dfc2a bellard
4002 148dfc2a bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4003 148dfc2a bellard
{
4004 148dfc2a bellard
    int eflags;
4005 148dfc2a bellard
    char cc_op_name[32];
4006 148dfc2a bellard
4007 148dfc2a bellard
    eflags = env->eflags;
4008 148dfc2a bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4009 148dfc2a bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4010 148dfc2a bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4011 148dfc2a bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
4012 148dfc2a bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
4013 148dfc2a bellard
            env->eip, eflags,
4014 148dfc2a bellard
            eflags & DF_MASK ? 'D' : '-',
4015 148dfc2a bellard
            eflags & CC_O ? 'O' : '-',
4016 148dfc2a bellard
            eflags & CC_S ? 'S' : '-',
4017 148dfc2a bellard
            eflags & CC_Z ? 'Z' : '-',
4018 148dfc2a bellard
            eflags & CC_A ? 'A' : '-',
4019 148dfc2a bellard
            eflags & CC_P ? 'P' : '-',
4020 148dfc2a bellard
            eflags & CC_C ? 'C' : '-');
4021 148dfc2a bellard
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4022 148dfc2a bellard
            env->segs[R_CS],
4023 148dfc2a bellard
            env->segs[R_SS],
4024 148dfc2a bellard
            env->segs[R_DS],
4025 148dfc2a bellard
            env->segs[R_ES],
4026 148dfc2a bellard
            env->segs[R_FS],
4027 148dfc2a bellard
            env->segs[R_GS]);
4028 148dfc2a bellard
    if (flags & X86_DUMP_CCOP) {
4029 148dfc2a bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
4030 148dfc2a bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
4031 148dfc2a bellard
        else
4032 148dfc2a bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4033 148dfc2a bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4034 148dfc2a bellard
                env->cc_src, env->cc_dst, cc_op_name);
4035 148dfc2a bellard
    }
4036 148dfc2a bellard
    if (flags & X86_DUMP_FPU) {
4037 148dfc2a bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
4038 148dfc2a bellard
                (double)env->fpregs[0], 
4039 148dfc2a bellard
                (double)env->fpregs[1], 
4040 148dfc2a bellard
                (double)env->fpregs[2], 
4041 148dfc2a bellard
                (double)env->fpregs[3]);
4042 148dfc2a bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
4043 148dfc2a bellard
                (double)env->fpregs[4], 
4044 148dfc2a bellard
                (double)env->fpregs[5], 
4045 148dfc2a bellard
                (double)env->fpregs[7], 
4046 148dfc2a bellard
                (double)env->fpregs[8]);
4047 148dfc2a bellard
    }
4048 148dfc2a bellard
}