Statistics
| Branch: | Revision:

root / translate-i386.c @ 2c1794c4

History | View | Annotate | Download (127.5 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 8a4c1cc4 bellard
    /* abort translation because the register may have a non zero base
1281 8a4c1cc4 bellard
       or because ss32 may change */
1282 8a4c1cc4 bellard
    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1283 8a4c1cc4 bellard
        s->is_jmp = 2; 
1284 6dbad63e bellard
}
1285 6dbad63e bellard
1286 dab2ed99 bellard
/* generate a push. It depends on ss32, addseg and dflag */
1287 dab2ed99 bellard
static void gen_push_T0(DisasContext *s)
1288 dab2ed99 bellard
{
1289 dab2ed99 bellard
    if (s->ss32) {
1290 dab2ed99 bellard
        if (!s->addseg) {
1291 dab2ed99 bellard
            if (s->dflag)
1292 dab2ed99 bellard
                gen_op_pushl_T0();
1293 dab2ed99 bellard
            else
1294 dab2ed99 bellard
                gen_op_pushw_T0();
1295 dab2ed99 bellard
        } else {
1296 dab2ed99 bellard
            if (s->dflag)
1297 dab2ed99 bellard
                gen_op_pushl_ss32_T0();
1298 dab2ed99 bellard
            else
1299 dab2ed99 bellard
                gen_op_pushw_ss32_T0();
1300 dab2ed99 bellard
        }
1301 dab2ed99 bellard
    } else {
1302 dab2ed99 bellard
        if (s->dflag)
1303 dab2ed99 bellard
            gen_op_pushl_ss16_T0();
1304 dab2ed99 bellard
        else
1305 dab2ed99 bellard
            gen_op_pushw_ss16_T0();
1306 dab2ed99 bellard
    }
1307 dab2ed99 bellard
}
1308 dab2ed99 bellard
1309 dab2ed99 bellard
/* two step pop is necessary for precise exceptions */
1310 dab2ed99 bellard
static void gen_pop_T0(DisasContext *s)
1311 dab2ed99 bellard
{
1312 dab2ed99 bellard
    if (s->ss32) {
1313 dab2ed99 bellard
        if (!s->addseg) {
1314 dab2ed99 bellard
            if (s->dflag)
1315 dab2ed99 bellard
                gen_op_popl_T0();
1316 dab2ed99 bellard
            else
1317 dab2ed99 bellard
                gen_op_popw_T0();
1318 dab2ed99 bellard
        } else {
1319 dab2ed99 bellard
            if (s->dflag)
1320 dab2ed99 bellard
                gen_op_popl_ss32_T0();
1321 dab2ed99 bellard
            else
1322 dab2ed99 bellard
                gen_op_popw_ss32_T0();
1323 dab2ed99 bellard
        }
1324 dab2ed99 bellard
    } else {
1325 dab2ed99 bellard
        if (s->dflag)
1326 dab2ed99 bellard
            gen_op_popl_ss16_T0();
1327 dab2ed99 bellard
        else
1328 dab2ed99 bellard
            gen_op_popw_ss16_T0();
1329 dab2ed99 bellard
    }
1330 dab2ed99 bellard
}
1331 dab2ed99 bellard
1332 d0a1ffc9 bellard
static inline void gen_stack_update(DisasContext *s, int addend)
1333 dab2ed99 bellard
{
1334 dab2ed99 bellard
    if (s->ss32) {
1335 d0a1ffc9 bellard
        if (addend == 2)
1336 dab2ed99 bellard
            gen_op_addl_ESP_2();
1337 d0a1ffc9 bellard
        else if (addend == 4)
1338 d0a1ffc9 bellard
            gen_op_addl_ESP_4();
1339 d0a1ffc9 bellard
        else 
1340 d0a1ffc9 bellard
            gen_op_addl_ESP_im(addend);
1341 dab2ed99 bellard
    } else {
1342 d0a1ffc9 bellard
        if (addend == 2)
1343 d0a1ffc9 bellard
            gen_op_addw_ESP_2();
1344 d0a1ffc9 bellard
        else if (addend == 4)
1345 dab2ed99 bellard
            gen_op_addw_ESP_4();
1346 dab2ed99 bellard
        else
1347 d0a1ffc9 bellard
            gen_op_addw_ESP_im(addend);
1348 dab2ed99 bellard
    }
1349 dab2ed99 bellard
}
1350 dab2ed99 bellard
1351 d0a1ffc9 bellard
static void gen_pop_update(DisasContext *s)
1352 d0a1ffc9 bellard
{
1353 d0a1ffc9 bellard
    gen_stack_update(s, 2 << s->dflag);
1354 d0a1ffc9 bellard
}
1355 d0a1ffc9 bellard
1356 d0a1ffc9 bellard
static void gen_stack_A0(DisasContext *s)
1357 d0a1ffc9 bellard
{
1358 d0a1ffc9 bellard
    gen_op_movl_A0_ESP();
1359 d0a1ffc9 bellard
    if (!s->ss32)
1360 d0a1ffc9 bellard
        gen_op_andl_A0_ffff();
1361 d0a1ffc9 bellard
    gen_op_movl_T1_A0();
1362 d0a1ffc9 bellard
    if (s->addseg)
1363 d8bc1fd0 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1364 d0a1ffc9 bellard
}
1365 d0a1ffc9 bellard
1366 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1367 dab2ed99 bellard
static void gen_pusha(DisasContext *s)
1368 dab2ed99 bellard
{
1369 dab2ed99 bellard
    int i;
1370 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1371 dab2ed99 bellard
    gen_op_addl_A0_im(-16 <<  s->dflag);
1372 dab2ed99 bellard
    if (!s->ss32)
1373 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1374 dab2ed99 bellard
    gen_op_movl_T1_A0();
1375 dab2ed99 bellard
    if (s->addseg)
1376 d8bc1fd0 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1377 dab2ed99 bellard
    for(i = 0;i < 8; i++) {
1378 dab2ed99 bellard
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1379 dab2ed99 bellard
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1380 dab2ed99 bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
1381 dab2ed99 bellard
    }
1382 dab2ed99 bellard
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1383 dab2ed99 bellard
}
1384 dab2ed99 bellard
1385 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1386 dab2ed99 bellard
static void gen_popa(DisasContext *s)
1387 dab2ed99 bellard
{
1388 dab2ed99 bellard
    int i;
1389 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1390 dab2ed99 bellard
    if (!s->ss32)
1391 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1392 dab2ed99 bellard
    gen_op_movl_T1_A0();
1393 dab2ed99 bellard
    gen_op_addl_T1_im(16 <<  s->dflag);
1394 dab2ed99 bellard
    if (s->addseg)
1395 d8bc1fd0 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1396 dab2ed99 bellard
    for(i = 0;i < 8; i++) {
1397 dab2ed99 bellard
        /* ESP is not reloaded */
1398 dab2ed99 bellard
        if (i != 3) {
1399 dab2ed99 bellard
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1400 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1401 dab2ed99 bellard
        }
1402 dab2ed99 bellard
        gen_op_addl_A0_im(2 <<  s->dflag);
1403 dab2ed99 bellard
    }
1404 dab2ed99 bellard
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1405 dab2ed99 bellard
}
1406 dab2ed99 bellard
1407 dab2ed99 bellard
/* NOTE: wrap around in 16 bit not fully handled */
1408 dab2ed99 bellard
/* XXX: check this */
1409 dab2ed99 bellard
static void gen_enter(DisasContext *s, int esp_addend, int level)
1410 dab2ed99 bellard
{
1411 dab2ed99 bellard
    int ot, level1, addend, opsize;
1412 dab2ed99 bellard
1413 dab2ed99 bellard
    ot = s->dflag + OT_WORD;
1414 dab2ed99 bellard
    level &= 0x1f;
1415 dab2ed99 bellard
    level1 = level;
1416 dab2ed99 bellard
    opsize = 2 << s->dflag;
1417 dab2ed99 bellard
1418 dab2ed99 bellard
    gen_op_movl_A0_ESP();
1419 dab2ed99 bellard
    gen_op_addl_A0_im(-opsize);
1420 dab2ed99 bellard
    if (!s->ss32)
1421 dab2ed99 bellard
        gen_op_andl_A0_ffff();
1422 dab2ed99 bellard
    gen_op_movl_T1_A0();
1423 dab2ed99 bellard
    if (s->addseg)
1424 d8bc1fd0 bellard
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1425 dab2ed99 bellard
    /* push bp */
1426 dab2ed99 bellard
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1427 dab2ed99 bellard
    gen_op_st_T0_A0[ot]();
1428 dab2ed99 bellard
    if (level) {
1429 dab2ed99 bellard
        while (level--) {
1430 dab2ed99 bellard
            gen_op_addl_A0_im(-opsize);
1431 dab2ed99 bellard
            gen_op_addl_T0_im(-opsize);
1432 dab2ed99 bellard
            gen_op_st_T0_A0[ot]();
1433 dab2ed99 bellard
        }
1434 dab2ed99 bellard
        gen_op_addl_A0_im(-opsize);
1435 dab2ed99 bellard
        /* XXX: add st_T1_A0 ? */
1436 dab2ed99 bellard
        gen_op_movl_T0_T1();
1437 dab2ed99 bellard
        gen_op_st_T0_A0[ot]();
1438 dab2ed99 bellard
    }
1439 dab2ed99 bellard
    gen_op_mov_reg_T1[ot][R_EBP]();
1440 dab2ed99 bellard
    addend = -esp_addend;
1441 dab2ed99 bellard
    if (level1)
1442 dab2ed99 bellard
        addend -= opsize * (level1 + 1);
1443 dab2ed99 bellard
    gen_op_addl_T1_im(addend);
1444 dab2ed99 bellard
    gen_op_mov_reg_T1[ot][R_ESP]();
1445 dab2ed99 bellard
}
1446 dab2ed99 bellard
1447 c50c0c3f bellard
static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1448 c50c0c3f bellard
{
1449 c50c0c3f bellard
    if (s->cc_op != CC_OP_DYNAMIC)
1450 c50c0c3f bellard
        gen_op_set_cc_op(s->cc_op);
1451 c50c0c3f bellard
    gen_op_jmp_im(cur_eip);
1452 c50c0c3f bellard
    gen_op_raise_exception(trapno);
1453 c50c0c3f bellard
    s->is_jmp = 1;
1454 c50c0c3f bellard
}
1455 c50c0c3f bellard
1456 5a91de8c bellard
/* an interrupt is different from an exception because of the
1457 5a91de8c bellard
   priviledge checks */
1458 5a91de8c bellard
static void gen_interrupt(DisasContext *s, int intno, 
1459 5a91de8c bellard
                          unsigned int cur_eip, unsigned int next_eip)
1460 5a91de8c bellard
{
1461 5a91de8c bellard
    if (s->cc_op != CC_OP_DYNAMIC)
1462 5a91de8c bellard
        gen_op_set_cc_op(s->cc_op);
1463 5a91de8c bellard
    gen_op_jmp_im(cur_eip);
1464 5a91de8c bellard
    gen_op_raise_interrupt(intno, next_eip);
1465 5a91de8c bellard
    s->is_jmp = 1;
1466 5a91de8c bellard
}
1467 5a91de8c bellard
1468 4c3a88a2 bellard
static void gen_debug(DisasContext *s, unsigned int cur_eip)
1469 4c3a88a2 bellard
{
1470 4c3a88a2 bellard
    if (s->cc_op != CC_OP_DYNAMIC)
1471 4c3a88a2 bellard
        gen_op_set_cc_op(s->cc_op);
1472 4c3a88a2 bellard
    gen_op_jmp_im(cur_eip);
1473 4c3a88a2 bellard
    gen_op_debug();
1474 4c3a88a2 bellard
    s->is_jmp = 1;
1475 4c3a88a2 bellard
}
1476 4c3a88a2 bellard
1477 d4e8164f bellard
/* generate a jump to eip. No segment change must happen before as a
1478 d4e8164f bellard
   direct call to the next block may occur */
1479 d4e8164f bellard
static void gen_jmp(DisasContext *s, unsigned int eip)
1480 d4e8164f bellard
{
1481 d4e8164f bellard
    TranslationBlock *tb = s->tb;
1482 d4e8164f bellard
1483 d4e8164f bellard
    if (s->cc_op != CC_OP_DYNAMIC)
1484 d4e8164f bellard
        gen_op_set_cc_op(s->cc_op);
1485 d4e8164f bellard
    gen_op_jmp_tb_next((long)tb, eip);
1486 d4e8164f bellard
    s->is_jmp = 3;
1487 d4e8164f bellard
}
1488 d4e8164f bellard
1489 0ecfa993 bellard
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1490 0ecfa993 bellard
   is set to true if the instruction sets the PC (last instruction of
1491 0ecfa993 bellard
   a basic block) */
