Statistics
| Branch: | Revision:

root / target-i386 / translate-copy.c @ 3d7374c5

History | View | Annotate | Download (33.8 kB)

1 58fe2f10 bellard
/*
2 58fe2f10 bellard
 *  i386 on i386 translation
3 58fe2f10 bellard
 * 
4 58fe2f10 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 58fe2f10 bellard
 *
6 58fe2f10 bellard
 * This library is free software; you can redistribute it and/or
7 58fe2f10 bellard
 * modify it under the terms of the GNU Lesser General Public
8 58fe2f10 bellard
 * License as published by the Free Software Foundation; either
9 58fe2f10 bellard
 * version 2 of the License, or (at your option) any later version.
10 58fe2f10 bellard
 *
11 58fe2f10 bellard
 * This library is distributed in the hope that it will be useful,
12 58fe2f10 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 58fe2f10 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 58fe2f10 bellard
 * Lesser General Public License for more details.
15 58fe2f10 bellard
 *
16 58fe2f10 bellard
 * You should have received a copy of the GNU Lesser General Public
17 58fe2f10 bellard
 * License along with this library; if not, write to the Free Software
18 58fe2f10 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 58fe2f10 bellard
 */
20 67b915a5 bellard
#include "config.h"
21 67b915a5 bellard
22 58fe2f10 bellard
#include <stdarg.h>
23 58fe2f10 bellard
#include <stdlib.h>
24 58fe2f10 bellard
#include <stdio.h>
25 58fe2f10 bellard
#include <string.h>
26 58fe2f10 bellard
#include <inttypes.h>
27 58fe2f10 bellard
#include <assert.h>
28 58fe2f10 bellard
29 58fe2f10 bellard
#include "cpu.h"
30 58fe2f10 bellard
#include "exec-all.h"
31 58fe2f10 bellard
#include "disas.h"
32 58fe2f10 bellard
33 42c3c0cc bellard
#ifdef USE_CODE_COPY
34 42c3c0cc bellard
35 67b915a5 bellard
#include <signal.h>
36 67b915a5 bellard
#include <sys/mman.h>
37 67b915a5 bellard
#include <sys/ucontext.h>
38 67b915a5 bellard
39 58fe2f10 bellard
extern char exec_loop;
40 58fe2f10 bellard
41 58fe2f10 bellard
/* operand size */
42 58fe2f10 bellard
enum {
43 58fe2f10 bellard
    OT_BYTE = 0,
44 58fe2f10 bellard
    OT_WORD,
45 58fe2f10 bellard
    OT_LONG, 
46 58fe2f10 bellard
    OT_QUAD,
47 58fe2f10 bellard
};
48 58fe2f10 bellard
49 58fe2f10 bellard
#define PREFIX_REPZ   0x01
50 58fe2f10 bellard
#define PREFIX_REPNZ  0x02
51 58fe2f10 bellard
#define PREFIX_LOCK   0x04
52 58fe2f10 bellard
#define PREFIX_DATA   0x08
53 58fe2f10 bellard
#define PREFIX_ADR    0x10
54 58fe2f10 bellard
55 58fe2f10 bellard
typedef struct DisasContext {
56 58fe2f10 bellard
    /* current insn context */
57 58fe2f10 bellard
    int override; /* -1 if no override */
58 58fe2f10 bellard
    int prefix;
59 58fe2f10 bellard
    int aflag, dflag;
60 14ce26e7 bellard
    target_ulong pc; /* pc = eip + cs_base */
61 58fe2f10 bellard
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
62 58fe2f10 bellard
                   static state change (stop translation) */
63 58fe2f10 bellard
    /* code output */
64 58fe2f10 bellard
    uint8_t *gen_code_ptr;
65 58fe2f10 bellard
    uint8_t *gen_code_start;
66 58fe2f10 bellard
    
67 58fe2f10 bellard
    /* current block context */
68 14ce26e7 bellard
    target_ulong cs_base; /* base of CS segment */
69 58fe2f10 bellard
    int pe;     /* protected mode */
70 58fe2f10 bellard
    int code32; /* 32 bit code segment */
71 58fe2f10 bellard
    int f_st;   /* currently unused */
72 58fe2f10 bellard
    int vm86;   /* vm86 mode */
73 58fe2f10 bellard
    int cpl;
74 58fe2f10 bellard
    int iopl;
75 42c3c0cc bellard
    int flags;
76 58fe2f10 bellard
    struct TranslationBlock *tb;
77 58fe2f10 bellard
} DisasContext;
78 58fe2f10 bellard
79 58fe2f10 bellard
#define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
80 58fe2f10 bellard
81 58fe2f10 bellard
#define CPU_SEG 0x64 /* fs override */
82 58fe2f10 bellard
83 58fe2f10 bellard
static inline void gb(DisasContext *s, uint32_t val)
84 58fe2f10 bellard
{
85 58fe2f10 bellard
    *s->gen_code_ptr++ = val;
86 58fe2f10 bellard
}
87 58fe2f10 bellard
88 58fe2f10 bellard
static inline void gw(DisasContext *s, uint32_t val)
89 58fe2f10 bellard
{
90 58fe2f10 bellard
    *s->gen_code_ptr++ = val;
91 58fe2f10 bellard
    *s->gen_code_ptr++ = val >> 8;
92 58fe2f10 bellard
}
93 58fe2f10 bellard
94 58fe2f10 bellard
static inline void gl(DisasContext *s, uint32_t val)
95 58fe2f10 bellard
{
96 58fe2f10 bellard
    *s->gen_code_ptr++ = val;
97 58fe2f10 bellard
    *s->gen_code_ptr++ = val >> 8;
98 58fe2f10 bellard
    *s->gen_code_ptr++ = val >> 16;
99 58fe2f10 bellard
    *s->gen_code_ptr++ = val >> 24;
100 58fe2f10 bellard
}
101 58fe2f10 bellard
102 58fe2f10 bellard
static inline void gjmp(DisasContext *s, long val)
103 58fe2f10 bellard
{
104 58fe2f10 bellard
    gb(s, 0xe9); /* jmp */
105 58fe2f10 bellard
    gl(s, val - (long)(s->gen_code_ptr + 4));
106 58fe2f10 bellard
}
107 58fe2f10 bellard
108 58fe2f10 bellard
static inline void gen_movl_addr_im(DisasContext *s, 
109 58fe2f10 bellard
                                    uint32_t addr, uint32_t val)
110 58fe2f10 bellard
{
111 58fe2f10 bellard
    gb(s, CPU_SEG); /* seg movl im, addr */
112 58fe2f10 bellard
    gb(s, 0xc7); 
113 58fe2f10 bellard
    gb(s, 0x05);
114 58fe2f10 bellard
    gl(s, addr);
115 58fe2f10 bellard
    gl(s, val);
116 58fe2f10 bellard
}
117 58fe2f10 bellard
118 58fe2f10 bellard
static inline void gen_movw_addr_im(DisasContext *s, 
119 58fe2f10 bellard
                                    uint32_t addr, uint32_t val)
120 58fe2f10 bellard
{
121 58fe2f10 bellard
    gb(s, CPU_SEG); /* seg movl im, addr */
122 58fe2f10 bellard
    gb(s, 0x66); 
123 58fe2f10 bellard
    gb(s, 0xc7); 
124 58fe2f10 bellard
    gb(s, 0x05);
125 58fe2f10 bellard
    gl(s, addr);
126 58fe2f10 bellard
    gw(s, val);
127 58fe2f10 bellard
}
128 58fe2f10 bellard
129 58fe2f10 bellard
130 58fe2f10 bellard
static void gen_jmp(DisasContext *s, uint32_t target_eip)
131 58fe2f10 bellard
{
132 58fe2f10 bellard
    TranslationBlock *tb = s->tb;
133 58fe2f10 bellard
134 58fe2f10 bellard
    gb(s, 0xe9); /* jmp */
135 58fe2f10 bellard
    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
136 58fe2f10 bellard
    gl(s, 0);
137 58fe2f10 bellard
138 58fe2f10 bellard
    tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
139 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
140 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
141 58fe2f10 bellard
    gjmp(s, (long)&exec_loop);
142 58fe2f10 bellard
143 58fe2f10 bellard
    s->is_jmp = 1;
144 58fe2f10 bellard
}
145 58fe2f10 bellard
146 58fe2f10 bellard
static void gen_jcc(DisasContext *s, int op,
147 58fe2f10 bellard
                    uint32_t target_eip, uint32_t next_eip)
