Statistics
| Branch: | Revision:

root / translate-i386.c @ dbc5594c

History | View | Annotate | Download (126.7 kB)

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