From 2ae27a0bb930880c58cc762f122981baaf12d9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Tue, 18 Apr 2006 17:44:25 +0000 Subject: [PATCH] precalculate inverted stack mask; improve dynamic core stack functions Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2606 --- include/cpu.h | 2 +- src/cpu/core_dyn_x86.cpp | 14 +--- src/cpu/core_dyn_x86/decoder.h | 136 +++++++++----------------------- src/cpu/core_dyn_x86/risc_x86.h | 32 +++++--- src/cpu/cpu.cpp | 34 +++++--- 5 files changed, 87 insertions(+), 131 deletions(-) diff --git a/include/cpu.h b/include/cpu.h index 9e755a12..8562ee0f 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -418,7 +418,7 @@ struct CPUBlock { GDTDescriptorTable gdt; DescriptorTable idt; struct { - Bitu mask; + Bitu mask,notmask; bool big; } stack; struct { diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 5dd4e64c..570a0b00 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -20,8 +20,6 @@ #if (C_DYNAMIC_X86) -#define CHECKED_MEMORY_ACCESS - #include #include #include @@ -46,11 +44,7 @@ #include "paging.h" #include "inout.h" -#ifdef CHECKED_MEMORY_ACCESS #define CACHE_MAXSIZE (4096*2) -#else -#define CACHE_MAXSIZE (4096) -#endif #define CACHE_PAGES (128*8) #define CACHE_TOTAL (CACHE_PAGES*4096) #define CACHE_BLOCKS (64*1024) @@ -73,7 +67,7 @@ enum { G_EAX,G_ECX,G_EDX,G_EBX, G_ESP,G_EBP,G_ESI,G_EDI, G_ES,G_CS,G_SS,G_DS,G_FS,G_GS, - G_FLAGS,G_SMASK,G_EIP, + G_FLAGS,G_NEWESP,G_EIP, G_EA,G_STACK,G_CYCLES, G_TMPB,G_TMPW,G_SHIFT, G_EXIT, @@ -155,7 +149,7 @@ static DynReg DynRegs[G_MAX]; #define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ] static struct { - Bitu ea,tmpb,tmpd,stack,shift; + Bitu ea,tmpb,tmpd,stack,shift,newesp; } extra_regs; static void IllegalOption(const char* msg) { @@ -326,8 +320,8 @@ void CPU_Core_Dyn_X86_Init(void) { DynRegs[G_FLAGS].data=®_flags; DynRegs[G_FLAGS].flags=DYNFLG_LOAD|DYNFLG_SAVE; - DynRegs[G_SMASK].data=&cpu.stack.mask; - DynRegs[G_SMASK].flags=DYNFLG_LOAD|DYNFLG_SAVE; + DynRegs[G_NEWESP].data=&extra_regs.newesp; + DynRegs[G_NEWESP].flags=0; DynRegs[G_EIP].data=®_eip; DynRegs[G_EIP].flags=DYNFLG_LOAD|DYNFLG_SAVE; diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 19dc1a4d..e851d6c1 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -220,7 +220,6 @@ static void dyn_fill_blocks(void) { used_save_info=0; } -#ifdef CHECKED_MEMORY_ACCESS static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { gen_protectflags(); gen_call_function((void *)&mem_readb_checked_x86,"%Dd%Id",addr,&core_dyn.readdata); @@ -271,50 +270,13 @@ static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { else gen_call_function((void *)&mem_writew_checked_x86,"%Ddr%Dd",addr,val); dyn_check_bool_exception_al(); } -#else -static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { - if (high) gen_call_function((void *)&mem_readb,"%Dd%Rh",addr,dst); - else gen_call_function((void *)&mem_readb,"%Dd%Rl",addr,dst); -} -static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { - if (high) gen_call_function((void *)&mem_writeb,"%Dd%Dh",addr,val); - else gen_call_function((void *)&mem_writeb,"%Dd%Dd",addr,val); -} -static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { - if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Dd%Rd",addr,dst); - else gen_call_function((void *)&mem_readw_dyncorex86,"%Dd%Rw",addr,dst); -} -static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { - if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Dd%Dd",addr,val); - else gen_call_function((void *)&mem_writew_dyncorex86,"%Dd%Dd",addr,val); -} -static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { - if (high) gen_call_function((void *)&mem_readb,"%Ddr%Rh",addr,dst); - else gen_call_function((void *)&mem_readb,"%Ddr%Rl",addr,dst); -} -static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) { - if (high) gen_call_function((void *)&mem_writeb,"%Ddr%Dh",addr,val); - else gen_call_function((void *)&mem_writeb,"%Ddr%Dd",addr,val); -} -static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) { - if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Ddr%Rd",addr,dst); - else gen_call_function((void *)&mem_readw_dyncorex86,"%Ddr%Rw",addr,dst); -} -static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { - if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Ddr%Dd",addr,val); - else gen_call_function((void *)&mem_writew_dyncorex86,"%Ddr%Dd",addr,val); -} -#endif static void dyn_push_unchecked(DynReg * dynreg) { gen_protectflags(); - if (decode.big_op) { - gen_dop_word_imm(DOP_SUB,true,DREG(ESP),4); - } else { - gen_dop_word_imm(DOP_SUB,true,DREG(ESP),2); - } - gen_dop_word(DOP_AND,true,DREG(ESP),DREG(SMASK)); - gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); + gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2)); + gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); + gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask); + gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK)); gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); if (decode.big_op) { gen_call_function((void *)&mem_writed,"%Drd%Dd",DREG(STACK),dynreg); @@ -326,13 +288,11 @@ static void dyn_push_unchecked(DynReg * dynreg) { static void dyn_push(DynReg * dynreg) { gen_protectflags(); - gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); - if (decode.big_op) { - gen_dop_word_imm(DOP_SUB,true,DREG(STACK),4); - } else { - gen_dop_word_imm(DOP_SUB,true,DREG(STACK),2); - } - gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); + gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2)); + gen_dop_word(DOP_MOV,true,DREG(NEWESP),DREG(ESP)); + gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); + gen_dop_word_var(DOP_AND,true,DREG(NEWESP),&cpu.stack.notmask); + gen_dop_word(DOP_OR,true,DREG(NEWESP),DREG(STACK)); gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); if (decode.big_op) { gen_call_function((void *)&mem_writed_checked_x86,"%Drd%Dd",DREG(STACK),dynreg); @@ -341,54 +301,36 @@ static void dyn_push(DynReg * dynreg) { gen_call_function((void *)&mem_writew_checked_x86,"%Drd%Dd",DREG(STACK),dynreg); } dyn_check_bool_exception_al(); - /* everything was ok, change registers now */ - if (decode.big_op) { - gen_dop_word_imm(DOP_SUB,true,DREG(ESP),4); - } else { - gen_dop_word_imm(DOP_SUB,true,DREG(ESP),2); - } - gen_dop_word(DOP_AND,true,DREG(ESP),DREG(SMASK)); + /* everything was ok, change register now */ + gen_dop_word(DOP_MOV,true,DREG(ESP),DREG(NEWESP)); + gen_releasereg(DREG(NEWESP)); } -static void dyn_pop_unchecked(DynReg * dynreg) { +static void dyn_pop(DynReg * dynreg,bool checked=true) { gen_protectflags(); gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); - gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); + gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); - if (decode.big_op) { - gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK)); + if (checked) { + if (decode.big_op) { + gen_call_function((void *)&mem_readd_checked_x86,"%Drd%Id",DREG(STACK),&core_dyn.readdata); + } else { + gen_call_function((void *)&mem_readw_checked_x86,"%Drd%Id",DREG(STACK),&core_dyn.readdata); + } + dyn_check_bool_exception_al(); + gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2); } else { - gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK)); + if (decode.big_op) { + gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK)); + } else { + gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK)); + } } if (dynreg!=DREG(ESP)) { - if (decode.big_op) { - gen_dop_word_imm(DOP_ADD,true,DREG(ESP),4); - } else { - gen_dop_word_imm(DOP_ADD,true,DREG(ESP),2); - } - gen_dop_word(DOP_AND,true,DREG(ESP),DREG(SMASK)); - } -} - -static void dyn_pop(DynReg * dynreg) { - gen_protectflags(); - gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); - gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); - gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); - if (decode.big_op) { - gen_call_function((void *)&mem_readd_checked_x86,"%Drd%Id",DREG(STACK),&core_dyn.readdata); - } else { - gen_call_function((void *)&mem_readw_checked_x86,"%Drd%Id",DREG(STACK),&core_dyn.readdata); - } - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2); - if (dynreg!=DREG(ESP)) { - if (decode.big_op) { - gen_dop_word_imm(DOP_ADD,true,DREG(ESP),4); - } else { - gen_dop_word_imm(DOP_ADD,true,DREG(ESP),2); - } - gen_dop_word(DOP_AND,true,DREG(ESP),DREG(SMASK)); + gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?4:2); + gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); + gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask); + gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK)); } } @@ -575,9 +517,7 @@ static void dyn_mov_ebib(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); gen_call_write(DREG(EA),decode_fetchb(),1); -#ifdef CHECKED_MEMORY_ACCESS dyn_check_bool_exception_al(); -#endif } else { gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); } @@ -696,9 +636,7 @@ static void dyn_mov_eviv(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); gen_call_write(DREG(EA),decode.big_op ? decode_fetchd() : decode_fetchw(),decode.big_op?4:2); -#ifdef CHECKED_MEMORY_ACCESS dyn_check_bool_exception_al(); -#endif } else { gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw()); } @@ -985,7 +923,6 @@ static void dyn_load_seg(SegNames seg,DynReg * src) { gen_releasereg(DREG(TMPB)); } else gen_call_function((void *)CPU_SetSegGeneral,"%Id%Drw",seg,src); gen_releasereg(&DynRegs[G_ES+seg]); - if (seg==ss) gen_releasereg(DREG(SMASK)); } static void dyn_load_seg_off_ea(SegNames seg) { @@ -1034,7 +971,6 @@ static void dyn_pop_seg(SegNames seg) { gen_releasereg(DREG(TMPB)); gen_releasereg(&DynRegs[G_ES+seg]); gen_releasereg(DREG(ESP)); - if (seg==ss) gen_releasereg(DREG(SMASK)); } } @@ -1062,13 +998,13 @@ static void dyn_enter(void) { static void dyn_leave(void) { gen_protectflags(); - gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(SMASK)); + gen_dop_word_var(DOP_MOV,true,DREG(TMPW),&cpu.stack.mask); gen_sop_word(SOP_NOT,true,DREG(TMPW)); gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW)); gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP)); - gen_dop_word(DOP_AND,true,DREG(TMPW),DREG(SMASK)); + gen_dop_word_var(DOP_AND,true,DREG(TMPW),&cpu.stack.mask); gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW)); - dyn_pop_unchecked(DREG(EBP)); + dyn_pop(DREG(EBP),false); gen_releasereg(DREG(TMPW)); } @@ -1444,7 +1380,7 @@ restart_prefix: break; case 0x61: /* POPA */ for (i=G_EDI;i>=G_EAX;i--) { - dyn_pop_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); + dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW),false); } gen_releasereg(DREG(TMPW)); break; @@ -1453,7 +1389,7 @@ restart_prefix: case 0x65:dyn_segprefix(gs);goto restart_prefix; //Push immediates //Operand size - case 0x66:decode.big_op=!cpu.code.big;;goto restart_prefix; + case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix; //Address size case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix; case 0x68: /* PUSH Iv */ diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index 7c9b5e3c..f3a809a3 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -457,6 +457,29 @@ finish: else cache_addw(imm); } +static void gen_dop_word_var(DualOps op,bool dword,DynReg * dr1,void* drd) { + GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); + Bit8u tmp; + switch (op) { + case DOP_ADD: tmp=0x03; break; + case DOP_ADC: tmp=0x13; break; + case DOP_SUB: tmp=0x2b; break; + case DOP_SBB: tmp=0x1b; break; + case DOP_CMP: tmp=0x3b; break; + case DOP_XOR: tmp=0x33; break; + case DOP_AND: tmp=0x23; break; + case DOP_OR: tmp=0x0b; break; + case DOP_TEST: tmp=0x85; break; + case DOP_MOV: tmp=0x8b; break; + case DOP_XCHG: tmp=0x87; break; + default: + IllegalOption("gen_dop_word_var"); + } + if (!dword) cache_addb(0x66); + cache_addw(tmp|(0x05+((gr1->index)<<3))<<8); + cache_addd((Bit32u)drd); +} + static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) { GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); dr1->flags|=DYNFLG_CHANGED; @@ -728,21 +751,12 @@ static void gen_call_write(DynReg * dr,Bit32u val,Bitu write_size) { x86gen.regs[X86_REG_EDX]->Clear(); /* Do the actual call to the procedure */ cache_addb(0xe8); -#ifdef CHECKED_MEMORY_ACCESS switch (write_size) { case 1: cache_addd((Bit32u)mem_writeb_checked_x86 - (Bit32u)cache.pos-4); break; case 2: cache_addd((Bit32u)mem_writew_checked_x86 - (Bit32u)cache.pos-4); break; case 4: cache_addd((Bit32u)mem_writed_checked_x86 - (Bit32u)cache.pos-4); break; default: IllegalOption("gen_call_write"); } -#else - switch (write_size) { - case 1: cache_addd((Bit32u)mem_writeb - (Bit32u)cache.pos-4); break; - case 2: cache_addd((Bit32u)mem_writew_dyncorex86 - (Bit32u)cache.pos-4); break; - case 4: cache_addd((Bit32u)mem_writed_dyncorex86 - (Bit32u)cache.pos-4); break; - default: IllegalOption("gen_call_write"); - } -#endif cache_addw(0xc483); //ADD ESP,8 cache_addb(2*4); diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 51e2b575..abe57759 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.79 2006-02-26 16:11:00 qbix79 Exp $ */ +/* $Id: cpu.cpp,v 1.80 2006-04-18 17:44:25 c2woody Exp $ */ #include #include "dosbox.h" @@ -90,26 +90,26 @@ void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache); void CPU_Push16(Bitu value) { - Bit32u new_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-2)&cpu.stack.mask); + Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); reg_esp=new_esp; } void CPU_Push32(Bitu value) { - Bit32u new_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-4)&cpu.stack.mask); + Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask); mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); reg_esp=new_esp; } Bitu CPU_Pop16(void) { Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+2)&cpu.stack.mask); + reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); return val; } Bitu CPU_Pop32(void) { Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+4)&cpu.stack.mask); + reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); return val; } @@ -409,11 +409,11 @@ doconforming: bool CPU_IO_Exception(Bitu port,Bitu size) { if (cpu.pmode && ((GETFLAG_IOPLcpu_tss.limit) goto doexception; - where=cpu_tss.base+ofs+(port/8); - Bitu map=mem_readw(where); + bwhere=cpu_tss.base+ofs+(port/8); + Bitu map=mem_readw(bwhere); Bitu mask=(0xffff>>(16-size)) << (port&7); if (map & mask) goto doexception; } @@ -552,10 +552,12 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; + cpu.stack.notmask=0; reg_esp=n_esp; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; reg_sp=n_esp & 0xffff; } @@ -814,10 +816,12 @@ void CPU_IRET(bool use32,Bitu oldeip) { if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; + cpu.stack.notmask=0; reg_esp=n_esp; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; reg_sp=n_esp & 0xffff; } @@ -1070,10 +1074,12 @@ call_code: if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; + cpu.stack.notmask=0; reg_esp=n_esp; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; reg_sp=n_esp & 0xffff; } @@ -1303,10 +1309,12 @@ RET_same_level: if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; + cpu.stack.notmask=0; reg_esp=n_esp+bytes; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; reg_sp=(n_esp & 0xffff)+bytes; } @@ -1712,6 +1720,7 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) { if (seg==ss) { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; } return false; } else { @@ -1750,9 +1759,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) { if (desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; + cpu.stack.notmask=0; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; } } else { if ((value & 0xfffc)==0) { @@ -1799,7 +1810,7 @@ bool CPU_PopSeg(SegNames seg,bool use32) { Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); if (CPU_SetSegGeneral(seg,val)) return true; Bitu addsp=use32?0x04:0x02; - reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask); + reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+addsp)&cpu.stack.mask); return false; } @@ -1872,7 +1883,7 @@ void CPU_ENTER(bool use32,Bitu bytes,Bitu level) { } } sp_index-=bytes; - reg_esp=(reg_esp&~cpu.stack.mask)|((sp_index)&cpu.stack.mask); + reg_esp=(reg_esp&cpu.stack.notmask)|((sp_index)&cpu.stack.mask); } extern void GFX_SetTitle(Bits cycles ,Bits frameskip,bool paused); @@ -1938,6 +1949,7 @@ public: CPU_SET_CRX(0,0); //Initialize cpu.code.big=false; cpu.stack.mask=0xffff; + cpu.stack.notmask=0xffff0000; cpu.stack.big=false; cpu.idt.SetBase(0); cpu.idt.SetLimit(1023);