148 58fe2f10 bellard
{
149 58fe2f10 bellard
    TranslationBlock *tb = s->tb;
150 58fe2f10 bellard
151 58fe2f10 bellard
    gb(s, 0x0f); /* jcc */
152 58fe2f10 bellard
    gb(s, 0x80 + op);
153 58fe2f10 bellard
    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
154 58fe2f10 bellard
    gl(s, 0);
155 58fe2f10 bellard
    gb(s, 0xe9); /* jmp */
156 58fe2f10 bellard
    tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
157 58fe2f10 bellard
    gl(s, 0);
158 58fe2f10 bellard
    
159 58fe2f10 bellard
    tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
160 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
161 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
162 58fe2f10 bellard
    gjmp(s, (long)&exec_loop);
163 58fe2f10 bellard
164 58fe2f10 bellard
    tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
165 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
166 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
167 58fe2f10 bellard
    gjmp(s, (long)&exec_loop);
168 58fe2f10 bellard
169 58fe2f10 bellard
    s->is_jmp = 1;
170 58fe2f10 bellard
}
171 58fe2f10 bellard
172 58fe2f10 bellard
static void gen_eob(DisasContext *s)
173 58fe2f10 bellard
{
174 58fe2f10 bellard
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
175 58fe2f10 bellard
    gjmp(s, (long)&exec_loop);
176 58fe2f10 bellard
177 58fe2f10 bellard
    s->is_jmp = 1;
178 58fe2f10 bellard
}
179 58fe2f10 bellard
180 58fe2f10 bellard
static inline void gen_lea_modrm(DisasContext *s, int modrm)
181 58fe2f10 bellard
{
182 58fe2f10 bellard
    int havesib;
183 58fe2f10 bellard
    int base, disp;
184 58fe2f10 bellard
    int index;
185 58fe2f10 bellard
    int scale;
186 58fe2f10 bellard
    int mod, rm, code;
187 58fe2f10 bellard
188 58fe2f10 bellard
    mod = (modrm >> 6) & 3;
189 58fe2f10 bellard
    rm = modrm & 7;
190 58fe2f10 bellard
191 58fe2f10 bellard
    if (s->aflag) {
192 58fe2f10 bellard
193 58fe2f10 bellard
        havesib = 0;
194 58fe2f10 bellard
        base = rm;
195 58fe2f10 bellard
        index = 0;
196 58fe2f10 bellard
        scale = 0;
197 58fe2f10 bellard
        
198 58fe2f10 bellard
        if (base == 4) {
199 58fe2f10 bellard
            havesib = 1;
200 58fe2f10 bellard
            code = ldub_code(s->pc++);
201 58fe2f10 bellard
            scale = (code >> 6) & 3;
202 58fe2f10 bellard
            index = (code >> 3) & 7;
203 58fe2f10 bellard
            base = code & 7;
204 58fe2f10 bellard
        }
205 58fe2f10 bellard
206 58fe2f10 bellard
        switch (mod) {
207 58fe2f10 bellard
        case 0:
208 58fe2f10 bellard
            if (base == 5) {
209 58fe2f10 bellard
                base = -1;
210 58fe2f10 bellard
                disp = ldl_code(s->pc);
211 58fe2f10 bellard
                s->pc += 4;
212 58fe2f10 bellard
            } else {
213 58fe2f10 bellard
                disp = 0;
214 58fe2f10 bellard
            }
215 58fe2f10 bellard
            break;
216 58fe2f10 bellard
        case 1:
217 58fe2f10 bellard
            disp = (int8_t)ldub_code(s->pc++);
218 58fe2f10 bellard
            break;
219 58fe2f10 bellard
        default:
220 58fe2f10 bellard
        case 2:
221 58fe2f10 bellard
            disp = ldl_code(s->pc);
222 58fe2f10 bellard
            s->pc += 4;
223 58fe2f10 bellard
            break;
224 58fe2f10 bellard
        }
225 58fe2f10 bellard
        
226 58fe2f10 bellard
    } else {
227 58fe2f10 bellard
        switch (mod) {
228 58fe2f10 bellard
        case 0:
229 58fe2f10 bellard
            if (rm == 6) {
230 58fe2f10 bellard
                disp = lduw_code(s->pc);
231 58fe2f10 bellard
                s->pc += 2;
232 58fe2f10 bellard
            } else {
233 58fe2f10 bellard
                disp = 0;
234 58fe2f10 bellard
            }
235 58fe2f10 bellard
            break;
236 58fe2f10 bellard
        case 1:
237 58fe2f10 bellard
            disp = (int8_t)ldub_code(s->pc++);
238 58fe2f10 bellard
            break;
239 58fe2f10 bellard
        default:
240 58fe2f10 bellard
        case 2:
241 58fe2f10 bellard
            disp = lduw_code(s->pc);
242 58fe2f10 bellard
            s->pc += 2;
243 58fe2f10 bellard
            break;
244 58fe2f10 bellard
        }
245 58fe2f10 bellard
    }
246 58fe2f10 bellard
}
247 58fe2f10 bellard
248 58fe2f10 bellard
static inline void parse_modrm(DisasContext *s, int modrm)
249 58fe2f10 bellard
{
250 58fe2f10 bellard
    if ((modrm & 0xc0) != 0xc0)
251 58fe2f10 bellard
        gen_lea_modrm(s, modrm);        
252 58fe2f10 bellard
}
253 58fe2f10 bellard
254 58fe2f10 bellard
static inline uint32_t insn_get(DisasContext *s, int ot)
255 58fe2f10 bellard
{
256 58fe2f10 bellard
    uint32_t ret;
257 58fe2f10 bellard
258 58fe2f10 bellard
    switch(ot) {
259 58fe2f10 bellard
    case OT_BYTE:
260 58fe2f10 bellard
        ret = ldub_code(s->pc);
261 58fe2f10 bellard
        s->pc++;
262 58fe2f10 bellard
        break;
263 58fe2f10 bellard
    case OT_WORD:
264 58fe2f10 bellard
        ret = lduw_code(s->pc);
265 58fe2f10 bellard
        s->pc += 2;
266 58fe2f10 bellard
        break;
267 58fe2f10 bellard
    default:
268 58fe2f10 bellard
    case OT_LONG:
269 58fe2f10 bellard
        ret = ldl_code(s->pc);
270 58fe2f10 bellard
        s->pc += 4;
271 58fe2f10 bellard
        break;
272 58fe2f10 bellard
    }
273 58fe2f10 bellard
    return ret;
274 58fe2f10 bellard
}
275 58fe2f10 bellard
276 58fe2f10 bellard
/* convert one instruction. s->is_jmp is set if the translation must
277 58fe2f10 bellard
   be stopped.  */
