Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 4136f33c

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