1492 6dbad63e bellard
long disas_insn(DisasContext *s, uint8_t *pc_start)
1493 367e86e8 bellard
{
1494 367e86e8 bellard
    int b, prefixes, aflag, dflag;
1495 367e86e8 bellard
    int shift, ot;
1496 367e86e8 bellard
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1497 dab2ed99 bellard
    unsigned int next_eip;
1498 367e86e8 bellard
1499 367e86e8 bellard
    s->pc = pc_start;
1500 367e86e8 bellard
    prefixes = 0;
1501 6dbad63e bellard
    aflag = s->code32;
1502 6dbad63e bellard
    dflag = s->code32;
1503 9c605cb1 bellard
    s->override = -1;
1504 367e86e8 bellard
 next_byte:
1505 367e86e8 bellard
    b = ldub(s->pc);
1506 367e86e8 bellard
    s->pc++;
1507 367e86e8 bellard
    /* check prefixes */
1508 367e86e8 bellard
    switch (b) {
1509 367e86e8 bellard
    case 0xf3:
1510 367e86e8 bellard
        prefixes |= PREFIX_REPZ;
1511 367e86e8 bellard
        goto next_byte;
1512 367e86e8 bellard
    case 0xf2:
1513 367e86e8 bellard
        prefixes |= PREFIX_REPNZ;
1514 367e86e8 bellard
        goto next_byte;
1515 367e86e8 bellard
    case 0xf0:
1516 367e86e8 bellard
        prefixes |= PREFIX_LOCK;
1517 367e86e8 bellard
        goto next_byte;
1518 367e86e8 bellard
    case 0x2e:
1519 9c605cb1 bellard
        s->override = R_CS;
1520 367e86e8 bellard
        goto next_byte;
1521 367e86e8 bellard
    case 0x36:
1522 9c605cb1 bellard
        s->override = R_SS;
1523 367e86e8 bellard
        goto next_byte;
1524 367e86e8 bellard
    case 0x3e:
1525 9c605cb1 bellard
        s->override = R_DS;
1526 367e86e8 bellard
        goto next_byte;
1527 367e86e8 bellard
    case 0x26:
1528 9c605cb1 bellard
        s->override = R_ES;
1529 367e86e8 bellard
        goto next_byte;
1530 367e86e8 bellard
    case 0x64:
1531 9c605cb1 bellard
        s->override = R_FS;
1532 367e86e8 bellard
        goto next_byte;
1533 367e86e8 bellard
    case 0x65:
1534 9c605cb1 bellard
        s->override = R_GS;
1535 367e86e8 bellard
        goto next_byte;
1536 367e86e8 bellard
    case 0x66:
1537 367e86e8 bellard
        prefixes |= PREFIX_DATA;
1538 367e86e8 bellard
        goto next_byte;
1539 367e86e8 bellard
    case 0x67:
1540 367e86e8 bellard
        prefixes |= PREFIX_ADR;
1541 367e86e8 bellard
        goto next_byte;
1542 367e86e8 bellard
    }
1543 367e86e8 bellard
1544 367e86e8 bellard
    if (prefixes & PREFIX_DATA)
1545 367e86e8 bellard
        dflag ^= 1;
1546 367e86e8 bellard
    if (prefixes & PREFIX_ADR)
1547 367e86e8 bellard
        aflag ^= 1;
1548 367e86e8 bellard
1549 367e86e8 bellard
    s->prefix = prefixes;
1550 367e86e8 bellard
    s->aflag = aflag;
1551 367e86e8 bellard
    s->dflag = dflag;
1552 367e86e8 bellard
1553 1b6b029e bellard
    /* lock generation */
1554 1b6b029e bellard
    if (prefixes & PREFIX_LOCK)
1555 1b6b029e bellard
        gen_op_lock();
1556 1b6b029e bellard
1557 367e86e8 bellard
    /* now check op code */
1558 367e86e8 bellard
 reswitch:
1559 367e86e8 bellard
    switch(b) {
1560 367e86e8 bellard
    case 0x0f:
1561 367e86e8 bellard
        /**************************/
1562 367e86e8 bellard
        /* extended op code */
1563 367e86e8 bellard
        b = ldub(s->pc++) | 0x100;
1564 367e86e8 bellard
        goto reswitch;
1565 367e86e8 bellard
        
1566 367e86e8 bellard
        /**************************/
1567 367e86e8 bellard
        /* arith & logic */
1568 367e86e8 bellard
    case 0x00 ... 0x05:
1569 367e86e8 bellard
    case 0x08 ... 0x0d:
1570 367e86e8 bellard
    case 0x10 ... 0x15:
1571 367e86e8 bellard
    case 0x18 ... 0x1d:
1572 367e86e8 bellard
    case 0x20 ... 0x25:
1573 367e86e8 bellard
    case 0x28 ... 0x2d:
1574 367e86e8 bellard
    case 0x30 ... 0x35:
1575 367e86e8 bellard
    case 0x38 ... 0x3d:
1576 367e86e8 bellard
        {
1577 367e86e8 bellard
            int op, f, val;
1578 367e86e8 bellard
            op = (b >> 3) & 7;
1579 367e86e8 bellard
            f = (b >> 1) & 3;
1580 367e86e8 bellard
1581 367e86e8 bellard
            if ((b & 1) == 0)
1582 367e86e8 bellard
                ot = OT_BYTE;
1583 367e86e8 bellard
            else
1584 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1585 367e86e8 bellard
            
1586 367e86e8 bellard
            switch(f) {
1587 367e86e8 bellard
            case 0: /* OP Ev, Gv */
1588 367e86e8 bellard
                modrm = ldub(s->pc++);
1589 3c1cf9fa bellard
                reg = ((modrm >> 3) & 7);
1590 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1591 367e86e8 bellard
                rm = modrm & 7;
1592 367e86e8 bellard
                if (mod != 3) {
1593 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1594 367e86e8 bellard
                    opreg = OR_TMP0;
1595 3c1cf9fa bellard
                } else if (op == OP_XORL && rm == reg) {
1596 3c1cf9fa bellard
                xor_zero:
1597 3c1cf9fa bellard
                    /* xor reg, reg optimisation */
1598 3c1cf9fa bellard
                    gen_op_movl_T0_0();
1599 3c1cf9fa bellard
                    s->cc_op = CC_OP_LOGICB + ot;
1600 3c1cf9fa bellard
                    gen_op_mov_reg_T0[ot][reg]();
1601 3c1cf9fa bellard
                    gen_op_update1_cc();
1602 3c1cf9fa bellard
                    break;
1603 367e86e8 bellard
                } else {
1604 3c1cf9fa bellard
                    opreg = rm;
1605 367e86e8 bellard
                }
1606 5797fa5d bellard
                gen_op_mov_TN_reg[ot][1][reg]();
1607 5797fa5d bellard
                gen_op(s, op, ot, opreg);
1608 367e86e8 bellard
                break;
1609 367e86e8 bellard
            case 1: /* OP Gv, Ev */
1610 367e86e8 bellard
                modrm = ldub(s->pc++);
1611 367e86e8 bellard
                mod = (modrm >> 6) & 3;
1612 3c1cf9fa bellard
                reg = ((modrm >> 3) & 7);
1613 367e86e8 bellard
                rm = modrm & 7;
1614 367e86e8 bellard
                if (mod != 3) {
1615 367e86e8 bellard
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1616 367e86e8 bellard
                    gen_op_ld_T1_A0[ot]();
1617 3c1cf9fa bellard
                } else if (op == OP_XORL && rm == reg) {
1618 3c1cf9fa bellard
                    goto xor_zero;
1619 367e86e8 bellard
                } else {
1620 5797fa5d bellard
                    gen_op_mov_TN_reg[ot][1][rm]();
1621 367e86e8 bellard
                }
1622 5797fa5d bellard
                gen_op(s, op, ot, reg);
1623 367e86e8 bellard
                break;
1624 367e86e8 bellard
            case 2: /* OP A, Iv */
1625 367e86e8 bellard
                val = insn_get(s, ot);
1626 5797fa5d bellard
                gen_op_movl_T1_im(val);
1627 5797fa5d bellard
                gen_op(s, op, ot, OR_EAX);
1628 367e86e8 bellard
                break;
1629 367e86e8 bellard
            }
1630 367e86e8 bellard
        }
1631 367e86e8 bellard
        break;
1632 367e86e8 bellard
1633 367e86e8 bellard
    case 0x80: /* GRP1 */
1634 367e86e8 bellard
    case 0x81:
1635 367e86e8 bellard
    case 0x83:
1636 367e86e8 bellard
        {
1637 367e86e8 bellard
            int val;
1638 367e86e8 bellard
1639 367e86e8 bellard
            if ((b & 1) == 0)
1640 367e86e8 bellard
                ot = OT_BYTE;
1641 367e86e8 bellard
            else
1642 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
1643 367e86e8 bellard
            
1644 367e86e8 bellard
            modrm = ldub(s->pc++);
1645 367e86e8 bellard
            mod = (modrm >> 6) & 3;
1646 367e86e8 bellard
            rm = modrm & 7;
1647 367e86e8 bellard
            op = (modrm >> 3) & 7;
1648 367e86e8 bellard
            
1649 367e86e8 bellard
            if (mod != 3) {
1650 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1651 367e86e8 bellard
                opreg = OR_TMP0;
1652 367e86e8 bellard
            } else {
1653 367e86e8 bellard
                opreg = rm + OR_EAX;
1654 367e86e8 bellard
            }
1655 367e86e8 bellard
1656 367e86e8 bellard
            switch(b) {
1657 367e86e8 bellard
            default:
1658 367e86e8 bellard
            case 0x80:
1659 367e86e8 bellard
            case 0x81:
1660 367e86e8 bellard
                val = insn_get(s, ot);
1661 367e86e8 bellard
                break;
1662 367e86e8 bellard
            case 0x83:
1663 367e86e8 bellard
                val = (int8_t)insn_get(s, OT_BYTE);
1664 367e86e8 bellard
                break;
1665 367e86e8 bellard
            }
1666 5797fa5d bellard
            gen_op_movl_T1_im(val);
1667 5797fa5d bellard
            gen_op(s, op, ot, opreg);
1668 367e86e8 bellard
        }
1669 367e86e8 bellard
        break;
1670 367e86e8 bellard
1671 367e86e8 bellard
        /**************************/
1672 367e86e8 bellard
        /* inc, dec, and other misc arith */
1673 367e86e8 bellard
    case 0x40 ... 0x47: /* inc Gv */
1674 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1675 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1676 367e86e8 bellard
        break;
1677 367e86e8 bellard
    case 0x48 ... 0x4f: /* dec Gv */
1678 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1679 367e86e8 bellard
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1680 367e86e8 bellard
        break;
1681 367e86e8 bellard
    case 0xf6: /* GRP3 */
1682 367e86e8 bellard
    case 0xf7:
1683 367e86e8 bellard
        if ((b & 1) == 0)
1684 367e86e8 bellard
            ot = OT_BYTE;
1685 367e86e8 bellard
        else
1686 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1687 367e86e8 bellard
1688 367e86e8 bellard
        modrm = ldub(s->pc++);
1689 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1690 367e86e8 bellard
        rm = modrm & 7;
1691 367e86e8 bellard
        op = (modrm >> 3) & 7;
1692 367e86e8 bellard
        if (mod != 3) {
1693 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1694 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
1695 367e86e8 bellard
        } else {
1696 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1697 367e86e8 bellard
        }
1698 367e86e8 bellard
1699 367e86e8 bellard
        switch(op) {
1700 367e86e8 bellard
        case 0: /* test */
1701 367e86e8 bellard
            val = insn_get(s, ot);
1702 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1703 367e86e8 bellard
            gen_op_testl_T0_T1_cc();
1704 367e86e8 bellard
            s->cc_op = CC_OP_LOGICB + ot;
1705 367e86e8 bellard
            break;
1706 367e86e8 bellard
        case 2: /* not */
1707 367e86e8 bellard
            gen_op_notl_T0();
1708 367e86e8 bellard
            if (mod != 3) {
1709 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1710 367e86e8 bellard
            } else {
1711 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1712 367e86e8 bellard
            }
1713 367e86e8 bellard
            break;
1714 367e86e8 bellard
        case 3: /* neg */
1715 5797fa5d bellard
            gen_op_negl_T0();
1716 367e86e8 bellard
            if (mod != 3) {
1717 367e86e8 bellard
                gen_op_st_T0_A0[ot]();
1718 367e86e8 bellard
            } else {
1719 367e86e8 bellard
                gen_op_mov_reg_T0[ot][rm]();
1720 367e86e8 bellard
            }
1721 5797fa5d bellard
            gen_op_update_neg_cc();
1722 367e86e8 bellard
            s->cc_op = CC_OP_SUBB + ot;
1723 367e86e8 bellard
            break;
1724 367e86e8 bellard
        case 4: /* mul */
1725 367e86e8 bellard
            switch(ot) {
1726 367e86e8 bellard
            case OT_BYTE:
1727 367e86e8 bellard
                gen_op_mulb_AL_T0();
1728 367e86e8 bellard
                break;
1729 367e86e8 bellard
            case OT_WORD:
1730 367e86e8 bellard
                gen_op_mulw_AX_T0();
1731 367e86e8 bellard
                break;
1732 367e86e8 bellard
            default:
1733 367e86e8 bellard
            case OT_LONG:
1734 367e86e8 bellard
                gen_op_mull_EAX_T0();
1735 367e86e8 bellard
                break;
1736 367e86e8 bellard
            }
1737 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1738 367e86e8 bellard
            break;
1739 367e86e8 bellard
        case 5: /* imul */
1740 367e86e8 bellard
            switch(ot) {
1741 367e86e8 bellard
            case OT_BYTE:
1742 367e86e8 bellard
                gen_op_imulb_AL_T0();
1743 367e86e8 bellard
                break;
1744 367e86e8 bellard
            case OT_WORD:
1745 367e86e8 bellard
                gen_op_imulw_AX_T0();
1746 367e86e8 bellard
                break;
1747 367e86e8 bellard
            default:
1748 367e86e8 bellard
            case OT_LONG:
1749 367e86e8 bellard
                gen_op_imull_EAX_T0();
1750 367e86e8 bellard
                break;
1751 367e86e8 bellard
            }
1752 0ecfa993 bellard
            s->cc_op = CC_OP_MUL;
1753 367e86e8 bellard
            break;
1754 367e86e8 bellard
        case 6: /* div */
1755 367e86e8 bellard
            switch(ot) {
1756 367e86e8 bellard
            case OT_BYTE:
1757 5a91de8c bellard
                gen_op_divb_AL_T0(pc_start - s->cs_base);
1758 367e86e8 bellard
                break;
1759 367e86e8 bellard
            case OT_WORD:
1760 5a91de8c bellard
                gen_op_divw_AX_T0(pc_start - s->cs_base);
1761 367e86e8 bellard
                break;
1762 367e86e8 bellard
            default:
1763 367e86e8 bellard
            case OT_LONG:
1764 5a91de8c bellard
                gen_op_divl_EAX_T0(pc_start - s->cs_base);
1765 367e86e8 bellard
                break;
1766 367e86e8 bellard
            }
1767 367e86e8 bellard
            break;
1768 367e86e8 bellard
        case 7: /* idiv */
1769 367e86e8 bellard
            switch(ot) {
1770 367e86e8 bellard
            case OT_BYTE:
1771 5a91de8c bellard
                gen_op_idivb_AL_T0(pc_start - s->cs_base);
1772 367e86e8 bellard
                break;
1773 367e86e8 bellard
            case OT_WORD:
1774 5a91de8c bellard
                gen_op_idivw_AX_T0(pc_start - s->cs_base);
1775 367e86e8 bellard
                break;
1776 367e86e8 bellard
            default:
1777 367e86e8 bellard
            case OT_LONG:
1778 5a91de8c bellard
                gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1779 367e86e8 bellard
                break;
1780 367e86e8 bellard
            }
1781 367e86e8 bellard
            break;
1782 367e86e8 bellard
        default:
1783 1a9353d2 bellard
            goto illegal_op;
1784 367e86e8 bellard
        }
1785 367e86e8 bellard
        break;
1786 367e86e8 bellard
1787 367e86e8 bellard
    case 0xfe: /* GRP4 */
1788 367e86e8 bellard
    case 0xff: /* GRP5 */
1789 367e86e8 bellard
        if ((b & 1) == 0)
1790 367e86e8 bellard
            ot = OT_BYTE;
1791 367e86e8 bellard
        else
1792 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1793 367e86e8 bellard
1794 367e86e8 bellard
        modrm = ldub(s->pc++);
1795 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1796 367e86e8 bellard
        rm = modrm & 7;
1797 367e86e8 bellard
        op = (modrm >> 3) & 7;
1798 367e86e8 bellard
        if (op >= 2 && b == 0xfe) {
1799 1a9353d2 bellard
            goto illegal_op;
1800 367e86e8 bellard
        }
1801 367e86e8 bellard
        if (mod != 3) {
1802 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1803 5797fa5d bellard
            if (op >= 2 && op != 3 && op != 5)
1804 dab2ed99 bellard
                gen_op_ld_T0_A0[ot]();
1805 367e86e8 bellard
        } else {
1806 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1807 367e86e8 bellard
        }
1808 367e86e8 bellard
1809 367e86e8 bellard
        switch(op) {
1810 367e86e8 bellard
        case 0: /* inc Ev */
1811 367e86e8 bellard
            if (mod != 3)
1812 5797fa5d bellard
                opreg = OR_TMP0;
1813 4b74fe1f bellard
            else
1814 5797fa5d bellard
                opreg = rm;
1815 5797fa5d bellard
            gen_inc(s, ot, opreg, 1);
1816 367e86e8 bellard
            break;
1817 367e86e8 bellard
        case 1: /* dec Ev */
1818 367e86e8 bellard
            if (mod != 3)
1819 5797fa5d bellard
                opreg = OR_TMP0;
1820 4b74fe1f bellard
            else
1821 5797fa5d bellard
                opreg = rm;
1822 5797fa5d bellard
            gen_inc(s, ot, opreg, -1);
1823 367e86e8 bellard
            break;
1824 367e86e8 bellard
        case 2: /* call Ev */
1825 dab2ed99 bellard
            /* XXX: optimize if memory (no and is necessary) */
1826 dab2ed99 bellard
            if (s->dflag == 0)
1827 dab2ed99 bellard
                gen_op_andl_T0_ffff();
1828 dab2ed99 bellard
            gen_op_jmp_T0();
1829 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
1830 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
1831 dab2ed99 bellard
            gen_push_T0(s);
1832 dab2ed99 bellard
            s->is_jmp = 1;
1833 dab2ed99 bellard
            break;
1834 dab2ed99 bellard
        case 3: /* lcall Ev */
1835 dab2ed99 bellard
            gen_op_ld_T1_A0[ot]();
1836 dab2ed99 bellard
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1837 dab2ed99 bellard
            gen_op_lduw_T0_A0();
1838 2c1794c4 bellard
        do_lcall:
1839 2c1794c4 bellard
            if (s->pe && !s->vm86) {
1840 2c1794c4 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
1841 2c1794c4 bellard
                    gen_op_set_cc_op(s->cc_op);
1842 2c1794c4 bellard
                gen_op_jmp_im(pc_start - s->cs_base);
1843 2c1794c4 bellard
                gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
1844 2c1794c4 bellard
            } else {
1845 2c1794c4 bellard
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
1846 2c1794c4 bellard
            }
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 2c1794c4 bellard
        do_ljmp:
1860 8f186479 bellard
            if (s->pe && !s->vm86) {
1861 2c1794c4 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
1862 2c1794c4 bellard
                    gen_op_set_cc_op(s->cc_op);
1863 d8bc1fd0 bellard
                gen_op_jmp_im(pc_start - s->cs_base);
1864 2c1794c4 bellard
                gen_op_ljmp_protected_T0_T1();
1865 d8bc1fd0 bellard
            } else {
1866 d8bc1fd0 bellard
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1867 d8bc1fd0 bellard
                gen_op_movl_T0_T1();
1868 d8bc1fd0 bellard
                gen_op_jmp_T0();
1869 d8bc1fd0 bellard
            }
1870 6dbad63e bellard
            s->is_jmp = 1;
1871 367e86e8 bellard
            break;
1872 367e86e8 bellard
        case 6: /* push Ev */
1873 dab2ed99 bellard
            gen_push_T0(s);
1874 367e86e8 bellard
            break;
1875 367e86e8 bellard
        default:
1876 1a9353d2 bellard
            goto illegal_op;
1877 367e86e8 bellard
        }
1878 367e86e8 bellard
        break;
1879 367e86e8 bellard
1880 367e86e8 bellard
    case 0x84: /* test Ev, Gv */
1881 367e86e8 bellard
    case 0x85: 
1882 367e86e8 bellard
        if ((b & 1) == 0)
1883 367e86e8 bellard
            ot = OT_BYTE;
1884 367e86e8 bellard
        else
1885 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1886 367e86e8 bellard
1887 367e86e8 bellard
        modrm = ldub(s->pc++);
1888 367e86e8 bellard
        mod = (modrm >> 6) & 3;
1889 367e86e8 bellard
        rm = modrm & 7;
1890 367e86e8 bellard
        reg = (modrm >> 3) & 7;
1891 367e86e8 bellard
        
1892 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1893 367e86e8 bellard
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1894 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1895 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1896 367e86e8 bellard
        break;
1897 367e86e8 bellard
        
1898 367e86e8 bellard
    case 0xa8: /* test eAX, Iv */
1899 367e86e8 bellard
    case 0xa9:
1900 367e86e8 bellard
        if ((b & 1) == 0)
1901 367e86e8 bellard
            ot = OT_BYTE;
1902 367e86e8 bellard
        else
1903 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1904 367e86e8 bellard
        val = insn_get(s, ot);
1905 367e86e8 bellard
1906 367e86e8 bellard
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1907 ba1c6e37 bellard
        gen_op_movl_T1_im(val);
1908 367e86e8 bellard
        gen_op_testl_T0_T1_cc();
1909 367e86e8 bellard
        s->cc_op = CC_OP_LOGICB + ot;
1910 367e86e8 bellard
        break;
1911 367e86e8 bellard
        
1912 367e86e8 bellard
    case 0x98: /* CWDE/CBW */
1913 367e86e8 bellard
        if (dflag)
1914 367e86e8 bellard
            gen_op_movswl_EAX_AX();
1915 367e86e8 bellard
        else
1916 367e86e8 bellard
            gen_op_movsbw_AX_AL();
1917 367e86e8 bellard
        break;
1918 367e86e8 bellard
    case 0x99: /* CDQ/CWD */
1919 367e86e8 bellard
        if (dflag)
1920 367e86e8 bellard
            gen_op_movslq_EDX_EAX();
1921 367e86e8 bellard
        else
1922 367e86e8 bellard
            gen_op_movswl_DX_AX();
1923 367e86e8 bellard
        break;
1924 367e86e8 bellard
    case 0x1af: /* imul Gv, Ev */
1925 367e86e8 bellard
    case 0x69: /* imul Gv, Ev, I */
1926 367e86e8 bellard
    case 0x6b:
1927 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1928 367e86e8 bellard
        modrm = ldub(s->pc++);
1929 367e86e8 bellard
        reg = ((modrm >> 3) & 7) + OR_EAX;
1930 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1931 367e86e8 bellard
        if (b == 0x69) {
1932 367e86e8 bellard
            val = insn_get(s, ot);
1933 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1934 367e86e8 bellard
        } else if (b == 0x6b) {
1935 367e86e8 bellard
            val = insn_get(s, OT_BYTE);
1936 ba1c6e37 bellard
            gen_op_movl_T1_im(val);
1937 367e86e8 bellard
        } else {
1938 367e86e8 bellard
            gen_op_mov_TN_reg[ot][1][reg]();
1939 367e86e8 bellard
        }
1940 367e86e8 bellard
1941 367e86e8 bellard
        if (ot == OT_LONG) {
1942 4b74fe1f bellard
            gen_op_imull_T0_T1();
1943 367e86e8 bellard
        } else {
1944 4b74fe1f bellard
            gen_op_imulw_T0_T1();
1945 367e86e8 bellard
        }
1946 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
1947 0ecfa993 bellard
        s->cc_op = CC_OP_MUL;
1948 367e86e8 bellard
        break;
1949 1a9353d2 bellard
    case 0x1c0:
1950 1a9353d2 bellard
    case 0x1c1: /* xadd Ev, Gv */
1951 1a9353d2 bellard
        if ((b & 1) == 0)
1952 1a9353d2 bellard
            ot = OT_BYTE;
1953 1a9353d2 bellard
        else
1954 1a9353d2 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1955 1a9353d2 bellard
        modrm = ldub(s->pc++);
1956 1a9353d2 bellard
        reg = (modrm >> 3) & 7;
1957 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
1958 1a9353d2 bellard
        if (mod == 3) {
1959 1a9353d2 bellard
            rm = modrm & 7;
1960 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
1961 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][1][rm]();
1962 5797fa5d bellard
            gen_op_addl_T0_T1();
1963 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
1964 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
1965 1a9353d2 bellard
        } else {
1966 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1967 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
1968 1a9353d2 bellard
            gen_op_ld_T1_A0[ot]();
1969 5797fa5d bellard
            gen_op_addl_T0_T1();
1970 1a9353d2 bellard
            gen_op_st_T0_A0[ot]();
1971 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
1972 1a9353d2 bellard
        }
1973 5797fa5d bellard
        gen_op_update2_cc();
1974 1a9353d2 bellard
        s->cc_op = CC_OP_ADDB + ot;
1975 1a9353d2 bellard
        break;
1976 1a9353d2 bellard
    case 0x1b0:
1977 1a9353d2 bellard
    case 0x1b1: /* cmpxchg Ev, Gv */
1978 1a9353d2 bellard
        if ((b & 1) == 0)
1979 1a9353d2 bellard
            ot = OT_BYTE;
1980 1a9353d2 bellard
        else
1981 1a9353d2 bellard
            ot = dflag ? OT_LONG : OT_WORD;
1982 1a9353d2 bellard
        modrm = ldub(s->pc++);
1983 1a9353d2 bellard
        reg = (modrm >> 3) & 7;
1984 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
1985 1a9353d2 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
1986 1a9353d2 bellard
        if (mod == 3) {
1987 1a9353d2 bellard
            rm = modrm & 7;
1988 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
1989 1a9353d2 bellard
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1990 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
1991 1a9353d2 bellard
        } else {
1992 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1993 1a9353d2 bellard
            gen_op_ld_T0_A0[ot]();
1994 e477b8b8 bellard
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
1995 1a9353d2 bellard
        }
1996 1a9353d2 bellard
        s->cc_op = CC_OP_SUBB + ot;
1997 1a9353d2 bellard
        break;
1998 9c605cb1 bellard
    case 0x1c7: /* cmpxchg8b */
1999 9c605cb1 bellard
        modrm = ldub(s->pc++);
2000 9c605cb1 bellard
        mod = (modrm >> 6) & 3;
2001 9c605cb1 bellard
        if (mod == 3)
2002 9c605cb1 bellard
            goto illegal_op;
2003 9c605cb1 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
2004 9c605cb1 bellard
            gen_op_set_cc_op(s->cc_op);
2005 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2006 9c605cb1 bellard
        gen_op_cmpxchg8b();
2007 9c605cb1 bellard
        s->cc_op = CC_OP_EFLAGS;
2008 9c605cb1 bellard
        break;
2009 367e86e8 bellard
        
2010 367e86e8 bellard
        /**************************/
2011 367e86e8 bellard
        /* push/pop */
2012 367e86e8 bellard
    case 0x50 ... 0x57: /* push */
2013 927f621e bellard
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2014 dab2ed99 bellard
        gen_push_T0(s);
2015 367e86e8 bellard
        break;
2016 367e86e8 bellard
    case 0x58 ... 0x5f: /* pop */
2017 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2018 dab2ed99 bellard
        gen_pop_T0(s);
2019 dab2ed99 bellard
        gen_op_mov_reg_T0[ot][b & 7]();
2020 dab2ed99 bellard
        gen_pop_update(s);
2021 367e86e8 bellard
        break;
2022 27362c82 bellard
    case 0x60: /* pusha */
2023 dab2ed99 bellard
        gen_pusha(s);
2024 27362c82 bellard
        break;
2025 27362c82 bellard
    case 0x61: /* popa */
2026 dab2ed99 bellard
        gen_popa(s);
2027 27362c82 bellard
        break;
2028 367e86e8 bellard
    case 0x68: /* push Iv */
2029 367e86e8 bellard
    case 0x6a:
2030 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2031 367e86e8 bellard
        if (b == 0x68)
2032 367e86e8 bellard
            val = insn_get(s, ot);
2033 367e86e8 bellard
        else
2034 367e86e8 bellard
            val = (int8_t)insn_get(s, OT_BYTE);
2035 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2036 dab2ed99 bellard
        gen_push_T0(s);
2037 367e86e8 bellard
        break;
2038 367e86e8 bellard
    case 0x8f: /* pop Ev */
2039 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2040 367e86e8 bellard
        modrm = ldub(s->pc++);
2041 dab2ed99 bellard
        gen_pop_T0(s);
2042 8f186479 bellard
        s->popl_esp_hack = 2 << dflag;
2043 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2044 717fc2ad bellard
        s->popl_esp_hack = 0;
2045 dab2ed99 bellard
        gen_pop_update(s);
2046 367e86e8 bellard
        break;
2047 27362c82 bellard
    case 0xc8: /* enter */
2048 27362c82 bellard
        {
2049 27362c82 bellard
            int level;
2050 27362c82 bellard
            val = lduw(s->pc);
2051 27362c82 bellard
            s->pc += 2;
2052 27362c82 bellard
            level = ldub(s->pc++);
2053 dab2ed99 bellard
            gen_enter(s, val, level);
2054 27362c82 bellard
        }
2055 27362c82 bellard
        break;
2056 367e86e8 bellard
    case 0xc9: /* leave */
2057 d0a1ffc9 bellard
        /* XXX: exception not precise (ESP is updated before potential exception) */
2058 dab2ed99 bellard
        if (s->ss32) {
2059 dab2ed99 bellard
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2060 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2061 dab2ed99 bellard
        } else {
2062 dab2ed99 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2063 dab2ed99 bellard
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2064 dab2ed99 bellard
        }
2065 dab2ed99 bellard
        gen_pop_T0(s);
2066 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2067 dab2ed99 bellard
        gen_op_mov_reg_T0[ot][R_EBP]();
2068 dab2ed99 bellard
        gen_pop_update(s);
2069 367e86e8 bellard
        break;
2070 6dbad63e bellard
    case 0x06: /* push es */
2071 6dbad63e bellard
    case 0x0e: /* push cs */
2072 6dbad63e bellard
    case 0x16: /* push ss */
2073 6dbad63e bellard
    case 0x1e: /* push ds */
2074 6dbad63e bellard
        gen_op_movl_T0_seg(b >> 3);
2075 dab2ed99 bellard
        gen_push_T0(s);
2076 6dbad63e bellard
        break;
2077 6dbad63e bellard
    case 0x1a0: /* push fs */
2078 6dbad63e bellard
    case 0x1a8: /* push gs */
2079 f631ef9b bellard
        gen_op_movl_T0_seg((b >> 3) & 7);
2080 dab2ed99 bellard
        gen_push_T0(s);
2081 6dbad63e bellard
        break;
2082 6dbad63e bellard
    case 0x07: /* pop es */
2083 6dbad63e bellard
    case 0x17: /* pop ss */
2084 6dbad63e bellard
    case 0x1f: /* pop ds */
2085 dab2ed99 bellard
        gen_pop_T0(s);
2086 5a91de8c bellard
        gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2087 dab2ed99 bellard
        gen_pop_update(s);
2088 8f186479 bellard
        /* XXX: if reg == SS, inhibit interrupts/trace */
2089 6dbad63e bellard
        break;
2090 6dbad63e bellard
    case 0x1a1: /* pop fs */
2091 6dbad63e bellard
    case 0x1a9: /* pop gs */
2092 dab2ed99 bellard
        gen_pop_T0(s);
2093 5a91de8c bellard
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2094 dab2ed99 bellard
        gen_pop_update(s);
2095 6dbad63e bellard
        break;
2096 6dbad63e bellard
2097 367e86e8 bellard
        /**************************/
2098 367e86e8 bellard
        /* mov */
2099 367e86e8 bellard
    case 0x88:
2100 367e86e8 bellard
    case 0x89: /* mov Gv, Ev */
2101 367e86e8 bellard
        if ((b & 1) == 0)
2102 367e86e8 bellard
            ot = OT_BYTE;
2103 367e86e8 bellard
        else
2104 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2105 367e86e8 bellard
        modrm = ldub(s->pc++);
2106 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2107 367e86e8 bellard
        
2108 367e86e8 bellard
        /* generate a generic store */
2109 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2110 367e86e8 bellard
        break;
2111 367e86e8 bellard
    case 0xc6:
2112 367e86e8 bellard
    case 0xc7: /* mov Ev, Iv */
2113 367e86e8 bellard
        if ((b & 1) == 0)
2114 367e86e8 bellard
            ot = OT_BYTE;
2115 367e86e8 bellard
        else
2116 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2117 367e86e8 bellard
        modrm = ldub(s->pc++);
2118 367e86e8 bellard
        mod = (modrm >> 6) & 3;
2119 0ecfa993 bellard
        if (mod != 3)
2120 0ecfa993 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2121 367e86e8 bellard
        val = insn_get(s, ot);
2122 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2123 0ecfa993 bellard
        if (mod != 3)
2124 0ecfa993 bellard
            gen_op_st_T0_A0[ot]();
2125 0ecfa993 bellard
        else
2126 0ecfa993 bellard
            gen_op_mov_reg_T0[ot][modrm & 7]();
2127 367e86e8 bellard
        break;
2128 367e86e8 bellard
    case 0x8a:
2129 367e86e8 bellard
    case 0x8b: /* mov Ev, Gv */
2130 367e86e8 bellard
        if ((b & 1) == 0)
2131 367e86e8 bellard
            ot = OT_BYTE;
2132 367e86e8 bellard
        else
2133 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2134 367e86e8 bellard
        modrm = ldub(s->pc++);
2135 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2136 367e86e8 bellard
        
2137 367e86e8 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2138 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
2139 367e86e8 bellard
        break;
2140 6dbad63e bellard
    case 0x8e: /* mov seg, Gv */
2141 6dbad63e bellard
        modrm = ldub(s->pc++);
2142 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2143 dab2ed99 bellard
        if (reg >= 6 || reg == R_CS)
2144 6dbad63e bellard
            goto illegal_op;
2145 8f186479 bellard
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2146 5a91de8c bellard
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2147 8f186479 bellard
        /* XXX: if reg == SS, inhibit interrupts/trace */
2148 6dbad63e bellard
        break;
2149 6dbad63e bellard
    case 0x8c: /* mov Gv, seg */
2150 6dbad63e bellard
        modrm = ldub(s->pc++);
2151 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2152 8f186479 bellard
        mod = (modrm >> 6) & 3;
2153 6dbad63e bellard
        if (reg >= 6)
2154 6dbad63e bellard
            goto illegal_op;
2155 6dbad63e bellard
        gen_op_movl_T0_seg(reg);
2156 8f186479 bellard
        ot = OT_WORD;
2157 8f186479 bellard
        if (mod == 3 && dflag)
2158 8f186479 bellard
            ot = OT_LONG;
2159 6dbad63e bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2160 6dbad63e bellard
        break;
2161 367e86e8 bellard
2162 367e86e8 bellard
    case 0x1b6: /* movzbS Gv, Eb */
2163 367e86e8 bellard
    case 0x1b7: /* movzwS Gv, Eb */
2164 367e86e8 bellard
    case 0x1be: /* movsbS Gv, Eb */
2165 367e86e8 bellard
    case 0x1bf: /* movswS Gv, Eb */
2166 367e86e8 bellard
        {
2167 367e86e8 bellard
            int d_ot;
2168 367e86e8 bellard
            /* d_ot is the size of destination */
2169 367e86e8 bellard
            d_ot = dflag + OT_WORD;
2170 367e86e8 bellard
            /* ot is the size of source */
2171 367e86e8 bellard
            ot = (b & 1) + OT_BYTE;
2172 367e86e8 bellard
            modrm = ldub(s->pc++);
2173 367e86e8 bellard
            reg = ((modrm >> 3) & 7) + OR_EAX;
2174 367e86e8 bellard
            mod = (modrm >> 6) & 3;
2175 367e86e8 bellard
            rm = modrm & 7;
2176 367e86e8 bellard
            
2177 367e86e8 bellard
            if (mod == 3) {
2178 367e86e8 bellard
                gen_op_mov_TN_reg[ot][0][rm]();
2179 367e86e8 bellard
                switch(ot | (b & 8)) {
2180 367e86e8 bellard
                case OT_BYTE:
2181 367e86e8 bellard
                    gen_op_movzbl_T0_T0();
2182 367e86e8 bellard
                    break;
2183 367e86e8 bellard
                case OT_BYTE | 8:
2184 367e86e8 bellard
                    gen_op_movsbl_T0_T0();
2185 367e86e8 bellard
                    break;
2186 367e86e8 bellard
                case OT_WORD:
2187 367e86e8 bellard
                    gen_op_movzwl_T0_T0();
2188 367e86e8 bellard
                    break;
2189 367e86e8 bellard
                default:
2190 367e86e8 bellard
                case OT_WORD | 8:
2191 367e86e8 bellard
                    gen_op_movswl_T0_T0();
2192 367e86e8 bellard
                    break;
2193 367e86e8 bellard
                }
2194 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
2195 367e86e8 bellard
            } else {
2196 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2197 367e86e8 bellard
                if (b & 8) {
2198 367e86e8 bellard
                    gen_op_lds_T0_A0[ot]();
2199 367e86e8 bellard
                } else {
2200 367e86e8 bellard
                    gen_op_ldu_T0_A0[ot]();
2201 367e86e8 bellard
                }
2202 367e86e8 bellard
                gen_op_mov_reg_T0[d_ot][reg]();
2203 367e86e8 bellard
            }
2204 367e86e8 bellard
        }
2205 367e86e8 bellard
        break;
2206 367e86e8 bellard
2207 367e86e8 bellard
    case 0x8d: /* lea */
2208 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2209 367e86e8 bellard
        modrm = ldub(s->pc++);
2210 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2211 6dbad63e bellard
        /* we must ensure that no segment is added */
2212 9c605cb1 bellard
        s->override = -1;
2213 6dbad63e bellard
        val = s->addseg;
2214 6dbad63e bellard
        s->addseg = 0;
2215 367e86e8 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2216 6dbad63e bellard
        s->addseg = val;
2217 367e86e8 bellard
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2218 367e86e8 bellard
        break;
2219 367e86e8 bellard
        
2220 367e86e8 bellard
    case 0xa0: /* mov EAX, Ov */
2221 367e86e8 bellard
    case 0xa1:
2222 367e86e8 bellard
    case 0xa2: /* mov Ov, EAX */
2223 367e86e8 bellard
    case 0xa3:
2224 367e86e8 bellard
        if ((b & 1) == 0)
2225 367e86e8 bellard
            ot = OT_BYTE;
2226 367e86e8 bellard
        else
2227 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2228 367e86e8 bellard
        if (s->aflag)
2229 367e86e8 bellard
            offset_addr = insn_get(s, OT_LONG);
2230 367e86e8 bellard
        else
2231 367e86e8 bellard
            offset_addr = insn_get(s, OT_WORD);
2232 4b74fe1f bellard
        gen_op_movl_A0_im(offset_addr);
2233 1a9353d2 bellard
        /* handle override */
2234 1a9353d2 bellard
        {
2235 1a9353d2 bellard
            int override, must_add_seg;
2236 1a9353d2 bellard
            must_add_seg = s->addseg;
2237 9c605cb1 bellard
            if (s->override >= 0) {
2238 9c605cb1 bellard
                override = s->override;
2239 1a9353d2 bellard
                must_add_seg = 1;
2240 9c605cb1 bellard
            } else {
2241 9c605cb1 bellard
                override = R_DS;
2242 1a9353d2 bellard
            }
2243 1a9353d2 bellard
            if (must_add_seg) {
2244 d8bc1fd0 bellard
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2245 1a9353d2 bellard
            }
2246 1a9353d2 bellard
        }
2247 367e86e8 bellard
        if ((b & 2) == 0) {
2248 367e86e8 bellard
            gen_op_ld_T0_A0[ot]();
2249 367e86e8 bellard
            gen_op_mov_reg_T0[ot][R_EAX]();
2250 367e86e8 bellard
        } else {
2251 367e86e8 bellard
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2252 367e86e8 bellard
            gen_op_st_T0_A0[ot]();
2253 367e86e8 bellard
        }
2254 367e86e8 bellard
        break;
2255 31bb950b bellard
    case 0xd7: /* xlat */
2256 31bb950b bellard
        gen_op_movl_A0_reg[R_EBX]();
2257 31bb950b bellard
        gen_op_addl_A0_AL();
2258 31bb950b bellard
        if (s->aflag == 0)
2259 31bb950b bellard
            gen_op_andl_A0_ffff();
2260 9c605cb1 bellard
        /* handle override */
2261 31bb950b bellard
        {
2262 31bb950b bellard
            int override, must_add_seg;
2263 31bb950b bellard
            must_add_seg = s->addseg;
2264 9c605cb1 bellard
            override = R_DS;
2265 9c605cb1 bellard
            if (s->override >= 0) {
2266 9c605cb1 bellard
                override = s->override;
2267 31bb950b bellard
                must_add_seg = 1;
2268 9c605cb1 bellard
            } else {
2269 9c605cb1 bellard
                override = R_DS;
2270 31bb950b bellard
            }
2271 31bb950b bellard
            if (must_add_seg) {
2272 d8bc1fd0 bellard
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2273 31bb950b bellard
            }
2274 31bb950b bellard
        }
2275 31bb950b bellard
        gen_op_ldub_T0_A0();
2276 31bb950b bellard
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2277 31bb950b bellard
        break;
2278 367e86e8 bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
2279 367e86e8 bellard
        val = insn_get(s, OT_BYTE);
2280 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2281 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2282 367e86e8 bellard
        break;
2283 367e86e8 bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
2284 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2285 367e86e8 bellard
        val = insn_get(s, ot);
2286 367e86e8 bellard
        reg = OR_EAX + (b & 7);
2287 ba1c6e37 bellard
        gen_op_movl_T0_im(val);
2288 367e86e8 bellard
        gen_op_mov_reg_T0[ot][reg]();
2289 367e86e8 bellard
        break;
2290 367e86e8 bellard
2291 367e86e8 bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
2292 367e86e8 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2293 367e86e8 bellard
        reg = b & 7;
2294 1a9353d2 bellard
        rm = R_EAX;
2295 1a9353d2 bellard
        goto do_xchg_reg;
2296 367e86e8 bellard
    case 0x86:
2297 367e86e8 bellard
    case 0x87: /* xchg Ev, Gv */
2298 367e86e8 bellard
        if ((b & 1) == 0)
2299 367e86e8 bellard
            ot = OT_BYTE;
2300 367e86e8 bellard
        else
2301 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2302 367e86e8 bellard
        modrm = ldub(s->pc++);
2303 367e86e8 bellard
        reg = (modrm >> 3) & 7;
2304 1a9353d2 bellard
        mod = (modrm >> 6) & 3;
2305 1a9353d2 bellard
        if (mod == 3) {
2306 1a9353d2 bellard
            rm = modrm & 7;
2307 1a9353d2 bellard
        do_xchg_reg:
2308 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
2309 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][1][rm]();
2310 1a9353d2 bellard
            gen_op_mov_reg_T0[ot][rm]();
2311 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
2312 1a9353d2 bellard
        } else {
2313 1a9353d2 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2314 1a9353d2 bellard
            gen_op_mov_TN_reg[ot][0][reg]();
2315 31bb950b bellard
            /* for xchg, lock is implicit */
2316 31bb950b bellard
            if (!(prefixes & PREFIX_LOCK))
2317 31bb950b bellard
                gen_op_lock();
2318 1a9353d2 bellard
            gen_op_ld_T1_A0[ot]();
2319 1a9353d2 bellard
            gen_op_st_T0_A0[ot]();
2320 31bb950b bellard
            if (!(prefixes & PREFIX_LOCK))
2321 31bb950b bellard
                gen_op_unlock();
2322 1a9353d2 bellard
            gen_op_mov_reg_T1[ot][reg]();
2323 1a9353d2 bellard
        }