278 58fe2f10 bellard
static int disas_insn(DisasContext *s)
279 58fe2f10 bellard
{
280 14ce26e7 bellard
    target_ulong pc_start, pc_tmp, pc_start_insn;
281 58fe2f10 bellard
    int b, prefixes, aflag, dflag, next_eip, val;
282 58fe2f10 bellard
    int ot;
283 42c3c0cc bellard
    int modrm, mod, op, rm;
284 58fe2f10 bellard
285 58fe2f10 bellard
    pc_start = s->pc;
286 58fe2f10 bellard
    prefixes = 0;
287 58fe2f10 bellard
    aflag = s->code32;
288 58fe2f10 bellard
    dflag = s->code32;
289 58fe2f10 bellard
    s->override = -1;
290 58fe2f10 bellard
 next_byte:
291 58fe2f10 bellard
    b = ldub_code(s->pc);
292 58fe2f10 bellard
    s->pc++;
293 58fe2f10 bellard
    /* check prefixes */
294 58fe2f10 bellard
    switch (b) {
295 58fe2f10 bellard
    case 0xf3:
296 58fe2f10 bellard
        prefixes |= PREFIX_REPZ;
297 58fe2f10 bellard
        goto next_byte;
298 58fe2f10 bellard
    case 0xf2:
299 58fe2f10 bellard
        prefixes |= PREFIX_REPNZ;
300 58fe2f10 bellard
        goto next_byte;
301 58fe2f10 bellard
    case 0xf0:
302 58fe2f10 bellard
        prefixes |= PREFIX_LOCK;
303 58fe2f10 bellard
        goto next_byte;
304 58fe2f10 bellard
    case 0x2e:
305 58fe2f10 bellard
        s->override = R_CS;
306 58fe2f10 bellard
        goto next_byte;
307 58fe2f10 bellard
    case 0x36:
308 58fe2f10 bellard
        s->override = R_SS;
309 58fe2f10 bellard
        goto next_byte;
310 58fe2f10 bellard
    case 0x3e:
311 58fe2f10 bellard
        s->override = R_DS;
312 58fe2f10 bellard
        goto next_byte;
313 58fe2f10 bellard
    case 0x26:
314 58fe2f10 bellard
        s->override = R_ES;
315 58fe2f10 bellard
        goto next_byte;
316 58fe2f10 bellard
    case 0x64:
317 58fe2f10 bellard
        s->override = R_FS;
318 58fe2f10 bellard
        goto next_byte;
319 58fe2f10 bellard
    case 0x65:
320 58fe2f10 bellard
        s->override = R_GS;
321 58fe2f10 bellard
        goto next_byte;
322 58fe2f10 bellard
    case 0x66:
323 58fe2f10 bellard
        prefixes |= PREFIX_DATA;
324 58fe2f10 bellard
        goto next_byte;
325 58fe2f10 bellard
    case 0x67:
326 58fe2f10 bellard
        prefixes |= PREFIX_ADR;
327 58fe2f10 bellard
        goto next_byte;
328 58fe2f10 bellard
    }
329 58fe2f10 bellard
330 58fe2f10 bellard
    if (prefixes & PREFIX_DATA)
331 58fe2f10 bellard
        dflag ^= 1;
332 58fe2f10 bellard
    if (prefixes & PREFIX_ADR)
333 58fe2f10 bellard
        aflag ^= 1;
334 58fe2f10 bellard
335 58fe2f10 bellard
    s->prefix = prefixes;
336 58fe2f10 bellard
    s->aflag = aflag;
337 58fe2f10 bellard
    s->dflag = dflag;
338 58fe2f10 bellard
339 58fe2f10 bellard
    /* lock generation */
340 58fe2f10 bellard
    if (prefixes & PREFIX_LOCK)
341 58fe2f10 bellard
        goto unsupported_op;
342 58fe2f10 bellard
    if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
343 58fe2f10 bellard
        goto unsupported_op;
344 58fe2f10 bellard
345 58fe2f10 bellard
    pc_start_insn = s->pc - 1;
346 58fe2f10 bellard
    /* now check op code */
347 58fe2f10 bellard
 reswitch:
348 58fe2f10 bellard
    switch(b) {
349 58fe2f10 bellard
    case 0x0f:
350 58fe2f10 bellard
        /**************************/
351 58fe2f10 bellard
        /* extended op code */
352 58fe2f10 bellard
        b = ldub_code(s->pc++) | 0x100;
353 58fe2f10 bellard
        goto reswitch;
354 58fe2f10 bellard
        
355 58fe2f10 bellard
        /**************************/
356 58fe2f10 bellard
        /* arith & logic */
357 58fe2f10 bellard
    case 0x00 ... 0x05:
358 58fe2f10 bellard
    case 0x08 ... 0x0d:
359 58fe2f10 bellard
    case 0x10 ... 0x15:
360 58fe2f10 bellard
    case 0x18 ... 0x1d:
361 58fe2f10 bellard
    case 0x20 ... 0x25:
362 58fe2f10 bellard
    case 0x28 ... 0x2d:
363 58fe2f10 bellard
    case 0x30 ... 0x35:
364 58fe2f10 bellard
    case 0x38 ... 0x3d:
365 58fe2f10 bellard
        {
366 58fe2f10 bellard
            int f;
367 58fe2f10 bellard
            f = (b >> 1) & 3;
368 58fe2f10 bellard
369 58fe2f10 bellard
            if ((b & 1) == 0)
370 58fe2f10 bellard
                ot = OT_BYTE;
371 58fe2f10 bellard
            else
372 58fe2f10 bellard
                ot = dflag ? OT_LONG : OT_WORD;
373 58fe2f10 bellard
            
374 58fe2f10 bellard
            switch(f) {
375 58fe2f10 bellard
            case 0: /* OP Ev, Gv */
376 58fe2f10 bellard
                modrm = ldub_code(s->pc++);
377 58fe2f10 bellard
                parse_modrm(s, modrm);
378 58fe2f10 bellard
                break;
379 58fe2f10 bellard
            case 1: /* OP Gv, Ev */
380 58fe2f10 bellard
                modrm = ldub_code(s->pc++);
381 58fe2f10 bellard
                parse_modrm(s, modrm);
382 58fe2f10 bellard
                break;
383 58fe2f10 bellard
            case 2: /* OP A, Iv */
384 58fe2f10 bellard
                insn_get(s, ot);
385 58fe2f10 bellard
                break;
386 58fe2f10 bellard
            }
387 58fe2f10 bellard
        }
388 58fe2f10 bellard
        break;
389 58fe2f10 bellard
390 58fe2f10 bellard
    case 0x80: /* GRP1 */
391 58fe2f10 bellard
    case 0x81:
392 d64477af bellard
    case 0x82:
393 58fe2f10 bellard
    case 0x83:
394 58fe2f10 bellard
        {
395 58fe2f10 bellard
            if ((b & 1) == 0)
396 58fe2f10 bellard
                ot = OT_BYTE;
397 58fe2f10 bellard
            else
398 58fe2f10 bellard
                ot = dflag ? OT_LONG : OT_WORD;
399 58fe2f10 bellard
            
400 58fe2f10 bellard
            modrm = ldub_code(s->pc++);
401 58fe2f10 bellard
            parse_modrm(s, modrm);
402 58fe2f10 bellard
403 58fe2f10 bellard
            switch(b) {
404 58fe2f10 bellard
            default:
405 58fe2f10 bellard
            case 0x80:
406 58fe2f10 bellard
            case 0x81:
407 d64477af bellard
            case 0x82:
408 58fe2f10 bellard
                insn_get(s, ot);
409 58fe2f10 bellard
                break;
410 58fe2f10 bellard
            case 0x83:
411 58fe2f10 bellard
                insn_get(s, OT_BYTE);
412 58fe2f10 bellard
                break;
413 58fe2f10 bellard
            }
414 58fe2f10 bellard
        }
415 58fe2f10 bellard
        break;
416 58fe2f10 bellard
417 58fe2f10 bellard
        /**************************/
418 58fe2f10 bellard
        /* inc, dec, and other misc arith */
419 58fe2f10 bellard
    case 0x40 ... 0x47: /* inc Gv */
420 58fe2f10 bellard
        break;
421 58fe2f10 bellard
    case 0x48 ... 0x4f: /* dec Gv */
422 58fe2f10 bellard
        break;
423 58fe2f10 bellard
    case 0xf6: /* GRP3 */
424 58fe2f10 bellard
    case 0xf7:
425 58fe2f10 bellard
        if ((b & 1) == 0)
426 58fe2f10 bellard
            ot = OT_BYTE;
427 58fe2f10 bellard
        else
428 58fe2f10 bellard
            ot = dflag ? OT_LONG : OT_WORD;
429 58fe2f10 bellard
430 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
431 58fe2f10 bellard
        op = (modrm >> 3) & 7;
432 58fe2f10 bellard
        parse_modrm(s, modrm);
433 58fe2f10 bellard
434 58fe2f10 bellard
        switch(op) {
435 58fe2f10 bellard
        case 0: /* test */
436 58fe2f10 bellard
            insn_get(s, ot);
437 58fe2f10 bellard
            break;
438 58fe2f10 bellard
        case 2: /* not */
439 58fe2f10 bellard
            break;
440 58fe2f10 bellard
        case 3: /* neg */
441 58fe2f10 bellard
            break;
442 58fe2f10 bellard
        case 4: /* mul */
443 58fe2f10 bellard
            break;
444 58fe2f10 bellard
        case 5: /* imul */
445 58fe2f10 bellard
            break;
446 58fe2f10 bellard
        case 6: /* div */
447 58fe2f10 bellard
            break;
448 58fe2f10 bellard
        case 7: /* idiv */
449 58fe2f10 bellard
            break;
450 58fe2f10 bellard
        default:
451 58fe2f10 bellard
            goto illegal_op;
452 58fe2f10 bellard
        }
453 58fe2f10 bellard
        break;
454 58fe2f10 bellard
455 58fe2f10 bellard
    case 0xfe: /* GRP4 */
456 58fe2f10 bellard
    case 0xff: /* GRP5 */
457 58fe2f10 bellard
        if ((b & 1) == 0)
458 58fe2f10 bellard
            ot = OT_BYTE;
459 58fe2f10 bellard
        else
460 58fe2f10 bellard
            ot = dflag ? OT_LONG : OT_WORD;
461 58fe2f10 bellard
462 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
463 58fe2f10 bellard
        mod = (modrm >> 6) & 3;
464 58fe2f10 bellard
        op = (modrm >> 3) & 7;
465 58fe2f10 bellard
        if (op >= 2 && b == 0xfe) {
466 58fe2f10 bellard
            goto illegal_op;
467 58fe2f10 bellard
        }
468 58fe2f10 bellard
        pc_tmp = s->pc;
469 58fe2f10 bellard
        parse_modrm(s, modrm);
470 58fe2f10 bellard
471 58fe2f10 bellard
        switch(op) {
472 58fe2f10 bellard
        case 0: /* inc Ev */
473 58fe2f10 bellard
            break;
474 58fe2f10 bellard
        case 1: /* dec Ev */
475 58fe2f10 bellard
            break;
476 58fe2f10 bellard
        case 2: /* call Ev */
477 58fe2f10 bellard
            /* XXX: optimize and handle MEM exceptions specifically
478 58fe2f10 bellard
               fs movl %eax, regs[0] 
479 58fe2f10 bellard
               movl Ev, %eax 
480 58fe2f10 bellard
               pushl next_eip
481 58fe2f10 bellard
               fs movl %eax, eip
482 58fe2f10 bellard
            */
483 58fe2f10 bellard
            goto unsupported_op;
484 58fe2f10 bellard
        case 3: /* lcall Ev */
485 58fe2f10 bellard
            goto unsupported_op;
486 58fe2f10 bellard
        case 4: /* jmp Ev */
487 58fe2f10 bellard
            /* XXX: optimize and handle MEM exceptions specifically
488 58fe2f10 bellard
               fs movl %eax, regs[0] 
489 58fe2f10 bellard
               movl Ev, %eax 
490 58fe2f10 bellard
               fs movl %eax, eip
491 58fe2f10 bellard
            */
492 58fe2f10 bellard
            goto unsupported_op;
493 58fe2f10 bellard
        case 5: /* ljmp Ev */
494 58fe2f10 bellard
            goto unsupported_op;
495 58fe2f10 bellard
        case 6: /* push Ev */
496 58fe2f10 bellard
            break;
497 58fe2f10 bellard
        default:
498 58fe2f10 bellard
            goto illegal_op;
499 58fe2f10 bellard
        }
500 58fe2f10 bellard
        break;
501 58fe2f10 bellard
    case 0xa8: /* test eAX, Iv */
502 58fe2f10 bellard
    case 0xa9:
503 58fe2f10 bellard
        if ((b & 1) == 0)
504 58fe2f10 bellard
            ot = OT_BYTE;
505 58fe2f10 bellard
        else
506 58fe2f10 bellard
            ot = dflag ? OT_LONG : OT_WORD;
507 58fe2f10 bellard
        insn_get(s, ot);
508 58fe2f10 bellard
        break;
509 58fe2f10 bellard
        
510 58fe2f10 bellard
    case 0x98: /* CWDE/CBW */
511 58fe2f10 bellard
        break;
512 58fe2f10 bellard
    case 0x99: /* CDQ/CWD */
513 58fe2f10 bellard
        break;
514 58fe2f10 bellard
    case 0x1af: /* imul Gv, Ev */
515 58fe2f10 bellard
    case 0x69: /* imul Gv, Ev, I */
516 58fe2f10 bellard
    case 0x6b:
517 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
518 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
519 58fe2f10 bellard
        parse_modrm(s, modrm);
520 58fe2f10 bellard
        if (b == 0x69) {
521 58fe2f10 bellard
            insn_get(s, ot);
522 58fe2f10 bellard
        } else if (b == 0x6b) {
523 58fe2f10 bellard
            insn_get(s, OT_BYTE);
524 58fe2f10 bellard
        } else {
525 58fe2f10 bellard
        }
526 58fe2f10 bellard
        break;
527 58fe2f10 bellard
528 58fe2f10 bellard
    case 0x84: /* test Ev, Gv */
529 58fe2f10 bellard
    case 0x85: 
530 58fe2f10 bellard
        
531 58fe2f10 bellard
    case 0x1c0:
532 58fe2f10 bellard
    case 0x1c1: /* xadd Ev, Gv */
533 58fe2f10 bellard
534 58fe2f10 bellard
    case 0x1b0:
535 58fe2f10 bellard
    case 0x1b1: /* cmpxchg Ev, Gv */
536 58fe2f10 bellard
537 58fe2f10 bellard
    case 0x8f: /* pop Ev */
538 58fe2f10 bellard
539 58fe2f10 bellard
    case 0x88:
540 58fe2f10 bellard
    case 0x89: /* mov Gv, Ev */
541 58fe2f10 bellard
542 58fe2f10 bellard
    case 0x8a:
543 58fe2f10 bellard
    case 0x8b: /* mov Ev, Gv */
544 58fe2f10 bellard
545 58fe2f10 bellard
    case 0x1b6: /* movzbS Gv, Eb */
546 58fe2f10 bellard
    case 0x1b7: /* movzwS Gv, Eb */
547 58fe2f10 bellard
    case 0x1be: /* movsbS Gv, Eb */
548 58fe2f10 bellard
    case 0x1bf: /* movswS Gv, Eb */
549 58fe2f10 bellard
550 58fe2f10 bellard
    case 0x86:
551 58fe2f10 bellard
    case 0x87: /* xchg Ev, Gv */
552 58fe2f10 bellard
553 58fe2f10 bellard
    case 0xd0:
554 58fe2f10 bellard
    case 0xd1: /* shift Ev,1 */
555 58fe2f10 bellard
556 58fe2f10 bellard
    case 0xd2:
557 58fe2f10 bellard
    case 0xd3: /* shift Ev,cl */
558 58fe2f10 bellard
559 58fe2f10 bellard
    case 0x1a5: /* shld cl */
560 58fe2f10 bellard
    case 0x1ad: /* shrd cl */
561 58fe2f10 bellard
562 58fe2f10 bellard
    case 0x190 ... 0x19f: /* setcc Gv */
563 58fe2f10 bellard
564 58fe2f10 bellard
    /* XXX: emulate cmov if not available ? */
565 58fe2f10 bellard
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
566 58fe2f10 bellard
567 58fe2f10 bellard
    case 0x1a3: /* bt Gv, Ev */
568 58fe2f10 bellard
    case 0x1ab: /* bts */
569 58fe2f10 bellard
    case 0x1b3: /* btr */
570 58fe2f10 bellard
    case 0x1bb: /* btc */
571 58fe2f10 bellard
572 58fe2f10 bellard
    case 0x1bc: /* bsf */
573 58fe2f10 bellard
    case 0x1bd: /* bsr */
574 58fe2f10 bellard
575 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
576 58fe2f10 bellard
        parse_modrm(s, modrm);
577 58fe2f10 bellard
        break;
578 58fe2f10 bellard
579 58fe2f10 bellard
    case 0x1c7: /* cmpxchg8b */
580 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
581 58fe2f10 bellard
        mod = (modrm >> 6) & 3;
582 58fe2f10 bellard
        if (mod == 3)
583 58fe2f10 bellard
            goto illegal_op;
584 58fe2f10 bellard
        parse_modrm(s, modrm);
585 58fe2f10 bellard
        break;
586 58fe2f10 bellard
        
587 58fe2f10 bellard
        /**************************/
588 58fe2f10 bellard
        /* push/pop */
589 58fe2f10 bellard
    case 0x50 ... 0x57: /* push */
590 58fe2f10 bellard
    case 0x58 ... 0x5f: /* pop */
591 58fe2f10 bellard
    case 0x60: /* pusha */
592 58fe2f10 bellard
    case 0x61: /* popa */
593 58fe2f10 bellard
        break;
594 58fe2f10 bellard
595 58fe2f10 bellard
    case 0x68: /* push Iv */
596 58fe2f10 bellard
    case 0x6a:
597 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
598 58fe2f10 bellard
        if (b == 0x68)
599 58fe2f10 bellard
            insn_get(s, ot);
600 58fe2f10 bellard
        else
601 58fe2f10 bellard
            insn_get(s, OT_BYTE);
602 58fe2f10 bellard
        break;
603 58fe2f10 bellard
    case 0xc8: /* enter */
604 58fe2f10 bellard
        lduw_code(s->pc);
605 58fe2f10 bellard
        s->pc += 2;
606 58fe2f10 bellard
        ldub_code(s->pc++);
607 58fe2f10 bellard
        break;
608 58fe2f10 bellard
    case 0xc9: /* leave */
609 58fe2f10 bellard
        break;
610 58fe2f10 bellard
611 58fe2f10 bellard
    case 0x06: /* push es */
612 58fe2f10 bellard
    case 0x0e: /* push cs */
613 58fe2f10 bellard
    case 0x16: /* push ss */
614 58fe2f10 bellard
    case 0x1e: /* push ds */
615 58fe2f10 bellard
        /* XXX: optimize:
616 58fe2f10 bellard
         push segs[n].selector
617 58fe2f10 bellard
        */
618 58fe2f10 bellard
        goto unsupported_op;
619 58fe2f10 bellard
    case 0x1a0: /* push fs */
620 58fe2f10 bellard
    case 0x1a8: /* push gs */
621 58fe2f10 bellard
        goto unsupported_op;
622 58fe2f10 bellard
    case 0x07: /* pop es */
623 58fe2f10 bellard
    case 0x17: /* pop ss */
624 58fe2f10 bellard
    case 0x1f: /* pop ds */
625 58fe2f10 bellard
        goto unsupported_op;
626 58fe2f10 bellard
    case 0x1a1: /* pop fs */
627 58fe2f10 bellard
    case 0x1a9: /* pop gs */
628 58fe2f10 bellard
        goto unsupported_op;
629 58fe2f10 bellard
    case 0x8e: /* mov seg, Gv */
630 58fe2f10 bellard
        /* XXX: optimize:
631 58fe2f10 bellard
           fs movl r, regs[]
632 58fe2f10 bellard
           movl segs[].selector, r
633 58fe2f10 bellard
           mov r, Gv
634 58fe2f10 bellard
           fs movl regs[], r
635 58fe2f10 bellard
        */
636 58fe2f10 bellard
        goto unsupported_op;
637 58fe2f10 bellard
    case 0x8c: /* mov Gv, seg */
638 58fe2f10 bellard
        goto unsupported_op;
639 58fe2f10 bellard
    case 0xc4: /* les Gv */
640 58fe2f10 bellard
        op = R_ES;
641 58fe2f10 bellard
        goto do_lxx;
642 58fe2f10 bellard
    case 0xc5: /* lds Gv */
643 58fe2f10 bellard
        op = R_DS;
644 58fe2f10 bellard
        goto do_lxx;
645 58fe2f10 bellard
    case 0x1b2: /* lss Gv */
646 58fe2f10 bellard
        op = R_SS;
647 58fe2f10 bellard
        goto do_lxx;
648 58fe2f10 bellard
    case 0x1b4: /* lfs Gv */
649 58fe2f10 bellard
        op = R_FS;
650 58fe2f10 bellard
        goto do_lxx;
651 58fe2f10 bellard
    case 0x1b5: /* lgs Gv */
652 58fe2f10 bellard
        op = R_GS;
653 58fe2f10 bellard
    do_lxx:
654 58fe2f10 bellard
        goto unsupported_op;
655 58fe2f10 bellard
        /************************/
656 58fe2f10 bellard
        /* floats */
657 58fe2f10 bellard
    case 0xd8 ... 0xdf: 
658 42c3c0cc bellard
#if 1
659 42c3c0cc bellard
        /* currently not stable enough */
660 42c3c0cc bellard
        goto unsupported_op;
661 42c3c0cc bellard
#else
662 42c3c0cc bellard
        if (s->flags & (HF_EM_MASK | HF_TS_MASK))
663 42c3c0cc bellard
            goto unsupported_op;
664 42c3c0cc bellard
#endif
665 42c3c0cc bellard
#if 0
666 42c3c0cc bellard
        /* for testing FPU context switch */
667 42c3c0cc bellard
        {
668 42c3c0cc bellard
            static int count;
669 42c3c0cc bellard
            count = (count + 1) % 3;
670 42c3c0cc bellard
            if (count != 0)
671 42c3c0cc bellard
                goto unsupported_op;
672 42c3c0cc bellard
        }
673 42c3c0cc bellard
#endif
674 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
675 58fe2f10 bellard
        mod = (modrm >> 6) & 3;
676 58fe2f10 bellard
        rm = modrm & 7;
677 58fe2f10 bellard
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
678 58fe2f10 bellard
        if (mod != 3) {
679 58fe2f10 bellard
            /* memory op */
680 42c3c0cc bellard
            parse_modrm(s, modrm);
681 58fe2f10 bellard
            switch(op) {
682 58fe2f10 bellard
            case 0x00 ... 0x07: /* fxxxs */
683 58fe2f10 bellard
            case 0x10 ... 0x17: /* fixxxl */
684 58fe2f10 bellard
            case 0x20 ... 0x27: /* fxxxl */
685 58fe2f10 bellard
            case 0x30 ... 0x37: /* fixxx */
686 58fe2f10 bellard
                break;
687 58fe2f10 bellard
            case 0x08: /* flds */
688 58fe2f10 bellard
            case 0x0a: /* fsts */
689 58fe2f10 bellard
            case 0x0b: /* fstps */
690 58fe2f10 bellard
            case 0x18: /* fildl */
691 58fe2f10 bellard
            case 0x1a: /* fistl */
692 58fe2f10 bellard
            case 0x1b: /* fistpl */
693 58fe2f10 bellard
            case 0x28: /* fldl */
694 58fe2f10 bellard
            case 0x2a: /* fstl */
695 58fe2f10 bellard
            case 0x2b: /* fstpl */
696 58fe2f10 bellard
            case 0x38: /* filds */
697 58fe2f10 bellard
            case 0x3a: /* fists */
698 58fe2f10 bellard
            case 0x3b: /* fistps */
699 58fe2f10 bellard
            case 0x0c: /* fldenv mem */
700 58fe2f10 bellard
            case 0x0d: /* fldcw mem */
701 58fe2f10 bellard
            case 0x0e: /* fnstenv mem */
702 58fe2f10 bellard
            case 0x0f: /* fnstcw mem */
703 58fe2f10 bellard
            case 0x1d: /* fldt mem */
704 58fe2f10 bellard
            case 0x1f: /* fstpt mem */
705 58fe2f10 bellard
            case 0x2c: /* frstor mem */
706 58fe2f10 bellard
            case 0x2e: /* fnsave mem */
707 58fe2f10 bellard
            case 0x2f: /* fnstsw mem */
708 58fe2f10 bellard
            case 0x3c: /* fbld */
709 58fe2f10 bellard
            case 0x3e: /* fbstp */
710 58fe2f10 bellard
            case 0x3d: /* fildll */
711 58fe2f10 bellard
            case 0x3f: /* fistpll */
712 58fe2f10 bellard
                break;
713 58fe2f10 bellard
            default:
714 58fe2f10 bellard
                goto illegal_op;
715 58fe2f10 bellard
            }
716 58fe2f10 bellard
        } else {
717 58fe2f10 bellard
            /* register float ops */
718 58fe2f10 bellard
            switch(op) {
719 58fe2f10 bellard
            case 0x08: /* fld sti */
720 58fe2f10 bellard
            case 0x09: /* fxchg sti */
721 58fe2f10 bellard
                break;
722 58fe2f10 bellard
            case 0x0a: /* grp d9/2 */
723 58fe2f10 bellard
                switch(rm) {
724 58fe2f10 bellard
                case 0: /* fnop */
725 58fe2f10 bellard
                    break;
726 58fe2f10 bellard
                default:
727 58fe2f10 bellard
                    goto illegal_op;
728 58fe2f10 bellard
                }
729 58fe2f10 bellard
                break;
730 58fe2f10 bellard
            case 0x0c: /* grp d9/4 */
731 58fe2f10 bellard
                switch(rm) {
732 58fe2f10 bellard
                case 0: /* fchs */
733 58fe2f10 bellard
                case 1: /* fabs */
734 58fe2f10 bellard
                case 4: /* ftst */
735 58fe2f10 bellard
                case 5: /* fxam */
736 58fe2f10 bellard
                    break;
737 58fe2f10 bellard
                default:
738 58fe2f10 bellard
                    goto illegal_op;
739 58fe2f10 bellard
                }
740 58fe2f10 bellard
                break;
741 58fe2f10 bellard
            case 0x0d: /* grp d9/5 */
742 58fe2f10 bellard
                switch(rm) {
743 42c3c0cc bellard
                case 0:
744 42c3c0cc bellard
                case 1:
745 42c3c0cc bellard
                case 2:
746 42c3c0cc bellard
                case 3:
747 42c3c0cc bellard
                case 4:
748 42c3c0cc bellard
                case 5:
749 42c3c0cc bellard
                case 6:
750 58fe2f10 bellard
                    break;
751 58fe2f10 bellard
                default:
752 42c3c0cc bellard
                    goto illegal_op;
753 58fe2f10 bellard
                }
754 58fe2f10 bellard
                break;
755 42c3c0cc bellard
            case 0x0e: /* grp d9/6 */
756 42c3c0cc bellard
                break;
757 58fe2f10 bellard
            case 0x0f: /* grp d9/7 */
758 58fe2f10 bellard
                break;
759 58fe2f10 bellard
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
760 58fe2f10 bellard
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
761 58fe2f10 bellard
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
762 58fe2f10 bellard
                break;
763 58fe2f10 bellard
            case 0x02: /* fcom */
764 58fe2f10 bellard
                break;
765 58fe2f10 bellard
            case 0x03: /* fcomp */
766 58fe2f10 bellard
                break;
767 58fe2f10 bellard
            case 0x15: /* da/5 */
768 58fe2f10 bellard
                switch(rm) {
769 58fe2f10 bellard
                case 1: /* fucompp */
770 58fe2f10 bellard
                    break;
771 58fe2f10 bellard
                default:
772 58fe2f10 bellard
                    goto illegal_op;
773 58fe2f10 bellard
                }
774 58fe2f10 bellard
                break;
775 58fe2f10 bellard
            case 0x1c:
776 58fe2f10 bellard
                switch(rm) {
777 58fe2f10 bellard
                case 0: /* feni (287 only, just do nop here) */
778 58fe2f10 bellard
                case 1: /* fdisi (287 only, just do nop here) */
779 42c3c0cc bellard
                    goto unsupported_op;
780 58fe2f10 bellard
                case 2: /* fclex */
781 58fe2f10 bellard
                case 3: /* fninit */
782 58fe2f10 bellard
                case 4: /* fsetpm (287 only, just do nop here) */
783 58fe2f10 bellard
                    break;
784 58fe2f10 bellard
                default:
785 58fe2f10 bellard
                    goto illegal_op;
786 58fe2f10 bellard
                }
787 58fe2f10 bellard
                break;
788 58fe2f10 bellard
            case 0x1d: /* fucomi */
789 58fe2f10 bellard
                break;
790 58fe2f10 bellard
            case 0x1e: /* fcomi */
791 58fe2f10 bellard
                break;
792 14ce26e7 bellard
            case 0x28: /* ffree sti */
793 14ce26e7 bellard
                break;
794 58fe2f10 bellard
            case 0x2a: /* fst sti */
795 58fe2f10 bellard
                break;
796 58fe2f10 bellard
            case 0x2b: /* fstp sti */
797 58fe2f10 bellard
                break;
798 58fe2f10 bellard
            case 0x2c: /* fucom st(i) */
799 58fe2f10 bellard
                break;
800 58fe2f10 bellard
            case 0x2d: /* fucomp st(i) */
801 58fe2f10 bellard
                break;
802 58fe2f10 bellard
            case 0x33: /* de/3 */
803 58fe2f10 bellard
                switch(rm) {
804 58fe2f10 bellard
                case 1: /* fcompp */
805 58fe2f10 bellard
                    break;
806 58fe2f10 bellard
                default:
807 58fe2f10 bellard
                    goto illegal_op;
808 58fe2f10 bellard
                }
809 58fe2f10 bellard
                break;
810 58fe2f10 bellard
            case 0x3c: /* df/4 */
811 58fe2f10 bellard
                switch(rm) {
812 58fe2f10 bellard
                case 0:
813 58fe2f10 bellard
                    break;
814 58fe2f10 bellard
                default:
815 58fe2f10 bellard
                    goto illegal_op;
816 58fe2f10 bellard
                }
817 58fe2f10 bellard
                break;
818 58fe2f10 bellard
            case 0x3d: /* fucomip */
819 58fe2f10 bellard
                break;
820 58fe2f10 bellard
            case 0x3e: /* fcomip */
821 58fe2f10 bellard
                break;
822 58fe2f10 bellard
            case 0x10 ... 0x13: /* fcmovxx */
823 58fe2f10 bellard
            case 0x18 ... 0x1b:
824 58fe2f10 bellard
                break;
825 58fe2f10 bellard
            default:
826 58fe2f10 bellard
                goto illegal_op;
827 58fe2f10 bellard
            }
828 58fe2f10 bellard
        }
829 42c3c0cc bellard
        s->tb->cflags |= CF_TB_FP_USED;
830 58fe2f10 bellard
        break;
831 42c3c0cc bellard
832 58fe2f10 bellard
        /**************************/
833 58fe2f10 bellard
        /* mov */
834 58fe2f10 bellard
    case 0xc6:
835 58fe2f10 bellard
    case 0xc7: /* mov Ev, Iv */
836 58fe2f10 bellard
        if ((b & 1) == 0)
837 58fe2f10 bellard
            ot = OT_BYTE;
838 58fe2f10 bellard
        else
839 58fe2f10 bellard
            ot = dflag ? OT_LONG : OT_WORD;
840 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
841 58fe2f10 bellard
        parse_modrm(s, modrm);
842 58fe2f10 bellard
        insn_get(s, ot);
843 58fe2f10 bellard
        break;
844 58fe2f10 bellard
845 58fe2f10 bellard
    case 0x8d: /* lea */
846 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
847 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
848 58fe2f10 bellard
        mod = (modrm >> 6) & 3;
849 58fe2f10 bellard
        if (mod == 3)
850 58fe2f10 bellard
            goto illegal_op;
851 58fe2f10 bellard
        parse_modrm(s, modrm);
852 58fe2f10 bellard
        break;
853 58fe2f10 bellard
        
854 58fe2f10 bellard
    case 0xa0: /* mov EAX, Ov */
855 58fe2f10 bellard
    case 0xa1:
856 58fe2f10 bellard
    case 0xa2: /* mov Ov, EAX */
857 58fe2f10 bellard
    case 0xa3:
858 58fe2f10 bellard
        if ((b & 1) == 0)
859 58fe2f10 bellard
            ot = OT_BYTE;
860 58fe2f10 bellard
        else
861 58fe2f10 bellard
            ot = dflag ? OT_LONG : OT_WORD;
862 58fe2f10 bellard
        if (s->aflag)
863 58fe2f10 bellard
            insn_get(s, OT_LONG);
864 58fe2f10 bellard
        else
865 58fe2f10 bellard
            insn_get(s, OT_WORD);
866 58fe2f10 bellard
        break;
867 58fe2f10 bellard
    case 0xd7: /* xlat */
868 58fe2f10 bellard
        break;
869 58fe2f10 bellard
    case 0xb0 ... 0xb7: /* mov R, Ib */
870 58fe2f10 bellard
        insn_get(s, OT_BYTE);
871 58fe2f10 bellard
        break;
872 58fe2f10 bellard
    case 0xb8 ... 0xbf: /* mov R, Iv */
873 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
874 58fe2f10 bellard
        insn_get(s, ot);
875 58fe2f10 bellard
        break;
876 58fe2f10 bellard
877 58fe2f10 bellard
    case 0x91 ... 0x97: /* xchg R, EAX */
878 58fe2f10 bellard
        break;
879 58fe2f10 bellard
880 58fe2f10 bellard
        /************************/
881 58fe2f10 bellard
        /* shifts */
882 58fe2f10 bellard
    case 0xc0:
883 58fe2f10 bellard
    case 0xc1: /* shift Ev,imm */
884 58fe2f10 bellard
885 58fe2f10 bellard
    case 0x1a4: /* shld imm */
886 58fe2f10 bellard
    case 0x1ac: /* shrd imm */
887 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
888 58fe2f10 bellard
        parse_modrm(s, modrm);
889 58fe2f10 bellard
        ldub_code(s->pc++);
890 58fe2f10 bellard
        break;
891 58fe2f10 bellard
        
892 58fe2f10 bellard
        /************************/
893 58fe2f10 bellard
        /* string ops */
894 58fe2f10 bellard
895 58fe2f10 bellard
    case 0xa4: /* movsS */
896 58fe2f10 bellard
    case 0xa5:
897 58fe2f10 bellard
        break;
898 58fe2f10 bellard
        
899 58fe2f10 bellard
    case 0xaa: /* stosS */
900 58fe2f10 bellard
    case 0xab:
901 58fe2f10 bellard
        break;
902 58fe2f10 bellard
903 58fe2f10 bellard
    case 0xac: /* lodsS */
904 58fe2f10 bellard
    case 0xad:
905 58fe2f10 bellard
        break;
906 58fe2f10 bellard
907 58fe2f10 bellard
    case 0xae: /* scasS */
908 58fe2f10 bellard
    case 0xaf:
909 58fe2f10 bellard
        break;
910 58fe2f10 bellard
911 58fe2f10 bellard
    case 0xa6: /* cmpsS */
912 58fe2f10 bellard
    case 0xa7:
913 58fe2f10 bellard
        break;
914 58fe2f10 bellard
915 58fe2f10 bellard
    case 0x6c: /* insS */
916 58fe2f10 bellard
    case 0x6d:
917 58fe2f10 bellard
        goto unsupported_op;
918 58fe2f10 bellard
919 58fe2f10 bellard
    case 0x6e: /* outsS */
920 58fe2f10 bellard
    case 0x6f:
921 58fe2f10 bellard
        goto unsupported_op;
922 58fe2f10 bellard
923 58fe2f10 bellard
        /************************/
924 58fe2f10 bellard
        /* port I/O */
925 58fe2f10 bellard
    case 0xe4:
926 58fe2f10 bellard
    case 0xe5:
927 58fe2f10 bellard
        goto unsupported_op;
928 58fe2f10 bellard
929 58fe2f10 bellard
    case 0xe6:
930 58fe2f10 bellard
    case 0xe7:
931 58fe2f10 bellard
        goto unsupported_op;
932 58fe2f10 bellard
933 58fe2f10 bellard
    case 0xec:
934 58fe2f10 bellard
    case 0xed:
935 58fe2f10 bellard
        goto unsupported_op;
936 58fe2f10 bellard
937 58fe2f10 bellard
    case 0xee:
938 58fe2f10 bellard
    case 0xef:
939 58fe2f10 bellard
        goto unsupported_op;
940 58fe2f10 bellard
941 58fe2f10 bellard
        /************************/
942 58fe2f10 bellard
        /* control */
943 58fe2f10 bellard
#if 0
944 58fe2f10 bellard
    case 0xc2: /* ret im */
945 58fe2f10 bellard
        val = ldsw_code(s->pc);
946 58fe2f10 bellard
        s->pc += 2;
947 58fe2f10 bellard
        gen_pop_T0(s);
948 58fe2f10 bellard
        gen_stack_update(s, val + (2 << s->dflag));
949 58fe2f10 bellard
        if (s->dflag == 0)
950 58fe2f10 bellard
            gen_op_andl_T0_ffff();
951 58fe2f10 bellard
        gen_op_jmp_T0();
952 58fe2f10 bellard
        gen_eob(s);
953 58fe2f10 bellard
        break;
954 58fe2f10 bellard
#endif
955 58fe2f10 bellard
956 58fe2f10 bellard
    case 0xc3: /* ret */
957 58fe2f10 bellard
        gb(s, CPU_SEG);
958 58fe2f10 bellard
        if (!s->dflag)  
959 58fe2f10 bellard
            gb(s, 0x66); /* d16 */
960 58fe2f10 bellard
        gb(s, 0x8f); /* pop addr */
961 58fe2f10 bellard
        gb(s, 0x05);
962 58fe2f10 bellard
        gl(s, CPU_FIELD_OFFSET(eip));
963 58fe2f10 bellard
        if (!s->dflag) {
964 58fe2f10 bellard
            /* reset high bits of EIP */
965 58fe2f10 bellard
            gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
966 58fe2f10 bellard
        }
967 58fe2f10 bellard
        gen_eob(s);
968 58fe2f10 bellard
        goto no_copy;
969 58fe2f10 bellard
    case 0xca: /* lret im */
970 58fe2f10 bellard
    case 0xcb: /* lret */
971 58fe2f10 bellard
    case 0xcf: /* iret */
972 58fe2f10 bellard
    case 0x9a: /* lcall im */
973 58fe2f10 bellard
    case 0xea: /* ljmp im */
974 58fe2f10 bellard
        goto unsupported_op;
975 58fe2f10 bellard
976 58fe2f10 bellard
    case 0xe8: /* call im */
977 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
978 58fe2f10 bellard
        val = insn_get(s, ot);
979 58fe2f10 bellard
        next_eip = s->pc - s->cs_base;
980 58fe2f10 bellard
        val += next_eip;
981 58fe2f10 bellard
        if (s->dflag) {
982 58fe2f10 bellard
            gb(s, 0x68); /* pushl imm */
983 58fe2f10 bellard
            gl(s, next_eip);
984 58fe2f10 bellard
        } else {
985 58fe2f10 bellard
            gb(s, 0x66); /* pushw imm */
986 58fe2f10 bellard
            gb(s, 0x68);
987 58fe2f10 bellard
            gw(s, next_eip);
988 58fe2f10 bellard
            val &= 0xffff;
989 58fe2f10 bellard
        }
990 58fe2f10 bellard
        gen_jmp(s, val);
991 58fe2f10 bellard
        goto no_copy;
992 58fe2f10 bellard
    case 0xe9: /* jmp */
993 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
994 58fe2f10 bellard
        val = insn_get(s, ot);
995 58fe2f10 bellard
        val += s->pc - s->cs_base;
996 58fe2f10 bellard
        if (s->dflag == 0)
997 58fe2f10 bellard
            val = val & 0xffff;
998 58fe2f10 bellard
        gen_jmp(s, val);
999 58fe2f10 bellard
        goto no_copy;
1000 58fe2f10 bellard
    case 0xeb: /* jmp Jb */
1001 58fe2f10 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
1002 58fe2f10 bellard
        val += s->pc - s->cs_base;
1003 58fe2f10 bellard
        if (s->dflag == 0)
1004 58fe2f10 bellard
            val = val & 0xffff;
1005 58fe2f10 bellard
        gen_jmp(s, val);
1006 58fe2f10 bellard
        goto no_copy;
1007 58fe2f10 bellard
    case 0x70 ... 0x7f: /* jcc Jb */
1008 58fe2f10 bellard
        val = (int8_t)insn_get(s, OT_BYTE);
1009 58fe2f10 bellard
        goto do_jcc;
1010 58fe2f10 bellard
    case 0x180 ... 0x18f: /* jcc Jv */
1011 58fe2f10 bellard
        if (dflag) {
1012 58fe2f10 bellard
            val = insn_get(s, OT_LONG);
1013 58fe2f10 bellard
        } else {
1014 58fe2f10 bellard
            val = (int16_t)insn_get(s, OT_WORD); 
1015 58fe2f10 bellard
        }
1016 58fe2f10 bellard
    do_jcc:
1017 58fe2f10 bellard
        next_eip = s->pc - s->cs_base;
1018 58fe2f10 bellard
        val += next_eip;
1019 58fe2f10 bellard
        if (s->dflag == 0)
1020 58fe2f10 bellard
            val &= 0xffff;
1021 58fe2f10 bellard
        gen_jcc(s, b & 0xf, val, next_eip);
1022 58fe2f10 bellard
        goto no_copy;
1023 58fe2f10 bellard
1024 58fe2f10 bellard
        /************************/
1025 58fe2f10 bellard
        /* flags */
1026 58fe2f10 bellard
    case 0x9c: /* pushf */
1027 58fe2f10 bellard
        /* XXX: put specific code ? */
1028 58fe2f10 bellard
        goto unsupported_op;
1029 58fe2f10 bellard
    case 0x9d: /* popf */
1030 58fe2f10 bellard
        goto unsupported_op;
1031 58fe2f10 bellard
1032 58fe2f10 bellard
    case 0x9e: /* sahf */
1033 58fe2f10 bellard
    case 0x9f: /* lahf */
1034 58fe2f10 bellard
    case 0xf5: /* cmc */
1035 58fe2f10 bellard
    case 0xf8: /* clc */
1036 58fe2f10 bellard
    case 0xf9: /* stc */
1037 58fe2f10 bellard
    case 0xfc: /* cld */
1038 58fe2f10 bellard
    case 0xfd: /* std */
1039 58fe2f10 bellard
        break;
1040 58fe2f10 bellard
1041 58fe2f10 bellard
        /************************/
1042 58fe2f10 bellard
        /* bit operations */
1043 58fe2f10 bellard
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
1044 58fe2f10 bellard
        ot = dflag ? OT_LONG : OT_WORD;
1045 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
1046 58fe2f10 bellard
        op = (modrm >> 3) & 7;
1047 58fe2f10 bellard
        parse_modrm(s, modrm);
1048 58fe2f10 bellard
        /* load shift */
1049 58fe2f10 bellard
        ldub_code(s->pc++);
1050 58fe2f10 bellard
        if (op < 4)
1051 58fe2f10 bellard
            goto illegal_op;
1052 58fe2f10 bellard
        break;
1053 58fe2f10 bellard
        /************************/
1054 58fe2f10 bellard
        /* bcd */
1055 58fe2f10 bellard
    case 0x27: /* daa */
1056 58fe2f10 bellard
        break;
1057 58fe2f10 bellard
    case 0x2f: /* das */
1058 58fe2f10 bellard
        break;
1059 58fe2f10 bellard
    case 0x37: /* aaa */
1060 58fe2f10 bellard
        break;
1061 58fe2f10 bellard
    case 0x3f: /* aas */
1062 58fe2f10 bellard
        break;
1063 58fe2f10 bellard
    case 0xd4: /* aam */
1064 58fe2f10 bellard
        ldub_code(s->pc++);
1065 58fe2f10 bellard
        break;
1066 58fe2f10 bellard
    case 0xd5: /* aad */
1067 58fe2f10 bellard
        ldub_code(s->pc++);
1068 58fe2f10 bellard
        break;
1069 58fe2f10 bellard
        /************************/
1070 58fe2f10 bellard
        /* misc */
1071 58fe2f10 bellard
    case 0x90: /* nop */
1072 58fe2f10 bellard
        break;
1073 58fe2f10 bellard
    case 0x9b: /* fwait */
1074 42c3c0cc bellard
        if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 
1075 42c3c0cc bellard
            (HF_MP_MASK | HF_TS_MASK)) {
1076 42c3c0cc bellard
            goto unsupported_op;
1077 42c3c0cc bellard
        }
1078 58fe2f10 bellard
        break;
1079 58fe2f10 bellard
    case 0xcc: /* int3 */
1080 58fe2f10 bellard
        goto unsupported_op;
1081 58fe2f10 bellard
    case 0xcd: /* int N */
1082 58fe2f10 bellard
        goto unsupported_op;
1083 58fe2f10 bellard
    case 0xce: /* into */
1084 58fe2f10 bellard
        goto unsupported_op;
1085 58fe2f10 bellard
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
1086 58fe2f10 bellard
        goto unsupported_op;
1087 58fe2f10 bellard
    case 0xfa: /* cli */
1088 58fe2f10 bellard
        goto unsupported_op;
1089 58fe2f10 bellard
    case 0xfb: /* sti */
1090 58fe2f10 bellard
        goto unsupported_op;
1091 58fe2f10 bellard
    case 0x62: /* bound */
1092 58fe2f10 bellard
        modrm = ldub_code(s->pc++);
1093 58fe2f10 bellard
        mod = (modrm >> 6) & 3;
1094 58fe2f10 bellard
        if (mod == 3)
1095 58fe2f10 bellard
            goto illegal_op;
1096 58fe2f10 bellard
        parse_modrm(s, modrm);
1097 58fe2f10 bellard
        break;
1098 58fe2f10 bellard
    case 0x1c8 ... 0x1cf: /* bswap reg */
1099 58fe2f10 bellard
        break;
1100 58fe2f10 bellard
    case 0xd6: /* salc */
1101 58fe2f10 bellard
        break;
1102 58fe2f10 bellard
    case 0xe0: /* loopnz */
1103 58fe2f10 bellard
    case 0xe1: /* loopz */
1104 58fe2f10 bellard
    case 0xe2: /* loop */
1105 58fe2f10 bellard
    case 0xe3: /* jecxz */
1106 58fe2f10 bellard
        goto unsupported_op;
1107 58fe2f10 bellard
1108 58fe2f10 bellard
    case 0x130: /* wrmsr */
1109 58fe2f10 bellard
    case 0x132: /* rdmsr */
1110 58fe2f10 bellard
        goto unsupported_op;
1111 58fe2f10 bellard
    case 0x131: /* rdtsc */
1112 58fe2f10 bellard
        goto unsupported_op;
1113 58fe2f10 bellard
    case 0x1a2: /* cpuid */
1114 58fe2f10 bellard
        goto unsupported_op;
1115 58fe2f10 bellard
    case 0xf4: /* hlt */
1116 58fe2f10 bellard
        goto unsupported_op;
1117 58fe2f10 bellard
    case 0x100:
1118 58fe2f10 bellard
        goto unsupported_op;
1119 58fe2f10 bellard
    case 0x101:
1120 58fe2f10 bellard
        goto unsupported_op;
1121 58fe2f10 bellard
    case 0x108: /* invd */
1122 58fe2f10 bellard
    case 0x109: /* wbinvd */
1123 58fe2f10 bellard
        goto unsupported_op;
1124 58fe2f10 bellard
    case 0x63: /* arpl */
1125 58fe2f10 bellard
        goto unsupported_op;
1126 58fe2f10 bellard
    case 0x102: /* lar */
1127 58fe2f10 bellard
    case 0x103: /* lsl */
1128 58fe2f10 bellard
        goto unsupported_op;
1129 58fe2f10 bellard
    case 0x118:
1130 58fe2f10 bellard
        goto unsupported_op;
1131 58fe2f10 bellard
    case 0x120: /* mov reg, crN */
1132 58fe2f10 bellard
    case 0x122: /* mov crN, reg */
1133 58fe2f10 bellard
        goto unsupported_op;
1134 58fe2f10 bellard
    case 0x121: /* mov reg, drN */
1135 58fe2f10 bellard
    case 0x123: /* mov drN, reg */
1136 58fe2f10 bellard
        goto unsupported_op;
1137 58fe2f10 bellard
    case 0x106: /* clts */
1138 58fe2f10 bellard
        goto unsupported_op;
1139 58fe2f10 bellard
    default:
1140 58fe2f10 bellard
        goto illegal_op;
1141 58fe2f10 bellard
    }
