Statistics
| Branch: | Revision:

root / translate-i386.c @ a412ac57

History | View | Annotate | Download (127.7 kB)

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