2324 367e86e8 bellard
        break;
2325 6dbad63e bellard
    case 0xc4: /* les Gv */
2326 6dbad63e bellard
        op = R_ES;
2327 6dbad63e bellard
        goto do_lxx;
2328 6dbad63e bellard
    case 0xc5: /* lds Gv */
2329 6dbad63e bellard
        op = R_DS;
2330 6dbad63e bellard
        goto do_lxx;
2331 6dbad63e bellard
    case 0x1b2: /* lss Gv */
2332 6dbad63e bellard
        op = R_SS;
2333 6dbad63e bellard
        goto do_lxx;
2334 6dbad63e bellard
    case 0x1b4: /* lfs Gv */
2335 6dbad63e bellard
        op = R_FS;
2336 6dbad63e bellard
        goto do_lxx;
2337 6dbad63e bellard
    case 0x1b5: /* lgs Gv */
2338 6dbad63e bellard
        op = R_GS;
2339 6dbad63e bellard
    do_lxx:
2340 6dbad63e bellard
        ot = dflag ? OT_LONG : OT_WORD;
2341 6dbad63e bellard
        modrm = ldub(s->pc++);
2342 6dbad63e bellard
        reg = (modrm >> 3) & 7;
2343 6dbad63e bellard
        mod = (modrm >> 6) & 3;
2344 6dbad63e bellard
        if (mod == 3)
2345 6dbad63e bellard
            goto illegal_op;
2346 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2347 6dbad63e bellard
        gen_op_ld_T1_A0[ot]();
2348 dc99065b bellard
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2349 6dbad63e bellard
        /* load the segment first to handle exceptions properly */
2350 6dbad63e bellard
        gen_op_lduw_T0_A0();
2351 5a91de8c bellard
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2352 6dbad63e bellard
        /* then put the data */
2353 6dbad63e bellard
        gen_op_mov_reg_T1[ot][reg]();
2354 6dbad63e bellard
        break;
2355 367e86e8 bellard
        
2356 367e86e8 bellard
        /************************/
2357 367e86e8 bellard
        /* shifts */
2358 367e86e8 bellard
    case 0xc0:
2359 367e86e8 bellard
    case 0xc1:
2360 367e86e8 bellard
        /* shift Ev,Ib */
2361 367e86e8 bellard
        shift = 2;
2362 367e86e8 bellard
    grp2:
2363 367e86e8 bellard
        {
2364 367e86e8 bellard
            if ((b & 1) == 0)
2365 367e86e8 bellard
                ot = OT_BYTE;
2366 367e86e8 bellard
            else
2367 367e86e8 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2368 367e86e8 bellard
            
2369 367e86e8 bellard
            modrm = ldub(s->pc++);
2370 367e86e8 bellard
            mod = (modrm >> 6) & 3;
2371 367e86e8 bellard
            rm = modrm & 7;
2372 367e86e8 bellard
            op = (modrm >> 3) & 7;
2373 367e86e8 bellard
            
2374 367e86e8 bellard
            if (mod != 3) {
2375 367e86e8 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2376 367e86e8 bellard
                opreg = OR_TMP0;
2377 367e86e8 bellard
            } else {
2378 367e86e8 bellard
                opreg = rm + OR_EAX;
2379 367e86e8 bellard
            }
2380 367e86e8 bellard
2381 367e86e8 bellard
            /* simpler op */
2382 367e86e8 bellard
            if (shift == 0) {
2383 367e86e8 bellard
                gen_shift(s, op, ot, opreg, OR_ECX);
2384 367e86e8 bellard
            } else {
2385 367e86e8 bellard
                if (shift == 2) {
2386 367e86e8 bellard
                    shift = ldub(s->pc++);
2387 367e86e8 bellard
                }
2388 367e86e8 bellard
                gen_shifti(s, op, ot, opreg, shift);
2389 367e86e8 bellard
            }
2390 367e86e8 bellard
        }
2391 367e86e8 bellard
        break;
2392 367e86e8 bellard
    case 0xd0:
2393 367e86e8 bellard
    case 0xd1:
2394 367e86e8 bellard
        /* shift Ev,1 */
2395 367e86e8 bellard
        shift = 1;
2396 367e86e8 bellard
        goto grp2;
2397 367e86e8 bellard
    case 0xd2:
2398 367e86e8 bellard
    case 0xd3:
2399 367e86e8 bellard
        /* shift Ev,cl */
2400 367e86e8 bellard
        shift = 0;
2401 367e86e8 bellard
        goto grp2;
2402 367e86e8 bellard
2403 d57c4e01 bellard
    case 0x1a4: /* shld imm */
2404 d57c4e01 bellard
        op = 0;
2405 d57c4e01 bellard
        shift = 1;
2406 d57c4e01 bellard
        goto do_shiftd;
2407 d57c4e01 bellard
    case 0x1a5: /* shld cl */
2408 d57c4e01 bellard
        op = 0;
2409 d57c4e01 bellard
        shift = 0;
2410 d57c4e01 bellard
        goto do_shiftd;
2411 d57c4e01 bellard
    case 0x1ac: /* shrd imm */
2412 d57c4e01 bellard
        op = 1;
2413 d57c4e01 bellard
        shift = 1;
2414 d57c4e01 bellard
        goto do_shiftd;
2415 d57c4e01 bellard
    case 0x1ad: /* shrd cl */
2416 d57c4e01 bellard
        op = 1;
2417 d57c4e01 bellard
        shift = 0;
2418 d57c4e01 bellard
    do_shiftd:
2419 d57c4e01 bellard
        ot = dflag ? OT_LONG : OT_WORD;
2420 d57c4e01 bellard
        modrm = ldub(s->pc++);
2421 d57c4e01 bellard
        mod = (modrm >> 6) & 3;
2422 d57c4e01 bellard
        rm = modrm & 7;
2423 d57c4e01 bellard
        reg = (modrm >> 3) & 7;
2424 d57c4e01 bellard
        
2425 d57c4e01 bellard
        if (mod != 3) {
2426 d57c4e01 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2427 d57c4e01 bellard
            gen_op_ld_T0_A0[ot]();
2428 d57c4e01 bellard
        } else {
2429 d57c4e01 bellard
            gen_op_mov_TN_reg[ot][0][rm]();
2430 d57c4e01 bellard
        }
2431 d57c4e01 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
2432 d57c4e01 bellard
        
2433 d57c4e01 bellard
        if (shift) {
2434 d57c4e01 bellard
            val = ldub(s->pc++);
2435 d57c4e01 bellard
            val &= 0x1f;
2436 d57c4e01 bellard
            if (val) {
2437 e477b8b8 bellard
                if (mod == 3)
2438 e477b8b8 bellard
                    gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2439 e477b8b8 bellard
                else
2440 e477b8b8 bellard
                    gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
2441 d57c4e01 bellard
                if (op == 0 && ot != OT_WORD)
2442 d57c4e01 bellard
                    s->cc_op = CC_OP_SHLB + ot;
2443 d57c4e01 bellard
                else
2444 d57c4e01 bellard
                    s->cc_op = CC_OP_SARB + ot;
2445 d57c4e01 bellard
            }
2446 d57c4e01 bellard
        } else {
2447 d57c4e01 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2448 d57c4e01 bellard
                gen_op_set_cc_op(s->cc_op);
2449 e477b8b8 bellard
            if (mod == 3)
2450 e477b8b8 bellard
                gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2451 e477b8b8 bellard
            else
2452 e477b8b8 bellard
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
2453 d57c4e01 bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2454 d57c4e01 bellard
        }
2455 e477b8b8 bellard
        if (mod == 3) {
2456 d57c4e01 bellard
            gen_op_mov_reg_T0[ot][rm]();
2457 d57c4e01 bellard
        }
2458 d57c4e01 bellard
        break;
2459 d57c4e01 bellard
2460 367e86e8 bellard
        /************************/
2461 367e86e8 bellard
        /* floats */
2462 367e86e8 bellard
    case 0xd8 ... 0xdf: 
2463 367e86e8 bellard
        modrm = ldub(s->pc++);
2464 367e86e8 bellard
        mod = (modrm >> 6) & 3;
2465 367e86e8 bellard
        rm = modrm & 7;
2466 367e86e8 bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2467 367e86e8 bellard
        
