Commit 8f186479e26e8207520c062248642153826d5cde
1 parent
4c3a88a2
real mode support (now boots from BOCHS BIOS and LGPL'ed VGA BIOS)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@333 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
78 additions
and
19 deletions
helper-i386.c
@@ -788,6 +788,37 @@ static inline void load_seg_vm(int seg, int selector) | @@ -788,6 +788,37 @@ static inline void load_seg_vm(int seg, int selector) | ||
788 | sc->limit = 0xffff; | 788 | sc->limit = 0xffff; |
789 | } | 789 | } |
790 | 790 | ||
791 | +/* real mode iret */ | ||
792 | +void helper_iret_real(int shift) | ||
793 | +{ | ||
794 | + uint32_t sp, new_cs, new_eip, new_eflags, new_esp; | ||
795 | + uint8_t *ssp; | ||
796 | + int eflags_mask; | ||
797 | + | ||
798 | + sp = env->regs[R_ESP] & 0xffff; | ||
799 | + ssp = env->segs[R_SS].base + sp; | ||
800 | + if (shift == 1) { | ||
801 | + /* 32 bits */ | ||
802 | + new_eflags = ldl(ssp + 8); | ||
803 | + new_cs = ldl(ssp + 4) & 0xffff; | ||
804 | + new_eip = ldl(ssp) & 0xffff; | ||
805 | + } else { | ||
806 | + /* 16 bits */ | ||
807 | + new_eflags = lduw(ssp + 4); | ||
808 | + new_cs = lduw(ssp + 2); | ||
809 | + new_eip = lduw(ssp); | ||
810 | + } | ||
811 | + new_esp = sp + (6 << shift); | ||
812 | + env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) | | ||
813 | + (new_esp & 0xffff); | ||
814 | + load_seg_vm(R_CS, new_cs); | ||
815 | + env->eip = new_eip; | ||
816 | + eflags_mask = FL_UPDATE_CPL0_MASK; | ||
817 | + if (shift == 0) | ||
818 | + eflags_mask &= 0xffff; | ||
819 | + load_eflags(new_eflags, eflags_mask); | ||
820 | +} | ||
821 | + | ||
791 | /* protected mode iret */ | 822 | /* protected mode iret */ |
792 | void helper_iret_protected(int shift) | 823 | void helper_iret_protected(int shift) |
793 | { | 824 | { |
op-i386.c
@@ -953,6 +953,11 @@ void OPPROTO op_ljmp_T0_T1(void) | @@ -953,6 +953,11 @@ void OPPROTO op_ljmp_T0_T1(void) | ||
953 | jmp_seg(T0 & 0xffff, T1); | 953 | jmp_seg(T0 & 0xffff, T1); |
954 | } | 954 | } |
955 | 955 | ||
956 | +void OPPROTO op_iret_real(void) | ||
957 | +{ | ||
958 | + helper_iret_real(PARAM1); | ||
959 | +} | ||
960 | + | ||
956 | void OPPROTO op_iret_protected(void) | 961 | void OPPROTO op_iret_protected(void) |
957 | { | 962 | { |
958 | helper_iret_protected(PARAM1); | 963 | helper_iret_protected(PARAM1); |
translate-i386.c
@@ -52,6 +52,7 @@ typedef struct DisasContext { | @@ -52,6 +52,7 @@ typedef struct DisasContext { | ||
52 | static state change (stop translation) */ | 52 | static state change (stop translation) */ |
53 | /* current block context */ | 53 | /* current block context */ |
54 | uint8_t *cs_base; /* base of CS segment */ | 54 | uint8_t *cs_base; /* base of CS segment */ |
55 | + int pe; /* protected mode */ | ||
55 | int code32; /* 32 bit code segment */ | 56 | int code32; /* 32 bit code segment */ |
56 | int ss32; /* 32 bit stack segment */ | 57 | int ss32; /* 32 bit stack segment */ |
57 | int cc_op; /* current CC operation */ | 58 | int cc_op; /* current CC operation */ |
@@ -989,7 +990,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -989,7 +990,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
989 | if (base >= 0) { | 990 | if (base >= 0) { |
990 | /* for correct popl handling with esp */ | 991 | /* for correct popl handling with esp */ |
991 | if (base == 4 && s->popl_esp_hack) | 992 | if (base == 4 && s->popl_esp_hack) |
992 | - disp += 4; | 993 | + disp += s->popl_esp_hack; |
993 | gen_op_movl_A0_reg[base](); | 994 | gen_op_movl_A0_reg[base](); |
994 | if (disp != 0) | 995 | if (disp != 0) |
995 | gen_op_addl_A0_im(disp); | 996 | gen_op_addl_A0_im(disp); |
@@ -1272,7 +1273,7 @@ static void gen_setcc(DisasContext *s, int b) | @@ -1272,7 +1273,7 @@ static void gen_setcc(DisasContext *s, int b) | ||
1272 | /* move T0 to seg_reg and compute if the CPU state may change */ | 1273 | /* move T0 to seg_reg and compute if the CPU state may change */ |
1273 | static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) | 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 | gen_op_movl_seg_T0(seg_reg, cur_eip); | 1277 | gen_op_movl_seg_T0(seg_reg, cur_eip); |
1277 | else | 1278 | else |
1278 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); | 1279 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
@@ -1855,7 +1856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1855,7 +1856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1855 | gen_op_ld_T1_A0[ot](); | 1856 | gen_op_ld_T1_A0[ot](); |
1856 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 1857 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1857 | gen_op_lduw_T0_A0(); | 1858 | gen_op_lduw_T0_A0(); |
1858 | - if (!s->vm86) { | 1859 | + if (s->pe && !s->vm86) { |
1859 | /* we compute EIP to handle the exception case */ | 1860 | /* we compute EIP to handle the exception case */ |
1860 | gen_op_jmp_im(pc_start - s->cs_base); | 1861 | gen_op_jmp_im(pc_start - s->cs_base); |
1861 | gen_op_ljmp_T0_T1(); | 1862 | gen_op_ljmp_T0_T1(); |
@@ -2036,7 +2037,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2036,7 +2037,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2036 | ot = dflag ? OT_LONG : OT_WORD; | 2037 | ot = dflag ? OT_LONG : OT_WORD; |
2037 | modrm = ldub(s->pc++); | 2038 | modrm = ldub(s->pc++); |
2038 | gen_pop_T0(s); | 2039 | gen_pop_T0(s); |
2039 | - s->popl_esp_hack = 1; | 2040 | + s->popl_esp_hack = 2 << dflag; |
2040 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | 2041 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2041 | s->popl_esp_hack = 0; | 2042 | s->popl_esp_hack = 0; |
2042 | gen_pop_update(s); | 2043 | gen_pop_update(s); |
@@ -2082,6 +2083,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2082,6 +2083,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2082 | gen_pop_T0(s); | 2083 | gen_pop_T0(s); |
2083 | gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base); | 2084 | gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base); |
2084 | gen_pop_update(s); | 2085 | gen_pop_update(s); |
2086 | + /* XXX: if reg == SS, inhibit interrupts/trace */ | ||
2085 | break; | 2087 | break; |
2086 | case 0x1a1: /* pop fs */ | 2088 | case 0x1a1: /* pop fs */ |
2087 | case 0x1a9: /* pop gs */ | 2089 | case 0x1a9: /* pop gs */ |
@@ -2134,21 +2136,24 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2134,21 +2136,24 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2134 | gen_op_mov_reg_T0[ot][reg](); | 2136 | gen_op_mov_reg_T0[ot][reg](); |
2135 | break; | 2137 | break; |
2136 | case 0x8e: /* mov seg, Gv */ | 2138 | case 0x8e: /* mov seg, Gv */ |
2137 | - ot = dflag ? OT_LONG : OT_WORD; | ||
2138 | modrm = ldub(s->pc++); | 2139 | modrm = ldub(s->pc++); |
2139 | reg = (modrm >> 3) & 7; | 2140 | reg = (modrm >> 3) & 7; |
2140 | - gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); | ||
2141 | if (reg >= 6 || reg == R_CS) | 2141 | if (reg >= 6 || reg == R_CS) |
2142 | goto illegal_op; | 2142 | goto illegal_op; |
2143 | + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | ||
2143 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); | 2144 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2145 | + /* XXX: if reg == SS, inhibit interrupts/trace */ | ||
2144 | break; | 2146 | break; |
2145 | case 0x8c: /* mov Gv, seg */ | 2147 | case 0x8c: /* mov Gv, seg */ |
2146 | - ot = dflag ? OT_LONG : OT_WORD; | ||
2147 | modrm = ldub(s->pc++); | 2148 | modrm = ldub(s->pc++); |
2148 | reg = (modrm >> 3) & 7; | 2149 | reg = (modrm >> 3) & 7; |
2150 | + mod = (modrm >> 6) & 3; | ||
2149 | if (reg >= 6) | 2151 | if (reg >= 6) |
2150 | goto illegal_op; | 2152 | goto illegal_op; |
2151 | gen_op_movl_T0_seg(reg); | 2153 | gen_op_movl_T0_seg(reg); |
2154 | + ot = OT_WORD; | ||
2155 | + if (mod == 3 && dflag) | ||
2156 | + ot = OT_LONG; | ||
2152 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | 2157 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2153 | break; | 2158 | break; |
2154 | 2159 | ||
@@ -2938,7 +2943,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2938,7 +2943,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2938 | break; | 2943 | break; |
2939 | case 0x6c: /* insS */ | 2944 | case 0x6c: /* insS */ |
2940 | case 0x6d: | 2945 | case 0x6d: |
2941 | - if (s->cpl > s->iopl || s->vm86) { | 2946 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2942 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2947 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
2943 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 2948 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2944 | } else { | 2949 | } else { |
@@ -2955,7 +2960,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2955,7 +2960,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2955 | break; | 2960 | break; |
2956 | case 0x6e: /* outsS */ | 2961 | case 0x6e: /* outsS */ |
2957 | case 0x6f: | 2962 | case 0x6f: |
2958 | - if (s->cpl > s->iopl || s->vm86) { | 2963 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2959 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2964 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
2960 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 2965 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2961 | } else { | 2966 | } else { |
@@ -2975,7 +2980,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2975,7 +2980,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2975 | /* port I/O */ | 2980 | /* port I/O */ |
2976 | case 0xe4: | 2981 | case 0xe4: |
2977 | case 0xe5: | 2982 | case 0xe5: |
2978 | - if (s->cpl > s->iopl || s->vm86) { | 2983 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2979 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 2984 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2980 | } else { | 2985 | } else { |
2981 | if ((b & 1) == 0) | 2986 | if ((b & 1) == 0) |
@@ -2990,7 +2995,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2990,7 +2995,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2990 | break; | 2995 | break; |
2991 | case 0xe6: | 2996 | case 0xe6: |
2992 | case 0xe7: | 2997 | case 0xe7: |
2993 | - if (s->cpl > s->iopl || s->vm86) { | 2998 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
2994 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 2999 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2995 | } else { | 3000 | } else { |
2996 | if ((b & 1) == 0) | 3001 | if ((b & 1) == 0) |
@@ -3005,7 +3010,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3005,7 +3010,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3005 | break; | 3010 | break; |
3006 | case 0xec: | 3011 | case 0xec: |
3007 | case 0xed: | 3012 | case 0xed: |
3008 | - if (s->cpl > s->iopl || s->vm86) { | 3013 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
3009 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3014 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3010 | } else { | 3015 | } else { |
3011 | if ((b & 1) == 0) | 3016 | if ((b & 1) == 0) |
@@ -3019,7 +3024,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3019,7 +3024,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3019 | break; | 3024 | break; |
3020 | case 0xee: | 3025 | case 0xee: |
3021 | case 0xef: | 3026 | case 0xef: |
3022 | - if (s->cpl > s->iopl || s->vm86) { | 3027 | + if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
3023 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3028 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3024 | } else { | 3029 | } else { |
3025 | if ((b & 1) == 0) | 3030 | if ((b & 1) == 0) |
@@ -3076,7 +3081,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3076,7 +3081,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3076 | val = 0; | 3081 | val = 0; |
3077 | goto do_lret; | 3082 | goto do_lret; |
3078 | case 0xcf: /* iret */ | 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 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3089 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3081 | } else { | 3090 | } else { |
3082 | if (s->cc_op != CC_OP_DYNAMIC) | 3091 | if (s->cc_op != CC_OP_DYNAMIC) |
@@ -3142,7 +3151,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3142,7 +3151,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3142 | 3151 | ||
3143 | /* change cs and pc */ | 3152 | /* change cs and pc */ |
3144 | gen_op_movl_T0_im(selector); | 3153 | gen_op_movl_T0_im(selector); |
3145 | - if (!s->vm86) { | 3154 | + if (s->pe && !s->vm86) { |
3146 | /* we compute EIP to handle the exception case */ | 3155 | /* we compute EIP to handle the exception case */ |
3147 | gen_op_jmp_im(pc_start - s->cs_base); | 3156 | gen_op_jmp_im(pc_start - s->cs_base); |
3148 | gen_op_movl_T1_im(offset); | 3157 | gen_op_movl_T1_im(offset); |
@@ -3442,6 +3451,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3442,6 +3451,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3442 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 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 | break; | 3455 | break; |
3446 | case 0x62: /* bound */ | 3456 | case 0x62: /* bound */ |
3447 | ot = dflag ? OT_LONG : OT_WORD; | 3457 | ot = dflag ? OT_LONG : OT_WORD; |
@@ -3628,7 +3638,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3628,7 +3638,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3628 | break; | 3638 | break; |
3629 | case 0x102: /* lar */ | 3639 | case 0x102: /* lar */ |
3630 | case 0x103: /* lsl */ | 3640 | case 0x103: /* lsl */ |
3631 | - if (s->vm86) | 3641 | + if (!s->pe || s->vm86) |
3632 | goto illegal_op; | 3642 | goto illegal_op; |
3633 | ot = dflag ? OT_LONG : OT_WORD; | 3643 | ot = dflag ? OT_LONG : OT_WORD; |
3634 | modrm = ldub(s->pc++); | 3644 | modrm = ldub(s->pc++); |
@@ -4106,19 +4116,26 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4106,19 +4116,26 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
4106 | cs_base = (uint8_t *)tb->cs_base; | 4116 | cs_base = (uint8_t *)tb->cs_base; |
4107 | flags = tb->flags; | 4117 | flags = tb->flags; |
4108 | 4118 | ||
4119 | + dc->pe = env->cr[0] & CR0_PE_MASK; | ||
4109 | dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; | 4120 | dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; |
4110 | dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; | 4121 | dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; |
4111 | dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; | 4122 | dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
4112 | dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; | 4123 | dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
4113 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; | 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 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; | 4132 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
4116 | dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; | 4133 | dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
4117 | dc->cc_op = CC_OP_DYNAMIC; | 4134 | dc->cc_op = CC_OP_DYNAMIC; |
4118 | dc->cs_base = cs_base; | 4135 | dc->cs_base = cs_base; |
4119 | dc->tb = tb; | 4136 | dc->tb = tb; |
4120 | dc->popl_esp_hack = 0; | 4137 | dc->popl_esp_hack = 0; |
4121 | - | 4138 | + |
4122 | gen_opc_ptr = gen_opc_buf; | 4139 | gen_opc_ptr = gen_opc_buf; |
4123 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | 4140 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
4124 | gen_opparam_ptr = gen_opparam_buf; | 4141 | gen_opparam_ptr = gen_opparam_buf; |
@@ -4270,13 +4287,14 @@ void cpu_x86_close(CPUX86State *env) | @@ -4270,13 +4287,14 @@ void cpu_x86_close(CPUX86State *env) | ||
4270 | 4287 | ||
4271 | /* called when cr3 or PG bit are modified */ | 4288 | /* called when cr3 or PG bit are modified */ |
4272 | static int last_pg_state = -1; | 4289 | static int last_pg_state = -1; |
4290 | +static int last_pe_state = 0; | ||
4273 | int phys_ram_size; | 4291 | int phys_ram_size; |
4274 | int phys_ram_fd; | 4292 | int phys_ram_fd; |
4275 | uint8_t *phys_ram_base; | 4293 | uint8_t *phys_ram_base; |
4276 | 4294 | ||
4277 | void cpu_x86_update_cr0(CPUX86State *env) | 4295 | void cpu_x86_update_cr0(CPUX86State *env) |
4278 | { | 4296 | { |
4279 | - int pg_state; | 4297 | + int pg_state, pe_state; |
4280 | void *map_addr; | 4298 | void *map_addr; |
4281 | 4299 | ||
4282 | #ifdef DEBUG_MMU | 4300 | #ifdef DEBUG_MMU |
@@ -4304,6 +4322,11 @@ void cpu_x86_update_cr0(CPUX86State *env) | @@ -4304,6 +4322,11 @@ void cpu_x86_update_cr0(CPUX86State *env) | ||
4304 | } | 4322 | } |
4305 | last_pg_state = pg_state; | 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 | void cpu_x86_update_cr3(CPUX86State *env) | 4332 | void cpu_x86_update_cr3(CPUX86State *env) |