Statistics
| Branch: | Revision:

root / target-i386 / translate-copy.c @ 58fe2f10

History | View | Annotate | Download (41.6 kB)

1
/*
2
 *  i386 on i386 translation
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27
#include <sys/mman.h>
28
#include <sys/ucontext.h>
29

    
30
#include "cpu.h"
31
#include "exec-all.h"
32
#include "disas.h"
33

    
34
extern char exec_loop;
35

    
36
/* operand size */
37
enum {
38
    OT_BYTE = 0,
39
    OT_WORD,
40
    OT_LONG, 
41
    OT_QUAD,
42
};
43

    
44
#define PREFIX_REPZ   0x01
45
#define PREFIX_REPNZ  0x02
46
#define PREFIX_LOCK   0x04
47
#define PREFIX_DATA   0x08
48
#define PREFIX_ADR    0x10
49

    
50
typedef struct DisasContext {
51
    /* current insn context */
52
    int override; /* -1 if no override */
53
    int prefix;
54
    int aflag, dflag;
55
    uint8_t *pc; /* pc = eip + cs_base */
56
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
57
                   static state change (stop translation) */
58
    /* code output */
59
    uint8_t *gen_code_ptr;
60
    uint8_t *gen_code_start;
61
    
62
    /* current block context */
63
    uint8_t *cs_base; /* base of CS segment */
64
    int pe;     /* protected mode */
65
    int code32; /* 32 bit code segment */
66
    int f_st;   /* currently unused */
67
    int vm86;   /* vm86 mode */
68
    int cpl;
69
    int iopl;
70
    struct TranslationBlock *tb;
71
} DisasContext;
72

    
73
#define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
74

    
75
#define CPU_SEG 0x64 /* fs override */
76

    
77
static inline void gb(DisasContext *s, uint32_t val)
78
{
79
    *s->gen_code_ptr++ = val;
80
}
81

    
82
static inline void gw(DisasContext *s, uint32_t val)
83
{
84
    *s->gen_code_ptr++ = val;
85
    *s->gen_code_ptr++ = val >> 8;
86
}
87

    
88
static inline void gl(DisasContext *s, uint32_t val)
89
{
90
    *s->gen_code_ptr++ = val;
91
    *s->gen_code_ptr++ = val >> 8;
92
    *s->gen_code_ptr++ = val >> 16;
93
    *s->gen_code_ptr++ = val >> 24;
94
}
95

    
96
static inline void gjmp(DisasContext *s, long val)
97
{
98
    gb(s, 0xe9); /* jmp */
99
    gl(s, val - (long)(s->gen_code_ptr + 4));
100
}
101

    
102
static inline void gen_movl_addr_im(DisasContext *s, 
103
                                    uint32_t addr, uint32_t val)
104
{
105
    gb(s, CPU_SEG); /* seg movl im, addr */
106
    gb(s, 0xc7); 
107
    gb(s, 0x05);
108
    gl(s, addr);
109
    gl(s, val);
110
}
111

    
112
static inline void gen_movw_addr_im(DisasContext *s, 
113
                                    uint32_t addr, uint32_t val)
114
{
115
    gb(s, CPU_SEG); /* seg movl im, addr */
116
    gb(s, 0x66); 
117
    gb(s, 0xc7); 
118
    gb(s, 0x05);
119
    gl(s, addr);
120
    gw(s, val);
121
}
122

    
123

    
124
static void gen_jmp(DisasContext *s, uint32_t target_eip)
125
{
126
    TranslationBlock *tb = s->tb;
127

    
128
    gb(s, 0xe9); /* jmp */
129
    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
130
    gl(s, 0);
131

    
132
    tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
133
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
134
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
135
    gjmp(s, (long)&exec_loop);
136

    
137
    s->is_jmp = 1;
138
}
139

    
140
static void gen_jcc(DisasContext *s, int op,
141
                    uint32_t target_eip, uint32_t next_eip)
142
{
143
    TranslationBlock *tb = s->tb;
144

    
145
    gb(s, 0x0f); /* jcc */
146
    gb(s, 0x80 + op);
147
    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
148
    gl(s, 0);
149
    gb(s, 0xe9); /* jmp */
150
    tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
151
    gl(s, 0);
152
    
153
    tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
154
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
155
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
156
    gjmp(s, (long)&exec_loop);
157

    
158
    tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
159
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
160
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
161
    gjmp(s, (long)&exec_loop);
162

    
163
    s->is_jmp = 1;
164
}
165

    
166
static void gen_eob(DisasContext *s)
167
{
168
    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
169
    gjmp(s, (long)&exec_loop);
170

    
171
    s->is_jmp = 1;
172
}
173

    
174
static inline void gen_lea_modrm(DisasContext *s, int modrm)
175
{
176
    int havesib;
177
    int base, disp;
178
    int index;
179
    int scale;
180
    int mod, rm, code;
181

    
182
    mod = (modrm >> 6) & 3;
183
    rm = modrm & 7;
184

    
185
    if (s->aflag) {
186

    
187
        havesib = 0;
188
        base = rm;
189
        index = 0;
190
        scale = 0;
191
        
192
        if (base == 4) {
193
            havesib = 1;
194
            code = ldub_code(s->pc++);
195
            scale = (code >> 6) & 3;
196
            index = (code >> 3) & 7;
197
            base = code & 7;
198
        }
199

    
200
        switch (mod) {
201
        case 0:
202
            if (base == 5) {
203
                base = -1;
204
                disp = ldl_code(s->pc);
205
                s->pc += 4;
206
            } else {
207
                disp = 0;
208
            }
209
            break;
210
        case 1:
211
            disp = (int8_t)ldub_code(s->pc++);
212
            break;
213
        default:
214
        case 2:
215
            disp = ldl_code(s->pc);
216
            s->pc += 4;
217
            break;
218
        }
219
        
220
    } else {
221
        switch (mod) {
222
        case 0:
223
            if (rm == 6) {
224
                disp = lduw_code(s->pc);
225
                s->pc += 2;
226
            } else {
227
                disp = 0;
228
            }
229
            break;
230
        case 1:
231
            disp = (int8_t)ldub_code(s->pc++);
232
            break;
233
        default:
234
        case 2:
235
            disp = lduw_code(s->pc);
236
            s->pc += 2;
237
            break;
238
        }
239
    }
240
}
241

    
242
static inline void parse_modrm(DisasContext *s, int modrm)
243
{
244
    if ((modrm & 0xc0) != 0xc0)
245
        gen_lea_modrm(s, modrm);        
246
}
247

    
248
static inline uint32_t insn_get(DisasContext *s, int ot)
249
{
250
    uint32_t ret;
251

    
252
    switch(ot) {
253
    case OT_BYTE:
254
        ret = ldub_code(s->pc);
255
        s->pc++;
256
        break;
257
    case OT_WORD:
258
        ret = lduw_code(s->pc);
259
        s->pc += 2;
260
        break;
261
    default:
262
    case OT_LONG:
263
        ret = ldl_code(s->pc);
264
        s->pc += 4;
265
        break;
266
    }
267
    return ret;
268
}
269

    
270
/* convert one instruction. s->is_jmp is set if the translation must
271
   be stopped.  */