2468 367e86e8 bellard
        if (mod != 3) {
2469 367e86e8 bellard
            /* memory op */
2470 367e86e8 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2471 367e86e8 bellard
            switch(op) {
2472 367e86e8 bellard
            case 0x00 ... 0x07: /* fxxxs */
2473 367e86e8 bellard
            case 0x10 ... 0x17: /* fixxxl */
2474 367e86e8 bellard
            case 0x20 ... 0x27: /* fxxxl */
2475 367e86e8 bellard
            case 0x30 ... 0x37: /* fixxx */
2476 367e86e8 bellard
                {
2477 927f621e bellard
                    int op1;
2478 927f621e bellard
                    op1 = op & 7;
2479 367e86e8 bellard
2480 367e86e8 bellard
                    switch(op >> 4) {
2481 367e86e8 bellard
                    case 0:
2482 927f621e bellard
                        gen_op_flds_FT0_A0();
2483 367e86e8 bellard
                        break;
2484 367e86e8 bellard
                    case 1:
2485 927f621e bellard
                        gen_op_fildl_FT0_A0();
2486 367e86e8 bellard
                        break;
2487 367e86e8 bellard
                    case 2:
2488 927f621e bellard
                        gen_op_fldl_FT0_A0();
2489 367e86e8 bellard
                        break;
2490 367e86e8 bellard
                    case 3:
2491 367e86e8 bellard
                    default:
2492 927f621e bellard
                        gen_op_fild_FT0_A0();
2493 367e86e8 bellard
                        break;
2494 367e86e8 bellard
                    }
2495 367e86e8 bellard
                    
2496 927f621e bellard
                    gen_op_fp_arith_ST0_FT0[op1]();
2497 927f621e bellard
                    if (op1 == 3) {
2498 367e86e8 bellard
                        /* fcomp needs pop */
2499 927f621e bellard
                        gen_op_fpop();
2500 367e86e8 bellard
                    }
2501 367e86e8 bellard
                }
2502 367e86e8 bellard
                break;
2503 367e86e8 bellard
            case 0x08: /* flds */
2504 367e86e8 bellard
            case 0x0a: /* fsts */
2505 367e86e8 bellard
            case 0x0b: /* fstps */
2506 367e86e8 bellard
            case 0x18: /* fildl */
2507 367e86e8 bellard
            case 0x1a: /* fistl */
2508 367e86e8 bellard
            case 0x1b: /* fistpl */
2509 367e86e8 bellard
            case 0x28: /* fldl */
2510 367e86e8 bellard
            case 0x2a: /* fstl */
2511 367e86e8 bellard
            case 0x2b: /* fstpl */
2512 367e86e8 bellard
            case 0x38: /* filds */
2513 367e86e8 bellard
            case 0x3a: /* fists */
2514 367e86e8 bellard
            case 0x3b: /* fistps */
2515 367e86e8 bellard
                
2516 367e86e8 bellard
                switch(op & 7) {
2517 367e86e8 bellard
                case 0:
2518 927f621e bellard
                    switch(op >> 4) {
2519 927f621e bellard
                    case 0:
2520 927f621e bellard
                        gen_op_flds_ST0_A0();
2521 927f621e bellard
                        break;
2522 927f621e bellard
                    case 1:
2523 927f621e bellard
                        gen_op_fildl_ST0_A0();
2524 927f621e bellard
                        break;
2525 927f621e bellard
                    case 2:
2526 927f621e bellard
                        gen_op_fldl_ST0_A0();
2527 927f621e bellard
                        break;
2528 927f621e bellard
                    case 3:
2529 927f621e bellard
                    default:
2530 927f621e bellard
                        gen_op_fild_ST0_A0();
2531 927f621e bellard
                        break;
2532 367e86e8 bellard
                    }
2533 367e86e8 bellard
                    break;
2534 367e86e8 bellard
                default:
2535 927f621e bellard
                    switch(op >> 4) {
2536 927f621e bellard
                    case 0:
2537 927f621e bellard
                        gen_op_fsts_ST0_A0();
2538 927f621e bellard
                        break;
2539 927f621e bellard
                    case 1:
2540 927f621e bellard
                        gen_op_fistl_ST0_A0();
2541 927f621e bellard
                        break;
2542 927f621e bellard
                    case 2:
2543 927f621e bellard
                        gen_op_fstl_ST0_A0();
2544 927f621e bellard
                        break;
2545 927f621e bellard
                    case 3:
2546 927f621e bellard
                    default:
2547 927f621e bellard
                        gen_op_fist_ST0_A0();
2548 927f621e bellard
                        break;
2549 367e86e8 bellard
                    }
2550 367e86e8 bellard
                    if ((op & 7) == 3)
2551 927f621e bellard
                        gen_op_fpop();
2552 367e86e8 bellard
                    break;
2553 367e86e8 bellard
                }
2554 367e86e8 bellard
                break;
2555 d0a1ffc9 bellard
            case 0x0c: /* fldenv mem */
2556 d0a1ffc9 bellard
                gen_op_fldenv_A0(s->dflag);
2557 d0a1ffc9 bellard
                break;
2558 4b74fe1f bellard
            case 0x0d: /* fldcw mem */
2559 4b74fe1f bellard
                gen_op_fldcw_A0();
2560 4b74fe1f bellard
                break;
2561 d0a1ffc9 bellard
            case 0x0e: /* fnstenv mem */
2562 d0a1ffc9 bellard
                gen_op_fnstenv_A0(s->dflag);
2563 d0a1ffc9 bellard
                break;
2564 4b74fe1f bellard
            case 0x0f: /* fnstcw mem */
2565 4b74fe1f bellard
                gen_op_fnstcw_A0();
2566 4b74fe1f bellard
                break;
2567 77f8dd5a bellard
            case 0x1d: /* fldt mem */
2568 77f8dd5a bellard
                gen_op_fldt_ST0_A0();
2569 77f8dd5a bellard
                break;
2570 77f8dd5a bellard
            case 0x1f: /* fstpt mem */
2571 77f8dd5a bellard
                gen_op_fstt_ST0_A0();
2572 77f8dd5a bellard
                gen_op_fpop();
2573 77f8dd5a bellard
                break;
2574 d0a1ffc9 bellard
            case 0x2c: /* frstor mem */
2575 d0a1ffc9 bellard
                gen_op_frstor_A0(s->dflag);
2576 d0a1ffc9 bellard
                break;
2577 d0a1ffc9 bellard
            case 0x2e: /* fnsave mem */
2578 d0a1ffc9 bellard
                gen_op_fnsave_A0(s->dflag);
2579 d0a1ffc9 bellard
                break;
2580 367e86e8 bellard
            case 0x2f: /* fnstsw mem */
2581 4b74fe1f bellard
                gen_op_fnstsw_A0();
2582 367e86e8 bellard
                break;
2583 367e86e8 bellard
            case 0x3c: /* fbld */
2584 1017ebe9 bellard
                gen_op_fbld_ST0_A0();
2585 77f8dd5a bellard
                break;
2586 367e86e8 bellard
            case 0x3e: /* fbstp */
2587 77f8dd5a bellard
                gen_op_fbst_ST0_A0();
2588 77f8dd5a bellard
                gen_op_fpop();
2589 77f8dd5a bellard
                break;
2590 367e86e8 bellard
            case 0x3d: /* fildll */
2591 927f621e bellard
                gen_op_fildll_ST0_A0();
2592 367e86e8 bellard
                break;
2593 367e86e8 bellard
            case 0x3f: /* fistpll */
2594 927f621e bellard
                gen_op_fistll_ST0_A0();
2595 927f621e bellard
                gen_op_fpop();
2596 367e86e8 bellard
                break;
2597 367e86e8 bellard
            default:
2598 1a9353d2 bellard
                goto illegal_op;
2599 367e86e8 bellard
            }
2600 367e86e8 bellard
        } else {
2601 367e86e8 bellard
            /* register float ops */
2602 927f621e bellard
            opreg = rm;
2603 367e86e8 bellard
2604 367e86e8 bellard
            switch(op) {
2605 367e86e8 bellard
            case 0x08: /* fld sti */
2606 927f621e bellard
                gen_op_fpush();
2607 927f621e bellard
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2608 367e86e8 bellard
                break;
2609 367e86e8 bellard
            case 0x09: /* fxchg sti */
2610 77f8dd5a bellard
                gen_op_fxchg_ST0_STN(opreg);
2611 367e86e8 bellard
                break;
2612 367e86e8 bellard
            case 0x0a: /* grp d9/2 */
2613 367e86e8 bellard
                switch(rm) {
2614 367e86e8 bellard
                case 0: /* fnop */
2615 367e86e8 bellard
                    break;
2616 367e86e8 bellard
                default:
2617 1a9353d2 bellard
                    goto illegal_op;
2618 367e86e8 bellard
                }
2619 367e86e8 bellard
                break;
2620 367e86e8 bellard
            case 0x0c: /* grp d9/4 */
2621 367e86e8 bellard
                switch(rm) {
2622 367e86e8 bellard
                case 0: /* fchs */
2623 927f621e bellard
                    gen_op_fchs_ST0();
2624 367e86e8 bellard
                    break;
2625 367e86e8 bellard
                case 1: /* fabs */
2626 927f621e bellard
                    gen_op_fabs_ST0();
2627 367e86e8 bellard
                    break;
2628 367e86e8 bellard
                case 4: /* ftst */
2629 927f621e bellard
                    gen_op_fldz_FT0();
2630 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2631 367e86e8 bellard
                    break;
2632 367e86e8 bellard
                case 5: /* fxam */
2633 927f621e bellard
                    gen_op_fxam_ST0();
2634 367e86e8 bellard
                    break;
2635 367e86e8 bellard
                default:
2636 1a9353d2 bellard
                    goto illegal_op;
2637 367e86e8 bellard
                }
2638 367e86e8 bellard
                break;
2639 367e86e8 bellard
            case 0x0d: /* grp d9/5 */
2640 367e86e8 bellard
                {
2641 927f621e bellard
                    switch(rm) {
2642 927f621e bellard
                    case 0:
2643 77f8dd5a bellard
                        gen_op_fpush();
2644 927f621e bellard
                        gen_op_fld1_ST0();
2645 927f621e bellard
                        break;
2646 927f621e bellard
                    case 1:
2647 77f8dd5a bellard
                        gen_op_fpush();
2648 77f8dd5a bellard
                        gen_op_fldl2t_ST0();
2649 927f621e bellard
                        break;
2650 927f621e bellard
                    case 2:
2651 77f8dd5a bellard
                        gen_op_fpush();
2652 77f8dd5a bellard
                        gen_op_fldl2e_ST0();
2653 927f621e bellard
                        break;
2654 927f621e bellard
                    case 3:
2655 77f8dd5a bellard
                        gen_op_fpush();
2656 927f621e bellard
                        gen_op_fldpi_ST0();
2657 927f621e bellard
                        break;
2658 927f621e bellard
                    case 4:
2659 77f8dd5a bellard
                        gen_op_fpush();
2660 927f621e bellard
                        gen_op_fldlg2_ST0();
2661 927f621e bellard
                        break;
2662 927f621e bellard
                    case 5:
2663 77f8dd5a bellard
                        gen_op_fpush();
2664 927f621e bellard
                        gen_op_fldln2_ST0();
2665 927f621e bellard
                        break;
2666 927f621e bellard
                    case 6:
2667 77f8dd5a bellard
                        gen_op_fpush();
2668 927f621e bellard
                        gen_op_fldz_ST0();
2669 927f621e bellard
                        break;
2670 927f621e bellard
                    default:
2671 1a9353d2 bellard
                        goto illegal_op;
2672 367e86e8 bellard
                    }
2673 367e86e8 bellard
                }
2674 367e86e8 bellard
                break;
2675 367e86e8 bellard
            case 0x0e: /* grp d9/6 */
2676 367e86e8 bellard
                switch(rm) {
2677 367e86e8 bellard
                case 0: /* f2xm1 */
2678 927f621e bellard
                    gen_op_f2xm1();
2679 367e86e8 bellard
                    break;
2680 367e86e8 bellard
                case 1: /* fyl2x */
2681 927f621e bellard
                    gen_op_fyl2x();
2682 367e86e8 bellard
                    break;
2683 367e86e8 bellard
                case 2: /* fptan */
2684 927f621e bellard
                    gen_op_fptan();
2685 367e86e8 bellard
                    break;
2686 367e86e8 bellard
                case 3: /* fpatan */
2687 927f621e bellard
                    gen_op_fpatan();
2688 367e86e8 bellard
                    break;
2689 367e86e8 bellard
                case 4: /* fxtract */
2690 927f621e bellard
                    gen_op_fxtract();
2691 367e86e8 bellard
                    break;
2692 367e86e8 bellard
                case 5: /* fprem1 */
2693 927f621e bellard
                    gen_op_fprem1();
2694 367e86e8 bellard
                    break;
2695 367e86e8 bellard
                case 6: /* fdecstp */
2696 927f621e bellard
                    gen_op_fdecstp();
2697 367e86e8 bellard
                    break;
2698 367e86e8 bellard
                default:
2699 927f621e bellard
                case 7: /* fincstp */
2700 927f621e bellard
                    gen_op_fincstp();
2701 367e86e8 bellard
                    break;
2702 367e86e8 bellard
                }
2703 367e86e8 bellard
                break;
2704 367e86e8 bellard
            case 0x0f: /* grp d9/7 */
2705 367e86e8 bellard
                switch(rm) {
2706 367e86e8 bellard
                case 0: /* fprem */
2707 927f621e bellard
                    gen_op_fprem();
2708 367e86e8 bellard
                    break;
2709 367e86e8 bellard
                case 1: /* fyl2xp1 */
2710 927f621e bellard
                    gen_op_fyl2xp1();
2711 927f621e bellard
                    break;
2712 927f621e bellard
                case 2: /* fsqrt */
2713 927f621e bellard
                    gen_op_fsqrt();
2714 367e86e8 bellard
                    break;
2715 367e86e8 bellard
                case 3: /* fsincos */
2716 927f621e bellard
                    gen_op_fsincos();
2717 367e86e8 bellard
                    break;
2718 367e86e8 bellard
                case 5: /* fscale */
2719 927f621e bellard
                    gen_op_fscale();
2720 367e86e8 bellard
                    break;
2721 367e86e8 bellard
                case 4: /* frndint */
2722 927f621e bellard
                    gen_op_frndint();
2723 927f621e bellard
                    break;
2724 367e86e8 bellard
                case 6: /* fsin */
2725 927f621e bellard
                    gen_op_fsin();
2726 927f621e bellard
                    break;
2727 367e86e8 bellard
                default:
2728 367e86e8 bellard
                case 7: /* fcos */
2729 927f621e bellard
                    gen_op_fcos();
2730 367e86e8 bellard
                    break;
2731 367e86e8 bellard
                }
2732 367e86e8 bellard
                break;
2733 367e86e8 bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2734 367e86e8 bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2735 367e86e8 bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2736 367e86e8 bellard
                {
2737 927f621e bellard
                    int op1;
2738 367e86e8 bellard
                    
2739 927f621e bellard
                    op1 = op & 7;
2740 367e86e8 bellard
                    if (op >= 0x20) {
2741 927f621e bellard
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2742 77f8dd5a bellard
                        if (op >= 0x30)
2743 77f8dd5a bellard
                            gen_op_fpop();
2744 367e86e8 bellard
                    } else {
2745 927f621e bellard
                        gen_op_fmov_FT0_STN(opreg);
2746 927f621e bellard
                        gen_op_fp_arith_ST0_FT0[op1]();
2747 367e86e8 bellard
                    }
2748 367e86e8 bellard
                }
2749 367e86e8 bellard
                break;
2750 367e86e8 bellard
            case 0x02: /* fcom */
2751 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2752 927f621e bellard
                gen_op_fcom_ST0_FT0();
2753 367e86e8 bellard
                break;
2754 367e86e8 bellard
            case 0x03: /* fcomp */
2755 927f621e bellard
                gen_op_fmov_FT0_STN(opreg);
2756 927f621e bellard
                gen_op_fcom_ST0_FT0();
2757 927f621e bellard
                gen_op_fpop();
2758 367e86e8 bellard
                break;
2759 367e86e8 bellard
            case 0x15: /* da/5 */
2760 367e86e8 bellard
                switch(rm) {
2761 367e86e8 bellard
                case 1: /* fucompp */
2762 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2763 77f8dd5a bellard
                    gen_op_fucom_ST0_FT0();
2764 927f621e bellard
                    gen_op_fpop();
2765 927f621e bellard
                    gen_op_fpop();
2766 367e86e8 bellard
                    break;
2767 367e86e8 bellard
                default:
2768 1a9353d2 bellard
                    goto illegal_op;
2769 1a9353d2 bellard
                }
2770 1a9353d2 bellard
                break;
2771 1a9353d2 bellard
            case 0x1c:
2772 1a9353d2 bellard
                switch(rm) {
2773 d8bc1fd0 bellard
                case 0: /* feni (287 only, just do nop here) */
2774 d8bc1fd0 bellard
                    break;
2775 d8bc1fd0 bellard
                case 1: /* fdisi (287 only, just do nop here) */
2776 d8bc1fd0 bellard
                    break;
2777 1a9353d2 bellard
                case 2: /* fclex */
2778 1a9353d2 bellard
                    gen_op_fclex();
2779 1a9353d2 bellard
                    break;
2780 1a9353d2 bellard
                case 3: /* fninit */
2781 1a9353d2 bellard
                    gen_op_fninit();
2782 1a9353d2 bellard
                    break;
2783 d8bc1fd0 bellard
                case 4: /* fsetpm (287 only, just do nop here) */
2784 d8bc1fd0 bellard
                    break;
2785 1a9353d2 bellard
                default:
2786 1a9353d2 bellard
                    goto illegal_op;
2787 367e86e8 bellard
                }
2788 367e86e8 bellard
                break;
2789 d0a1ffc9 bellard
            case 0x1d: /* fucomi */
2790 d0a1ffc9 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
2791 d0a1ffc9 bellard
                    gen_op_set_cc_op(s->cc_op);
2792 d0a1ffc9 bellard
                gen_op_fmov_FT0_STN(opreg);
2793 d0a1ffc9 bellard
                gen_op_fucomi_ST0_FT0();
2794 d0a1ffc9 bellard
                s->cc_op = CC_OP_EFLAGS;
2795 d0a1ffc9 bellard
                break;
2796 d0a1ffc9 bellard
            case 0x1e: /* fcomi */
2797 d0a1ffc9 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
2798 d0a1ffc9 bellard
                    gen_op_set_cc_op(s->cc_op);
2799 d0a1ffc9 bellard
                gen_op_fmov_FT0_STN(opreg);
2800 d0a1ffc9 bellard
                gen_op_fcomi_ST0_FT0();
2801 d0a1ffc9 bellard
                s->cc_op = CC_OP_EFLAGS;
2802 d0a1ffc9 bellard
                break;
2803 367e86e8 bellard
            case 0x2a: /* fst sti */
2804 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2805 367e86e8 bellard
                break;
2806 367e86e8 bellard
            case 0x2b: /* fstp sti */
2807 927f621e bellard
                gen_op_fmov_STN_ST0(opreg);
2808 927f621e bellard
                gen_op_fpop();
2809 367e86e8 bellard
                break;
2810 77f8dd5a bellard
            case 0x2c: /* fucom st(i) */
2811 77f8dd5a bellard
                gen_op_fmov_FT0_STN(opreg);
2812 77f8dd5a bellard
                gen_op_fucom_ST0_FT0();
2813 77f8dd5a bellard
                break;
2814 77f8dd5a bellard
            case 0x2d: /* fucomp st(i) */
2815 77f8dd5a bellard
                gen_op_fmov_FT0_STN(opreg);
2816 77f8dd5a bellard
                gen_op_fucom_ST0_FT0();
2817 77f8dd5a bellard
                gen_op_fpop();
2818 77f8dd5a bellard
                break;
2819 367e86e8 bellard
            case 0x33: /* de/3 */
2820 367e86e8 bellard
                switch(rm) {
2821 367e86e8 bellard
                case 1: /* fcompp */
2822 927f621e bellard
                    gen_op_fmov_FT0_STN(1);
2823 927f621e bellard
                    gen_op_fcom_ST0_FT0();
2824 927f621e bellard
                    gen_op_fpop();
2825 927f621e bellard
                    gen_op_fpop();
2826 367e86e8 bellard
                    break;
2827 367e86e8 bellard
                default:
2828 1a9353d2 bellard
                    goto illegal_op;
2829 367e86e8 bellard
                }
2830 367e86e8 bellard
                break;
2831 367e86e8 bellard
            case 0x3c: /* df/4 */
2832 367e86e8 bellard
                switch(rm) {
2833 367e86e8 bellard
                case 0:
2834 77f8dd5a bellard
                    gen_op_fnstsw_EAX();
2835 367e86e8 bellard
                    break;
2836 367e86e8 bellard
                default:
2837 1a9353d2 bellard
                    goto illegal_op;
2838 367e86e8 bellard
                }
2839 367e86e8 bellard
                break;
2840 d0a1ffc9 bellard
            case 0x3d: /* fucomip */
2841 d0a1ffc9 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
2842 d0a1ffc9 bellard
                    gen_op_set_cc_op(s->cc_op);
2843 d0a1ffc9 bellard
                gen_op_fmov_FT0_STN(opreg);
2844 d0a1ffc9 bellard
                gen_op_fucomi_ST0_FT0();
2845 d0a1ffc9 bellard
                gen_op_fpop();
2846 d0a1ffc9 bellard
                s->cc_op = CC_OP_EFLAGS;
2847 d0a1ffc9 bellard
                break;
2848 d0a1ffc9 bellard
            case 0x3e: /* fcomip */
2849 d0a1ffc9 bellard
                if (s->cc_op != CC_OP_DYNAMIC)
2850 d0a1ffc9 bellard
                    gen_op_set_cc_op(s->cc_op);
2851 d0a1ffc9 bellard
                gen_op_fmov_FT0_STN(opreg);
2852 d0a1ffc9 bellard
                gen_op_fcomi_ST0_FT0();
2853 d0a1ffc9 bellard
                gen_op_fpop();
2854 d0a1ffc9 bellard
                s->cc_op = CC_OP_EFLAGS;
2855 d0a1ffc9 bellard
                break;
2856 367e86e8 bellard
            default:
2857 1a9353d2 bellard
                goto illegal_op;
2858 367e86e8 bellard
            }
2859 367e86e8 bellard
        }
2860 367e86e8 bellard
        break;
2861 367e86e8 bellard
        /************************/
2862 367e86e8 bellard
        /* string ops */
2863 9c605cb1 bellard
2864 367e86e8 bellard
    case 0xa4: /* movsS */
2865 367e86e8 bellard
    case 0xa5:
2866 367e86e8 bellard
        if ((b & 1) == 0)
2867 367e86e8 bellard
            ot = OT_BYTE;
2868 367e86e8 bellard
        else
2869 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2870 9c605cb1 bellard
2871 2c1794c4 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2872 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_movs + 9);
2873 367e86e8 bellard
        } else {
2874 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_movs);
2875 367e86e8 bellard
        }
2876 367e86e8 bellard
        break;
2877 367e86e8 bellard
        
2878 367e86e8 bellard
    case 0xaa: /* stosS */
2879 367e86e8 bellard
    case 0xab:
2880 367e86e8 bellard
        if ((b & 1) == 0)
2881 367e86e8 bellard
            ot = OT_BYTE;
2882 367e86e8 bellard
        else
2883 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2884 9c605cb1 bellard
2885 2c1794c4 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2886 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_stos + 9);
2887 367e86e8 bellard
        } else {
2888 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_stos);
2889 367e86e8 bellard
        }
2890 367e86e8 bellard
        break;
2891 367e86e8 bellard
    case 0xac: /* lodsS */
2892 367e86e8 bellard
    case 0xad:
2893 367e86e8 bellard
        if ((b & 1) == 0)