1142 58fe2f10 bellard
1143 58fe2f10 bellard
    /* just copy the code */
1144 58fe2f10 bellard
1145 58fe2f10 bellard
    /* no override yet */
1146 58fe2f10 bellard
    if (!s->dflag)
1147 58fe2f10 bellard
        gb(s, 0x66);
1148 58fe2f10 bellard
    if (!s->aflag)
1149 58fe2f10 bellard
        gb(s, 0x67);
1150 58fe2f10 bellard
    if (prefixes & PREFIX_REPZ)
1151 58fe2f10 bellard
        gb(s, 0xf3);
1152 58fe2f10 bellard
    else if (prefixes & PREFIX_REPNZ)
1153 58fe2f10 bellard
        gb(s, 0xf2);
1154 58fe2f10 bellard
    {
1155 58fe2f10 bellard
        int len, i;
1156 58fe2f10 bellard
        len = s->pc - pc_start_insn;
1157 58fe2f10 bellard
        for(i = 0; i < len; i++) {
1158 58fe2f10 bellard
            *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1159 58fe2f10 bellard
        }
1160 58fe2f10 bellard
    }
1161 58fe2f10 bellard
 no_copy:
1162 58fe2f10 bellard
    return 0;
1163 58fe2f10 bellard
 illegal_op:
1164 58fe2f10 bellard
 unsupported_op:
1165 58fe2f10 bellard
    /* fall back to slower code gen necessary */
1166 58fe2f10 bellard
    s->pc = pc_start;
1167 58fe2f10 bellard
    return -1;
1168 58fe2f10 bellard
}
1169 58fe2f10 bellard
1170 58fe2f10 bellard
#define GEN_CODE_MAX_SIZE      8192
1171 58fe2f10 bellard
#define GEN_CODE_MAX_INSN_SIZE 512
1172 58fe2f10 bellard
1173 58fe2f10 bellard
static inline int gen_intermediate_code_internal(CPUState *env,
1174 58fe2f10 bellard
                                                 TranslationBlock *tb, 
1175 58fe2f10 bellard
                                                 uint8_t *gen_code_ptr,
1176 58fe2f10 bellard
                                                 int *gen_code_size_ptr,
1177 58fe2f10 bellard
                                                 int search_pc,
1178 58fe2f10 bellard
                                                 uint8_t *tc_ptr)
1179 58fe2f10 bellard
{
1180 58fe2f10 bellard
    DisasContext dc1, *dc = &dc1;
1181 14ce26e7 bellard
    target_ulong pc_insn, pc_start, cs_base;
1182 14ce26e7 bellard
    uint8_t *gen_code_end;
1183 58fe2f10 bellard
    int flags, ret;
1184 58fe2f10 bellard
1185 58fe2f10 bellard
    if (env->nb_breakpoints > 0 ||
1186 58fe2f10 bellard
        env->singlestep_enabled)
1187 58fe2f10 bellard
        return -1;
1188 58fe2f10 bellard
    flags = tb->flags;
1189 58fe2f10 bellard
    if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | 
1190 58fe2f10 bellard
                 HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1191 58fe2f10 bellard
        return -1;
1192 58fe2f10 bellard
    if (!(flags & HF_SS32_MASK))
1193 58fe2f10 bellard
        return -1;
1194 d720b93d bellard
    if (tb->cflags & CF_SINGLE_INSN)
1195 d720b93d bellard
        return -1;
1196 58fe2f10 bellard
    gen_code_end = gen_code_ptr + 
1197 58fe2f10 bellard
        GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1198 58fe2f10 bellard
    dc->gen_code_ptr = gen_code_ptr;
1199 58fe2f10 bellard
    dc->gen_code_start = gen_code_ptr;
1200 58fe2f10 bellard
1201 58fe2f10 bellard
    /* generate intermediate code */
1202 14ce26e7 bellard
    pc_start = tb->pc;
1203 14ce26e7 bellard
    cs_base = tb->cs_base;
1204 58fe2f10 bellard
    dc->pc = pc_start;
1205 58fe2f10 bellard
    dc->cs_base = cs_base;
1206 58fe2f10 bellard
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
1207 58fe2f10 bellard
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1208 58fe2f10 bellard
    dc->f_st = 0;
1209 58fe2f10 bellard
    dc->vm86 = (flags >> VM_SHIFT) & 1;
1210 58fe2f10 bellard
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1211 58fe2f10 bellard
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
1212 58fe2f10 bellard
    dc->tb = tb;
1213 42c3c0cc bellard
    dc->flags = flags;
1214 42c3c0cc bellard
1215 58fe2f10 bellard
    dc->is_jmp = 0;
1216 58fe2f10 bellard
1217 58fe2f10 bellard
    for(;;) {
1218 58fe2f10 bellard
        pc_insn = dc->pc;
1219 58fe2f10 bellard
        ret = disas_insn(dc);
1220 58fe2f10 bellard
        if (ret < 0) {
1221 58fe2f10 bellard
            /* unsupported insn */
1222 58fe2f10 bellard
            if (dc->pc == pc_start) {
1223 58fe2f10 bellard
                /* if first instruction, signal that no copying was done */
1224 58fe2f10 bellard
                return -1;
1225 58fe2f10 bellard
            } else {
1226 58fe2f10 bellard
                gen_jmp(dc, dc->pc - dc->cs_base);
1227 58fe2f10 bellard
                dc->is_jmp = 1;
1228 58fe2f10 bellard
            }
1229 58fe2f10 bellard
        }
1230 58fe2f10 bellard
        if (search_pc) {
1231 58fe2f10 bellard
            /* search pc mode */
1232 58fe2f10 bellard
            if (tc_ptr < dc->gen_code_ptr) {
1233 58fe2f10 bellard
                env->eip = pc_insn - cs_base;
1234 58fe2f10 bellard
                return 0;
1235 58fe2f10 bellard
            }
1236 58fe2f10 bellard
        }
1237 58fe2f10 bellard
        /* stop translation if indicated */
1238 58fe2f10 bellard
        if (dc->is_jmp)
1239 58fe2f10 bellard
            break;
1240 58fe2f10 bellard
        /* if too long translation, stop generation */
1241 58fe2f10 bellard
        if (dc->gen_code_ptr >= gen_code_end ||
1242 58fe2f10 bellard
            (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1243 58fe2f10 bellard
            gen_jmp(dc, dc->pc - dc->cs_base);
1244 58fe2f10 bellard
            break;
1245 58fe2f10 bellard
        }
1246 58fe2f10 bellard
    }
1247 58fe2f10 bellard
    
1248 58fe2f10 bellard
#ifdef DEBUG_DISAS
1249 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1250 58fe2f10 bellard
        fprintf(logfile, "----------------\n");
1251 42c3c0cc bellard
        fprintf(logfile, "IN: COPY: %s fpu=%d\n", 
1252 42c3c0cc bellard
                lookup_symbol(pc_start),
1253 42c3c0cc bellard
                tb->cflags & CF_TB_FP_USED ? 1 : 0);
1254 14ce26e7 bellard
        target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32);
1255 58fe2f10 bellard
        fprintf(logfile, "\n");
1256 58fe2f10 bellard
    }
