Revision 8f186479 translate-i386.c

b/translate-i386.c
52 52
                   static state change (stop translation) */
53 53
    /* current block context */
54 54
    uint8_t *cs_base; /* base of CS segment */
55
    int pe;     /* protected mode */
55 56
    int code32; /* 32 bit code segment */
56 57
    int ss32;   /* 32 bit stack segment */
57 58
    int cc_op;  /* current CC operation */
......
989 990
        if (base >= 0) {
990 991
            /* for correct popl handling with esp */
991 992
            if (base == 4 && s->popl_esp_hack)
992
                disp += 4;
993
                disp += s->popl_esp_hack;
993 994
            gen_op_movl_A0_reg[base]();
994 995
            if (disp != 0)
995 996
                gen_op_addl_A0_im(disp);
......
1272 1273
/* move T0 to seg_reg and compute if the CPU state may change */
1273 1274
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1274 1275
{
1275
    if (!s->vm86)
1276
    if (s->pe && !s->vm86)
1276 1277
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1277 1278
    else
1278 1279
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
......
1855 1856
            gen_op_ld_T1_A0[ot]();
1856 1857
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1857 1858
            gen_op_lduw_T0_A0();
1858
            if (!s->vm86) {
1859
            if (s->pe && !s->vm86) {
1859 1860
                /* we compute EIP to handle the exception case */
1860 1861
                gen_op_jmp_im(pc_start - s->cs_base);
1861 1862
                gen_op_ljmp_T0_T1();
......
2036 2037
        ot = dflag ? OT_LONG : OT_WORD;
2037 2038
        modrm = ldub(s->pc++);
2038 2039
        gen_pop_T0(s);
2039
        s->popl_esp_hack = 1;
2040
        s->popl_esp_hack = 2 << dflag;
2040 2041
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2041 2042
        s->popl_esp_hack = 0;
2042 2043
        gen_pop_update(s);
......
2082 2083
        gen_pop_T0(s);
2083 2084
        gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2084 2085
        gen_pop_update(s);
2086
        /* XXX: if reg == SS, inhibit interrupts/trace */
2085 2087
        break;
2086 2088
    case 0x1a1: /* pop fs */
2087 2089
    case 0x1a9: /* pop gs */
......
2134 2136
        gen_op_mov_reg_T0[ot][reg]();
2135 2137
        break;
2136 2138
    case 0x8e: /* mov seg, Gv */
2137
        ot = dflag ? OT_LONG : OT_WORD;
2138 2139
        modrm = ldub(s->pc++);
2139 2140
        reg = (modrm >> 3) & 7;
2140
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2141 2141
        if (reg >= 6 || reg == R_CS)
2142 2142
            goto illegal_op;
2143
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2143 2144
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2145
        /* XXX: if reg == SS, inhibit interrupts/trace */
2144 2146
        break;
2145 2147
    case 0x8c: /* mov Gv, seg */
2146
        ot = dflag ? OT_LONG : OT_WORD;
2147 2148
        modrm = ldub(s->pc++);
2148 2149
        reg = (modrm >> 3) & 7;
2150
        mod = (modrm >> 6) & 3;
2149 2151
        if (reg >= 6)
2150 2152
            goto illegal_op;
2151 2153
        gen_op_movl_T0_seg(reg);
2154
        ot = OT_WORD;
2155
        if (mod == 3 && dflag)
2156
            ot = OT_LONG;
2152 2157
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2153 2158
        break;
2154 2159

  
......
2938 2943
        break;
2939 2944
    case 0x6c: /* insS */
2940 2945
    case 0x6d:
2941
        if (s->cpl > s->iopl || s->vm86) {
2946
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2942 2947
            /* NOTE: even for (E)CX = 0 the exception is raised */
2943 2948
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2944 2949
        } else {
......
2955 2960
        break;
2956 2961
    case 0x6e: /* outsS */
2957 2962
    case 0x6f:
2958
        if (s->cpl > s->iopl || s->vm86) {
2963
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2959 2964
            /* NOTE: even for (E)CX = 0 the exception is raised */
2960 2965
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2961 2966
        } else {
......
2975 2980
        /* port I/O */
2976 2981
    case 0xe4:
2977 2982
    case 0xe5:
2978
        if (s->cpl > s->iopl || s->vm86) {
2983
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2979 2984
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2980 2985
        } else {
2981 2986
            if ((b & 1) == 0)
......
2990 2995
        break;
2991 2996
    case 0xe6:
2992 2997
    case 0xe7:
2993
        if (s->cpl > s->iopl || s->vm86) {
2998
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2994 2999
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2995 3000
        } else {
2996 3001
            if ((b & 1) == 0)
......
3005 3010
        break;
3006 3011
    case 0xec:
3007 3012
    case 0xed:
3008
        if (s->cpl > s->iopl || s->vm86) {
3013
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3009 3014
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3010 3015
        } else {
3011 3016
            if ((b & 1) == 0)
......
3019 3024
        break;
3020 3025
    case 0xee:
3021 3026
    case 0xef:
3022
        if (s->cpl > s->iopl || s->vm86) {
3027
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3023 3028
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3024 3029
        } else {
3025 3030
            if ((b & 1) == 0)
......
3076 3081
        val = 0;
3077 3082
        goto do_lret;
3078 3083
    case 0xcf: /* iret */
3079
        if (s->vm86 && s->iopl != 3) {
3084
        if (!s->pe) {
3085
            /* real mode */
3086
            gen_op_iret_real(s->dflag);
3087
            s->cc_op = CC_OP_EFLAGS;
3088
        } else if (s->vm86 && s->iopl != 3) {
3080 3089
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3081 3090
        } else {
3082 3091
            if (s->cc_op != CC_OP_DYNAMIC)
......
3142 3151
            
3143 3152
            /* change cs and pc */
3144 3153
            gen_op_movl_T0_im(selector);
3145
            if (!s->vm86) {
3154
            if (s->pe && !s->vm86) {
3146 3155
                /* we compute EIP to handle the exception case */
3147 3156
                gen_op_jmp_im(pc_start - s->cs_base);
3148 3157
                gen_op_movl_T1_im(offset);
......
3442 3451
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3443 3452
            }
3444 3453
        }
3454
        /* XXX: interruptions are enabled only the first insn after sti */
3445 3455
        break;
3446 3456
    case 0x62: /* bound */
3447 3457
        ot = dflag ? OT_LONG : OT_WORD;
......
3628 3638
        break;
3629 3639
    case 0x102: /* lar */
3630 3640
    case 0x103: /* lsl */
3631
        if (s->vm86)
3641
        if (!s->pe || s->vm86)
3632 3642
            goto illegal_op;
3633 3643
        ot = dflag ? OT_LONG : OT_WORD;
3634 3644
        modrm = ldub(s->pc++);
......
4106 4116
    cs_base = (uint8_t *)tb->cs_base;
4107 4117
    flags = tb->flags;
4108 4118
       
4119
    dc->pe = env->cr[0] & CR0_PE_MASK;
4109 4120
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4110 4121
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4111 4122
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4112 4123
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4113 4124
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4114
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4125
    /* CPL is implicit if real mode or vm86 mode */
4126
    if (!dc->pe)
4127
        dc->cpl = 0;
4128
    else if (dc->vm86)
4129
        dc->cpl = 3;
4130
    else
4131
        dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4115 4132
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4116 4133
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4117 4134
    dc->cc_op = CC_OP_DYNAMIC;
4118 4135
    dc->cs_base = cs_base;
4119 4136
    dc->tb = tb;
4120 4137
    dc->popl_esp_hack = 0;
4121
    
4138

  
4122 4139
    gen_opc_ptr = gen_opc_buf;
4123 4140
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4124 4141
    gen_opparam_ptr = gen_opparam_buf;
......
4270 4287

  
4271 4288
/* called when cr3 or PG bit are modified */
4272 4289
static int last_pg_state = -1;
4290
static int last_pe_state = 0;
4273 4291
int phys_ram_size;
4274 4292
int phys_ram_fd;
4275 4293
uint8_t *phys_ram_base;
4276 4294

  
4277 4295
void cpu_x86_update_cr0(CPUX86State *env)
4278 4296
{
4279
    int pg_state;
4297
    int pg_state, pe_state;
4280 4298
    void *map_addr;
4281 4299

  
4282 4300
#ifdef DEBUG_MMU
......
4304 4322
        }
4305 4323
        last_pg_state = pg_state;
4306 4324
    }
4325
    pe_state = env->cr[0] & CR0_PE_MASK;
4326
    if (last_pe_state != pe_state) {
4327
        tb_flush();
4328
        last_pe_state = pe_state;
4329
    }
4307 4330
}
4308 4331

  
4309 4332
void cpu_x86_update_cr3(CPUX86State *env)

Also available in: Unified diff