272
static int disas_insn(DisasContext *s)
273
{
274
    uint8_t *pc_start, *pc_tmp, *pc_start_insn;
275
    int b, prefixes, aflag, dflag, next_eip, val;
276
    int ot;
277
    int modrm, mod, op;
278

    
279
    pc_start = s->pc;
280
    prefixes = 0;
281
    aflag = s->code32;
282
    dflag = s->code32;
283
    s->override = -1;
284
 next_byte:
285
    b = ldub_code(s->pc);
286
    s->pc++;
287
    /* check prefixes */
288
    switch (b) {
289
    case 0xf3:
290
        prefixes |= PREFIX_REPZ;
291
        goto next_byte;
292
    case 0xf2:
293
        prefixes |= PREFIX_REPNZ;
294
        goto next_byte;
295
    case 0xf0:
296
        prefixes |= PREFIX_LOCK;
297
        goto next_byte;
298
    case 0x2e:
299
        s->override = R_CS;
300
        goto next_byte;
301
    case 0x36:
302
        s->override = R_SS;
303
        goto next_byte;
304
    case 0x3e:
305
        s->override = R_DS;
306
        goto next_byte;
307
    case 0x26:
308
        s->override = R_ES;
309
        goto next_byte;
310
    case 0x64:
311
        s->override = R_FS;
312
        goto next_byte;
313
    case 0x65:
314
        s->override = R_GS;
315
        goto next_byte;
316
    case 0x66:
317
        prefixes |= PREFIX_DATA;
318
        goto next_byte;
319
    case 0x67:
320
        prefixes |= PREFIX_ADR;
321
        goto next_byte;
322
    }
323

    
324
    if (prefixes & PREFIX_DATA)
325
        dflag ^= 1;
326
    if (prefixes & PREFIX_ADR)
327
        aflag ^= 1;
328

    
329
    s->prefix = prefixes;
330
    s->aflag = aflag;
331
    s->dflag = dflag;
332

    
333
    /* lock generation */
334
    if (prefixes & PREFIX_LOCK)
335
        goto unsupported_op;
336
    if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
337
        goto unsupported_op;
338

    
339
    pc_start_insn = s->pc - 1;
340
    /* now check op code */
341
 reswitch:
342
    switch(b) {
343
    case 0x0f:
344
        /**************************/
345
        /* extended op code */
346
        b = ldub_code(s->pc++) | 0x100;
347
        goto reswitch;
348
        
349
        /**************************/
350
        /* arith & logic */
351
    case 0x00 ... 0x05:
352
    case 0x08 ... 0x0d:
353
    case 0x10 ... 0x15:
354
    case 0x18 ... 0x1d:
355
    case 0x20 ... 0x25:
356
    case 0x28 ... 0x2d:
357
    case 0x30 ... 0x35:
358
    case 0x38 ... 0x3d:
359
        {
360
            int f;
361
            f = (b >> 1) & 3;
362

    
363
            if ((b & 1) == 0)
364
                ot = OT_BYTE;
365
            else
366
                ot = dflag ? OT_LONG : OT_WORD;
367
            
368
            switch(f) {
369
            case 0: /* OP Ev, Gv */
370
                modrm = ldub_code(s->pc++);
371
                parse_modrm(s, modrm);
372
                break;
373
            case 1: /* OP Gv, Ev */
374
                modrm = ldub_code(s->pc++);
375
                parse_modrm(s, modrm);
376
                break;
377
            case 2: /* OP A, Iv */
378
                insn_get(s, ot);
379
                break;
380
            }
381
        }
382
        break;
383

    
384
    case 0x80: /* GRP1 */
385
    case 0x81:
386
    case 0x83:
387
        {
388
            if ((b & 1) == 0)
389
                ot = OT_BYTE;
390
            else
391
                ot = dflag ? OT_LONG : OT_WORD;
392
            
393
            modrm = ldub_code(s->pc++);
394
            parse_modrm(s, modrm);
395

    
396
            switch(b) {
397
            default:
398
            case 0x80:
399
            case 0x81:
400
                insn_get(s, ot);
401
                break;
402
            case 0x83:
403
                insn_get(s, OT_BYTE);
404
                break;
405
            }
406
        }
407
        break;
408

    
409
        /**************************/
410
        /* inc, dec, and other misc arith */
411
    case 0x40 ... 0x47: /* inc Gv */
412
        break;
413
    case 0x48 ... 0x4f: /* dec Gv */
414
        break;
415
    case 0xf6: /* GRP3 */
416
    case 0xf7:
417
        if ((b & 1) == 0)
418
            ot = OT_BYTE;
419
        else
420
            ot = dflag ? OT_LONG : OT_WORD;
421

    
422
        modrm = ldub_code(s->pc++);
423
        op = (modrm >> 3) & 7;
424
        parse_modrm(s, modrm);
425

    
426
        switch(op) {
427
        case 0: /* test */
428
            insn_get(s, ot);
429
            break;
430
        case 2: /* not */
431
            break;
432
        case 3: /* neg */
433
            break;
434
        case 4: /* mul */
435
            break;
436
        case 5: /* imul */
437
            break;
438
        case 6: /* div */
439
            break;
440
        case 7: /* idiv */
441
            break;
442
        default:
443
            goto illegal_op;
444
        }
445
        break;
446

    
447
    case 0xfe: /* GRP4 */
448
    case 0xff: /* GRP5 */
449
        if ((b & 1) == 0)
450
            ot = OT_BYTE;
451
        else
452
            ot = dflag ? OT_LONG : OT_WORD;
453

    
454
        modrm = ldub_code(s->pc++);
455
        mod = (modrm >> 6) & 3;
456
        op = (modrm >> 3) & 7;
457
        if (op >= 2 && b == 0xfe) {
458
            goto illegal_op;
459
        }
460
        pc_tmp = s->pc;
461
        parse_modrm(s, modrm);
462

    
463
        switch(op) {
464
        case 0: /* inc Ev */
465
            break;
466
        case 1: /* dec Ev */
467
            break;
468
        case 2: /* call Ev */
469
            /* XXX: optimize and handle MEM exceptions specifically
470
               fs movl %eax, regs[0] 
471
               movl Ev, %eax 
472
               pushl next_eip
473
               fs movl %eax, eip
474
            */
475
            goto unsupported_op;
476
        case 3: /* lcall Ev */
477
            goto unsupported_op;
478
        case 4: /* jmp Ev */
479
            /* XXX: optimize and handle MEM exceptions specifically
480
               fs movl %eax, regs[0] 
481
               movl Ev, %eax 
482
               fs movl %eax, eip
483
            */
484
            goto unsupported_op;
485
        case 5: /* ljmp Ev */
486
            goto unsupported_op;
487
        case 6: /* push Ev */
488
            break;
489
        default:
490
            goto illegal_op;
491
        }
492
        break;
493
    case 0xa8: /* test eAX, Iv */
494
    case 0xa9:
495
        if ((b & 1) == 0)
496
            ot = OT_BYTE;
497
        else
498
            ot = dflag ? OT_LONG : OT_WORD;
499
        insn_get(s, ot);
500
        break;
501
        
502
    case 0x98: /* CWDE/CBW */
503
        break;
504
    case 0x99: /* CDQ/CWD */
505
        break;
506
    case 0x1af: /* imul Gv, Ev */
507
    case 0x69: /* imul Gv, Ev, I */
508
    case 0x6b:
509
        ot = dflag ? OT_LONG : OT_WORD;
510
        modrm = ldub_code(s->pc++);
511
        parse_modrm(s, modrm);
512
        if (b == 0x69) {
513
            insn_get(s, ot);
514
        } else if (b == 0x6b) {
515
            insn_get(s, OT_BYTE);
516
        } else {
517
        }
518
        break;
519

    
520
    case 0x84: /* test Ev, Gv */
521
    case 0x85: 
522
        
523
    case 0x1c0:
524
    case 0x1c1: /* xadd Ev, Gv */
525

    
526
    case 0x1b0:
527
    case 0x1b1: /* cmpxchg Ev, Gv */
528

    
529
    case 0x8f: /* pop Ev */
530

    
531
    case 0x88:
532
    case 0x89: /* mov Gv, Ev */
533

    
534
    case 0x8a:
535
    case 0x8b: /* mov Ev, Gv */
536

    
537
    case 0x1b6: /* movzbS Gv, Eb */
538
    case 0x1b7: /* movzwS Gv, Eb */
539
    case 0x1be: /* movsbS Gv, Eb */
540
    case 0x1bf: /* movswS Gv, Eb */
541

    
542
    case 0x86:
543
    case 0x87: /* xchg Ev, Gv */
544

    
545
    case 0xd0:
546
    case 0xd1: /* shift Ev,1 */
547

    
548
    case 0xd2:
549
    case 0xd3: /* shift Ev,cl */
550

    
551
    case 0x1a5: /* shld cl */
552
    case 0x1ad: /* shrd cl */
553

    
554
    case 0x190 ... 0x19f: /* setcc Gv */
555

    
556
    /* XXX: emulate cmov if not available ? */
557
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
558

    
559
    case 0x1a3: /* bt Gv, Ev */
560
    case 0x1ab: /* bts */
561
    case 0x1b3: /* btr */
562
    case 0x1bb: /* btc */
563

    
564
    case 0x1bc: /* bsf */
565
    case 0x1bd: /* bsr */
566

    
567
        modrm = ldub_code(s->pc++);
568
        parse_modrm(s, modrm);
569
        break;
570

    
571
    case 0x1c7: /* cmpxchg8b */
572
        modrm = ldub_code(s->pc++);
573
        mod = (modrm >> 6) & 3;
574
        if (mod == 3)
575
            goto illegal_op;
576
        parse_modrm(s, modrm);
577
        break;
578
        
579
        /**************************/
580
        /* push/pop */
581
    case 0x50 ... 0x57: /* push */
582
    case 0x58 ... 0x5f: /* pop */
583
    case 0x60: /* pusha */
584
    case 0x61: /* popa */
585
        break;
586

    
587
    case 0x68: /* push Iv */
588
    case 0x6a:
589
        ot = dflag ? OT_LONG : OT_WORD;
590
        if (b == 0x68)
591
            insn_get(s, ot);
592
        else
593
            insn_get(s, OT_BYTE);
594
        break;
595
    case 0xc8: /* enter */
596
        lduw_code(s->pc);
597
        s->pc += 2;
598
        ldub_code(s->pc++);
599
        break;
600
    case 0xc9: /* leave */
601
        break;
602

    
603
    case 0x06: /* push es */
604
    case 0x0e: /* push cs */
605
    case 0x16: /* push ss */
606
    case 0x1e: /* push ds */
607
        /* XXX: optimize:
608
         push segs[n].selector
609
        */
610
        goto unsupported_op;
611
    case 0x1a0: /* push fs */
612
    case 0x1a8: /* push gs */
613
        goto unsupported_op;
614
    case 0x07: /* pop es */
615
    case 0x17: /* pop ss */
616
    case 0x1f: /* pop ds */
617
        goto unsupported_op;
618
    case 0x1a1: /* pop fs */
619
    case 0x1a9: /* pop gs */
620
        goto unsupported_op;
621
    case 0x8e: /* mov seg, Gv */
622
        /* XXX: optimize:
623
           fs movl r, regs[]
624
           movl segs[].selector, r
625
           mov r, Gv
626
           fs movl regs[], r
627
        */
628
        goto unsupported_op;
629
    case 0x8c: /* mov Gv, seg */
630
        goto unsupported_op;
631
    case 0xc4: /* les Gv */
632
        op = R_ES;
633
        goto do_lxx;
634
    case 0xc5: /* lds Gv */
635
        op = R_DS;
636
        goto do_lxx;
637
    case 0x1b2: /* lss Gv */
638
        op = R_SS;
639
        goto do_lxx;
640
    case 0x1b4: /* lfs Gv */
641
        op = R_FS;
642
        goto do_lxx;
643
    case 0x1b5: /* lgs Gv */
644
        op = R_GS;
645
    do_lxx:
646
        goto unsupported_op;
647
#if 0
648
        /************************/
649
        /* floats */
650
    case 0xd8 ... 0xdf: 
651
        modrm = ldub_code(s->pc++);
652
        mod = (modrm >> 6) & 3;
653
        rm = modrm & 7;
654
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
655
        if (mod != 3) {
656
            /* memory op */
657
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
658
            switch(op) {
659
            case 0x00 ... 0x07: /* fxxxs */
660
            case 0x10 ... 0x17: /* fixxxl */
661
            case 0x20 ... 0x27: /* fxxxl */
662
            case 0x30 ... 0x37: /* fixxx */
663
                {
664
                    int op1;
665
                    op1 = op & 7;
666

667
                    switch(op >> 4) {
668
                    case 0:
669
                        gen_op_flds_FT0_A0();
670
                        break;
671
                    case 1:
672
                        gen_op_fildl_FT0_A0();
673
                        break;
674
                    case 2:
675
                        gen_op_fldl_FT0_A0();
676
                        break;
677
                    case 3:
678
                    default:
679
                        gen_op_fild_FT0_A0();
680
                        break;
681
                    }
682
                    
683
                    gen_op_fp_arith_ST0_FT0[op1]();
684
                    if (op1 == 3) {
685
                        /* fcomp needs pop */
686
                        gen_op_fpop();
687
                    }
688
                }
689
                break;
690
            case 0x08: /* flds */
691
            case 0x0a: /* fsts */
692
            case 0x0b: /* fstps */
693
            case 0x18: /* fildl */
694
            case 0x1a: /* fistl */
695
            case 0x1b: /* fistpl */
696
            case 0x28: /* fldl */
697
            case 0x2a: /* fstl */
698
            case 0x2b: /* fstpl */
699
            case 0x38: /* filds */
700
            case 0x3a: /* fists */
701
            case 0x3b: /* fistps */
702
                
703
                switch(op & 7) {
704
                case 0:
705
                    switch(op >> 4) {
706
                    case 0:
707
                        gen_op_flds_ST0_A0();
708
                        break;
709
                    case 1:
710
                        gen_op_fildl_ST0_A0();
711
                        break;
712
                    case 2:
713
                        gen_op_fldl_ST0_A0();
714
                        break;
715
                    case 3:
716
                    default:
717
                        gen_op_fild_ST0_A0();
718
                        break;
719
                    }
720
                    break;
721
                default:
722
                    switch(op >> 4) {
723
                    case 0:
724
                        gen_op_fsts_ST0_A0();
725
                        break;
726
                    case 1:
727
                        gen_op_fistl_ST0_A0();
728
                        break;
729
                    case 2:
730
                        gen_op_fstl_ST0_A0();
731
                        break;
732
                    case 3:
733
                    default:
734
                        gen_op_fist_ST0_A0();
735
                        break;
736
                    }
737
                    if ((op & 7) == 3)
738
                        gen_op_fpop();
739
                    break;
740
                }
741
                break;
742
            case 0x0c: /* fldenv mem */
743
                gen_op_fldenv_A0(s->dflag);
744
                break;
745
            case 0x0d: /* fldcw mem */
746
                gen_op_fldcw_A0();
747
                break;
748
            case 0x0e: /* fnstenv mem */
749
                gen_op_fnstenv_A0(s->dflag);
750
                break;
751
            case 0x0f: /* fnstcw mem */
752
                gen_op_fnstcw_A0();
753
                break;
754
            case 0x1d: /* fldt mem */
755
                gen_op_fldt_ST0_A0();
756
                break;
757
            case 0x1f: /* fstpt mem */
758
                gen_op_fstt_ST0_A0();
759
                gen_op_fpop();
760
                break;
761
            case 0x2c: /* frstor mem */
762
                gen_op_frstor_A0(s->dflag);
763
                break;
764
            case 0x2e: /* fnsave mem */
765
                gen_op_fnsave_A0(s->dflag);
766
                break;
767
            case 0x2f: /* fnstsw mem */
768
                gen_op_fnstsw_A0();
769
                break;
770
            case 0x3c: /* fbld */
771
                gen_op_fbld_ST0_A0();
772
                break;
773
            case 0x3e: /* fbstp */
774
                gen_op_fbst_ST0_A0();
775
                gen_op_fpop();
776
                break;
777
            case 0x3d: /* fildll */
778
                gen_op_fildll_ST0_A0();
779
                break;
780
            case 0x3f: /* fistpll */
781
                gen_op_fistll_ST0_A0();
782
                gen_op_fpop();
783
                break;
784
            default:
785
                goto illegal_op;
786
            }
787
        } else {
788
            /* register float ops */
789
            opreg = rm;
790

791
            switch(op) {
792
            case 0x08: /* fld sti */
793
                gen_op_fpush();
794
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
795
                break;
796
            case 0x09: /* fxchg sti */
797
                gen_op_fxchg_ST0_STN(opreg);
798
                break;
799
            case 0x0a: /* grp d9/2 */
800
                switch(rm) {
801
                case 0: /* fnop */
802
                    break;
803
                default:
804
                    goto illegal_op;
805
                }
806
                break;
807
            case 0x0c: /* grp d9/4 */
808
                switch(rm) {
809
                case 0: /* fchs */
810
                    gen_op_fchs_ST0();
811
                    break;
812
                case 1: /* fabs */
813
                    gen_op_fabs_ST0();
814
                    break;
815
                case 4: /* ftst */
816
                    gen_op_fldz_FT0();
817
                    gen_op_fcom_ST0_FT0();
818
                    break;
819
                case 5: /* fxam */
820
                    gen_op_fxam_ST0();
821
                    break;
822
                default:
823
                    goto illegal_op;
824
                }
825
                break;
826
            case 0x0d: /* grp d9/5 */
827
                {
828
                    switch(rm) {
829
                    case 0:
830
                        gen_op_fpush();
831
                        gen_op_fld1_ST0();
832
                        break;
833
                    case 1:
834
                        gen_op_fpush();
835
                        gen_op_fldl2t_ST0();
836
                        break;
837
                    case 2:
838
                        gen_op_fpush();
839
                        gen_op_fldl2e_ST0();
840
                        break;
841
                    case 3:
842
                        gen_op_fpush();
843
                        gen_op_fldpi_ST0();
844
                        break;
845
                    case 4:
846
                        gen_op_fpush();
847
                        gen_op_fldlg2_ST0();
848
                        break;
849
                    case 5:
850
                        gen_op_fpush();
851
                        gen_op_fldln2_ST0();
852
                        break;
853
                    case 6:
854
                        gen_op_fpush();
855
                        gen_op_fldz_ST0();
856
                        break;
857
                    default:
858
                        goto illegal_op;
859
                    }
860
                }
861
                break;
862
            case 0x0e: /* grp d9/6 */
863
                switch(rm) {
864
                case 0: /* f2xm1 */
865
                    gen_op_f2xm1();
866
                    break;
867
                case 1: /* fyl2x */
868
                    gen_op_fyl2x();
869
                    break;
870
                case 2: /* fptan */
871
                    gen_op_fptan();
872
                    break;
873
                case 3: /* fpatan */
874
                    gen_op_fpatan();
875
                    break;
876
                case 4: /* fxtract */
877
                    gen_op_fxtract();
878
                    break;
879
                case 5: /* fprem1 */
880
                    gen_op_fprem1();
881
                    break;
882
                case 6: /* fdecstp */
883
                    gen_op_fdecstp();
884
                    break;
885
                default:
886
                case 7: /* fincstp */
887
                    gen_op_fincstp();
888
                    break;
889
                }
890
                break;
891
            case 0x0f: /* grp d9/7 */
892
                switch(rm) {
893
                case 0: /* fprem */
894
                    gen_op_fprem();
895
                    break;
896
                case 1: /* fyl2xp1 */
897
                    gen_op_fyl2xp1();
898
                    break;
899
                case 2: /* fsqrt */
900
                    gen_op_fsqrt();
901
                    break;
902
                case 3: /* fsincos */
903
                    gen_op_fsincos();
904
                    break;
905
                case 5: /* fscale */
906
                    gen_op_fscale();
907
                    break;
908
                case 4: /* frndint */
909
                    gen_op_frndint();
910
                    break;
911
                case 6: /* fsin */
912
                    gen_op_fsin();
913
                    break;
914
                default:
915
                case 7: /* fcos */
916
                    gen_op_fcos();
917
                    break;
918
                }
919
                break;
920
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
921
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
922
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
923
                {
924
                    int op1;
925
                    
926
                    op1 = op & 7;
927
                    if (op >= 0x20) {
928
                        gen_op_fp_arith_STN_ST0[op1](opreg);
929
                        if (op >= 0x30)
930
                            gen_op_fpop();
931
                    } else {
932
                        gen_op_fmov_FT0_STN(opreg);
933
                        gen_op_fp_arith_ST0_FT0[op1]();
934
                    }
935
                }
936
                break;
937
            case 0x02: /* fcom */
938
                gen_op_fmov_FT0_STN(opreg);
939
                gen_op_fcom_ST0_FT0();
940
                break;
941
            case 0x03: /* fcomp */
942
                gen_op_fmov_FT0_STN(opreg);
943
                gen_op_fcom_ST0_FT0();
944
                gen_op_fpop();
945
                break;
946
            case 0x15: /* da/5 */
947
                switch(rm) {
948
                case 1: /* fucompp */
949
                    gen_op_fmov_FT0_STN(1);
950
                    gen_op_fucom_ST0_FT0();
951
                    gen_op_fpop();
952
                    gen_op_fpop();
953
                    break;
954
                default:
955
                    goto illegal_op;
956
                }
957
                break;
958
            case 0x1c:
959
                switch(rm) {
960
                case 0: /* feni (287 only, just do nop here) */
961
                    break;
962
                case 1: /* fdisi (287 only, just do nop here) */
963
                    break;
964
                case 2: /* fclex */
965
                    gen_op_fclex();
966
                    break;
967
                case 3: /* fninit */
968
                    gen_op_fninit();
969
                    break;
970
                case 4: /* fsetpm (287 only, just do nop here) */
971
                    break;
972
                default:
973
                    goto illegal_op;
974
                }
975
                break;
976
            case 0x1d: /* fucomi */
977
                if (s->cc_op != CC_OP_DYNAMIC)
978
                    gen_op_set_cc_op(s->cc_op);
979
                gen_op_fmov_FT0_STN(opreg);
980
                gen_op_fucomi_ST0_FT0();
981
                s->cc_op = CC_OP_EFLAGS;
982
                break;
983
            case 0x1e: /* fcomi */
984
                if (s->cc_op != CC_OP_DYNAMIC)
985
                    gen_op_set_cc_op(s->cc_op);
986
                gen_op_fmov_FT0_STN(opreg);
987
                gen_op_fcomi_ST0_FT0();
988
                s->cc_op = CC_OP_EFLAGS;
989
                break;
990
            case 0x2a: /* fst sti */
991
                gen_op_fmov_STN_ST0(opreg);
992
                break;
993
            case 0x2b: /* fstp sti */
994
                gen_op_fmov_STN_ST0(opreg);
995
                gen_op_fpop();
996
                break;
997
            case 0x2c: /* fucom st(i) */
998
                gen_op_fmov_FT0_STN(opreg);
999
                gen_op_fucom_ST0_FT0();
1000
                break;
1001
            case 0x2d: /* fucomp st(i) */
1002
                gen_op_fmov_FT0_STN(opreg);
1003
                gen_op_fucom_ST0_FT0();
1004
                gen_op_fpop();
1005
                break;
1006
            case 0x33: /* de/3 */
1007
                switch(rm) {
1008
                case 1: /* fcompp */
1009
                    gen_op_fmov_FT0_STN(1);
1010
                    gen_op_fcom_ST0_FT0();
1011
                    gen_op_fpop();
1012
                    gen_op_fpop();
1013
                    break;
1014
                default:
1015
                    goto illegal_op;
1016
                }
1017
                break;
1018
            case 0x3c: /* df/4 */
1019
                switch(rm) {
1020
                case 0:
1021
                    gen_op_fnstsw_EAX();
1022
                    break;
1023
                default:
1024
                    goto illegal_op;
1025
                }
1026
                break;
1027
            case 0x3d: /* fucomip */
1028
                if (s->cc_op != CC_OP_DYNAMIC)
1029
                    gen_op_set_cc_op(s->cc_op);
1030
                gen_op_fmov_FT0_STN(opreg);
1031
                gen_op_fucomi_ST0_FT0();
1032
                gen_op_fpop();
1033
                s->cc_op = CC_OP_EFLAGS;
1034
                break;
1035
            case 0x3e: /* fcomip */
1036
                if (s->cc_op != CC_OP_DYNAMIC)
1037
                    gen_op_set_cc_op(s->cc_op);
1038
                gen_op_fmov_FT0_STN(opreg);
1039
                gen_op_fcomi_ST0_FT0();
1040
                gen_op_fpop();
1041
                s->cc_op = CC_OP_EFLAGS;
1042
                break;
1043
            case 0x10 ... 0x13: /* fcmovxx */
1044
            case 0x18 ... 0x1b:
1045
                {
1046
                    int op1;
1047
                    const static uint8_t fcmov_cc[8] = {
1048
                        (JCC_B << 1),
1049
                        (JCC_Z << 1),
1050
                        (JCC_BE << 1),
1051
                        (JCC_P << 1),
1052
                    };
1053
                    op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
1054
                    gen_setcc(s, op1);
1055
                    gen_op_fcmov_ST0_STN_T0(opreg);
1056
                }
1057
                break;
1058
            default:
1059
                goto illegal_op;
1060
            }
1061
        }
1062
        break;
1063
#endif
1064
        /**************************/
1065
        /* mov */
1066
    case 0xc6:
1067
    case 0xc7: /* mov Ev, Iv */
1068
        if ((b & 1) == 0)
1069
            ot = OT_BYTE;
1070
        else
1071
            ot = dflag ? OT_LONG : OT_WORD;
1072
        modrm = ldub_code(s->pc++);
1073
        parse_modrm(s, modrm);
1074
        insn_get(s, ot);
1075
        break;
1076

    
1077
    case 0x8d: /* lea */
1078
        ot = dflag ? OT_LONG : OT_WORD;
1079
        modrm = ldub_code(s->pc++);
1080
        mod = (modrm >> 6) & 3;
1081
        if (mod == 3)
1082
            goto illegal_op;
1083
        parse_modrm(s, modrm);
1084
        break;
1085
        
1086
    case 0xa0: /* mov EAX, Ov */
1087
    case 0xa1:
1088
    case 0xa2: /* mov Ov, EAX */
1089
    case 0xa3:
1090
        if ((b & 1) == 0)
1091
            ot = OT_BYTE;
1092
        else
1093
            ot = dflag ? OT_LONG : OT_WORD;
1094
        if (s->aflag)
1095
            insn_get(s, OT_LONG);
1096
        else
1097
            insn_get(s, OT_WORD);
1098
        break;
1099
    case 0xd7: /* xlat */
1100
        break;
1101
    case 0xb0 ... 0xb7: /* mov R, Ib */
1102
        insn_get(s, OT_BYTE);
1103
        break;
1104
    case 0xb8 ... 0xbf: /* mov R, Iv */
1105
        ot = dflag ? OT_LONG : OT_WORD;
1106
        insn_get(s, ot);
1107
        break;
1108

    
1109
    case 0x91 ... 0x97: /* xchg R, EAX */
1110
        break;
1111

    
1112
        /************************/
1113
        /* shifts */
1114
    case 0xc0:
1115
    case 0xc1: /* shift Ev,imm */
1116

    
1117
    case 0x1a4: /* shld imm */
1118
    case 0x1ac: /* shrd imm */
1119
        modrm = ldub_code(s->pc++);
1120
        parse_modrm(s, modrm);
1121
        ldub_code(s->pc++);
1122
        break;
1123
        
1124
        /************************/
1125
        /* string ops */
1126

    
1127
    case 0xa4: /* movsS */
1128
    case 0xa5:
1129
        break;
1130
        
1131
    case 0xaa: /* stosS */
1132
    case 0xab:
1133
        break;
1134

    
1135
    case 0xac: /* lodsS */
1136
    case 0xad:
1137
        break;
1138

    
1139
    case 0xae: /* scasS */
1140
    case 0xaf:
1141
        break;
1142

    
1143
    case 0xa6: /* cmpsS */
1144
    case 0xa7:
1145
        break;
1146

    
1147
    case 0x6c: /* insS */
1148
    case 0x6d:
1149
        goto unsupported_op;
1150

    
1151
    case 0x6e: /* outsS */
1152
    case 0x6f:
1153
        goto unsupported_op;
1154

    
1155
        /************************/
1156
        /* port I/O */
1157
    case 0xe4:
1158
    case 0xe5:
1159
        goto unsupported_op;
1160

    
1161
    case 0xe6:
1162
    case 0xe7:
1163
        goto unsupported_op;
1164

    
1165
    case 0xec:
1166
    case 0xed:
1167
        goto unsupported_op;
1168

    
1169
    case 0xee:
1170
    case 0xef:
1171
        goto unsupported_op;
1172

    
1173
        /************************/
1174
        /* control */
1175
#if 0
1176
    case 0xc2: /* ret im */
1177
        val = ldsw_code(s->pc);
1178
        s->pc += 2;
1179
        gen_pop_T0(s);
1180
        gen_stack_update(s, val + (2 << s->dflag));
1181
        if (s->dflag == 0)
1182
            gen_op_andl_T0_ffff();
1183
        gen_op_jmp_T0();
1184
        gen_eob(s);
1185
        break;
1186
#endif
1187

    
1188
    case 0xc3: /* ret */
1189
        gb(s, CPU_SEG);
1190
        if (!s->dflag)  
1191
            gb(s, 0x66); /* d16 */
1192
        gb(s, 0x8f); /* pop addr */
1193
        gb(s, 0x05);
1194
        gl(s, CPU_FIELD_OFFSET(eip));
1195
        if (!s->dflag) {
1196
            /* reset high bits of EIP */
1197
            gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
1198
        }
1199
        gen_eob(s);
1200
        goto no_copy;
1201
    case 0xca: /* lret im */
1202
    case 0xcb: /* lret */
1203
    case 0xcf: /* iret */
1204
    case 0x9a: /* lcall im */
1205
    case 0xea: /* ljmp im */
1206
        goto unsupported_op;
1207

    
1208
    case 0xe8: /* call im */
1209
        ot = dflag ? OT_LONG : OT_WORD;
1210
        val = insn_get(s, ot);
1211
        next_eip = s->pc - s->cs_base;
1212
        val += next_eip;
1213
        if (s->dflag) {
1214
            gb(s, 0x68); /* pushl imm */
1215
            gl(s, next_eip);
1216
        } else {
1217
            gb(s, 0x66); /* pushw imm */
1218
            gb(s, 0x68);
1219
            gw(s, next_eip);
1220
            val &= 0xffff;
1221
        }
1222
        gen_jmp(s, val);
1223
        goto no_copy;
1224
    case 0xe9: /* jmp */
1225
        ot = dflag ? OT_LONG : OT_WORD;
1226
        val = insn_get(s, ot);
1227
        val += s->pc - s->cs_base;
1228
        if (s->dflag == 0)
1229
            val = val & 0xffff;
1230
        gen_jmp(s, val);
1231
        goto no_copy;
1232
    case 0xeb: /* jmp Jb */
1233
        val = (int8_t)insn_get(s, OT_BYTE);
1234
        val += s->pc - s->cs_base;
1235
        if (s->dflag == 0)
1236
            val = val & 0xffff;
1237
        gen_jmp(s, val);
1238
        goto no_copy;
1239
    case 0x70 ... 0x7f: /* jcc Jb */
1240
        val = (int8_t)insn_get(s, OT_BYTE);
1241
        goto do_jcc;
1242
    case 0x180 ... 0x18f: /* jcc Jv */
1243
        if (dflag) {
1244
            val = insn_get(s, OT_LONG);
1245
        } else {
1246
            val = (int16_t)insn_get(s, OT_WORD); 
1247
        }
1248
    do_jcc:
1249
        next_eip = s->pc - s->cs_base;
1250
        val += next_eip;
1251
        if (s->dflag == 0)
1252
            val &= 0xffff;
1253
        gen_jcc(s, b & 0xf, val, next_eip);
1254
        goto no_copy;
1255

    
1256
        /************************/
1257
        /* flags */
1258
    case 0x9c: /* pushf */
1259
        /* XXX: put specific code ? */
1260
        goto unsupported_op;
1261
    case 0x9d: /* popf */
1262
        goto unsupported_op;
1263

    
1264
    case 0x9e: /* sahf */
1265
    case 0x9f: /* lahf */
1266
    case 0xf5: /* cmc */
1267
    case 0xf8: /* clc */
1268
    case 0xf9: /* stc */
1269
    case 0xfc: /* cld */
1270
    case 0xfd: /* std */
1271
        break;
1272

    
1273
        /************************/
1274
        /* bit operations */
1275
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
1276
        ot = dflag ? OT_LONG : OT_WORD;
1277
        modrm = ldub_code(s->pc++);
1278
        op = (modrm >> 3) & 7;
1279
        parse_modrm(s, modrm);
1280
        /* load shift */
1281
        ldub_code(s->pc++);
1282
        if (op < 4)
1283
            goto illegal_op;
1284
        break;
1285
        /************************/
1286
        /* bcd */
1287
    case 0x27: /* daa */
1288
        break;
1289
    case 0x2f: /* das */
1290
        break;
1291
    case 0x37: /* aaa */
1292
        break;
1293
    case 0x3f: /* aas */
1294
        break;
1295
    case 0xd4: /* aam */
1296
        ldub_code(s->pc++);
1297
        break;
1298
    case 0xd5: /* aad */
1299
        ldub_code(s->pc++);
1300
        break;
1301
        /************************/
1302
        /* misc */
1303
    case 0x90: /* nop */
1304
        break;
1305
    case 0x9b: /* fwait */
1306
        break;
1307
    case 0xcc: /* int3 */
1308
        goto unsupported_op;
1309
    case 0xcd: /* int N */
1310
        goto unsupported_op;
1311
    case 0xce: /* into */
1312
        goto unsupported_op;
1313
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
1314
        goto unsupported_op;
1315
    case 0xfa: /* cli */
1316
        goto unsupported_op;
1317
    case 0xfb: /* sti */
1318
        goto unsupported_op;
1319
    case 0x62: /* bound */
1320
        modrm = ldub_code(s->pc++);
1321
        mod = (modrm >> 6) & 3;
1322
        if (mod == 3)
1323
            goto illegal_op;
1324
        parse_modrm(s, modrm);
1325
        break;
1326
    case 0x1c8 ... 0x1cf: /* bswap reg */
1327
        break;
1328
    case 0xd6: /* salc */
1329
        break;
1330
    case 0xe0: /* loopnz */
1331
    case 0xe1: /* loopz */
1332
    case 0xe2: /* loop */
1333
    case 0xe3: /* jecxz */
1334
        goto unsupported_op;
1335

    
1336
    case 0x130: /* wrmsr */
1337
    case 0x132: /* rdmsr */
1338
        goto unsupported_op;
1339
    case 0x131: /* rdtsc */
1340
        goto unsupported_op;
1341
    case 0x1a2: /* cpuid */
1342
        goto unsupported_op;
1343
    case 0xf4: /* hlt */
1344
        goto unsupported_op;
1345
    case 0x100:
1346
        goto unsupported_op;
1347
    case 0x101:
1348
        goto unsupported_op;
1349
    case 0x108: /* invd */
1350
    case 0x109: /* wbinvd */
1351
        goto unsupported_op;
1352
    case 0x63: /* arpl */
1353
        goto unsupported_op;
1354
    case 0x102: /* lar */
1355
    case 0x103: /* lsl */
1356
        goto unsupported_op;
1357
    case 0x118:
1358
        goto unsupported_op;
1359
    case 0x120: /* mov reg, crN */
1360
    case 0x122: /* mov crN, reg */
1361
        goto unsupported_op;
1362
    case 0x121: /* mov reg, drN */
1363
    case 0x123: /* mov drN, reg */
1364
        goto unsupported_op;
1365
    case 0x106: /* clts */
1366
        goto unsupported_op;
1367
    default:
1368
        goto illegal_op;
1369
    }
1370

    
1371
    /* just copy the code */
1372

    
1373
    /* no override yet */
1374
    if (!s->dflag)
1375
        gb(s, 0x66);
1376
    if (!s->aflag)
1377
        gb(s, 0x67);
1378
    if (prefixes & PREFIX_REPZ)
1379
        gb(s, 0xf3);
1380
    else if (prefixes & PREFIX_REPNZ)
1381
        gb(s, 0xf2);
1382
    {
1383
        int len, i;
1384
        len = s->pc - pc_start_insn;
1385
        for(i = 0; i < len; i++) {
1386
            *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1387
        }
1388
    }
1389
 no_copy:
1390
    return 0;
1391
 illegal_op:
1392
 unsupported_op:
1393
    /* fall back to slower code gen necessary */
1394
    s->pc = pc_start;
1395
    return -1;
1396
}
1397

    
1398
#define GEN_CODE_MAX_SIZE      8192
1399
#define GEN_CODE_MAX_INSN_SIZE 512
1400

    
1401
static inline int gen_intermediate_code_internal(CPUState *env,
1402
                                                 TranslationBlock *tb, 
1403
                                                 uint8_t *gen_code_ptr,
1404
                                                 int *gen_code_size_ptr,
1405
                                                 int search_pc,
1406
                                                 uint8_t *tc_ptr)