1257 58fe2f10 bellard
#endif
1258 58fe2f10 bellard
1259 58fe2f10 bellard
    if (!search_pc) {
1260 58fe2f10 bellard
        *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1261 58fe2f10 bellard
        tb->size = dc->pc - pc_start;
1262 42c3c0cc bellard
        tb->cflags |= CF_CODE_COPY;
1263 58fe2f10 bellard
        return 0;
1264 58fe2f10 bellard
    } else {
1265 58fe2f10 bellard
        return -1;
1266 58fe2f10 bellard
    }
1267 58fe2f10 bellard
}
1268 58fe2f10 bellard
1269 58fe2f10 bellard
/* generate code by just copying data. Return -1 if cannot generate
1270 58fe2f10 bellard
   any code. Return 0 if code was generated */
1271 58fe2f10 bellard
int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1272 58fe2f10 bellard
                      int max_code_size, int *gen_code_size_ptr)
1273 58fe2f10 bellard
{
1274 58fe2f10 bellard
    /* generate machine code */
1275 58fe2f10 bellard
    tb->tb_next_offset[0] = 0xffff;
1276 58fe2f10 bellard
    tb->tb_next_offset[1] = 0xffff;
1277 58fe2f10 bellard
#ifdef USE_DIRECT_JUMP
1278 58fe2f10 bellard
    /* the following two entries are optional (only used for string ops) */
1279 58fe2f10 bellard
    tb->tb_jmp_offset[2] = 0xffff;
1280 58fe2f10 bellard
    tb->tb_jmp_offset[3] = 0xffff;
1281 58fe2f10 bellard
#endif
1282 58fe2f10 bellard
    return gen_intermediate_code_internal(env, tb, 
1283 58fe2f10 bellard
                                          tb->tc_ptr, gen_code_size_ptr,
1284 58fe2f10 bellard
                                          0, NULL);
1285 58fe2f10 bellard
}
1286 58fe2f10 bellard
1287 58fe2f10 bellard
static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1288 58fe2f10 bellard
1289 58fe2f10 bellard
int cpu_restore_state_copy(TranslationBlock *tb, 
1290 58fe2f10 bellard
                           CPUState *env, unsigned long searched_pc,
1291 58fe2f10 bellard
                           void *puc)