2894 367e86e8 bellard
            ot = OT_BYTE;
2895 367e86e8 bellard
        else
2896 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2897 2c1794c4 bellard
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2898 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_lods + 9);
2899 367e86e8 bellard
        } else {
2900 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_lods);
2901 367e86e8 bellard
        }
2902 367e86e8 bellard
        break;
2903 367e86e8 bellard
    case 0xae: /* scasS */
2904 367e86e8 bellard
    case 0xaf:
2905 367e86e8 bellard
        if ((b & 1) == 0)
2906 367e86e8 bellard
            ot = OT_BYTE;
2907 367e86e8 bellard
        else
2908 9c605cb1 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2909 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2910 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2911 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2912 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2913 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2914 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2915 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2916 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2917 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas + 9);
2918 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2919 367e86e8 bellard
        } else {
2920 9c605cb1 bellard
            gen_string_es(s, ot, gen_op_scas);
2921 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2922 367e86e8 bellard
        }
2923 367e86e8 bellard
        break;
2924 367e86e8 bellard
2925 367e86e8 bellard
    case 0xa6: /* cmpsS */
2926 367e86e8 bellard
    case 0xa7:
2927 367e86e8 bellard
        if ((b & 1) == 0)
2928 367e86e8 bellard
            ot = OT_BYTE;
2929 367e86e8 bellard
        else
2930 367e86e8 bellard
            ot = dflag ? OT_LONG : OT_WORD;
2931 367e86e8 bellard
        if (prefixes & PREFIX_REPNZ) {
2932 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2933 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2934 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2935 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2936 367e86e8 bellard
        } else if (prefixes & PREFIX_REPZ) {
2937 4b74fe1f bellard
            if (s->cc_op != CC_OP_DYNAMIC)
2938 4b74fe1f bellard
                gen_op_set_cc_op(s->cc_op);
2939 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps + 9);
2940 4b74fe1f bellard
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2941 367e86e8 bellard
        } else {
2942 9c605cb1 bellard
            gen_string_ds(s, ot, gen_op_cmps);
2943 4b74fe1f bellard
            s->cc_op = CC_OP_SUBB + ot;
2944 367e86e8 bellard
        }
2945 367e86e8 bellard
        break;
2946 367e86e8 bellard
    case 0x6c: /* insS */
2947 367e86e8 bellard
    case 0x6d:
2948 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2949 982b4315 bellard
            /* NOTE: even for (E)CX = 0 the exception is raised */
2950 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2951 367e86e8 bellard
        } else {
2952 982b4315 bellard
            if ((b & 1) == 0)
2953 982b4315 bellard
                ot = OT_BYTE;
2954 982b4315 bellard
            else
2955 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2956 2c1794c4 bellard
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2957 982b4315 bellard
                gen_string_es(s, ot, gen_op_ins + 9);
2958 982b4315 bellard
            } else {
2959 982b4315 bellard
                gen_string_es(s, ot, gen_op_ins);
2960 982b4315 bellard
            }
2961 367e86e8 bellard
        }
2962 367e86e8 bellard
        break;
2963 367e86e8 bellard
    case 0x6e: /* outsS */
2964 367e86e8 bellard
    case 0x6f:
2965 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2966 982b4315 bellard
            /* NOTE: even for (E)CX = 0 the exception is raised */
2967 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2968 367e86e8 bellard
        } else {
2969 982b4315 bellard
            if ((b & 1) == 0)
2970 982b4315 bellard
                ot = OT_BYTE;
2971 982b4315 bellard
            else
2972 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2973 2c1794c4 bellard
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2974 982b4315 bellard
                gen_string_ds(s, ot, gen_op_outs + 9);
2975 982b4315 bellard
            } else {
2976 982b4315 bellard
                gen_string_ds(s, ot, gen_op_outs);
2977 982b4315 bellard
            }
2978 367e86e8 bellard
        }
2979 367e86e8 bellard
        break;
2980 9c605cb1 bellard
2981 9c605cb1 bellard
        /************************/
2982 9c605cb1 bellard
        /* port I/O */
2983 ba1c6e37 bellard
    case 0xe4:
2984 ba1c6e37 bellard
    case 0xe5:
2985 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2986 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2987 982b4315 bellard
        } else {
2988 982b4315 bellard
            if ((b & 1) == 0)
2989 982b4315 bellard
                ot = OT_BYTE;
2990 982b4315 bellard
            else
2991 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
2992 982b4315 bellard
            val = ldub(s->pc++);
2993 982b4315 bellard
            gen_op_movl_T0_im(val);
2994 982b4315 bellard
            gen_op_in[ot]();
2995 982b4315 bellard
            gen_op_mov_reg_T1[ot][R_EAX]();
2996 982b4315 bellard
        }
2997 ba1c6e37 bellard
        break;
2998 ba1c6e37 bellard
    case 0xe6:
2999 ba1c6e37 bellard
    case 0xe7:
3000 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3001 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3002 982b4315 bellard
        } else {
3003 982b4315 bellard
            if ((b & 1) == 0)
3004 982b4315 bellard
                ot = OT_BYTE;
3005 982b4315 bellard
            else
3006 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
3007 982b4315 bellard
            val = ldub(s->pc++);
3008 982b4315 bellard
            gen_op_movl_T0_im(val);
3009 982b4315 bellard
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3010 982b4315 bellard
            gen_op_out[ot]();
3011 982b4315 bellard
        }
3012 ba1c6e37 bellard
        break;
3013 ba1c6e37 bellard
    case 0xec:
3014 ba1c6e37 bellard
    case 0xed:
3015 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3016 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3017 982b4315 bellard
        } else {
3018 982b4315 bellard
            if ((b & 1) == 0)
3019 982b4315 bellard
                ot = OT_BYTE;
3020 982b4315 bellard
            else
3021 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
3022 982b4315 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3023 982b4315 bellard
            gen_op_in[ot]();
3024 982b4315 bellard
            gen_op_mov_reg_T1[ot][R_EAX]();
3025 982b4315 bellard
        }
3026 ba1c6e37 bellard
        break;
3027 ba1c6e37 bellard
    case 0xee:
3028 ba1c6e37 bellard
    case 0xef:
3029 8f186479 bellard
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3030 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3031 982b4315 bellard
        } else {
3032 982b4315 bellard
            if ((b & 1) == 0)
3033 982b4315 bellard
                ot = OT_BYTE;
3034 982b4315 bellard
            else
3035 982b4315 bellard
                ot = dflag ? OT_LONG : OT_WORD;
3036 982b4315 bellard
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3037 982b4315 bellard
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3038 982b4315 bellard
            gen_op_out[ot]();
3039 982b4315 bellard
        }
3040 ba1c6e37 bellard
        break;
3041 367e86e8 bellard
3042 367e86e8 bellard
        /************************/
3043 367e86e8 bellard
        /* control */
3044 367e86e8 bellard
    case 0xc2: /* ret im */
3045 367e86e8 bellard
        val = ldsw(s->pc);
3046 367e86e8 bellard
        s->pc += 2;
3047 dab2ed99 bellard
        gen_pop_T0(s);
3048 d0a1ffc9 bellard
        gen_stack_update(s, val + (2 << s->dflag));
3049 dab2ed99 bellard
        if (s->dflag == 0)
3050 dab2ed99 bellard
            gen_op_andl_T0_ffff();
3051 367e86e8 bellard
        gen_op_jmp_T0();
3052 6dbad63e bellard
        s->is_jmp = 1;
3053 367e86e8 bellard
        break;
3054 367e86e8 bellard
    case 0xc3: /* ret */
3055 dab2ed99 bellard
        gen_pop_T0(s);
3056 dab2ed99 bellard
        gen_pop_update(s);
3057 dab2ed99 bellard
        if (s->dflag == 0)
3058 dab2ed99 bellard
            gen_op_andl_T0_ffff();
3059 367e86e8 bellard
        gen_op_jmp_T0();
3060 6dbad63e bellard
        s->is_jmp = 1;
3061 367e86e8 bellard
        break;
3062 dab2ed99 bellard
    case 0xca: /* lret im */
3063 dab2ed99 bellard
        val = ldsw(s->pc);
3064 dab2ed99 bellard
        s->pc += 2;
3065 d0a1ffc9 bellard
    do_lret:
3066 2c1794c4 bellard
        if (s->pe && !s->vm86) {
3067 2c1794c4 bellard
            if (s->cc_op != CC_OP_DYNAMIC)
3068 2c1794c4 bellard
                gen_op_set_cc_op(s->cc_op);
3069 2c1794c4 bellard
            gen_op_jmp_im(pc_start - s->cs_base);
3070 2c1794c4 bellard
            gen_op_lret_protected(s->dflag, val);
3071 2c1794c4 bellard
        } else {
3072 2c1794c4 bellard
            gen_stack_A0(s);
3073 2c1794c4 bellard
            /* pop offset */
3074 2c1794c4 bellard
            gen_op_ld_T0_A0[1 + s->dflag]();
3075 2c1794c4 bellard
            if (s->dflag == 0)
3076 2c1794c4 bellard
                gen_op_andl_T0_ffff();
3077 2c1794c4 bellard
            /* NOTE: keeping EIP updated is not a problem in case of
3078 2c1794c4 bellard
               exception */
3079 2c1794c4 bellard
            gen_op_jmp_T0();
3080 2c1794c4 bellard
            /* pop selector */
3081 2c1794c4 bellard
            gen_op_addl_A0_im(2 << s->dflag);
3082 2c1794c4 bellard
            gen_op_ld_T0_A0[1 + s->dflag]();
3083 2c1794c4 bellard
            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3084 2c1794c4 bellard
            /* add stack offset */
3085 2c1794c4 bellard
            gen_stack_update(s, val + (4 << s->dflag));
3086 2c1794c4 bellard
        }
3087 dab2ed99 bellard
        s->is_jmp = 1;
3088 dab2ed99 bellard
        break;
3089 dab2ed99 bellard
    case 0xcb: /* lret */
3090 d0a1ffc9 bellard
        val = 0;
3091 d0a1ffc9 bellard
        goto do_lret;
3092 f631ef9b bellard
    case 0xcf: /* iret */
3093 8f186479 bellard
        if (!s->pe) {
3094 8f186479 bellard
            /* real mode */
3095 8f186479 bellard
            gen_op_iret_real(s->dflag);
3096 8f186479 bellard
            s->cc_op = CC_OP_EFLAGS;
3097 8f186479 bellard
        } else if (s->vm86 && s->iopl != 3) {
3098 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3099 f631ef9b bellard
        } else {
3100 717fc2ad bellard
            if (s->cc_op != CC_OP_DYNAMIC)
3101 717fc2ad bellard
                gen_op_set_cc_op(s->cc_op);
3102 717fc2ad bellard
            gen_op_jmp_im(pc_start - s->cs_base);
3103 717fc2ad bellard
            gen_op_iret_protected(s->dflag);
3104 148dfc2a bellard
            s->cc_op = CC_OP_EFLAGS;
3105 f631ef9b bellard
        }
3106 f631ef9b bellard
        s->is_jmp = 1;
3107 f631ef9b bellard
        break;
3108 dab2ed99 bellard
    case 0xe8: /* call im */
3109 dab2ed99 bellard
        {
3110 dab2ed99 bellard
            unsigned int next_eip;
3111 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
3112 dab2ed99 bellard
            val = insn_get(s, ot);
3113 dab2ed99 bellard
            next_eip = s->pc - s->cs_base;
3114 dab2ed99 bellard
            val += next_eip;
3115 dab2ed99 bellard
            if (s->dflag == 0)
3116 dab2ed99 bellard
                val &= 0xffff;
3117 dab2ed99 bellard
            gen_op_movl_T0_im(next_eip);
3118 dab2ed99 bellard
            gen_push_T0(s);
3119 d4e8164f bellard
            gen_jmp(s, val);
3120 dab2ed99 bellard
        }
3121 dab2ed99 bellard
        break;
3122 dab2ed99 bellard
    case 0x9a: /* lcall im */
3123 dab2ed99 bellard
        {
3124 dab2ed99 bellard
            unsigned int selector, offset;
3125 dab2ed99 bellard
3126 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
3127 dab2ed99 bellard
            offset = insn_get(s, ot);
3128 dab2ed99 bellard
            selector = insn_get(s, OT_WORD);
3129 dab2ed99 bellard
            
3130 dab2ed99 bellard
            gen_op_movl_T0_im(selector);
3131 2c1794c4 bellard
            gen_op_movl_T1_im(offset);
3132 dab2ed99 bellard
        }
3133 2c1794c4 bellard
        goto do_lcall;
3134 367e86e8 bellard
    case 0xe9: /* jmp */
3135 dab2ed99 bellard
        ot = dflag ? OT_LONG : OT_WORD;
3136 dab2ed99 bellard
        val = insn_get(s, ot);
3137 dab2ed99 bellard
        val += s->pc - s->cs_base;
3138 dab2ed99 bellard
        if (s->dflag == 0)
3139 dab2ed99 bellard
            val = val & 0xffff;
3140 d4e8164f bellard
        gen_jmp(s, val);
3141 367e86e8 bellard
        break;
3142 dab2ed99 bellard
    case 0xea: /* ljmp im */
3143 dab2ed99 bellard
        {
3144 dab2ed99 bellard
            unsigned int selector, offset;
3145 dab2ed99 bellard
3146 dab2ed99 bellard
            ot = dflag ? OT_LONG : OT_WORD;
3147 dab2ed99 bellard
            offset = insn_get(s, ot);
3148 dab2ed99 bellard
            selector = insn_get(s, OT_WORD);
3149 dab2ed99 bellard
            
3150 dab2ed99 bellard
            gen_op_movl_T0_im(selector);
3151 2c1794c4 bellard
            gen_op_movl_T1_im(offset);
3152 dab2ed99 bellard
        }
3153 2c1794c4 bellard
        goto do_ljmp;
3154 367e86e8 bellard
    case 0xeb: /* jmp Jb */
3155 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3156 dab2ed99 bellard
        val += s->pc - s->cs_base;
3157 dab2ed99 bellard
        if (s->dflag == 0)
3158 dab2ed99 bellard
            val = val & 0xffff;
3159 d4e8164f bellard
        gen_jmp(s, val);
3160 367e86e8 bellard
        break;
3161 367e86e8 bellard
    case 0x70 ... 0x7f: /* jcc Jb */
3162 367e86e8 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3163 367e86e8 bellard
        goto do_jcc;
3164 367e86e8 bellard
    case 0x180 ... 0x18f: /* jcc Jv */
3165 367e86e8 bellard
        if (dflag) {
3166 367e86e8 bellard
            val = insn_get(s, OT_LONG);
3167 367e86e8 bellard
        } else {
3168 367e86e8 bellard
            val = (int16_t)insn_get(s, OT_WORD); 
3169 367e86e8 bellard
        }
3170 367e86e8 bellard
    do_jcc:
3171 dab2ed99 bellard
        next_eip = s->pc - s->cs_base;
3172 dab2ed99 bellard
        val += next_eip;
3173 dab2ed99 bellard
        if (s->dflag == 0)
3174 dab2ed99 bellard
            val &= 0xffff;
3175 dab2ed99 bellard
        gen_jcc(s, b, val, next_eip);
3176 367e86e8 bellard
        break;
3177 367e86e8 bellard
3178 5dd9488c bellard
    case 0x190 ... 0x19f: /* setcc Gv */
3179 367e86e8 bellard
        modrm = ldub(s->pc++);
3180 367e86e8 bellard
        gen_setcc(s, b);
3181 367e86e8 bellard
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3182 367e86e8 bellard
        break;
3183 5dd9488c bellard
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3184 5dd9488c bellard
        ot = dflag ? OT_LONG : OT_WORD;
3185 5dd9488c bellard
        modrm = ldub(s->pc++);
3186 5dd9488c bellard
        reg = (modrm >> 3) & 7;
3187 5dd9488c bellard
        mod = (modrm >> 6) & 3;
3188 5dd9488c bellard
        gen_setcc(s, b);
3189 5dd9488c bellard
        if (mod != 3) {
3190 5dd9488c bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3191 5dd9488c bellard
            gen_op_ld_T1_A0[ot]();
3192 5dd9488c bellard
        } else {
3193 5dd9488c bellard
            rm = modrm & 7;
3194 5dd9488c bellard
            gen_op_mov_TN_reg[ot][1][rm]();
3195 5dd9488c bellard
        }
3196 5dd9488c bellard
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3197 5dd9488c bellard
        break;
3198 5dd9488c bellard
        
3199 367e86e8 bellard
        /************************/
3200 367e86e8 bellard
        /* flags */
3201 367e86e8 bellard
    case 0x9c: /* pushf */
3202 148dfc2a bellard
        if (s->vm86 && s->iopl != 3) {
3203 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3204 148dfc2a bellard
        } else {
3205 148dfc2a bellard
            if (s->cc_op != CC_OP_DYNAMIC)
3206 148dfc2a bellard
                gen_op_set_cc_op(s->cc_op);
3207 f631ef9b bellard
            gen_op_movl_T0_eflags();
3208 148dfc2a bellard
            gen_push_T0(s);
3209 148dfc2a bellard
        }
3210 367e86e8 bellard
        break;
3211 367e86e8 bellard
    case 0x9d: /* popf */
3212 148dfc2a bellard
        if (s->vm86 && s->iopl != 3) {
3213 c50c0c3f bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3214 f631ef9b bellard
        } else {
3215 148dfc2a bellard
            gen_pop_T0(s);
3216 717fc2ad bellard
            if (s->cpl == 0) {
3217 717fc2ad bellard
                if (s->dflag) {
3218 717fc2ad bellard
                    gen_op_movl_eflags_T0_cpl0();
3219 717fc2ad bellard
                } else {
3220 717fc2ad bellard
                    gen_op_movw_eflags_T0_cpl0();
3221 717fc2ad bellard
                }
3222 148dfc2a bellard
            } else {
3223 717fc2ad bellard
                if (s->dflag) {
3224 717fc2ad bellard
                    gen_op_movl_eflags_T0();
3225 717fc2ad bellard
                } else {
3226 717fc2ad bellard
                    gen_op_movw_eflags_T0();
3227 717fc2ad bellard
                }
3228 148dfc2a bellard
            }
3229 148dfc2a bellard
            gen_pop_update(s);
3230 148dfc2a bellard
            s->cc_op = CC_OP_EFLAGS;
3231 c0ad5542 bellard
            s->is_jmp = 2; /* abort translation because TF flag may change */
3232 f631ef9b bellard
        }
3233 367e86e8 bellard
        break;
3234 367e86e8 bellard
    case 0x9e: /* sahf */
3235 367e86e8 bellard
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3236 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3237 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3238 367e86e8 bellard
        gen_op_movb_eflags_T0();
3239 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3240 367e86e8 bellard
        break;
3241 367e86e8 bellard
    case 0x9f: /* lahf */
3242 367e86e8 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3243 1017ebe9 bellard
            gen_op_set_cc_op(s->cc_op);
3244 367e86e8 bellard
        gen_op_movl_T0_eflags();
3245 367e86e8 bellard
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3246 367e86e8 bellard
        break;
3247 367e86e8 bellard
    case 0xf5: /* cmc */
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_cmc();
3251 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3252 367e86e8 bellard
        break;
3253 367e86e8 bellard
    case 0xf8: /* clc */
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_clc();
3257 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3258 367e86e8 bellard
        break;
3259 367e86e8 bellard
    case 0xf9: /* stc */
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_stc();
3263 367e86e8 bellard
        s->cc_op = CC_OP_EFLAGS;
3264 367e86e8 bellard
        break;
3265 367e86e8 bellard
    case 0xfc: /* cld */
3266 367e86e8 bellard
        gen_op_cld();
3267 367e86e8 bellard
        break;
3268 367e86e8 bellard
    case 0xfd: /* std */
3269 367e86e8 bellard
        gen_op_std();
3270 367e86e8 bellard
        break;
3271 367e86e8 bellard
3272 367e86e8 bellard
        /************************/
3273 4b74fe1f bellard
        /* bit operations */
3274 4b74fe1f bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3275 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
3276 4b74fe1f bellard
        modrm = ldub(s->pc++);
3277 4b74fe1f bellard
        op = (modrm >> 3) & 7;
3278 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
3279 4b74fe1f bellard
        rm = modrm & 7;
3280 4b74fe1f bellard
        if (mod != 3) {
3281 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3282 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
3283 4b74fe1f bellard
        } else {
3284 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
3285 4b74fe1f bellard
        }
3286 4b74fe1f bellard
        /* load shift */
3287 4b74fe1f bellard
        val = ldub(s->pc++);
3288 4b74fe1f bellard
        gen_op_movl_T1_im(val);
3289 4b74fe1f bellard
        if (op < 4)
3290 1a9353d2 bellard
            goto illegal_op;
3291 4b74fe1f bellard
        op -= 4;
3292 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3293 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
3294 4b74fe1f bellard
        if (op != 0) {
3295 4b74fe1f bellard
            if (mod != 3)
3296 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
3297 4b74fe1f bellard
            else
3298 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
3299 e477b8b8 bellard
            gen_op_update_bt_cc();
3300 4b74fe1f bellard
        }
3301 4b74fe1f bellard
        break;
3302 4b74fe1f bellard
    case 0x1a3: /* bt Gv, Ev */
3303 4b74fe1f bellard
        op = 0;
3304 4b74fe1f bellard
        goto do_btx;
3305 4b74fe1f bellard
    case 0x1ab: /* bts */
3306 4b74fe1f bellard
        op = 1;
3307 4b74fe1f bellard
        goto do_btx;
3308 4b74fe1f bellard
    case 0x1b3: /* btr */
3309 4b74fe1f bellard
        op = 2;
3310 4b74fe1f bellard
        goto do_btx;
3311 4b74fe1f bellard
    case 0x1bb: /* btc */
3312 4b74fe1f bellard
        op = 3;
3313 4b74fe1f bellard
    do_btx:
3314 4b74fe1f bellard
        ot = dflag ? OT_LONG : OT_WORD;
3315 4b74fe1f bellard
        modrm = ldub(s->pc++);
3316 4b74fe1f bellard
        reg = (modrm >> 3) & 7;
3317 4b74fe1f bellard
        mod = (modrm >> 6) & 3;
3318 4b74fe1f bellard
        rm = modrm & 7;