1407
{
1408
    DisasContext dc1, *dc = &dc1;
1409
    uint8_t *pc_insn, *pc_start, *gen_code_end;
1410
    int flags, ret;
1411
    uint8_t *cs_base;
1412

    
1413
    if (env->nb_breakpoints > 0 ||
1414
        env->singlestep_enabled)
1415
        return -1;
1416
    flags = tb->flags;
1417
    if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | 
1418
                 HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1419
        return -1;
1420
    if (!(flags & HF_SS32_MASK))
1421
        return -1;
1422
    gen_code_end = gen_code_ptr + 
1423
        GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1424
    dc->gen_code_ptr = gen_code_ptr;
1425
    dc->gen_code_start = gen_code_ptr;
1426

    
1427
    /* generate intermediate code */
1428
    pc_start = (uint8_t *)tb->pc;
1429
    cs_base = (uint8_t *)tb->cs_base;
1430
    dc->pc = pc_start;
1431
    dc->cs_base = cs_base;
1432
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
1433
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1434
    dc->f_st = 0;
1435
    dc->vm86 = (flags >> VM_SHIFT) & 1;
1436
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1437
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
1438
    dc->tb = tb;
1439
    
1440
    dc->is_jmp = 0;
1441

    
1442
    for(;;) {
1443
        pc_insn = dc->pc;
1444
        ret = disas_insn(dc);
1445
        if (ret < 0) {
1446
            /* unsupported insn */
1447
            if (dc->pc == pc_start) {
1448
                /* if first instruction, signal that no copying was done */
1449
                return -1;
1450
            } else {
1451
                gen_jmp(dc, dc->pc - dc->cs_base);
1452
                dc->is_jmp = 1;
1453
            }
1454
        }
1455
        if (search_pc) {
1456
            /* search pc mode */
1457
            if (tc_ptr < dc->gen_code_ptr) {
1458
                env->eip = pc_insn - cs_base;
1459
                return 0;
1460
            }
1461
        }
1462
        /* stop translation if indicated */
1463
        if (dc->is_jmp)
1464
            break;
1465
        /* if too long translation, stop generation */
1466
        if (dc->gen_code_ptr >= gen_code_end ||
1467
            (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1468
            gen_jmp(dc, dc->pc - dc->cs_base);
1469
            break;
1470
        }
1471
    }
1472
    
1473
#ifdef DEBUG_DISAS
1474
    if (loglevel) {
1475
        fprintf(logfile, "----------------\n");
1476
        fprintf(logfile, "IN: COPY: %s\n", lookup_symbol(pc_start));
1477
        disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
1478
        fprintf(logfile, "\n");
1479
    }
1480
#endif
1481

    
1482
    if (!search_pc) {
1483
        *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1484
        tb->size = dc->pc - pc_start;
1485
        tb->cflags = CF_CODE_COPY;
1486
        return 0;
1487
    } else {
1488
        return -1;
1489
    }
1490
}
1491

    
1492
/* generate code by just copying data. Return -1 if cannot generate
1493
   any code. Return 0 if code was generated */
1494
int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1495
                      int max_code_size, int *gen_code_size_ptr)
