From 2b61d6eaf56c99fd62e18e6cd35e8637b72b6de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Wed, 28 Nov 2007 23:06:54 +0000 Subject: [PATCH] move state commit point of pmode/v86 iret further back Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3052 --- src/cpu/cpu.cpp | 124 ++++++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 46 deletions(-) diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index d1a71535..254d15b0 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.104 2007-11-26 00:00:58 c2woody Exp $ */ +/* $Id: cpu.cpp,v 1.105 2007-11-28 23:06:54 c2woody Exp $ */ #include #include @@ -711,15 +711,29 @@ void CPU_IRET(bool use32,Bitu oldeip) { return; } else { if (use32) { - reg_eip=CPU_Pop32(); - SegSet16(cs,CPU_Pop32()); + Bit32u new_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); + Bit32u new_cs=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); + Bit32u new_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); + reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); + + reg_eip=new_eip; + SegSet16(cs,(Bit16u)(new_cs&0xffff)); /* IOPL can not be modified in v86 mode by IRET */ - CPU_SetFlags(CPU_Pop32(),FMASK_NORMAL|FLAG_NT); + CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT); } else { - reg_eip=CPU_Pop16(); - SegSet16(cs,CPU_Pop16()); + Bit16u new_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); + Bit16u new_cs=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); + Bit16u new_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); + reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); + + reg_eip=(Bit32u)new_eip; + SegSet16(cs,new_cs); /* IOPL can not be modified in v86 mode by IRET */ - CPU_SetFlags(CPU_Pop16(),FMASK_NORMAL|FLAG_NT); + CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT); } cpu.code.big=false; DestroyConditionFlags(); @@ -738,12 +752,18 @@ void CPU_IRET(bool use32,Bitu oldeip) { return; } Bitu n_cs_sel,n_eip,n_flags; + Bit32u tempesp; if (use32) { - // commit point - n_eip=CPU_Pop32(); - n_cs_sel=CPU_Pop32() & 0xffff; - n_flags=CPU_Pop32(); + n_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); + n_cs_sel=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)) & 0xffff; + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); + n_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); + if ((n_flags & FLAG_VM) && (cpu.cpl==0)) { + // commit point + reg_esp=tempesp; reg_eip=n_eip & 0xffff; Bitu n_ss,n_esp,n_es,n_ds,n_fs,n_gs; n_esp=CPU_Pop32(); @@ -770,9 +790,14 @@ void CPU_IRET(bool use32,Bitu oldeip) { } if (n_flags & FLAG_VM) E_Exit("IRET from pmode to v86 with CPL!=0"); } else { - n_eip=CPU_Pop16(); - n_cs_sel=CPU_Pop16(); - n_flags=(reg_flags & 0xffff0000) | CPU_Pop16(); + n_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); + n_cs_sel=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); + n_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); + n_flags|=(reg_flags & 0xffff0000); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); + if (n_flags & FLAG_VM) E_Exit("VM Flag in 16-bit iret"); } CPU_CHECK_COND((n_cs_sel & 0xfffc)==0, @@ -809,6 +834,9 @@ void CPU_IRET(bool use32,Bitu oldeip) { if (n_cs_rpl==cpu.cpl) { /* Return to same level */ + + // commit point + reg_esp=tempesp; Segs.phys[cs]=n_cs_desc.GetBase(); cpu.code.big=n_cs_desc.Big()>0; Segs.val[cs]=n_cs_sel; @@ -823,11 +851,13 @@ void CPU_IRET(bool use32,Bitu oldeip) { /* Return to outer level */ Bitu n_ss,n_esp; if (use32) { - n_esp=CPU_Pop32(); - n_ss=CPU_Pop32() & 0xffff; + n_esp=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); + n_ss=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)) & 0xffff; } else { - n_esp=CPU_Pop16(); - n_ss=CPU_Pop16(); + n_esp=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); + tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); + n_ss=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); } CPU_CHECK_COND((n_ss & 0xfffc)==0, "IRET:Outer level:SS selector zero", @@ -855,6 +885,8 @@ void CPU_IRET(bool use32,Bitu oldeip) { "IRET:Outer level:Stack segment not present", EXCEPTION_NP,n_ss & 0xfffc) + // commit point + Segs.phys[cs]=n_cs_desc.GetBase(); cpu.code.big=n_cs_desc.Big()>0; Segs.val[cs]=n_cs_sel; @@ -883,34 +915,34 @@ void CPU_IRET(bool use32,Bitu oldeip) { // borland extender, zrdx Descriptor desc; - cpu.gdt.GetDescriptor(SegValue(es),desc); - switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(es,0); break; - default: break; } - cpu.gdt.GetDescriptor(SegValue(ds),desc); - switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(ds,0); break; - default: break; } - cpu.gdt.GetDescriptor(SegValue(fs),desc); - switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(fs,0); break; - default: break; } - cpu.gdt.GetDescriptor(SegValue(gs),desc); - switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(gs,0); break; - default: break; } + if (cpu.gdt.GetDescriptor(SegValue(es),desc)) + switch (desc.Type()) { + case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: + case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: + case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: + if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(es,0); break; + default: break; } + if (cpu.gdt.GetDescriptor(SegValue(ds),desc)) + switch (desc.Type()) { + case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: + case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: + case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: + if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(ds,0); break; + default: break; } + if (cpu.gdt.GetDescriptor(SegValue(fs),desc)) + switch (desc.Type()) { + case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: + case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: + case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: + if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(fs,0); break; + default: break; } + if (cpu.gdt.GetDescriptor(SegValue(gs),desc)) + switch (desc.Type()) { + case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: + case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: + case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: + if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(gs,0); break; + default: break; } LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); }