Commit 8f186479e26e8207520c062248642153826d5cde

Authored by bellard
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
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)