1496
{
1497
    /* generate machine code */
1498
    tb->tb_next_offset[0] = 0xffff;
1499
    tb->tb_next_offset[1] = 0xffff;
1500
#ifdef USE_DIRECT_JUMP
1501
    /* the following two entries are optional (only used for string ops) */
1502
    tb->tb_jmp_offset[2] = 0xffff;
1503
    tb->tb_jmp_offset[3] = 0xffff;
1504
#endif
1505
    return gen_intermediate_code_internal(env, tb, 
1506
                                          tb->tc_ptr, gen_code_size_ptr,
1507
                                          0, NULL);
1508
}
1509

    
1510
static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1511

    
1512
int cpu_restore_state_copy(TranslationBlock *tb, 
1513
                           CPUState *env, unsigned long searched_pc,
1514
                           void *puc)
1515
{
1516
    struct ucontext *uc = puc;
1517
    int ret, eflags;
1518

    
1519
    /* find opc index corresponding to search_pc */
1520
    if (searched_pc < (unsigned long)tb->tc_ptr)
1521
        return -1;
1522
    searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1523
    ret = gen_intermediate_code_internal(env, tb, 
1524
                                         dummy_gen_code_buf, NULL,
1525
                                         1, (uint8_t *)searched_pc);
1526
    if (ret < 0)
1527
        return ret;
1528
    /* restore all the CPU state from the CPU context from the
1529
       signal */
1530
    
1531
    env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1532
    env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1533
    env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1534
    env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1535
    env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1536
    env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1537
    env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1538
    env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1539
    eflags = uc->uc_mcontext.gregs[REG_EFL];
1540
    env->df = 1 - (2 * ((eflags >> 10) & 1));
1541
    env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1542
    env->cc_op = CC_OP_EFLAGS;
1543
    return 0;
1544
}