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