1292 58fe2f10 bellard
{
1293 58fe2f10 bellard
    struct ucontext *uc = puc;
1294 58fe2f10 bellard
    int ret, eflags;
1295 58fe2f10 bellard
1296 58fe2f10 bellard
    /* find opc index corresponding to search_pc */
1297 58fe2f10 bellard
    if (searched_pc < (unsigned long)tb->tc_ptr)
1298 58fe2f10 bellard
        return -1;
1299 58fe2f10 bellard
    searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1300 58fe2f10 bellard
    ret = gen_intermediate_code_internal(env, tb, 
1301 58fe2f10 bellard
                                         dummy_gen_code_buf, NULL,
1302 58fe2f10 bellard
                                         1, (uint8_t *)searched_pc);
1303 58fe2f10 bellard
    if (ret < 0)
1304 58fe2f10 bellard
        return ret;
1305 58fe2f10 bellard
    /* restore all the CPU state from the CPU context from the
1306 42c3c0cc bellard
       signal. The FPU context stays in the host CPU. */
1307 58fe2f10 bellard
    
1308 58fe2f10 bellard
    env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1309 58fe2f10 bellard
    env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1310 58fe2f10 bellard
    env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1311 58fe2f10 bellard
    env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1312 58fe2f10 bellard
    env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1313 58fe2f10 bellard
    env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1314 58fe2f10 bellard
    env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1315 58fe2f10 bellard
    env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1316 58fe2f10 bellard
    eflags = uc->uc_mcontext.gregs[REG_EFL];
1317 58fe2f10 bellard
    env->df = 1 - (2 * ((eflags >> 10) & 1));
1318 58fe2f10 bellard
    env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1319 58fe2f10 bellard
    env->cc_op = CC_OP_EFLAGS;
1320 58fe2f10 bellard
    return 0;
1321 58fe2f10 bellard
}
1322 42c3c0cc bellard
1323 42c3c0cc bellard
#endif /* USE_CODE_COPY */