Revision 5a91de8c translate-i386.c

b/translate-i386.c
160 160
};
161 161

  
162 162
enum {
163
#define DEF(s, n) INDEX_op_ ## s,
163
#define DEF(s, n, copy_size) INDEX_op_ ## s,
164 164
#include "opc-i386.h"
165 165
#undef DEF
166 166
    NB_OPS,
......
1215 1215
}
1216 1216

  
1217 1217
/* move T0 to seg_reg and compute if the CPU state may change */
1218
static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1218
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1219 1219
{
1220
    gen_op_movl_seg_T0(seg_reg);
1220
    if (!s->vm86)
1221
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1222
    else
1223
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
1224
                              offsetof(CPUX86State,seg_cache[seg_reg].base));
1221 1225
    if (!s->addseg && seg_reg < R_FS)
1222 1226
        s->is_jmp = 2; /* abort translation because the register may
1223 1227
                          have a non zero base */
......
1374 1378
    s->is_jmp = 1;
1375 1379
}
1376 1380

  
1381
/* an interrupt is different from an exception because of the
1382
   priviledge checks */
1383
static void gen_interrupt(DisasContext *s, int intno, 
1384
                          unsigned int cur_eip, unsigned int next_eip)
1385
{
1386
    if (s->cc_op != CC_OP_DYNAMIC)
1387
        gen_op_set_cc_op(s->cc_op);
1388
    gen_op_jmp_im(cur_eip);
1389
    gen_op_raise_interrupt(intno, next_eip);
1390
    s->is_jmp = 1;
1391
}
1392

  
1377 1393
/* generate a jump to eip. No segment change must happen before as a
1378 1394
   direct call to the next block may occur */
1379 1395
static void gen_jmp(DisasContext *s, unsigned int eip)
......
1650 1666
        case 6: /* div */
1651 1667
            switch(ot) {
1652 1668
            case OT_BYTE:
1653
                gen_op_divb_AL_T0();
1669
                gen_op_divb_AL_T0(pc_start - s->cs_base);
1654 1670
                break;
1655 1671
            case OT_WORD:
1656
                gen_op_divw_AX_T0();
1672
                gen_op_divw_AX_T0(pc_start - s->cs_base);
1657 1673
                break;
1658 1674
            default:
1659 1675
            case OT_LONG:
1660
                gen_op_divl_EAX_T0();
1676
                gen_op_divl_EAX_T0(pc_start - s->cs_base);
1661 1677
                break;
1662 1678
            }
1663 1679
            break;
1664 1680
        case 7: /* idiv */
1665 1681
            switch(ot) {
1666 1682
            case OT_BYTE:
1667
                gen_op_idivb_AL_T0();
1683
                gen_op_idivb_AL_T0(pc_start - s->cs_base);
1668 1684
                break;
1669 1685
            case OT_WORD:
1670
                gen_op_idivw_AX_T0();
1686
                gen_op_idivw_AX_T0(pc_start - s->cs_base);
1671 1687
                break;
1672 1688
            default:
1673 1689
            case OT_LONG:
1674
                gen_op_idivl_EAX_T0();
1690
                gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1675 1691
                break;
1676 1692
            }
1677 1693
            break;
......
1738 1754
            gen_op_ld_T1_A0[ot]();
1739 1755
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1740 1756
            gen_op_lduw_T0_A0();
1741
            gen_movl_seg_T0(s, R_CS);
1757
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1742 1758
            gen_op_movl_T0_T1();
1743 1759
            gen_op_jmp_T0();
1744 1760
            s->is_jmp = 1;
......
1753 1769
            gen_op_ld_T1_A0[ot]();
1754 1770
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1755 1771
            gen_op_lduw_T0_A0();
1756
            gen_movl_seg_T0(s, R_CS);
1772
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1757 1773
            gen_op_movl_T0_T1();
1758 1774
            gen_op_jmp_T0();
1759 1775
            s->is_jmp = 1;
......
1970 1986
    case 0x17: /* pop ss */
1971 1987
    case 0x1f: /* pop ds */
1972 1988
        gen_pop_T0(s);
1973
        gen_movl_seg_T0(s, b >> 3);
1989
        gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
1974 1990
        gen_pop_update(s);
1975 1991
        break;
1976 1992
    case 0x1a1: /* pop fs */
1977 1993
    case 0x1a9: /* pop gs */
1978 1994
        gen_pop_T0(s);
1979
        gen_movl_seg_T0(s, (b >> 3) & 7);
1995
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
1980 1996
        gen_pop_update(s);
1981 1997
        break;
1982 1998

  
......
2030 2046
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2031 2047
        if (reg >= 6 || reg == R_CS)
2032 2048
            goto illegal_op;
2033
        gen_movl_seg_T0(s, reg);
2049
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2034 2050
        break;
2035 2051
    case 0x8c: /* mov Gv, seg */
2036 2052
        ot = dflag ? OT_LONG : OT_WORD;
......
2231 2247
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2232 2248
        /* load the segment first to handle exceptions properly */
2233 2249
        gen_op_lduw_T0_A0();
