52 |
static state change (stop translation) */ |
static state change (stop translation) */ |
53 |
/* current block context */ |
/* current block context */ |
54 |
uint8_t *cs_base; /* base of CS segment */ |
uint8_t *cs_base; /* base of CS segment */ |
55 |
|
int pe; /* protected mode */ |
56 |
int code32; /* 32 bit code segment */ |
int code32; /* 32 bit code segment */ |
57 |
int ss32; /* 32 bit stack segment */ |
int ss32; /* 32 bit stack segment */ |
58 |
int cc_op; /* current CC operation */ |
int cc_op; /* current CC operation */ |
990 |
if (base >= 0) { |
if (base >= 0) { |
991 |
/* for correct popl handling with esp */ |
/* for correct popl handling with esp */ |
992 |
if (base == 4 && s->popl_esp_hack) |
if (base == 4 && s->popl_esp_hack) |
993 |
disp += 4; |
disp += s->popl_esp_hack; |
994 |
gen_op_movl_A0_reg[base](); |
gen_op_movl_A0_reg[base](); |
995 |
if (disp != 0) |
if (disp != 0) |
996 |
gen_op_addl_A0_im(disp); |
gen_op_addl_A0_im(disp); |
1273 |
/* move T0 to seg_reg and compute if the CPU state may change */ |
/* move T0 to seg_reg and compute if the CPU state may change */ |
1274 |
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) |
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) |
1275 |
{ |
{ |
1276 |
if (!s->vm86) |
if (s->pe && !s->vm86) |
1277 |
gen_op_movl_seg_T0(seg_reg, cur_eip); |
gen_op_movl_seg_T0(seg_reg, cur_eip); |
1278 |
else |
else |
1279 |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
1856 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
1857 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1858 |
gen_op_lduw_T0_A0(); |
gen_op_lduw_T0_A0(); |
1859 |
if (!s->vm86) { |
if (s->pe && !s->vm86) { |
1860 |
/* we compute EIP to handle the exception case */ |
/* we compute EIP to handle the exception case */ |
1861 |
gen_op_jmp_im(pc_start - s->cs_base); |
gen_op_jmp_im(pc_start - s->cs_base); |
1862 |
gen_op_ljmp_T0_T1(); |
gen_op_ljmp_T0_T1(); |
2037 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2038 |
modrm = ldub(s->pc++); |
modrm = ldub(s->pc++); |
2039 |
gen_pop_T0(s); |
gen_pop_T0(s); |
2040 |
s->popl_esp_hack = 1; |
s->popl_esp_hack = 2 << dflag; |
2041 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2042 |
s->popl_esp_hack = 0; |
s->popl_esp_hack = 0; |
2043 |
gen_pop_update(s); |
gen_pop_update(s); |
2083 |
gen_pop_T0(s); |
gen_pop_T0(s); |
2084 |
gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base); |
gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base); |
2085 |
gen_pop_update(s); |
gen_pop_update(s); |
2086 |
|
/* XXX: if reg == SS, inhibit interrupts/trace */ |
2087 |
break; |
break; |
2088 |
case 0x1a1: /* pop fs */ |
case 0x1a1: /* pop fs */ |
2089 |
case 0x1a9: /* pop gs */ |
case 0x1a9: /* pop gs */ |
2136 |
gen_op_mov_reg_T0[ot][reg](); |
gen_op_mov_reg_T0[ot][reg](); |
2137 |
break; |
break; |
2138 |
case 0x8e: /* mov seg, Gv */ |
case 0x8e: /* mov seg, Gv */ |
|
ot = dflag ? OT_LONG : OT_WORD; |
|
2139 |
modrm = ldub(s->pc++); |
modrm = ldub(s->pc++); |
2140 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
|
2141 |
if (reg >= 6 || reg == R_CS) |
if (reg >= 6 || reg == R_CS) |
2142 |
goto illegal_op; |
goto illegal_op; |
2143 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
2144 |
gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2145 |
|
/* XXX: if reg == SS, inhibit interrupts/trace */ |
2146 |
break; |
break; |
2147 |
case 0x8c: /* mov Gv, seg */ |
case 0x8c: /* mov Gv, seg */ |
|
ot = dflag ? OT_LONG : OT_WORD; |
|
2148 |
modrm = ldub(s->pc++); |
modrm = ldub(s->pc++); |
2149 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2150 |
|
mod = (modrm >> 6) & 3; |
2151 |
if (reg >= 6) |
if (reg >= 6) |
2152 |
goto illegal_op; |
goto illegal_op; |
2153 |
gen_op_movl_T0_seg(reg); |
gen_op_movl_T0_seg(reg); |
2154 |
|
ot = OT_WORD; |
2155 |
|
if (mod == 3 && dflag) |
2156 |
|
ot = OT_LONG; |
2157 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2158 |
break; |
break; |
2159 |
|
|
2943 |
break; |
break; |
2944 |
case 0x6c: /* insS */ |
case 0x6c: /* insS */ |
2945 |
case 0x6d: |
case 0x6d: |
2946 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2947 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2948 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2949 |
} else { |
} else { |
2960 |
break; |
break; |
2961 |
case 0x6e: /* outsS */ |
case 0x6e: /* outsS */ |
2962 |
case 0x6f: |
case 0x6f: |
2963 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2964 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2965 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2966 |
} else { |
} else { |
2980 |
/* port I/O */ |
/* port I/O */ |
2981 |
case 0xe4: |
case 0xe4: |
2982 |
case 0xe5: |
case 0xe5: |
2983 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2984 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2985 |
} else { |
} else { |
2986 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2995 |
break; |
break; |
2996 |
case 0xe6: |
case 0xe6: |
2997 |
case 0xe7: |
case 0xe7: |
2998 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2999 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3000 |
} else { |
} else { |
3001 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
3010 |
break; |
break; |
3011 |
case 0xec: |
case 0xec: |
3012 |
case 0xed: |
case 0xed: |
3013 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
3014 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3015 |
} else { |
} else { |
3016 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
3024 |
break; |
break; |
3025 |
case 0xee: |
case 0xee: |
3026 |
case 0xef: |
case 0xef: |
3027 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
3028 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3029 |
} else { |
} else { |
3030 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
3081 |
val = 0; |
val = 0; |
3082 |
goto do_lret; |
goto do_lret; |
3083 |
case 0xcf: /* iret */ |
case 0xcf: /* iret */ |
3084 |
if (s->vm86 && s->iopl != 3) { |
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) { |
3089 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3090 |
} else { |
} else { |
3091 |
if (s->cc_op != CC_OP_DYNAMIC) |
if (s->cc_op != CC_OP_DYNAMIC) |
3151 |
|
|
3152 |
/* change cs and pc */ |
/* change cs and pc */ |
3153 |
gen_op_movl_T0_im(selector); |
gen_op_movl_T0_im(selector); |
3154 |
if (!s->vm86) { |
if (s->pe && !s->vm86) { |
3155 |
/* we compute EIP to handle the exception case */ |
/* we compute EIP to handle the exception case */ |
3156 |
gen_op_jmp_im(pc_start - s->cs_base); |
gen_op_jmp_im(pc_start - s->cs_base); |
3157 |
gen_op_movl_T1_im(offset); |
gen_op_movl_T1_im(offset); |
3451 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3452 |
} |
} |
3453 |
} |
} |
3454 |
|
/* XXX: interruptions are enabled only the first insn after sti */ |
3455 |
break; |
break; |
3456 |
case 0x62: /* bound */ |
case 0x62: /* bound */ |
3457 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3638 |
break; |
break; |
3639 |
case 0x102: /* lar */ |
case 0x102: /* lar */ |
3640 |
case 0x103: /* lsl */ |
case 0x103: /* lsl */ |
3641 |
if (s->vm86) |
if (!s->pe || s->vm86) |
3642 |
goto illegal_op; |
goto illegal_op; |
3643 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3644 |
modrm = ldub(s->pc++); |
modrm = ldub(s->pc++); |
4116 |
cs_base = (uint8_t *)tb->cs_base; |
cs_base = (uint8_t *)tb->cs_base; |
4117 |
flags = tb->flags; |
flags = tb->flags; |
4118 |
|
|
4119 |
|
dc->pe = env->cr[0] & CR0_PE_MASK; |
4120 |
dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; |
dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; |
4121 |
dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; |
dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; |
4122 |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
4123 |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
4124 |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
4125 |
dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
/* 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; |
4132 |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
4133 |
dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
4134 |
dc->cc_op = CC_OP_DYNAMIC; |
dc->cc_op = CC_OP_DYNAMIC; |
4135 |
dc->cs_base = cs_base; |
dc->cs_base = cs_base; |
4136 |
dc->tb = tb; |
dc->tb = tb; |
4137 |
dc->popl_esp_hack = 0; |
dc->popl_esp_hack = 0; |
4138 |
|
|
4139 |
gen_opc_ptr = gen_opc_buf; |
gen_opc_ptr = gen_opc_buf; |
4140 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
4141 |
gen_opparam_ptr = gen_opparam_buf; |
gen_opparam_ptr = gen_opparam_buf; |
4287 |
|
|
4288 |
/* called when cr3 or PG bit are modified */ |
/* called when cr3 or PG bit are modified */ |
4289 |
static int last_pg_state = -1; |
static int last_pg_state = -1; |
4290 |
|
static int last_pe_state = 0; |
4291 |
int phys_ram_size; |
int phys_ram_size; |
4292 |
int phys_ram_fd; |
int phys_ram_fd; |
4293 |
uint8_t *phys_ram_base; |
uint8_t *phys_ram_base; |
4294 |
|
|
4295 |
void cpu_x86_update_cr0(CPUX86State *env) |
void cpu_x86_update_cr0(CPUX86State *env) |
4296 |
{ |
{ |
4297 |
int pg_state; |
int pg_state, pe_state; |
4298 |
void *map_addr; |
void *map_addr; |
4299 |
|
|
4300 |
#ifdef DEBUG_MMU |
#ifdef DEBUG_MMU |
4322 |
} |
} |
4323 |
last_pg_state = pg_state; |
last_pg_state = pg_state; |
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 |
|
} |
4330 |
} |
} |
4331 |
|
|
4332 |
void cpu_x86_update_cr3(CPUX86State *env) |
void cpu_x86_update_cr3(CPUX86State *env) |