Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 2ee73ac3

History | View | Annotate | Download (132.3 kB)

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