3319 4b74fe1f bellard
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3320 4b74fe1f bellard
        if (mod != 3) {
3321 4b74fe1f bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3322 4b74fe1f bellard
            /* specific case: we need to add a displacement */
3323 4b74fe1f bellard
            if (ot == OT_WORD)
3324 4b74fe1f bellard
                gen_op_add_bitw_A0_T1();
3325 4b74fe1f bellard
            else
3326 4b74fe1f bellard
                gen_op_add_bitl_A0_T1();
3327 4b74fe1f bellard
            gen_op_ld_T0_A0[ot]();
3328 4b74fe1f bellard
        } else {
3329 4b74fe1f bellard
            gen_op_mov_TN_reg[ot][0][rm]();
3330 4b74fe1f bellard
        }
3331 4b74fe1f bellard
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3332 d57c4e01 bellard
        s->cc_op = CC_OP_SARB + ot;
3333 4b74fe1f bellard
        if (op != 0) {
3334 4b74fe1f bellard
            if (mod != 3)
3335 4b74fe1f bellard
                gen_op_st_T0_A0[ot]();
3336 4b74fe1f bellard
            else
3337 4b74fe1f bellard
                gen_op_mov_reg_T0[ot][rm]();
3338 e477b8b8 bellard
            gen_op_update_bt_cc();
3339 4b74fe1f bellard
        }
3340 4b74fe1f bellard
        break;
3341 77f8dd5a bellard
    case 0x1bc: /* bsf */
3342 77f8dd5a bellard
    case 0x1bd: /* bsr */
3343 77f8dd5a bellard
        ot = dflag ? OT_LONG : OT_WORD;
3344 77f8dd5a bellard
        modrm = ldub(s->pc++);
3345 77f8dd5a bellard
        reg = (modrm >> 3) & 7;
3346 77f8dd5a bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3347 77f8dd5a bellard
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3348 77f8dd5a bellard
        /* NOTE: we always write back the result. Intel doc says it is
3349 77f8dd5a bellard
           undefined if T0 == 0 */
3350 77f8dd5a bellard
        gen_op_mov_reg_T0[ot][reg]();
3351 77f8dd5a bellard
        s->cc_op = CC_OP_LOGICB + ot;
3352 77f8dd5a bellard
        break;
3353 4b74fe1f bellard
        /************************/
3354 27362c82 bellard
        /* bcd */
3355 27362c82 bellard
    case 0x27: /* daa */
3356 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3357 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3358 27362c82 bellard
        gen_op_daa();
3359 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3360 27362c82 bellard
        break;
3361 27362c82 bellard
    case 0x2f: /* das */
3362 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3363 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3364 27362c82 bellard
        gen_op_das();
3365 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3366 27362c82 bellard
        break;
3367 27362c82 bellard
    case 0x37: /* aaa */
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_aaa();
3371 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3372 27362c82 bellard
        break;
3373 27362c82 bellard
    case 0x3f: /* aas */
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_aas();
3377 27362c82 bellard
        s->cc_op = CC_OP_EFLAGS;
3378 27362c82 bellard
        break;
3379 27362c82 bellard
    case 0xd4: /* aam */
3380 27362c82 bellard
        val = ldub(s->pc++);
3381 27362c82 bellard
        gen_op_aam(val);
3382 27362c82 bellard
        s->cc_op = CC_OP_LOGICB;
3383 27362c82 bellard
        break;
3384 27362c82 bellard
    case 0xd5: /* aad */
3385 27362c82 bellard
        val = ldub(s->pc++);
3386 27362c82 bellard
        gen_op_aad(val);
3387 27362c82 bellard
        s->cc_op = CC_OP_LOGICB;
3388 27362c82 bellard
        break;
3389 27362c82 bellard
        /************************/
3390 367e86e8 bellard
        /* misc */
3391 367e86e8 bellard
    case 0x90: /* nop */
3392 367e86e8 bellard
        break;
3393 a37904dd bellard
    case 0x9b: /* fwait */
3394 a37904dd bellard
        break;
3395 0ecfa993 bellard
    case 0xcc: /* int3 */
3396 5a91de8c bellard
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3397 0ecfa993 bellard
        break;
3398 0ecfa993 bellard
    case 0xcd: /* int N */
3399 0ecfa993 bellard
        val = ldub(s->pc++);
3400 5a91de8c bellard
        /* XXX: add error code for vm86 GPF */
3401 5a91de8c bellard
        if (!s->vm86)
3402 5a91de8c bellard
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3403 5a91de8c bellard
        else
3404 5a91de8c bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3405 0ecfa993 bellard
        break;
3406 0ecfa993 bellard
    case 0xce: /* into */
3407 0ecfa993 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3408 0ecfa993 bellard
            gen_op_set_cc_op(s->cc_op);
3409 78c34e98 bellard
        gen_op_into(s->pc - s->cs_base);
3410 9c605cb1 bellard
        break;
3411 8a4c1cc4 bellard
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
3412 8a4c1cc4 bellard
        gen_debug(s, pc_start - s->cs_base);
3413 8a4c1cc4 bellard
        break;
3414 f631ef9b bellard
    case 0xfa: /* cli */
3415 982b4315 bellard
        if (!s->vm86) {
3416 148dfc2a bellard
            if (s->cpl <= s->iopl) {
3417 982b4315 bellard
                gen_op_cli();
3418 148dfc2a bellard
            } else {
3419 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3420 148dfc2a bellard
            }
3421 982b4315 bellard
        } else {
3422 148dfc2a bellard
            if (s->iopl == 3) {
3423 982b4315 bellard
                gen_op_cli();
3424 148dfc2a bellard
            } else {
3425 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3426 148dfc2a bellard
            }
3427 982b4315 bellard
        }
3428 f631ef9b bellard
        break;
3429 f631ef9b bellard
    case 0xfb: /* sti */
3430 982b4315 bellard
        if (!s->vm86) {
3431 148dfc2a bellard
            if (s->cpl <= s->iopl) {
3432 982b4315 bellard
                gen_op_sti();
3433 68a79315 bellard
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3434 148dfc2a bellard
            } else {
3435 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3436 148dfc2a bellard
            }
3437 982b4315 bellard
        } else {
3438 148dfc2a bellard
            if (s->iopl == 3) {
3439 982b4315 bellard
                gen_op_sti();
3440 68a79315 bellard
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3441 148dfc2a bellard
            } else {
3442 c50c0c3f bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3443 148dfc2a bellard
            }
3444 982b4315 bellard
        }
3445 8f186479 bellard
        /* XXX: interruptions are enabled only the first insn after sti */
3446 f631ef9b bellard
        break;
3447 9c605cb1 bellard
    case 0x62: /* bound */
3448 9c605cb1 bellard
        ot = dflag ? OT_LONG : OT_WORD;
3449 9c605cb1 bellard
        modrm = ldub(s->pc++);
3450 9c605cb1 bellard
        reg = (modrm >> 3) & 7;
3451 9c605cb1 bellard
        mod = (modrm >> 6) & 3;
3452 9c605cb1 bellard
        if (mod == 3)
3453 9c605cb1 bellard
            goto illegal_op;
3454 9c605cb1 bellard
        gen_op_mov_reg_T0[ot][reg]();
3455 9c605cb1 bellard
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3456 9c605cb1 bellard
        if (ot == OT_WORD)
3457 5a91de8c bellard
            gen_op_boundw(pc_start - s->cs_base);
3458 9c605cb1 bellard
        else
3459 5a91de8c bellard
            gen_op_boundl(pc_start - s->cs_base);
3460 0ecfa993 bellard
        break;
3461 4b74fe1f bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
3462 27362c82 bellard
        reg = b & 7;
3463 27362c82 bellard
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3464 27362c82 bellard
        gen_op_bswapl_T0();
3465 27362c82 bellard
        gen_op_mov_reg_T0[OT_LONG][reg]();
3466 27362c82 bellard
        break;
3467 27362c82 bellard
    case 0xd6: /* salc */
3468 27362c82 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3469 27362c82 bellard
            gen_op_set_cc_op(s->cc_op);
3470 27362c82 bellard
        gen_op_salc();
3471 27362c82 bellard
        break;
3472 1a9353d2 bellard
    case 0xe0: /* loopnz */
3473 1a9353d2 bellard
    case 0xe1: /* loopz */
3474 1a9353d2 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3475 1a9353d2 bellard
            gen_op_set_cc_op(s->cc_op);
3476 1a9353d2 bellard
        /* FALL THRU */
3477 1a9353d2 bellard
    case 0xe2: /* loop */
3478 1a9353d2 bellard
    case 0xe3: /* jecxz */
3479 1a9353d2 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
3480 dab2ed99 bellard
        next_eip = s->pc - s->cs_base;
3481 dab2ed99 bellard
        val += next_eip;
3482 dab2ed99 bellard
        if (s->dflag == 0)
3483 dab2ed99 bellard
            val &= 0xffff;
3484 dab2ed99 bellard
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3485 1a9353d2 bellard
        s->is_jmp = 1;
3486 1a9353d2 bellard
        break;
3487 3c1cf9fa bellard
    case 0x130: /* wrmsr */
3488 3c1cf9fa bellard
    case 0x132: /* rdmsr */
3489 3c1cf9fa bellard
        if (s->cpl != 0) {
3490 3c1cf9fa bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3491 3c1cf9fa bellard
        } else {
3492 3c1cf9fa bellard
            if (b & 2)
3493 3c1cf9fa bellard
                gen_op_rdmsr();
3494 3c1cf9fa bellard
            else
3495 3c1cf9fa bellard
                gen_op_wrmsr();
3496 3c1cf9fa bellard
        }
3497 3c1cf9fa bellard
        break;
3498 5dd9488c bellard
    case 0x131: /* rdtsc */
3499 27362c82 bellard
        gen_op_rdtsc();
3500 27362c82 bellard
        break;
3501 367e86e8 bellard
    case 0x1a2: /* cpuid */
3502 9c605cb1 bellard
        gen_op_cpuid();
3503 367e86e8 bellard
        break;
3504 982b4315 bellard
    case 0xf4: /* hlt */
3505 717fc2ad bellard
        if (s->cpl != 0) {
3506 717fc2ad bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3507 717fc2ad bellard
        } else {
3508 717fc2ad bellard
            if (s->cc_op != CC_OP_DYNAMIC)
3509 717fc2ad bellard
                gen_op_set_cc_op(s->cc_op);
3510 717fc2ad bellard
            gen_op_jmp_im(s->pc - s->cs_base);
3511 717fc2ad bellard
            gen_op_hlt();
3512 717fc2ad bellard
            s->is_jmp = 1;
3513 717fc2ad bellard
        }
3514 982b4315 bellard
        break;
3515 d8bc1fd0 bellard
    case 0x100:
3516 d8bc1fd0 bellard
        modrm = ldub(s->pc++);
3517 d8bc1fd0 bellard
        mod = (modrm >> 6) & 3;
3518 d8bc1fd0 bellard
        op = (modrm >> 3) & 7;
3519 d8bc1fd0 bellard
        switch(op) {
3520 d8bc1fd0 bellard
        case 0: /* sldt */
3521 d8bc1fd0 bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3522 d8bc1fd0 bellard
            ot = OT_WORD;
3523 d8bc1fd0 bellard
            if (mod == 3)
3524 d8bc1fd0 bellard
                ot += s->dflag;
3525 d8bc1fd0 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3526 d8bc1fd0 bellard
            break;
3527 d8bc1fd0 bellard
        case 2: /* lldt */
3528 d8bc1fd0 bellard
            if (s->cpl != 0) {
3529 d8bc1fd0 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3530 d8bc1fd0 bellard
            } else {
3531 d8bc1fd0 bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3532 d8bc1fd0 bellard
                gen_op_jmp_im(pc_start - s->cs_base);
3533 d8bc1fd0 bellard
                gen_op_lldt_T0();
3534 d8bc1fd0 bellard
            }
3535 d8bc1fd0 bellard
            break;
3536 d8bc1fd0 bellard
        case 1: /* str */
3537 d8bc1fd0 bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3538 d8bc1fd0 bellard
            ot = OT_WORD;
3539 d8bc1fd0 bellard
            if (mod == 3)
3540 d8bc1fd0 bellard
                ot += s->dflag;
3541 d8bc1fd0 bellard
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3542 d8bc1fd0 bellard
            break;
3543 d8bc1fd0 bellard
        case 3: /* ltr */
3544 d8bc1fd0 bellard
            if (s->cpl != 0) {
3545 d8bc1fd0 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3546 d8bc1fd0 bellard
            } else {
3547 d8bc1fd0 bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3548 d8bc1fd0 bellard
                gen_op_jmp_im(pc_start - s->cs_base);
3549 d8bc1fd0 bellard
                gen_op_ltr_T0();
3550 d8bc1fd0 bellard
            }
3551 d8bc1fd0 bellard
            break;
3552 d8bc1fd0 bellard
        case 4: /* verr */
3553 d8bc1fd0 bellard
        case 5: /* verw */
3554 d8bc1fd0 bellard
        default:
3555 d8bc1fd0 bellard
            goto illegal_op;
3556 d8bc1fd0 bellard
        }
3557 d8bc1fd0 bellard
        break;
3558 d8bc1fd0 bellard
    case 0x101:
3559 d8bc1fd0 bellard
        modrm = ldub(s->pc++);
3560 d8bc1fd0 bellard
        mod = (modrm >> 6) & 3;
3561 d8bc1fd0 bellard
        op = (modrm >> 3) & 7;
3562 d8bc1fd0 bellard
        switch(op) {
3563 d8bc1fd0 bellard
        case 0: /* sgdt */
3564 d8bc1fd0 bellard
        case 1: /* sidt */
3565 d8bc1fd0 bellard
            if (mod == 3)
3566 d8bc1fd0 bellard
                goto illegal_op;
3567 d8bc1fd0 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3568 d8bc1fd0 bellard
            if (op == 0)
3569 d8bc1fd0 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3570 d8bc1fd0 bellard
            else
3571 d8bc1fd0 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3572 d8bc1fd0 bellard
            gen_op_stw_T0_A0();
3573 d8bc1fd0 bellard
            gen_op_addl_A0_im(2);
3574 d8bc1fd0 bellard
            if (op == 0)
3575 d8bc1fd0 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3576 d8bc1fd0 bellard
            else
3577 d8bc1fd0 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3578 d8bc1fd0 bellard
            if (!s->dflag)
3579 d8bc1fd0 bellard
                gen_op_andl_T0_im(0xffffff);
3580 d8bc1fd0 bellard
            gen_op_stl_T0_A0();
3581 d8bc1fd0 bellard
            break;
3582 d8bc1fd0 bellard
        case 2: /* lgdt */
3583 d8bc1fd0 bellard
        case 3: /* lidt */
3584 d8bc1fd0 bellard
            if (mod == 3)
3585 d8bc1fd0 bellard
                goto illegal_op;
3586 d8bc1fd0 bellard
            if (s->cpl != 0) {
3587 d8bc1fd0 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3588 d8bc1fd0 bellard
            } else {
3589 d8bc1fd0 bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3590 d8bc1fd0 bellard
                gen_op_lduw_T1_A0();
3591 d8bc1fd0 bellard
                gen_op_addl_A0_im(2);
3592 d8bc1fd0 bellard
                gen_op_ldl_T0_A0();
3593 d8bc1fd0 bellard
                if (!s->dflag)
3594 d8bc1fd0 bellard
                    gen_op_andl_T0_im(0xffffff);
3595 d8bc1fd0 bellard
                if (op == 2) {
3596 d8bc1fd0 bellard
                    gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3597 d8bc1fd0 bellard
                    gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3598 d8bc1fd0 bellard
                } else {
3599 d8bc1fd0 bellard
                    gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3600 d8bc1fd0 bellard
                    gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3601 d8bc1fd0 bellard
                }
3602 d8bc1fd0 bellard
            }
3603 d8bc1fd0 bellard
            break;
3604 d8bc1fd0 bellard
        case 4: /* smsw */
3605 d8bc1fd0 bellard
            gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3606 d8bc1fd0 bellard
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3607 d8bc1fd0 bellard
            break;
3608 d8bc1fd0 bellard
        case 6: /* lmsw */
3609 d8bc1fd0 bellard
            if (s->cpl != 0) {
3610 d8bc1fd0 bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3611 d8bc1fd0 bellard
            } else {
3612 d8bc1fd0 bellard
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3613 d8bc1fd0 bellard
                gen_op_lmsw_T0();
3614 d8bc1fd0 bellard
            }
3615 d8bc1fd0 bellard
            break;
3616 717fc2ad bellard
        case 7: /* invlpg */
3617 717fc2ad bellard
            if (s->cpl != 0) {
3618 717fc2ad bellard
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3619 717fc2ad bellard
            } else {
3620 717fc2ad bellard
                if (mod == 3)
3621 717fc2ad bellard
                    goto illegal_op;
3622 717fc2ad bellard
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3623 717fc2ad bellard
                gen_op_invlpg_A0();
3624 717fc2ad bellard
            }
3625 717fc2ad bellard
            break;
3626 d8bc1fd0 bellard
        default:
3627 d8bc1fd0 bellard
            goto illegal_op;
3628 d8bc1fd0 bellard
        }
3629 d8bc1fd0 bellard
        break;
3630 78c34e98 bellard
    case 0x102: /* lar */
3631 78c34e98 bellard
    case 0x103: /* lsl */
3632 8f186479 bellard
        if (!s->pe || s->vm86)
3633 78c34e98 bellard
            goto illegal_op;
3634 78c34e98 bellard
        ot = dflag ? OT_LONG : OT_WORD;
3635 78c34e98 bellard
        modrm = ldub(s->pc++);
3636 78c34e98 bellard
        reg = (modrm >> 3) & 7;
3637 78c34e98 bellard
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3638 78c34e98 bellard
        gen_op_mov_TN_reg[ot][1][reg]();
3639 78c34e98 bellard
        if (s->cc_op != CC_OP_DYNAMIC)
3640 78c34e98 bellard
            gen_op_set_cc_op(s->cc_op);
3641 78c34e98 bellard
        if (b == 0x102)
3642 78c34e98 bellard
            gen_op_lar();
3643 78c34e98 bellard
        else
3644 78c34e98 bellard
            gen_op_lsl();
3645 78c34e98 bellard
        s->cc_op = CC_OP_EFLAGS;
3646 78c34e98 bellard
        gen_op_mov_reg_T1[ot][reg]();
3647 78c34e98 bellard
        break;
3648 d8bc1fd0 bellard
    case 0x118:
3649 d8bc1fd0 bellard
        modrm = ldub(s->pc++);
3650 d8bc1fd0 bellard
        mod = (modrm >> 6) & 3;
3651 d8bc1fd0 bellard
        op = (modrm >> 3) & 7;
3652 d8bc1fd0 bellard
        switch(op) {
3653 d8bc1fd0 bellard
        case 0: /* prefetchnta */
3654 d8bc1fd0 bellard
        case 1: /* prefetchnt0 */
3655 d8bc1fd0 bellard
        case 2: /* prefetchnt0 */
3656 d8bc1fd0 bellard
        case 3: /* prefetchnt0 */
3657 d8bc1fd0 bellard
            if (mod == 3)
3658 d8bc1fd0 bellard
                goto illegal_op;
3659 d8bc1fd0 bellard
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3660 d8bc1fd0 bellard
            /* nothing more to do */
3661 d8bc1fd0 bellard
            break;
3662 d8bc1fd0 bellard
        default:
3663 d8bc1fd0 bellard
            goto illegal_op;
3664 d8bc1fd0 bellard
        }
3665 d8bc1fd0 bellard
        break;
3666 d8bc1fd0 bellard
    case 0x120: /* mov reg, crN */
3667 d8bc1fd0 bellard
    case 0x122: /* mov crN, reg */
3668 d8bc1fd0 bellard
        if (s->cpl != 0) {
3669 d8bc1fd0 bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3670 d8bc1fd0 bellard
        } else {
3671 d8bc1fd0 bellard
            modrm = ldub(s->pc++);
3672 d8bc1fd0 bellard
            if ((modrm & 0xc0) != 0xc0)
3673 d8bc1fd0 bellard
                goto illegal_op;
3674 d8bc1fd0 bellard
            rm = modrm & 7;
3675 d8bc1fd0 bellard
            reg = (modrm >> 3) & 7;
3676 d8bc1fd0 bellard
            switch(reg) {
3677 d8bc1fd0 bellard
            case 0:
3678 d8bc1fd0 bellard
            case 2:
3679 d8bc1fd0 bellard
            case 3:
3680 d8bc1fd0 bellard
            case 4:
3681 d8bc1fd0 bellard
                if (b & 2) {
3682 d8bc1fd0 bellard
                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
3683 d8bc1fd0 bellard
                    gen_op_movl_crN_T0(reg);
3684 d8bc1fd0 bellard
                    s->is_jmp = 2;
3685 d8bc1fd0 bellard
                } else {
3686 d8bc1fd0 bellard
                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3687 d8bc1fd0 bellard
                    gen_op_mov_reg_T0[OT_LONG][rm]();
3688 d8bc1fd0 bellard
                }
3689 d8bc1fd0 bellard
                break;
3690 d8bc1fd0 bellard
            default:
3691 d8bc1fd0 bellard
                goto illegal_op;
3692 d8bc1fd0 bellard
            }
3693 d8bc1fd0 bellard
        }
3694 d8bc1fd0 bellard
        break;
3695 d8bc1fd0 bellard
    case 0x121: /* mov reg, drN */
3696 d8bc1fd0 bellard
    case 0x123: /* mov drN, reg */
3697 d8bc1fd0 bellard
        if (s->cpl != 0) {
3698 d8bc1fd0 bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3699 d8bc1fd0 bellard
        } else {
3700 d8bc1fd0 bellard
            modrm = ldub(s->pc++);
3701 d8bc1fd0 bellard
            if ((modrm & 0xc0) != 0xc0)
3702 d8bc1fd0 bellard
                goto illegal_op;
3703 d8bc1fd0 bellard
            rm = modrm & 7;
3704 d8bc1fd0 bellard
            reg = (modrm >> 3) & 7;
3705 d8bc1fd0 bellard
            /* XXX: do it dynamically with CR4.DE bit */
3706 d8bc1fd0 bellard
            if (reg == 4 || reg == 5)
3707 d8bc1fd0 bellard
                goto illegal_op;
3708 d8bc1fd0 bellard
            if (b & 2) {
3709 d8bc1fd0 bellard
                gen_op_mov_TN_reg[OT_LONG][0][rm]();
3710 d8bc1fd0 bellard
                gen_op_movl_drN_T0(reg);
3711 d8bc1fd0 bellard
                s->is_jmp = 2;
3712 d8bc1fd0 bellard
            } else {
3713 d8bc1fd0 bellard
                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3714 d8bc1fd0 bellard
                gen_op_mov_reg_T0[OT_LONG][rm]();
3715 d8bc1fd0 bellard
            }
3716 d8bc1fd0 bellard
        }