2234
        gen_movl_seg_T0(s, op);
2250
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2235 2251
        /* then put the data */
2236 2252
        gen_op_mov_reg_T1[ot][reg]();
2237 2253
        break;
......
2914 2930
        gen_pop_update(s);
2915 2931
        /* pop selector */
2916 2932
        gen_pop_T0(s);
2917
        gen_movl_seg_T0(s, R_CS);
2933
        gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2918 2934
        gen_pop_update(s);
2919 2935
        /* add stack offset */
2920 2936
        if (s->ss32)
......
2933 2949
        gen_pop_update(s);
2934 2950
        /* pop selector */
2935 2951
        gen_pop_T0(s);
2936
        gen_movl_seg_T0(s, R_CS);
2952
        gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2937 2953
        gen_pop_update(s);
2938 2954
        s->is_jmp = 1;
2939 2955
        break;
......
2950 2966
            gen_pop_update(s);
2951 2967
            /* pop selector */
2952 2968
            gen_pop_T0(s);
2953
            gen_movl_seg_T0(s, R_CS);
2969
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2954 2970
            gen_pop_update(s);
2955 2971
            /* pop eflags */
2956 2972
            gen_pop_T0(s);
......
2995 3011

  
2996 3012
            /* change cs and pc */
2997 3013
            gen_op_movl_T0_im(selector);
2998
            gen_movl_seg_T0(s, R_CS);
3014
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2999 3015
            gen_op_jmp_im((unsigned long)offset);
3000 3016
            s->is_jmp = 1;
3001 3017
        }
......
3018 3034
            
3019 3035
            /* change cs and pc */
3020 3036
            gen_op_movl_T0_im(selector);
3021
            gen_movl_seg_T0(s, R_CS);
3037
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3022 3038
            gen_op_jmp_im((unsigned long)offset);
3023 3039
            s->is_jmp = 1;
3024 3040
        }
......
3255 3271
    case 0x9b: /* fwait */
3256 3272
        break;
3257 3273
    case 0xcc: /* int3 */
3258
        gen_exception(s, EXCP03_INT3, s->pc - s->cs_base);
3274
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3259 3275
        break;
3260 3276
    case 0xcd: /* int N */
3261 3277
        val = ldub(s->pc++);
3262
        if (s->cc_op != CC_OP_DYNAMIC)
3263
            gen_op_set_cc_op(s->cc_op);
3264
        gen_op_int_im(val, pc_start - s->cs_base);
3265
        s->is_jmp = 1;
3278
        /* XXX: add error code for vm86 GPF */
3279
        if (!s->vm86)
3280
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3281
        else
3282
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3266 3283
        break;
3267 3284
    case 0xce: /* into */
3268 3285
        if (s->cc_op != CC_OP_DYNAMIC)
......
3309 3326
        gen_op_mov_reg_T0[ot][reg]();
3310 3327
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3311 3328
        if (ot == OT_WORD)
3312
            gen_op_boundw();
3329
            gen_op_boundw(pc_start - s->cs_base);
3313 3330
        else
3314
            gen_op_boundl();
3331
            gen_op_boundl(pc_start - s->cs_base);
3315 3332
        break;
3316 3333
    case 0x1c8 ... 0x1cf: /* bswap reg */
3317 3334
        reg = b & 7;
......
3670 3687

  
3671 3688
#ifdef DEBUG_DISAS
3672 3689
static const char *op_str[] = {
3673
#define DEF(s, n) #s,
3690
#define DEF(s, n, copy_size) #s,
3674 3691
#include "opc-i386.h"
3675 3692
#undef DEF
3676 3693
};
3677 3694

  
3678 3695
static uint8_t op_nb_args[] = {
3679
#define DEF(s, n) n,
3696
#define DEF(s, n, copy_size) n,
3680 3697
#include "opc-i386.h"
3681 3698
#undef DEF
3682 3699
};
......
3706 3723

  
3707 3724
#endif
3708 3725

  
3709
/* XXX: make this buffer thread safe */
3710 3726
/* XXX: make safe guess about sizes */
3711 3727
#define MAX_OP_PER_INSTR 32
3712 3728
#define OPC_BUF_SIZE 512
......
3716 3732

  
3717 3733
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3718 3734
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3735
static uint32_t gen_opc_pc[OPC_BUF_SIZE];
3736
static uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
3719 3737

  
3720
/* return non zero if the very first instruction is invalid so that
3721
   the virtual CPU can trigger an exception. 
3722

  
3723
   '*code_size_ptr' contains the target code size including the
3724
   instruction which triggered an exception, except in case of invalid
3725
   illegal opcode. It must never exceed one target page. 
3726
   
3727
   '*gen_code_size_ptr' contains the size of the generated code (host
3728
   code).
3729
*/
3730
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3731
                     int *gen_code_size_ptr,
3732
                     uint8_t *pc_start,  uint8_t *cs_base, int flags,
3733
                     int *code_size_ptr, TranslationBlock *tb)
3738
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3739
   basic block 'tb'. If search_pc is TRUE, also generate PC
3740
   information for each intermediate instruction. */
