Statistics
| Branch: | Revision:

root / translate-i386.c @ d05e66d2

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