3717 d8bc1fd0 bellard
        break;
3718 d8bc1fd0 bellard
    case 0x106: /* clts */
3719 d8bc1fd0 bellard
        if (s->cpl != 0) {
3720 d8bc1fd0 bellard
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3721 d8bc1fd0 bellard
        } else {
3722 d8bc1fd0 bellard
            gen_op_clts();
3723 d8bc1fd0 bellard
        }
3724 d8bc1fd0 bellard
        break;
3725 367e86e8 bellard
    default:
3726 1a9353d2 bellard
        goto illegal_op;
3727 367e86e8 bellard
    }
3728 1b6b029e bellard
    /* lock generation */
3729 1b6b029e bellard
    if (s->prefix & PREFIX_LOCK)
3730 1b6b029e bellard
        gen_op_unlock();
3731 367e86e8 bellard
    return (long)s->pc;
3732 6dbad63e bellard
 illegal_op:
3733 1b6b029e bellard
    /* XXX: ensure that no lock was generated */
3734 6dbad63e bellard
    return -1;
3735 367e86e8 bellard
}
3736 367e86e8 bellard
3737 dc99065b bellard
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3738 dc99065b bellard
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3739 dc99065b bellard
3740 dc99065b bellard
/* flags read by an operation */
3741 dc99065b bellard
static uint16_t opc_read_flags[NB_OPS] = { 
3742 dc99065b bellard
    [INDEX_op_aas] = CC_A,
3743 dc99065b bellard
    [INDEX_op_aaa] = CC_A,
3744 dc99065b bellard
    [INDEX_op_das] = CC_A | CC_C,
3745 dc99065b bellard
    [INDEX_op_daa] = CC_A | CC_C,
3746 dc99065b bellard
3747 dc99065b bellard
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3748 dc99065b bellard
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3749 dc99065b bellard
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3750 dc99065b bellard
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3751 dc99065b bellard
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3752 dc99065b bellard
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3753 dc99065b bellard
3754 e477b8b8 bellard
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
3755 e477b8b8 bellard
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
3756 e477b8b8 bellard
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
3757 e477b8b8 bellard
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
3758 e477b8b8 bellard
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
3759 e477b8b8 bellard
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
3760 e477b8b8 bellard
3761 982b4315 bellard
    /* subtle: due to the incl/decl implementation, C is used */
3762 5797fa5d bellard
    [INDEX_op_update_inc_cc] = CC_C, 
3763 982b4315 bellard
3764 dc99065b bellard
    [INDEX_op_into] = CC_O,
3765 dc99065b bellard
3766 dc99065b bellard
    [INDEX_op_jb_subb] = CC_C,
3767 dc99065b bellard
    [INDEX_op_jb_subw] = CC_C,
3768 dc99065b bellard
    [INDEX_op_jb_subl] = CC_C,
3769 dc99065b bellard
3770 dc99065b bellard
    [INDEX_op_jz_subb] = CC_Z,
3771 dc99065b bellard
    [INDEX_op_jz_subw] = CC_Z,
3772 dc99065b bellard
    [INDEX_op_jz_subl] = CC_Z,
3773 dc99065b bellard
3774 dc99065b bellard
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3775 dc99065b bellard
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3776 dc99065b bellard
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3777 dc99065b bellard
3778 dc99065b bellard
    [INDEX_op_js_subb] = CC_S,
3779 dc99065b bellard
    [INDEX_op_js_subw] = CC_S,
3780 dc99065b bellard
    [INDEX_op_js_subl] = CC_S,
3781 dc99065b bellard
3782 dc99065b bellard
    [INDEX_op_jl_subb] = CC_O | CC_S,
3783 dc99065b bellard
    [INDEX_op_jl_subw] = CC_O | CC_S,
3784 dc99065b bellard
    [INDEX_op_jl_subl] = CC_O | CC_S,
3785 dc99065b bellard
3786 dc99065b bellard
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3787 dc99065b bellard
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3788 dc99065b bellard
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3789 dc99065b bellard
3790 dc99065b bellard
    [INDEX_op_loopnzw] = CC_Z,
3791 dc99065b bellard
    [INDEX_op_loopnzl] = CC_Z,
3792 dc99065b bellard
    [INDEX_op_loopzw] = CC_Z,
3793 dc99065b bellard
    [INDEX_op_loopzl] = CC_Z,
3794 dc99065b bellard
3795 dc99065b bellard
    [INDEX_op_seto_T0_cc] = CC_O,
3796 dc99065b bellard
    [INDEX_op_setb_T0_cc] = CC_C,
3797 dc99065b bellard
    [INDEX_op_setz_T0_cc] = CC_Z,
3798 dc99065b bellard
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3799 dc99065b bellard
    [INDEX_op_sets_T0_cc] = CC_S,
3800 dc99065b bellard
    [INDEX_op_setp_T0_cc] = CC_P,
3801 dc99065b bellard
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3802 dc99065b bellard
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3803 dc99065b bellard
3804 dc99065b bellard
    [INDEX_op_setb_T0_subb] = CC_C,
3805 dc99065b bellard
    [INDEX_op_setb_T0_subw] = CC_C,
3806 dc99065b bellard
    [INDEX_op_setb_T0_subl] = CC_C,
3807 dc99065b bellard
3808 dc99065b bellard
    [INDEX_op_setz_T0_subb] = CC_Z,
3809 dc99065b bellard
    [INDEX_op_setz_T0_subw] = CC_Z,
3810 dc99065b bellard
    [INDEX_op_setz_T0_subl] = CC_Z,
3811 dc99065b bellard
3812 dc99065b bellard
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3813 dc99065b bellard
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3814 dc99065b bellard
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3815 dc99065b bellard
3816 dc99065b bellard
    [INDEX_op_sets_T0_subb] = CC_S,
3817 dc99065b bellard
    [INDEX_op_sets_T0_subw] = CC_S,
3818 dc99065b bellard
    [INDEX_op_sets_T0_subl] = CC_S,
3819 dc99065b bellard
3820 dc99065b bellard
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3821 dc99065b bellard
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3822 dc99065b bellard
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3823 dc99065b bellard
3824 dc99065b bellard
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3825 dc99065b bellard
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3826 dc99065b bellard
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3827 dc99065b bellard
3828 dc99065b bellard
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3829 dc99065b bellard
    [INDEX_op_cmc] = CC_C,
3830 dc99065b bellard
    [INDEX_op_salc] = CC_C,
3831 dc99065b bellard
3832 dc99065b bellard
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3833 dc99065b bellard
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3834 dc99065b bellard
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3835 dc99065b bellard
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3836 dc99065b bellard
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3837 dc99065b bellard
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3838 e477b8b8 bellard
3839 e477b8b8 bellard
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
3840 e477b8b8 bellard
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
3841 e477b8b8 bellard
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
3842 e477b8b8 bellard
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
3843 e477b8b8 bellard
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
3844 e477b8b8 bellard
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
3845 dc99065b bellard
};
3846 dc99065b bellard
3847 dc99065b bellard
/* flags written by an operation */
3848 dc99065b bellard
static uint16_t opc_write_flags[NB_OPS] = { 
3849 5797fa5d bellard
    [INDEX_op_update2_cc] = CC_OSZAPC,
3850 5797fa5d bellard
    [INDEX_op_update1_cc] = CC_OSZAPC,
3851 e477b8b8 bellard
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3852 e477b8b8 bellard
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
3853 e477b8b8 bellard
    /* subtle: due to the incl/decl implementation, C is used */
3854 e477b8b8 bellard
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
3855 e477b8b8 bellard
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3856 e477b8b8 bellard
3857 dc99065b bellard
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3858 dc99065b bellard
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3859 dc99065b bellard
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3860 dc99065b bellard
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3861 dc99065b bellard
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3862 dc99065b bellard
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3863 e477b8b8 bellard
3864 e477b8b8 bellard
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
3865 e477b8b8 bellard
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
3866 e477b8b8 bellard
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
3867 e477b8b8 bellard
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
3868 e477b8b8 bellard
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
3869 e477b8b8 bellard
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
3870 dc99065b bellard
3871 dc99065b bellard
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3872 dc99065b bellard
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3873 dc99065b bellard
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3874 dc99065b bellard
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3875 dc99065b bellard
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3876 dc99065b bellard
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3877 dc99065b bellard
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3878 dc99065b bellard
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3879 dc99065b bellard
    
3880 dc99065b bellard
    /* bcd */
3881 dc99065b bellard
    [INDEX_op_aam] = CC_OSZAPC,
3882 dc99065b bellard
    [INDEX_op_aad] = CC_OSZAPC,
3883 dc99065b bellard
    [INDEX_op_aas] = CC_OSZAPC,
3884 dc99065b bellard
    [INDEX_op_aaa] = CC_OSZAPC,
3885 dc99065b bellard
    [INDEX_op_das] = CC_OSZAPC,
3886 dc99065b bellard
    [INDEX_op_daa] = CC_OSZAPC,
3887 dc99065b bellard
3888 dc99065b bellard
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3889 f631ef9b bellard
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3890 dc99065b bellard
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3891 dc99065b bellard
    [INDEX_op_clc] = CC_C,
3892 dc99065b bellard
    [INDEX_op_stc] = CC_C,
3893 dc99065b bellard
    [INDEX_op_cmc] = CC_C,
3894 dc99065b bellard
3895 dc99065b bellard
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3896 dc99065b bellard
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3897 dc99065b bellard
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3898 dc99065b bellard
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3899 dc99065b bellard
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3900 dc99065b bellard
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3901 dc99065b bellard
3902 dc99065b bellard
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3903 dc99065b bellard
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3904 dc99065b bellard
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3905 dc99065b bellard
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3906 dc99065b bellard
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3907 dc99065b bellard
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3908 dc99065b bellard
3909 dc99065b bellard
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3910 dc99065b bellard
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3911 dc99065b bellard
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3912 dc99065b bellard
3913 dc99065b bellard
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3914 dc99065b bellard
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3915 dc99065b bellard
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3916 dc99065b bellard
3917 dc99065b bellard
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3918 dc99065b bellard
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3919 dc99065b bellard
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3920 dc99065b bellard
3921 dc99065b bellard
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3922 dc99065b bellard
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3923 dc99065b bellard
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3924 dc99065b bellard
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3925 dc99065b bellard
3926 dc99065b bellard
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3927 dc99065b bellard
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3928 dc99065b bellard
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3929 dc99065b bellard
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3930 dc99065b bellard
3931 e477b8b8 bellard
    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
3932 e477b8b8 bellard
    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
3933 e477b8b8 bellard
    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
3934 e477b8b8 bellard
    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
3935 e477b8b8 bellard
    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
3936 e477b8b8 bellard
    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
3937 e477b8b8 bellard
3938 e477b8b8 bellard
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
3939 e477b8b8 bellard
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
3940 e477b8b8 bellard
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
3941 e477b8b8 bellard
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
3942 e477b8b8 bellard
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
3943 e477b8b8 bellard
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
3944 e477b8b8 bellard
3945 e477b8b8 bellard
    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
3946 e477b8b8 bellard
    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
3947 e477b8b8 bellard
    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
3948 e477b8b8 bellard
3949 e477b8b8 bellard
    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
3950 e477b8b8 bellard
    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
3951 e477b8b8 bellard
    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
3952 e477b8b8 bellard
3953 e477b8b8 bellard
    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
3954 e477b8b8 bellard
    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
3955 e477b8b8 bellard
    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
3956 e477b8b8 bellard
3957 e477b8b8 bellard
    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3958 e477b8b8 bellard
    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3959 e477b8b8 bellard
    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
3960 e477b8b8 bellard
    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
3961 e477b8b8 bellard
3962 e477b8b8 bellard
    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3963 e477b8b8 bellard
    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3964 e477b8b8 bellard
    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
3965 e477b8b8 bellard
    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
3966 e477b8b8 bellard
3967 dc99065b bellard
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3968 dc99065b bellard
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3969 dc99065b bellard
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3970 dc99065b bellard
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3971 dc99065b bellard
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3972 dc99065b bellard
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3973 dc99065b bellard
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3974 dc99065b bellard
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3975 dc99065b bellard
3976 dc99065b bellard
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3977 dc99065b bellard
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3978 dc99065b bellard
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3979 dc99065b bellard
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3980 dc99065b bellard
3981 9c605cb1 bellard
#undef STRINGOP
3982 9c605cb1 bellard
#define STRINGOP(x) \
3983 9c605cb1 bellard
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3984 9c605cb1 bellard
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3985 9c605cb1 bellard
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3986 9c605cb1 bellard
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3987 9c605cb1 bellard
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3988 9c605cb1 bellard
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3989 9c605cb1 bellard
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3990 9c605cb1 bellard
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3991 9c605cb1 bellard
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3992 9c605cb1 bellard
3993 9c605cb1 bellard
    STRINGOP(scas)
3994 9c605cb1 bellard
    STRINGOP(repz_scas)
3995 9c605cb1 bellard
    STRINGOP(repnz_scas)
3996 9c605cb1 bellard
    STRINGOP(cmps)
3997 9c605cb1 bellard
    STRINGOP(repz_cmps)
3998 9c605cb1 bellard
    STRINGOP(repnz_cmps)
3999 9c605cb1 bellard
4000 9c605cb1 bellard
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4001 dc99065b bellard
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4002 dc99065b bellard
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4003 9c605cb1 bellard
4004 e477b8b8 bellard
    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4005 e477b8b8 bellard
    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4006 e477b8b8 bellard
    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4007 e477b8b8 bellard
4008 9c605cb1 bellard
    [INDEX_op_cmpxchg8b] = CC_Z,
4009 78c34e98 bellard
    [INDEX_op_lar] = CC_Z,
4010 78c34e98 bellard
    [INDEX_op_lsl] = CC_Z,
4011 d0a1ffc9 bellard
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4012 d0a1ffc9 bellard
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4013 dc99065b bellard
};
4014 dc99065b bellard
4015 dc99065b bellard
/* simpler form of an operation if no flags need to be generated */
4016 dc99065b bellard
static uint16_t opc_simpler[NB_OPS] = { 
4017 5797fa5d bellard
    [INDEX_op_update2_cc] = INDEX_op_nop,
4018 5797fa5d bellard
    [INDEX_op_update1_cc] = INDEX_op_nop,
4019 5797fa5d bellard
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4020 e477b8b8 bellard
#if 0
4021 e477b8b8 bellard
    /* broken: CC_OP logic must be rewritten */
4022 5797fa5d bellard
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4023 e477b8b8 bellard
#endif
4024 dc99065b bellard
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4025 dc99065b bellard
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4026 dc99065b bellard
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4027 dc99065b bellard
4028 dc99065b bellard
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4029 dc99065b bellard
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4030 dc99065b bellard
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4031 dc99065b bellard
4032 e477b8b8 bellard
    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4033 e477b8b8 bellard
    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4034 e477b8b8 bellard
    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4035 e477b8b8 bellard
4036 e477b8b8 bellard
    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4037 e477b8b8 bellard
    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4038 e477b8b8 bellard
    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4039 e477b8b8 bellard
4040 dc99065b bellard
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4041 dc99065b bellard
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4042 dc99065b bellard
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4043 dc99065b bellard
4044 dc99065b bellard
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4045 dc99065b bellard
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4046 dc99065b bellard
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4047 dc99065b bellard
4048 dc99065b bellard
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4049 dc99065b bellard
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4050 dc99065b bellard
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4051 dc99065b bellard
};
4052 dc99065b bellard
4053 dc99065b bellard
static void optimize_flags_init(void)
4054 dc99065b bellard
{
4055 dc99065b bellard
    int i;
4056 dc99065b bellard
    /* put default values in arrays */
4057 dc99065b bellard
    for(i = 0; i < NB_OPS; i++) {
4058 dc99065b bellard
        if (opc_simpler[i] == 0)
4059 dc99065b bellard
            opc_simpler[i] = i;
4060 dc99065b bellard
    }
4061 dc99065b bellard
}
4062 dc99065b bellard
4063 dc99065b bellard
/* CPU flags computation optimization: we move backward thru the
4064 dc99065b bellard
   generated code to see which flags are needed. The operation is
4065 dc99065b bellard
   modified if suitable */
4066 dc99065b bellard
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4067 dc99065b bellard
{
4068 dc99065b bellard
    uint16_t *opc_ptr;
4069 dc99065b bellard
    int live_flags, write_flags, op;
4070 dc99065b bellard
4071 dc99065b bellard
    opc_ptr = opc_buf + opc_buf_len;
4072 dc99065b bellard
    /* live_flags contains the flags needed by the next instructions
4073 dc99065b bellard
       in the code. At the end of the bloc, we consider that all the
4074 dc99065b bellard
       flags are live. */
4075 dc99065b bellard
    live_flags = CC_OSZAPC;
4076 dc99065b bellard
    while (opc_ptr > opc_buf) {
4077 dc99065b bellard
        op = *--opc_ptr;
4078 dc99065b bellard
        /* if none of the flags written by the instruction is used,
4079 dc99065b bellard
           then we can try to find a simpler instruction */
4080 dc99065b bellard
        write_flags = opc_write_flags[op];
4081 dc99065b bellard
        if ((live_flags & write_flags) == 0) {
4082 dc99065b bellard
            *opc_ptr = opc_simpler[op];
4083 dc99065b bellard
        }
4084 dc99065b bellard
        /* compute the live flags before the instruction */
4085 dc99065b bellard
        live_flags &= ~write_flags;
4086 dc99065b bellard
        live_flags |= opc_read_flags[op];
4087 dc99065b bellard
    }
4088 dc99065b bellard
}
4089 dc99065b bellard
4090 5a91de8c bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4091 5a91de8c bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
4092 5a91de8c bellard
   information for each intermediate instruction. */
4093 4c3a88a2 bellard
static inline int gen_intermediate_code_internal(CPUState *env,
4094 4c3a88a2 bellard
                                                 TranslationBlock *tb, 
4095 4c3a88a2 bellard
                                                 int search_pc)
4096 ba1c6e37 bellard
{
4097 ba1c6e37 bellard
    DisasContext dc1, *dc = &dc1;
4098 dc99065b bellard
    uint8_t *pc_ptr;
4099 dc99065b bellard
    uint16_t *gen_opc_end;
4100 5a91de8c bellard
    int flags, j, lj;
4101 ba1c6e37 bellard
    long ret;
4102 5a91de8c bellard
    uint8_t *pc_start;
4103 5a91de8c bellard
    uint8_t *cs_base;
4104 dc99065b bellard
    
4105 dc99065b bellard
    /* generate intermediate code */
4106 5a91de8c bellard
    pc_start = (uint8_t *)tb->pc;
4107 5a91de8c bellard
    cs_base = (uint8_t *)tb->cs_base;
4108 5a91de8c bellard
    flags = tb->flags;
4109 5a91de8c bellard
       
4110 8f186479 bellard
    dc->pe = env->cr[0] & CR0_PE_MASK;
4111 6dbad63e bellard
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4112 dab2ed99 bellard
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4113 6dbad63e bellard
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4114 6dbad63e bellard
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4115 9c605cb1 bellard
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4116 8f186479 bellard
    /* CPL is implicit if real mode or vm86 mode */
4117 8f186479 bellard
    if (!dc->pe)
4118 8f186479 bellard
        dc->cpl = 0;
4119 8f186479 bellard
    else if (dc->vm86)
4120 8f186479 bellard
        dc->cpl = 3;
4121 8f186479 bellard
    else
4122 8f186479 bellard
        dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4123 982b4315 bellard
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4124 c50c0c3f bellard
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4125 ba1c6e37 bellard
    dc->cc_op = CC_OP_DYNAMIC;
4126 dab2ed99 bellard
    dc->cs_base = cs_base;
4127 d4e8164f bellard
    dc->tb = tb;
4128 717fc2ad bellard
    dc->popl_esp_hack = 0;
4129 8f186479 bellard
4130 dc99065b bellard
    gen_opc_ptr = gen_opc_buf;
4131 dc99065b bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4132 dc99065b bellard
    gen_opparam_ptr = gen_opparam_buf;
4133 0ecfa993 bellard
4134 d19893da bellard
    dc->is_jmp = DISAS_NEXT;
4135 1017ebe9 bellard
    pc_ptr = pc_start;
4136 5a91de8c bellard
    lj = -1;
4137 1017ebe9 bellard
    do {
4138 4c3a88a2 bellard
        if (env->nb_breakpoints > 0) {
4139 4c3a88a2 bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
4140 4c3a88a2 bellard
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4141 4c3a88a2 bellard
                    gen_debug(dc, pc_ptr - dc->cs_base);
4142 4c3a88a2 bellard
                    goto the_end;
4143 4c3a88a2 bellard
                }
4144 4c3a88a2 bellard
            }
4145 4c3a88a2 bellard
        }
4146 5a91de8c bellard
        if (search_pc) {
4147 5a91de8c bellard
            j = gen_opc_ptr - gen_opc_buf;
4148 5a91de8c bellard
            if (lj < j) {
4149 5a91de8c bellard
                lj++;
4150 5a91de8c bellard
                while (lj < j)
4151 5a91de8c bellard
                    gen_opc_instr_start[lj++] = 0;
4152 5a91de8c bellard
            }
4153 7739f36e bellard
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4154 7739f36e bellard
            gen_opc_cc_op[lj] = dc->cc_op;
4155 7739f36e bellard
            gen_opc_instr_start[lj] = 1;
4156 5a91de8c bellard
        }
4157 6dbad63e bellard
        ret = disas_insn(dc, pc_ptr);
4158 1a9353d2 bellard
        if (ret == -1) {
4159 9de5e440 bellard
            /* we trigger an illegal instruction operation only if it
4160 9de5e440 bellard
               is the first instruction. Otherwise, we simply stop
4161 9de5e440 bellard
               generating the code just before it */
4162 9de5e440 bellard
            if (pc_ptr == pc_start)
4163 9de5e440 bellard
                return -1;
4164 9de5e440 bellard
            else
4165 9de5e440 bellard
                break;
4166 1a9353d2 bellard
        }