3741
static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc)
3734 3742
{
3735 3743
    DisasContext dc1, *dc = &dc1;
3736 3744
    uint8_t *pc_ptr;
3737 3745
    uint16_t *gen_opc_end;
3738
    int gen_code_size;
3746
    int flags, j, lj;
3739 3747
    long ret;
3748
    uint8_t *pc_start;
3749
    uint8_t *cs_base;
3740 3750
    
3741 3751
    /* generate intermediate code */
3742

  
3752
    pc_start = (uint8_t *)tb->pc;
3753
    cs_base = (uint8_t *)tb->cs_base;
3754
    flags = tb->flags;
3755
       
3743 3756
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3744 3757
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3745 3758
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
......
3758 3771

  
3759 3772
    dc->is_jmp = 0;
3760 3773
    pc_ptr = pc_start;
3774
    lj = -1;
3761 3775
    do {
3776
        if (search_pc) {
3777
            j = gen_opc_ptr - gen_opc_buf;
3778
            if (lj < j) {
3779
                lj++;
3780
                while (lj < j)
3781
                    gen_opc_instr_start[lj++] = 0;
3782
                gen_opc_pc[lj] = (uint32_t)pc_ptr;
3783
                gen_opc_instr_start[lj] = 1;
3784
            }
3785
        }
3762 3786
        ret = disas_insn(dc, pc_ptr);
3763 3787
        if (ret == -1) {
3764 3788
            /* we trigger an illegal instruction operation only if it
......
3819 3843
        fprintf(logfile, "\n");
3820 3844
    }
3821 3845
#endif
3846
    if (!search_pc)
3847
        tb->size = pc_ptr - pc_start;
3848
    return 0;
3849
}
3850

  
3851

  
3852
/* return non zero if the very first instruction is invalid so that
3853
   the virtual CPU can trigger an exception. 
3854

  
3855
   '*gen_code_size_ptr' contains the size of the generated code (host
3856
   code).
3857
*/
3858
int cpu_x86_gen_code(TranslationBlock *tb,
3859
                     int max_code_size, int *gen_code_size_ptr)
3860
{
3861
    uint8_t *gen_code_buf;
3862
    int gen_code_size;
3863

  
3864
    if (gen_intermediate_code(tb, 0) < 0)
3865
        return -1;
3822 3866

  
3823 3867
    /* generate machine code */
3824 3868
    tb->tb_next_offset[0] = 0xffff;
3825 3869
    tb->tb_next_offset[1] = 0xffff;
3870
    gen_code_buf = tb->tc_ptr;
3826 3871
    gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3827 3872
#ifdef USE_DIRECT_JUMP
3828 3873
                                tb->tb_jmp_offset,
......
3831 3876
#endif
3832 3877
                                gen_opc_buf, gen_opparam_buf);
3833 3878
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3834

  
3879
    
3835 3880
    *gen_code_size_ptr = gen_code_size;
3836
    *code_size_ptr = pc_ptr - pc_start;
3837 3881
#ifdef DEBUG_DISAS
3838 3882
    if (loglevel) {
3839 3883
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3840
	disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3884
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3841 3885
        fprintf(logfile, "\n");
3842 3886
        fflush(logfile);
3843 3887
    }
......
3845 3889
    return 0;
3846 3890
}
3847 3891

  
3892
static const unsigned short opc_copy_size[] = {
3893
#define DEF(s, n, copy_size) copy_size,
3894
#include "opc-i386.h"
3895
#undef DEF
3896
};
3897

  
3898
/* The simulated PC corresponding to
3899
   'searched_pc' in the generated code is searched. 0 is returned if
3900
   found. *found_pc contains the found PC. 
3901
 */
3902
int cpu_x86_search_pc(TranslationBlock *tb, 
3903
                      uint32_t *found_pc, unsigned long searched_pc)
3904
{
3905
    int j, c;
3906
    unsigned long tc_ptr;
3907
    uint16_t *opc_ptr;
3908

  
3909
    if (gen_intermediate_code(tb, 1) < 0)
3910
        return -1;
3911
    
3912
    /* find opc index corresponding to search_pc */
3913
    tc_ptr = (unsigned long)tb->tc_ptr;
3914
    if (searched_pc < tc_ptr)
3915
        return -1;
3916
    j = 0;
3917
    opc_ptr = gen_opc_buf;
3918
    for(;;) {
3919
        c = *opc_ptr;
3920
        if (c == INDEX_op_end)
3921
            return -1;
3922
        tc_ptr += opc_copy_size[c];
3923
        if (searched_pc < tc_ptr)
3924
            break;
3925
        opc_ptr++;
3926
    }
3927
    j = opc_ptr - gen_opc_buf;
3928
    /* now find start of instruction before */
3929
    while (gen_opc_instr_start[j] == 0)
3930
        j--;
3931
    *found_pc = gen_opc_pc[j];
3932
    return 0;
3933
}
3934

  
3935

  
3848 3936
CPUX86State *cpu_x86_init(void)
3849 3937
{
3850 3938
    CPUX86State *env;

Also available in: Unified diff