4167 1017ebe9 bellard
        pc_ptr = (void *)ret;
4168 c50c0c3f bellard
        /* if single step mode, we generate only one instruction and
4169 c50c0c3f bellard
           generate an exception */
4170 c50c0c3f bellard
        if (dc->tf)
4171 c50c0c3f bellard
            break;
4172 727d01d4 bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
4173 727d01d4 bellard
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4174 e477b8b8 bellard
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4175 e477b8b8 bellard
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4176 e477b8b8 bellard
    }
4177 e477b8b8 bellard
4178 0ecfa993 bellard
    /* we must store the eflags state if it is not already done */
4179 d19893da bellard
    if (dc->is_jmp != DISAS_TB_JUMP) {
4180 d4e8164f bellard
        if (dc->cc_op != CC_OP_DYNAMIC)
4181 d4e8164f bellard
            gen_op_set_cc_op(dc->cc_op);
4182 d19893da bellard
        if (dc->is_jmp != DISAS_JUMP) {
4183 d4e8164f bellard
            /* we add an additionnal jmp to update the simulated PC */
4184 d4e8164f bellard
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4185 d4e8164f bellard
        }
4186 0ecfa993 bellard
    }
4187 c50c0c3f bellard
    if (dc->tf) {
4188 c50c0c3f bellard
        gen_op_raise_exception(EXCP01_SSTP);
4189 c50c0c3f bellard
    }
4190 4c3a88a2 bellard
 the_end:
4191 e477b8b8 bellard
    if (dc->is_jmp != DISAS_TB_JUMP) {
4192 d4e8164f bellard
        /* indicate that the hash table must be used to find the next TB */
4193 d4e8164f bellard
        gen_op_movl_T0_0();
4194 9621339d bellard
        gen_op_exit_tb();
4195 d4e8164f bellard
    }
4196 dc99065b bellard
    *gen_opc_ptr = INDEX_op_end;
4197 e477b8b8 bellard
    /* we don't forget to fill the last values */
4198 e477b8b8 bellard
    if (search_pc) {
4199 e477b8b8 bellard
        j = gen_opc_ptr - gen_opc_buf;
4200 e477b8b8 bellard
        lj++;
4201 e477b8b8 bellard
        while (lj <= j)
4202 e477b8b8 bellard
            gen_opc_instr_start[lj++] = 0;
4203 e477b8b8 bellard
    }
4204 e477b8b8 bellard
        
4205 0ecfa993 bellard
#ifdef DEBUG_DISAS
4206 586314f2 bellard
    if (loglevel) {
4207 dc99065b bellard
        fprintf(logfile, "----------------\n");
4208 b9adb4a6 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4209 d19893da bellard
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4210 1017ebe9 bellard
        fprintf(logfile, "\n");
4211 982b4315 bellard
4212 dc99065b bellard
        fprintf(logfile, "OP:\n");
4213 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
4214 dc99065b bellard
        fprintf(logfile, "\n");
4215 dc99065b bellard
    }
4216 dc99065b bellard
#endif
4217 dc99065b bellard
4218 dc99065b bellard
    /* optimize flag computations */
4219 dc99065b bellard
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4220 dc99065b bellard
4221 dc99065b bellard
#ifdef DEBUG_DISAS
4222 dc99065b bellard
    if (loglevel) {
4223 dc99065b bellard
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4224 9c605cb1 bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
4225 dc99065b bellard
        fprintf(logfile, "\n");
4226 dc99065b bellard
    }
4227 dc99065b bellard
#endif
4228 5a91de8c bellard
    if (!search_pc)
4229 5a91de8c bellard
        tb->size = pc_ptr - pc_start;
4230 5a91de8c bellard
    return 0;
4231 5a91de8c bellard
}
4232 5a91de8c bellard
4233 4c3a88a2 bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4234 717fc2ad bellard
{
4235 4c3a88a2 bellard
    return gen_intermediate_code_internal(env, tb, 0);
4236 717fc2ad bellard
}
4237 717fc2ad bellard
4238 4c3a88a2 bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4239 717fc2ad bellard
{
4240 4c3a88a2 bellard
    return gen_intermediate_code_internal(env, tb, 1);
4241 717fc2ad bellard
}
4242 717fc2ad bellard
4243 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void)
4244 ba1c6e37 bellard
{
4245 ba1c6e37 bellard
    CPUX86State *env;
4246 ba1c6e37 bellard
    int i;
4247 dc99065b bellard
    static int inited;
4248 ba1c6e37 bellard
4249 d19893da bellard
    cpu_exec_init();
4250 7d13299d bellard
4251 ba1c6e37 bellard
    env = malloc(sizeof(CPUX86State));
4252 ba1c6e37 bellard
    if (!env)
4253 ba1c6e37 bellard
        return NULL;
4254 ba1c6e37 bellard
    memset(env, 0, sizeof(CPUX86State));
4255 ba1c6e37 bellard
    /* basic FPU init */
4256 ba1c6e37 bellard
    for(i = 0;i < 8; i++)
4257 ba1c6e37 bellard
        env->fptags[i] = 1;
4258 ba1c6e37 bellard
    env->fpuc = 0x37f;
4259 9c605cb1 bellard
    /* flags setup : we activate the IRQs by default as in user mode */
4260 9c605cb1 bellard
    env->eflags = 0x2 | IF_MASK;
4261 dc99065b bellard
4262 dc99065b bellard
    /* init various static tables */
4263 dc99065b bellard
    if (!inited) {
4264 dc99065b bellard
        inited = 1;
4265 dc99065b bellard
        optimize_flags_init();
4266 dc99065b bellard
    }
4267 ba1c6e37 bellard
    return env;
4268 ba1c6e37 bellard
}
4269 ba1c6e37 bellard
4270 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *env)
4271 ba1c6e37 bellard
{
4272 ba1c6e37 bellard
    free(env);
4273 ba1c6e37 bellard
}
4274 148dfc2a bellard
4275 717fc2ad bellard
/***********************************************************/
4276 717fc2ad bellard
/* x86 mmu */
4277 43518323 bellard
/* XXX: add PGE support */
4278 717fc2ad bellard
4279 717fc2ad bellard
/* called when cr3 or PG bit are modified */
4280 717fc2ad bellard
static int last_pg_state = -1;
4281 8f186479 bellard
static int last_pe_state = 0;
4282 717fc2ad bellard
int phys_ram_size;
4283 717fc2ad bellard
int phys_ram_fd;
4284 717fc2ad bellard
uint8_t *phys_ram_base;
4285 717fc2ad bellard
4286 717fc2ad bellard
void cpu_x86_update_cr0(CPUX86State *env)
4287 717fc2ad bellard
{
4288 8f186479 bellard
    int pg_state, pe_state;
4289 717fc2ad bellard
    void *map_addr;
4290 717fc2ad bellard
4291 717fc2ad bellard
#ifdef DEBUG_MMU
4292 717fc2ad bellard
    printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
4293 717fc2ad bellard
#endif
4294 717fc2ad bellard
    pg_state = env->cr[0] & CR0_PG_MASK;
4295 717fc2ad bellard
    if (pg_state != last_pg_state) {
4296 717fc2ad bellard
        if (!pg_state) {
4297 717fc2ad bellard
            /* we map the physical memory at address 0 */
4298 717fc2ad bellard
            
4299 717fc2ad bellard
            map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ, 
4300 717fc2ad bellard
                            MAP_SHARED | MAP_FIXED, phys_ram_fd, 0);
4301 717fc2ad bellard
            if (map_addr == MAP_FAILED) {
4302 717fc2ad bellard
                fprintf(stderr, 
4303 717fc2ad bellard
                        "Could not map physical memory at host address 0x%08x\n",
4304 717fc2ad bellard
                        0);
4305 717fc2ad bellard
                exit(1);
4306 717fc2ad bellard
            }
4307 717fc2ad bellard
            page_set_flags(0, phys_ram_size, 
4308 717fc2ad bellard
                           PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC);
4309 717fc2ad bellard
        } else {
4310 717fc2ad bellard
            /* we unmap the physical memory */
4311 717fc2ad bellard
            munmap((void *)0, phys_ram_size);
4312 717fc2ad bellard
            page_set_flags(0, phys_ram_size, 0);
4313 717fc2ad bellard
        }
4314 717fc2ad bellard
        last_pg_state = pg_state;
4315 717fc2ad bellard
    }
4316 8f186479 bellard
    pe_state = env->cr[0] & CR0_PE_MASK;
4317 8f186479 bellard
    if (last_pe_state != pe_state) {
4318 8f186479 bellard
        tb_flush();
4319 8f186479 bellard
        last_pe_state = pe_state;
4320 8f186479 bellard
    }
4321 717fc2ad bellard
}
4322 717fc2ad bellard
4323 717fc2ad bellard
void cpu_x86_update_cr3(CPUX86State *env)
4324 717fc2ad bellard
{
4325 717fc2ad bellard
    if (env->cr[0] & CR0_PG_MASK) {
4326 3c1cf9fa bellard
#if defined(DEBUG_MMU)
4327 717fc2ad bellard
        printf("CR3 update: CR3=%08x\n", env->cr[3]);
4328 717fc2ad bellard
#endif
4329 717fc2ad bellard
        page_unmap();
4330 717fc2ad bellard
    }
4331 717fc2ad bellard
}
4332 717fc2ad bellard
4333 717fc2ad bellard
void cpu_x86_init_mmu(CPUX86State *env)
4334 717fc2ad bellard
{
4335 717fc2ad bellard
    last_pg_state = -1;
4336 717fc2ad bellard
    cpu_x86_update_cr0(env);
4337 717fc2ad bellard
}
4338 717fc2ad bellard
4339 43518323 bellard
/* XXX: also flush 4MB pages */
4340 717fc2ad bellard
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
4341 717fc2ad bellard
{
4342 43518323 bellard
    int flags;
4343 43518323 bellard
    unsigned long virt_addr;
4344 43518323 bellard
4345 43518323 bellard
    flags = page_get_flags(addr);
4346 43518323 bellard
    if (flags & PAGE_VALID) {
4347 43518323 bellard
        virt_addr = addr & ~0xfff;
4348 43518323 bellard
        munmap((void *)virt_addr, 4096);
4349 43518323 bellard
        page_set_flags(virt_addr, virt_addr + 4096, 0);
4350 43518323 bellard
    }
4351 717fc2ad bellard
}
4352 717fc2ad bellard
4353 717fc2ad bellard
/* return value:
4354 717fc2ad bellard
   -1 = cannot handle fault 
4355 717fc2ad bellard
   0  = nothing more to do 
4356 717fc2ad bellard
   1  = generate PF fault
4357 717fc2ad bellard
*/
4358 717fc2ad bellard
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
4359 717fc2ad bellard
{
4360 717fc2ad bellard
    uint8_t *pde_ptr, *pte_ptr;
4361 717fc2ad bellard
    uint32_t pde, pte, virt_addr;
4362 717fc2ad bellard
    int cpl, error_code, is_dirty, is_user, prot, page_size;
4363 717fc2ad bellard
    void *map_addr;
4364 717fc2ad bellard
4365 717fc2ad bellard
    cpl = env->segs[R_CS].selector & 3;
4366 717fc2ad bellard
    is_user = (cpl == 3);
4367 717fc2ad bellard
    
4368 717fc2ad bellard
#ifdef DEBUG_MMU
4369 717fc2ad bellard
    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
4370 717fc2ad bellard
           addr, is_write, is_user, env->eip);
4371 717fc2ad bellard
#endif
4372 717fc2ad bellard
4373 717fc2ad bellard
    if (env->user_mode_only) {
4374 717fc2ad bellard
        /* user mode only emulation */
4375 717fc2ad bellard
        error_code = 0;
4376 717fc2ad bellard
        goto do_fault;
4377 717fc2ad bellard
    }
4378 717fc2ad bellard
4379 717fc2ad bellard
    if (!(env->cr[0] & CR0_PG_MASK))
4380 717fc2ad bellard
        return -1;
4381 717fc2ad bellard
4382 717fc2ad bellard
    /* page directory entry */
4383 717fc2ad bellard
    pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
4384 717fc2ad bellard
    pde = ldl(pde_ptr);
4385 717fc2ad bellard
    if (!(pde & PG_PRESENT_MASK)) {
4386 717fc2ad bellard
        error_code = 0;
4387 717fc2ad bellard
        goto do_fault;
4388 717fc2ad bellard
    }
4389 717fc2ad bellard
    if (is_user) {
4390 717fc2ad bellard
        if (!(pde & PG_USER_MASK))
4391 717fc2ad bellard
            goto do_fault_protect;
4392 717fc2ad bellard
        if (is_write && !(pde & PG_RW_MASK))
4393 717fc2ad bellard
            goto do_fault_protect;
4394 717fc2ad bellard
    } else {
4395 717fc2ad bellard
        if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
4396 717fc2ad bellard
            is_write && !(pde & PG_RW_MASK)) 
4397 717fc2ad bellard
            goto do_fault_protect;
4398 717fc2ad bellard
    }
4399 717fc2ad bellard
    /* if PSE bit is set, then we use a 4MB page */
4400 717fc2ad bellard
    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4401 717fc2ad bellard
        is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4402 717fc2ad bellard
        if (!(pde & PG_ACCESSED_MASK)) {
4403 717fc2ad bellard
            pde |= PG_ACCESSED_MASK;
4404 717fc2ad bellard
            if (is_dirty)
4405 717fc2ad bellard
                pde |= PG_DIRTY_MASK;
4406 717fc2ad bellard
            stl(pde_ptr, pde);
4407 717fc2ad bellard
        }
4408 717fc2ad bellard
        
4409 717fc2ad bellard
        pte = pde & ~0x003ff000; /* align to 4MB */
4410 717fc2ad bellard
        page_size = 4096 * 1024;
4411 717fc2ad bellard
        virt_addr = addr & ~0x003fffff;
4412 717fc2ad bellard
    } else {
4413 717fc2ad bellard
        if (!(pde & PG_ACCESSED_MASK)) {
4414 717fc2ad bellard
            pde |= PG_ACCESSED_MASK;
4415 717fc2ad bellard
            stl(pde_ptr, pde);
4416 717fc2ad bellard
        }
4417 717fc2ad bellard
4418 717fc2ad bellard
        /* page directory entry */
4419 717fc2ad bellard
        pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
4420 717fc2ad bellard
        pte = ldl(pte_ptr);
4421 717fc2ad bellard
        if (!(pte & PG_PRESENT_MASK)) {
4422 717fc2ad bellard
            error_code = 0;
4423 717fc2ad bellard
            goto do_fault;
4424 717fc2ad bellard
        }
4425 717fc2ad bellard
        if (is_user) {
4426 717fc2ad bellard
            if (!(pte & PG_USER_MASK))
4427 717fc2ad bellard
                goto do_fault_protect;
4428 717fc2ad bellard
            if (is_write && !(pte & PG_RW_MASK))
4429 717fc2ad bellard
                goto do_fault_protect;
4430 717fc2ad bellard
        } else {
4431 717fc2ad bellard
            if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
4432 717fc2ad bellard
                is_write && !(pte & PG_RW_MASK)) 
4433 717fc2ad bellard
                goto do_fault_protect;
4434 717fc2ad bellard
        }
4435 717fc2ad bellard
        is_dirty = is_write && !(pte & PG_DIRTY_MASK);
4436 717fc2ad bellard
        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
4437 717fc2ad bellard
            pte |= PG_ACCESSED_MASK;
4438 717fc2ad bellard
            if (is_dirty)
4439 717fc2ad bellard
                pte |= PG_DIRTY_MASK;
4440 717fc2ad bellard
            stl(pte_ptr, pte);
4441 717fc2ad bellard
        }
4442 717fc2ad bellard
        page_size = 4096;
4443 717fc2ad bellard
        virt_addr = addr & ~0xfff;
4444 717fc2ad bellard
    }
4445 717fc2ad bellard
    /* the page can be put in the TLB */
4446 717fc2ad bellard
    prot = PROT_READ;
4447 717fc2ad bellard
    if (is_user) {
4448 717fc2ad bellard
        if (pte & PG_RW_MASK)
4449 717fc2ad bellard
            prot |= PROT_WRITE;
4450 717fc2ad bellard
    } else {
4451 717fc2ad bellard
        if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
4452 717fc2ad bellard
            (pte & PG_RW_MASK))
4453 717fc2ad bellard
            prot |= PROT_WRITE;
4454 717fc2ad bellard
    }
4455 717fc2ad bellard
    map_addr = mmap((void *)virt_addr, page_size, prot, 
4456 717fc2ad bellard
                    MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff);
4457 717fc2ad bellard
    if (map_addr == MAP_FAILED) {
4458 717fc2ad bellard
        fprintf(stderr, 
4459 717fc2ad bellard
                "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
4460 717fc2ad bellard
                pte & ~0xfff, virt_addr);
4461 717fc2ad bellard
        exit(1);
4462 717fc2ad bellard
    }
4463 717fc2ad bellard
    page_set_flags(virt_addr, virt_addr + page_size, 
4464 717fc2ad bellard
                   PAGE_VALID | PAGE_EXEC | prot);
4465 717fc2ad bellard
#ifdef DEBUG_MMU
4466 717fc2ad bellard
    printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", 
4467 717fc2ad bellard
           pte & ~0xfff, virt_addr, (page_size != 4096));
4468 717fc2ad bellard
#endif
4469 717fc2ad bellard
    return 0;
4470 717fc2ad bellard
 do_fault_protect:
4471 717fc2ad bellard
    error_code = PG_ERROR_P_MASK;
4472 717fc2ad bellard
 do_fault:
4473 717fc2ad bellard
    env->cr[2] = addr;
4474 717fc2ad bellard
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
4475 717fc2ad bellard
    if (is_user)
4476 717fc2ad bellard
        env->error_code |= PG_ERROR_U_MASK;
4477 717fc2ad bellard
    return 1;
4478 717fc2ad bellard
}
4479 717fc2ad bellard
4480 717fc2ad bellard
/***********************************************************/
4481 717fc2ad bellard
/* x86 debug */
4482 717fc2ad bellard
4483 148dfc2a bellard
static const char *cc_op_str[] = {
4484 148dfc2a bellard
    "DYNAMIC",
4485 148dfc2a bellard
    "EFLAGS",
4486 148dfc2a bellard
    "MUL",
4487 148dfc2a bellard
    "ADDB",
4488 148dfc2a bellard
    "ADDW",
4489 148dfc2a bellard
    "ADDL",
4490 148dfc2a bellard
    "ADCB",
4491 148dfc2a bellard
    "ADCW",
4492 148dfc2a bellard
    "ADCL",
4493 148dfc2a bellard
    "SUBB",
4494 148dfc2a bellard
    "SUBW",
4495 148dfc2a bellard
    "SUBL",
4496 148dfc2a bellard
    "SBBB",
4497 148dfc2a bellard
    "SBBW",
4498 148dfc2a bellard
    "SBBL",
4499 148dfc2a bellard
    "LOGICB",
4500 148dfc2a bellard
    "LOGICW",
4501 148dfc2a bellard
    "LOGICL",
4502 148dfc2a bellard
    "INCB",
4503 148dfc2a bellard
    "INCW",
4504 148dfc2a bellard
    "INCL",
4505 148dfc2a bellard
    "DECB",
4506 148dfc2a bellard
    "DECW",
4507 148dfc2a bellard
    "DECL",
4508 148dfc2a bellard
    "SHLB",
4509 148dfc2a bellard
    "SHLW",
4510 148dfc2a bellard
    "SHLL",
4511 148dfc2a bellard
    "SARB",
4512 148dfc2a bellard
    "SARW",
4513 148dfc2a bellard
    "SARL",
4514 148dfc2a bellard
};
4515 148dfc2a bellard
4516 148dfc2a bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4517 148dfc2a bellard
{
4518 148dfc2a bellard
    int eflags;
4519 148dfc2a bellard
    char cc_op_name[32];
4520 148dfc2a bellard
4521 148dfc2a bellard
    eflags = env->eflags;
4522 148dfc2a bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4523 148dfc2a bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4524 148dfc2a bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4525 148dfc2a bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
4526 148dfc2a bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
4527 148dfc2a bellard
            env->eip, eflags,
4528 148dfc2a bellard
            eflags & DF_MASK ? 'D' : '-',
4529 148dfc2a bellard
            eflags & CC_O ? 'O' : '-',
4530 148dfc2a bellard
            eflags & CC_S ? 'S' : '-',
4531 148dfc2a bellard
            eflags & CC_Z ? 'Z' : '-',
4532 148dfc2a bellard
            eflags & CC_A ? 'A' : '-',
4533 148dfc2a bellard
            eflags & CC_P ? 'P' : '-',
4534 148dfc2a bellard
            eflags & CC_C ? 'C' : '-');
4535 148dfc2a bellard
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4536 d8bc1fd0 bellard
            env->segs[R_CS].selector,
4537 d8bc1fd0 bellard
            env->segs[R_SS].selector,
4538 d8bc1fd0 bellard
            env->segs[R_DS].selector,
4539 d8bc1fd0 bellard
            env->segs[R_ES].selector,
4540 d8bc1fd0 bellard
            env->segs[R_FS].selector,
4541 d8bc1fd0 bellard
            env->segs[R_GS].selector);
4542 148dfc2a bellard
    if (flags & X86_DUMP_CCOP) {
4543 148dfc2a bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
4544 148dfc2a bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
4545 148dfc2a bellard
        else
4546 148dfc2a bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4547 148dfc2a bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4548 148dfc2a bellard
                env->cc_src, env->cc_dst, cc_op_name);
4549 148dfc2a bellard
    }
4550 148dfc2a bellard
    if (flags & X86_DUMP_FPU) {
4551 148dfc2a bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
4552 148dfc2a bellard
                (double)env->fpregs[0], 
4553 148dfc2a bellard
                (double)env->fpregs[1], 
4554 148dfc2a bellard
                (double)env->fpregs[2], 
4555 148dfc2a bellard
                (double)env->fpregs[3]);
4556 148dfc2a bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
4557 148dfc2a bellard
                (double)env->fpregs[4], 
4558 148dfc2a bellard
                (double)env->fpregs[5], 
4559 148dfc2a bellard
                (double)env->fpregs[7], 
4560 148dfc2a bellard
                (double)env->fpregs[8]);
4561 148dfc2a bellard
    }
4562 148dfc2a bellard
}