From 5460def6342b1127f453e7db680c6958561e7605 Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Thu, 22 Apr 2004 22:40:46 +0000 Subject: [PATCH] Changes to cpu cores. Save/Load eip after each opcode Handle IO exceptions Handle protection exception for protected opcodes with too less privilege Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1773 --- include/cpu.h | 35 ++-- src/cpu/core_full.cpp | 41 ++--- src/cpu/core_full/load.h | 187 ++++++------------- src/cpu/core_full/loadwrite.h | 48 ++--- src/cpu/core_full/op.h | 38 ++-- src/cpu/core_full/optable.h | 9 +- src/cpu/core_full/save.h | 33 +--- src/cpu/core_full/string.h | 2 +- src/cpu/core_full/support.h | 15 +- src/cpu/core_normal.cpp | 64 +++---- src/cpu/core_normal/helpers.h | 14 -- src/cpu/core_normal/prefix_0f.h | 27 ++- src/cpu/core_normal/prefix_66.h | 198 +++++++++++--------- src/cpu/core_normal/prefix_66_0f.h | 12 +- src/cpu/core_normal/prefix_none.h | 281 ++++++++++++++--------------- src/cpu/core_normal/string.h | 19 +- src/cpu/core_normal/support.h | 127 ++++--------- src/cpu/cpu.cpp | 181 ++++++++++++------- 18 files changed, 589 insertions(+), 742 deletions(-) diff --git a/include/cpu.h b/include/cpu.h index 3225738e..b30aabfb 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -52,7 +52,6 @@ void CPU_SLDT(Bitu & selector); void CPU_SIDT(Bitu & limit,Bitu & base); void CPU_SGDT(Bitu & limit,Bitu & base); - void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); void CPU_LAR(Bitu selector,Bitu & ar); void CPU_LSL(Bitu selector,Bitu & limit); @@ -61,37 +60,43 @@ bool CPU_SET_CRX(Bitu cr,Bitu value); Bitu CPU_GET_CRX(Bitu cr); void CPU_SMSW(Bitu & word); -bool CPU_LMSW(Bitu word); +Bitu CPU_LMSW(Bitu word); void CPU_VERR(Bitu selector); void CPU_VERW(Bitu selector); -void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen); -void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen); -void CPU_RET(bool use32,Bitu bytes,Bitu opLen); -void CPU_IRET(bool use32,Bitu opLen); +void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip); +void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip); +void CPU_RET(bool use32,Bitu bytes,Bitu oldeip); +void CPU_IRET(bool use32,Bitu oldeip); +void CPU_HLT(Bitu oldeip); -bool CPU_CLI(Bitu opLen); -bool CPU_STI(Bitu opLen); +bool CPU_POPF(Bitu use32); +bool CPU_PUSHF(Bitu use32); +bool CPU_CLI(void); +bool CPU_STI(void); + +bool CPU_IO_Exception(Bitu port,Bitu size); +void CPU_RunException(void); + +void CPU_ENTER(bool use32,Bitu bytes,Bitu level); #define CPU_INT_SOFTWARE 0x1 #define CPU_INT_EXCEPTION 0x2 #define CPU_INT_HAS_ERROR 0x4 -void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0); +void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip); INLINE void CPU_HW_Interrupt(Bitu num) { - CPU_Interrupt(num,0); + CPU_Interrupt(num,0,reg_eip); } -INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) { - CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen); +INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) { + CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip); } void CPU_Exception(Bitu which,Bitu error=0); -void CPU_StartException(void); -void CPU_SetupException(Bitu which,Bitu error=0); bool CPU_SetSegGeneral(SegNames seg,Bitu value); -void CPU_HLT(Bitu opLen); +bool CPU_PopSeg(SegNames seg,bool use32); void CPU_CPUID(void); Bitu CPU_Pop16(void); diff --git a/src/cpu/core_full.cpp b/src/cpu/core_full.cpp index 9fdc76be..54cea6fe 100644 --- a/src/cpu/core_full.cpp +++ b/src/cpu/core_full.cpp @@ -54,47 +54,28 @@ typedef PhysPt EAPoint; #include "core_full/optable.h" #include "instructions.h" -#define LEAVECORE \ - SaveIP(); \ - FillFlags(); - #define EXCEPTION(blah) \ { \ Bit8u new_num=blah; \ - IPPoint=inst.opcode_start; \ - LEAVECORE; \ CPU_Exception(new_num,0); \ - LoadIP(); \ - goto nextopcode; \ + continue; \ } Bits CPU_Core_Full_Run(void) { FullData inst; -restart_core: - if (!cpu.code.big) { - inst.start_prefix=0x0;; - inst.start_entry=0x0; - } else { - inst.start_prefix=PREFIX_ADDR; - inst.start_entry=0x200; - } - EAPoint IPPoint; - LoadIP(); - lflags.type=t_UNKNOWN; while (CPU_Cycles-->0) { #if C_DEBUG cycle_count++; #if C_HEAVY_DEBUG - SaveIP(); if (DEBUG_HeavyIsBreakpoint()) { LEAVECORE; return debugCallback; }; #endif #endif - inst.opcode_start=IPPoint; - inst.entry=inst.start_entry; - inst.prefix=inst.start_prefix; + LoadIP(); + inst.entry=cpu.code.big*0x200; + inst.prefix=cpu.code.big; restartopcode: inst.entry=(inst.entry & 0xffffff00) | Fetchb(); inst.code=OpCodeTable[inst.entry]; @@ -102,14 +83,14 @@ restartopcode: #include "core_full/op.h" #include "core_full/save.h" nextopcode:; - } - LEAVECORE; - return CBRET_NONE; + SaveIP(); + continue; illegalopcode: - LEAVECORE; - reg_eip-=(IPPoint-inst.opcode_start); - CPU_Exception(0x6,0); - goto restart_core; + LOG_MSG("Illegal opcode"); + CPU_Exception(0x6,0); + } + FillFlags(); + return CBRET_NONE; } diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h index fc009821..3a63a3de 100644 --- a/src/cpu/core_full/load.h +++ b/src/cpu/core_full/load.h @@ -144,18 +144,12 @@ l_M_Ed: inst.op1.d=SegValue((SegNames)inst.rm_index); break; case M_Efw: - if (inst.rm>=0xC0) { - LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); - goto nextopcode; - } + if (inst.rm>=0xc0) goto illegalopcode; inst.op1.d=LoadMw(inst.rm_eaa); inst.op2.d=LoadMw(inst.rm_eaa+2); break; case M_Efd: - if (inst.rm>=0xc0) { - LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); - goto nextopcode; - } + if (inst.rm>=0xc0) goto illegalopcode; inst.op1.d=LoadMd(inst.rm_eaa); inst.op2.d=LoadMw(inst.rm_eaa+4); break; @@ -183,8 +177,6 @@ l_M_Ed: inst.op2.d=1; inst.code=Groups[inst.code.op][inst.rm_index]; goto l_MODRMswitch; - - /* Should continue with normal handler afterwards */ case 0: break; default: @@ -206,30 +198,6 @@ l_M_Ed: inst.op1.d = Pop_32(); inst.op2.d = Pop_16(); break; - case L_PFLGw: - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=IPPoint-inst.opcode_start; - CPU_Exception(13,0); - goto restart_core; - } - SETFLAGSw(Pop_16()); - if (GETFLAG(IF) && PIC_IRQCheck) { - SaveIP(); - return CBRET_NONE; - } - break; - case L_PFLGd: - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=IPPoint-inst.opcode_start; - CPU_Exception(13,0); - goto restart_core; - } - SETFLAGSd(Pop_32()); - if (GETFLAG(IF) && PIC_IRQCheck) { - SaveIP(); - return CBRET_NONE; - } - break; case L_Ib: inst.op1.d=Fetchb(); break; @@ -270,9 +238,6 @@ l_M_Ed: case L_REGd: inst.op1.d=reg_32(inst.code.extra); break; - case L_FLG: - inst.op1.d = FillFlags(); - break; case L_SEG: inst.op1.d=SegValue((SegNames)inst.code.extra); break; @@ -306,10 +271,10 @@ l_M_Ed: inst.repz=true; goto restartopcode; case L_PREOP: - inst.entry=inst.start_entry ^ 0x200; + inst.entry=(cpu.code.big ^1) * 0x200; goto restartopcode; case L_PREADD: - inst.prefix^=PREFIX_ADDR; + inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1); goto restartopcode; case L_VAL: inst.op1.d=inst.code.extra; @@ -319,41 +284,40 @@ l_M_Ed: inst.op1.d=4; break; case D_IRETw: - LEAVECORE; - CPU_IRET(false,IPPoint-inst.opcode_start); + FillFlags(); + CPU_IRET(false,GetIP()); if (GETFLAG(IF) && PIC_IRQCheck) { return CBRET_NONE; } - goto restart_core; + continue; case D_IRETd: - LEAVECORE; - CPU_IRET(true,IPPoint-inst.opcode_start); - if (GETFLAG(IF) && PIC_IRQCheck) { + FillFlags(); + CPU_IRET(true,GetIP()); + if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; - } - goto restart_core; + continue; case D_RETFwIw: { Bitu words=Fetchw(); - LEAVECORE; - CPU_RET(false,words,IPPoint-inst.opcode_start); - goto restart_core; + FillFlags(); + CPU_RET(false,words,GetIP()); + continue; } case D_RETFw: - LEAVECORE; - CPU_RET(false,0,IPPoint-inst.opcode_start); - goto restart_core; + FillFlags(); + CPU_RET(false,0,GetIP()); + continue; case D_RETFdIw: { Bitu words=Fetchw(); - LEAVECORE; - CPU_RET(true,words,IPPoint-inst.opcode_start); - goto restart_core; + FillFlags(); + CPU_RET(true,words,GetIP()); + continue; } case D_RETFd: - LEAVECORE; - CPU_RET(true,0,IPPoint-inst.opcode_start); - goto restart_core; + FillFlags(); + CPU_RET(true,0,GetIP()); + continue; /* Direct operations */ case L_STRING: #include "string.h" @@ -381,18 +345,10 @@ l_M_Ed: reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); goto nextopcode; case D_POPSEGw: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) { - LEAVECORE; - reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2; - CPU_StartException();goto restart_core; - } + if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException(); goto nextopcode; case D_POPSEGd: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) { - LEAVECORE; - reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4; - CPU_StartException();goto restart_core; - } + if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException(); goto nextopcode; case D_SETALC: reg_al = get_CF() ? 0xFF : 0; @@ -427,14 +383,10 @@ l_M_Ed: else reg_edx=0; goto nextopcode; case D_CLI: - LEAVECORE; - if (CPU_CLI(IPPoint-inst.opcode_start)) - goto restart_core; + if (CPU_CLI()) RunException(); goto nextopcode; case D_STI: - LEAVECORE; - if (CPU_STI(IPPoint-inst.opcode_start)) - goto restart_core; + if (CPU_STI()) RunException(); goto nextopcode; case D_STC: FillFlags();SETFLAGBIT(CF,true); @@ -454,71 +406,40 @@ l_M_Ed: SETFLAGBIT(DF,true); cpu.direction=-1; goto nextopcode; + case D_PUSHF: + FillFlags(); + if (CPU_PUSHF(inst.code.extra)) RunException(); + goto nextopcode; + case D_POPF: + if (CPU_POPF(inst.code.extra)) RunException(); + lflags.type=t_UNKNOWN; + if (GETFLAG(IF) && PIC_IRQCheck) { + SaveIP(); + return CBRET_NONE; + } + goto nextopcode; + case D_SAHF: + SETFLAGSb(reg_ah); + goto nextopcode; + case D_LAHF: + FillFlags(); + reg_ah=reg_flags&0xff; + goto nextopcode; case D_WAIT: case D_NOP: goto nextopcode; case D_ENTERw: { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-2; - if (cpu.stack.big) { - reg_esp-=2; - mem_writew(SegBase(ss)+reg_esp,reg_bp); - for (Bitu i=1;i0) { - core.op_start=core.ip_lookup; - core.opcode_index=core.index_default; - core.prefixes=core.prefix_default; + LOADIP; + core.opcode_index=cpu.code.big*0x200; + core.prefixes=cpu.code.big; #if C_DEBUG - cycle_count++; #if C_HEAVY_DEBUG - SAVEIP; if (DEBUG_HeavyIsBreakpoint()) { - LEAVECORE; + FillFlags(); return debugCallback; }; #endif + cycle_count++; #endif restart_prefix: core.ea_table=EAPrefixTable[core.prefixes]; @@ -189,27 +177,29 @@ restart_opcode: #include "core_normal/prefix_66_0f.h" default: illegal_opcode: - LEAVECORE; - reg_eip-=core.ip_lookup-core.op_start; #if C_DEBUG { - Bitu len=core.ip_lookup-core.op_start; + Bitu len=(GETIP-reg_eip); + LOADIP; if (len>16) len=16; char tempcode[16*2+1];char * writecode=tempcode; for (;len>0;len--) { - sprintf(writecode,"%X",mem_readb(core.op_start++)); + sprintf(writecode,"%X",mem_readb(core.cseip++)); writecode+=2; } LOG(LOG_CPU,LOG_ERROR)("Illegal/Unhandled opcode %s",tempcode); } #endif CPU_Exception(6,0); - goto decode_start; - + continue; } + SAVEIP; } + FillFlags(); + return CBRET_NONE; decode_end: - LEAVECORE; + SAVEIP; + FillFlags(); return CBRET_NONE; } @@ -220,7 +210,7 @@ Bits CPU_Core_Normal_Trap_Run(void) { core.trap.skip=false; Bits ret=CPU_Core_Normal_Run(); - if (!core.trap.skip) CPU_SW_Interrupt(1,0); + if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip); CPU_Cycles = oldCycles-1; cpudecoder = &CPU_Core_Normal_Run; diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h index b7acd35b..d7326488 100644 --- a/src/cpu/core_normal/helpers.h +++ b/src/cpu/core_normal/helpers.h @@ -141,17 +141,3 @@ } \ } -#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \ - if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \ - LEAVECORE; \ - reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \ - CPU_StartException();goto decode_start; \ - } - -#define LOADSEG(_SEG_,_SEG_VAL_) \ - if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \ - LEAVECORE; \ - reg_eip-=(core.ip_lookup-core.op_start); \ - CPU_StartException();goto decode_start; \ - } \ - diff --git a/src/cpu/core_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h index bbe95b9c..f562d051 100644 --- a/src/cpu/core_normal/prefix_0f.h +++ b/src/cpu/core_normal/prefix_0f.h @@ -45,7 +45,7 @@ } break; default: - LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); + goto illegal_opcode; } } break; @@ -77,7 +77,7 @@ break; case 0x06: /* LMSW */ limit=LoadMw(eaa); - if (!CPU_LMSW(limit)) goto decode_end; + if (CPU_LMSW(limit)) RUNEXCEPTION(); break; } } else { @@ -88,11 +88,10 @@ *earw=limit; break; case 0x06: /* LMSW */ - if (!CPU_LMSW(*earw)) goto decode_end; + if (CPU_LMSW(*earw)) RUNEXCEPTION(); break; default: - LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); - break; + goto illegal_opcode; } } } @@ -154,11 +153,8 @@ Bitu which=(rm >> 3) & 7; if (rm >= 0xc0 ) { GetEArd; - CPU_SET_CRX(which,*eard); - } else { - GetEAa; - LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which); - } + if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION(); + } else goto illegal_opcode; } break; CASE_0F_B(0x23) /* MOV DRx,Rd */ @@ -241,7 +237,7 @@ CASE_0F_W(0xa0) /* PUSH FS */ Push_16(SegValue(fs));break; CASE_0F_W(0xa1) /* POP FS */ - POPSEG(fs,Pop_16(),2); + if (CPU_PopSeg(fs,false)) RUNEXCEPTION(); break; CASE_0F_B(0xa2) /* CPUID */ CPU_CPUID();break; @@ -268,7 +264,8 @@ CASE_0F_W(0xa8) /* PUSH GS */ Push_16(SegValue(gs));break; CASE_0F_W(0xa9) /* POP GS */ - POPSEG(gs,Pop_16(),2);break; + if (CPU_PopSeg(gs,false)) RUNEXCEPTION(); + break; CASE_0F_W(0xab) /* BTS Ew,Gw */ { FillFlags();GetRMrw; @@ -297,7 +294,7 @@ CASE_0F_W(0xb2) /* LSS Ew */ { GetRMrw;GetEAa; - LOADSEG(ss,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } @@ -320,14 +317,14 @@ CASE_0F_W(0xb4) /* LFS Ew */ { GetRMrw;GetEAa; - LOADSEG(fs,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } CASE_0F_W(0xb5) /* LGS Ew */ { GetRMrw;GetEAa; - LOADSEG(gs,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h index 94d99c07..28cd7ccd 100644 --- a/src/cpu/core_normal/prefix_66.h +++ b/src/cpu/core_normal/prefix_66.h @@ -25,7 +25,8 @@ CASE_D(0x06) /* PUSH ES */ Push_32(SegValue(es));break; CASE_D(0x07) /* POP ES */ - POPSEG(es,Pop_32(),4);break; + if (CPU_PopSeg(es,true)) RUNEXCEPTION(); + break; CASE_D(0x09) /* OR Ed,Gd */ RMEdGd(ORD);break; CASE_D(0x0b) /* OR Gd,Ed */ @@ -43,7 +44,7 @@ CASE_D(0x16) /* PUSH SS */ Push_32(SegValue(ss));break; CASE_D(0x17) /* POP SS */ - POPSEG(ss,Pop_32(),4); + if (CPU_PopSeg(ss,true)) RUNEXCEPTION(); CPU_Cycles++; break; CASE_D(0x19) /* SBB Ed,Gd */ @@ -55,7 +56,8 @@ CASE_D(0x1e) /* PUSH DS */ Push_32(SegValue(ds));break; CASE_D(0x1f) /* POP DS */ - POPSEG(ds,Pop_32(),4);break; + if (CPU_PopSeg(ds,true)) RUNEXCEPTION(); + break; CASE_D(0x21) /* AND Ed,Gd */ RMEdGd(ANDD);break; CASE_D(0x23) /* AND Gd,Ed */ @@ -191,6 +193,12 @@ CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ RMGdEdOp3(DIMULD,Fetchbs()); break; + CASE_D(0x6d) /* INSD */ + if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); + DoString(R_INSD);break; + CASE_D(0x6f) /* OUTSD */ + if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); + DoString(R_OUTSD);break; CASE_D(0x70) /* JO */ JumpCond32_b(TFLG_O);break; CASE_D(0x71) /* JNO */ @@ -379,21 +387,17 @@ CASE_D(0x9a) /* CALL FAR Ad */ { Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); - LEAVECORE; - CPU_CALL(true,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_CALL(true,newcs,newip,GETIP); + continue; } CASE_D(0x9c) /* PUSHFD */ FillFlags(); - Push_32(reg_flags); + if (CPU_PUSHF(true)) RUNEXCEPTION(); break; CASE_D(0x9d) /* POPFD */ - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; - CPU_Exception(13,0); - goto decode_start; - } - SETFLAGSd(Pop_32()) + if (CPU_POPF(true)) RUNEXCEPTION(); + lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -403,7 +407,6 @@ #if CPU_PIC_CHECK if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; #endif - break; CASE_D(0xa1) /* MOV EAX,Od */ { @@ -448,25 +451,23 @@ CASE_D(0xc1) /* GRP2 Ed,Ib */ GRP2D(Fetchb());break; CASE_D(0xc2) /* RETN Iw */ - { - Bit16u addsp=Fetchw(); - SETIP(Pop_32());reg_esp+=addsp; - break; - } + reg_eip=Pop_32(); + reg_esp+=Fetchw(); + continue; CASE_D(0xc3) /* RETN */ - SETIP(Pop_32()); - break; + reg_eip=Pop_32(); + continue; CASE_D(0xc4) /* LES */ { GetRMrd;GetEAa; - LOADSEG(es,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } CASE_D(0xc5) /* LDS */ { GetRMrd;GetEAa; - LOADSEG(ds,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } @@ -479,36 +480,11 @@ } CASE_D(0xc8) /* ENTER Iw,Ib */ { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-4; - if (cpu.stack.big) { - reg_esp-=4; - mem_writed(SegBase(ss)+reg_esp,reg_ebp); - for (Bitu i=1;i= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);} - else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));} - break; + if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} + else {GetEAa;reg_eip=LoadMd(eaa);} + Push_32(GETIP); + continue; case 0x03: /* CALL FAR Ed */ { GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - LEAVECORE; - CPU_CALL(true,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_CALL(true,newcs,newip,GETIP); + continue; } - break; case 0x04: /* JMP NEAR Ed */ - if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);} - else {GetEAa;SETIP(LoadMd(eaa));} - break; + if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} + else {GetEAa;reg_eip=LoadMd(eaa);} + continue; case 0x05: /* JMP FAR Ed */ { GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - LEAVECORE; - CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_JMP(true,newcs,newip,GETIP); + continue; } break; case 0x06: /* Push Ed */ diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h index 8c53663c..d9be36f5 100644 --- a/src/cpu/core_normal/prefix_66_0f.h +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -159,7 +159,8 @@ CASE_0F_D(0xa0) /* PUSH FS */ Push_32(SegValue(fs));break; CASE_0F_D(0xa1) /* POP FS */ - POPSEG(fs,Pop_32(),4);break; + if (CPU_PopSeg(fs,true)) RUNEXCEPTION(); + break; CASE_0F_D(0xa3) /* BT Ed,Gd */ { FillFlags();GetRMrd; @@ -183,7 +184,8 @@ CASE_0F_D(0xa8) /* PUSH GS */ Push_32(SegValue(gs));break; CASE_0F_D(0xa9) /* POP GS */ - POPSEG(gs,Pop_32(),4);break; + if (CPU_PopSeg(gs,true)) RUNEXCEPTION(); + break; CASE_0F_D(0xab) /* BTS Ed,Gd */ { FillFlags();GetRMrd; @@ -215,7 +217,7 @@ CASE_0F_D(0xb2) /* LSS Ed */ { GetRMrd;GetEAa; - LOADSEG(ss,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } @@ -238,14 +240,14 @@ CASE_0F_D(0xb4) /* LFS Ed */ { GetRMrd;GetEAa; - LOADSEG(fs,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } CASE_0F_D(0xb5) /* LGS Ed */ { GetRMrd;GetEAa; - LOADSEG(gs,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h index 9e8a1b58..287254ec 100644 --- a/src/cpu/core_normal/prefix_none.h +++ b/src/cpu/core_normal/prefix_none.h @@ -31,7 +31,8 @@ CASE_W(0x06) /* PUSH ES */ Push_16(SegValue(es));break; CASE_W(0x07) /* POP ES */ - POPSEG(es,Pop_16(),2);break; + if (CPU_PopSeg(es,false)) RUNEXCEPTION(); + break; CASE_B(0x08) /* OR Eb,Gb */ RMEbGb(ORB);break; CASE_W(0x09) /* OR Ew,Gw */ @@ -65,7 +66,7 @@ CASE_W(0x16) /* PUSH SS */ Push_16(SegValue(ss));break; CASE_W(0x17) /* POP SS */ - POPSEG(ss,Pop_16(),2); + if (CPU_PopSeg(ss,false)) RUNEXCEPTION(); CPU_Cycles++; //Always do another instruction break; CASE_B(0x18) /* SBB Eb,Gb */ @@ -83,7 +84,7 @@ CASE_W(0x1e) /* PUSH DS */ Push_16(SegValue(ds));break; CASE_W(0x1f) /* POP DS */ - POPSEG(ds,Pop_16(),2); + if (CPU_PopSeg(ds,false)) RUNEXCEPTION(); break; CASE_B(0x20) /* AND Eb,Gb */ RMEbGb(ANDB);break; @@ -256,7 +257,7 @@ CASE_B(0x65) /* SEG GS: */ DO_PREFIX_SEG(gs);break; CASE_B(0x66) /* Operand Size Prefix */ - core.opcode_index=core.index_default^OPCODE_SIZE; + core.opcode_index=(cpu.code.big^0x1)*0x200; goto restart_opcode; CASE_B(0x67) /* Address Size Prefix */ DO_PREFIX_ADDR(); @@ -272,12 +273,16 @@ RMGwEwOp3(DIMULW,Fetchbs()); break; CASE_B(0x6c) /* INSB */ + if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); DoString(R_INSB);break; CASE_W(0x6d) /* INSW */ + if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); DoString(R_INSW);break; CASE_B(0x6e) /* OUTSB */ + if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); DoString(R_OUTSB);break; CASE_W(0x6f) /* OUTSW */ + if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); DoString(R_OUTSW);break; CASE_W(0x70) /* JO */ JumpCond16_b(TFLG_O);break; @@ -498,13 +503,10 @@ case 0x03: /* MOV DS,Ew */ case 0x05: /* MOV GS,Ew */ case 0x04: /* MOV FS,Ew */ - LOADSEG((SegNames)which,val); - break; - case 0x01: /* MOV CS,Ew Illegal*/ - E_Exit("CPU:Illegal MOV CS Call"); + if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION(); break; default: - E_Exit("CPU:8E:Illegal RM Byte"); + goto illegal_opcode; } break; } @@ -546,24 +548,20 @@ break; CASE_W(0x9a) /* CALL Ap */ { + FillFlags(); Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - LEAVECORE; - CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + CPU_CALL(false,newcs,newip,GETIP); + continue; } CASE_B(0x9b) /* WAIT */ break; /* No waiting here */ CASE_W(0x9c) /* PUSHF */ FillFlags(); - Push_16(reg_flags); + if (CPU_PUSHF(false)) RUNEXCEPTION(); break; CASE_W(0x9d) /* POPF */ - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; - CPU_Exception(13,0); - goto decode_start; - } - SETFLAGSw(Pop_16()); + if (CPU_POPF(false)) RUNEXCEPTION(); + lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -666,25 +664,23 @@ CASE_W(0xc1) /* GRP2 Ew,Ib */ GRP2W(Fetchb());break; CASE_W(0xc2) /* RETN Iw */ - { - Bit16u addsp=Fetchw(); - SETIP(Pop_16());reg_esp+=addsp; - break; - } + reg_eip=Pop_16(); + reg_esp+=Fetchw(); + continue; CASE_W(0xc3) /* RETN */ - SETIP(Pop_16()); - break; + reg_eip=Pop_16(); + continue; CASE_W(0xc4) /* LES */ { GetRMrw;GetEAa; - LOADSEG(es,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } CASE_W(0xc5) /* LDS */ { GetRMrw;GetEAa; - LOADSEG(ds,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } @@ -704,36 +700,11 @@ } CASE_W(0xc8) /* ENTER Iw,Ib */ { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-2; - if (cpu.stack.big) { - reg_esp-=2; - mem_writew(SegBase(ss)+reg_esp,reg_bp); - for (Bitu i=1;i= 0xc0 ) {GetEArw;Push_16((Bit16u)GETIP);SETIP(*earw);} - else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));} - break; + if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} + else {GetEAa;reg_eip=LoadMw(eaa);} + Push_16(GETIP); + continue; case 0x03: /* CALL Ep */ { GetEAa; Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - LEAVECORE; - CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_CALL(false,newcs,newip,GETIP); + continue; } break; case 0x04: /* JMP Ev */ - if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} - else {GetEAa;SETIP(LoadMw(eaa));} - break; + if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} + else {GetEAa;reg_eip=LoadMw(eaa);} + continue; case 0x05: /* JMP Ep */ { GetEAa; Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - LEAVECORE; - CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_JMP(false,newcs,newip,GETIP); + continue; } break; case 0x06: /* PUSH Ev */ diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h index c2f3013e..45a61474 100644 --- a/src/cpu/core_normal/string.h +++ b/src/cpu/core_normal/string.h @@ -20,18 +20,11 @@ static void DoString(STRING_OP type) { if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base; else si_base=SegBase(ds); di_base=SegBase(es); - if (TEST_PREFIX_ADDR) { - add_mask=0xFFFFFFFF; - si_index=reg_esi; - di_index=reg_edi; - count=reg_ecx; - } else { - add_mask=0xFFFF; - si_index=reg_si; - di_index=reg_di; - count=reg_cx; - } - if (!(TEST_PREFIX_REP)) { + add_mask=AddrMaskTable[core.prefixes& PREFIX_ADDR]; + si_index=reg_esi & add_mask; + di_index=reg_edi & add_mask; + count=reg_ecx & add_mask; + if (!TEST_PREFIX_REP) { count=1; } else { CPU_Cycles++; @@ -40,7 +33,7 @@ static void DoString(STRING_OP type) { count_left=count-CPU_Cycles; count=CPU_Cycles; CPU_Cycles=0; - core.ip_lookup=core.op_start; //Reset IP to start of instruction + LOADIP; //RESET IP to the start } else { /* Won't interrupt scas and cmps instruction since they can interrupt themselves */ count_left=0; diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h index e9ce3c8e..8f25ef4c 100644 --- a/src/cpu/core_normal/support.h +++ b/src/cpu/core_normal/support.h @@ -16,57 +16,36 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_) -#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs)) -#define SAVEIP {reg_eip=GETIP;} -#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);} +#define GETIP (core.cseip-SegBase(cs)) +#define SAVEIP reg_eip=GETIP; +#define LOADIP core.cseip=(SegBase(cs)+reg_eip); -#define LEAVECORE \ - SAVEIP; \ - FillFlags(); - -static INLINE void ADDIPw(Bits add) { - SAVEIP; - reg_eip=(Bit16u)(reg_eip+add); - LOADIP; -} - -static INLINE void ADDIPd(Bits add) { - SAVEIP; - reg_eip=(reg_eip+add); - LOADIP; -} - -static INLINE void ADDIPFAST(Bits blah) { -// core.ip_lookup+=blah; - SAVEIP; - reg_eip=(reg_eip+blah); - LOADIP; +#define RUNEXCEPTION() { \ + FillFlags(); \ + CPU_Exception(cpu.exception.which,cpu.exception.error); \ + continue; \ } #define EXCEPTION(blah) \ { \ - Bit8u new_num=blah; \ - core.ip_lookup=core.op_start; \ - LEAVECORE; \ - CPU_Exception(new_num); \ - goto decode_start; \ + CPU_Exception(blah); \ + continue; \ } static INLINE Bit8u Fetchb() { - Bit8u temp=LoadMb(core.ip_lookup); - core.ip_lookup+=1; + Bit8u temp=LoadMb(core.cseip); + core.cseip+=1; return temp; } static INLINE Bit16u Fetchw() { - Bit16u temp=LoadMw(core.ip_lookup); - core.ip_lookup+=2; + Bit16u temp=LoadMw(core.cseip); + core.cseip+=2; return temp; } static INLINE Bit32u Fetchd() { - Bit32u temp=LoadMd(core.ip_lookup); - core.ip_lookup+=4; + Bit32u temp=LoadMd(core.cseip); + core.cseip+=4; return temp; } @@ -81,68 +60,40 @@ static INLINE Bit32s Fetchds() { return Fetchd(); } -#if 0 - -static INLINE void Push_16(Bit16u blah) { - reg_esp-=2; - SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); -}; - -static INLINE void Push_32(Bit32u blah) { - reg_esp-=4; - SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); -}; - -static INLINE Bit16u Pop_16() { - Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask)); - reg_esp+=2; - return temp; -}; - -static INLINE Bit32u Pop_32() { - Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask)); - reg_esp+=4; - return temp; -}; - -#else - #define Push_16 CPU_Push16 #define Push_32 CPU_Push32 #define Pop_16 CPU_Pop16 #define Pop_32 CPU_Pop32 -#endif - //TODO Could probably make all byte operands fast? -#define JumpCond16_b(blah) \ - if (blah) { \ - ADDIPw(Fetchbs()); \ - } else { \ - ADDIPFAST(1); \ - } +#define JumpCond16_b(COND) { \ + SAVEIP; \ + if (COND) reg_ip+=Fetchbs(); \ + reg_ip+=1; \ + continue; \ +} -#define JumpCond32_b(blah) \ - if (blah) { \ - ADDIPd(Fetchbs()); \ - } else { \ - ADDIPFAST(1); \ - } +#define JumpCond16_w(COND) { \ + SAVEIP; \ + if (COND) reg_ip+=Fetchws(); \ + reg_ip+=2; \ + continue; \ +} -#define JumpCond16_w(blah) \ - if (blah) { \ - ADDIPw(Fetchws()); \ - } else { \ - ADDIPFAST(2); \ - } +#define JumpCond32_b(COND) { \ + SAVEIP; \ + if (COND) reg_eip+=Fetchbs(); \ + reg_eip+=1; \ + continue; \ +} +#define JumpCond32_d(COND) { \ + SAVEIP; \ + if (COND) reg_eip+=Fetchds(); \ + reg_eip+=4; \ + continue; \ +} -#define JumpCond32_d(blah) \ - if (blah) { \ - ADDIPd(Fetchds()); \ - } else { \ - ADDIPFAST(4); \ - } #define SETcc(cc) \ { \ diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 546022b4..097e3ce0 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.55 2004-03-31 17:24:30 harekiet Exp $ */ +/* $Id: cpu.cpp,v 1.56 2004-04-22 22:40:45 harekiet Exp $ */ #include #include "dosbox.h" @@ -46,10 +46,6 @@ Bits CPU_CycleUp = 0; Bits CPU_CycleDown = 0; CPU_Decoder * cpudecoder; -static struct { - Bitu which,errorcode; -} exception; - void CPU_Core_Full_Init(void); void CPU_Core_Normal_Init(void); void CPU_Core_Dyn_X86_Init(void); @@ -91,28 +87,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) { cpu.direction=1-((reg_flags & FLAG_DF) >> 9); } -bool CPU_CLI(Bitu opLen) { +static bool CPU_PrepareException(Bitu which,Bitu error) { + cpu.exception.which=which; + cpu.exception.error=error; + return true; +} + +bool CPU_CLI(void) { if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL=8) ? CPU_INT_HAS_ERROR : 0)); -} - -void CPU_SetupException(Bitu which,Bitu error) { - cpu.exception.which=which; - cpu.exception.error=error; +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); + Bitu mask=(0xffff>>(16-size)) << (port&7); + if (map & mask) goto doexception; + } + return false; +doexception: + LOG_MSG("Exception"); + return CPU_PrepareException(13,0); } void CPU_Exception(Bitu which,Bitu error ) { -// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags); - CPU_SetupException(which,error); - CPU_StartException(); + LOG_MSG("Exception %d error %x",which,error); + cpu.exception.error=error; + CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip); } Bit8u lastint; -void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { +void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { lastint=num; #if C_DEBUG switch (num) { @@ -324,10 +348,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { }; #endif if (!cpu.pmode) { - /* Save everything on a 16-bit stack */ + /* Save everything on a 16-bit stack */ CPU_Push16(reg_flags & 0xffff); CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); + CPU_Push16(oldeip); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); /* Get the new CS:IP from vector table */ @@ -345,7 +369,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) { // LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12); if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { - reg_eip-=opLen; CPU_Exception(13,0); return; } @@ -354,7 +377,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { //TODO Check for software interrupt and check gate's dpl=0;i--) CPU_Push32(mem_readd(o_stack+i*4)); CPU_Push32(SegValue(cs)); - CPU_Push32(reg_eip); + CPU_Push32(oldeip); } else { CPU_Push16(o_ss); //save old stack CPU_Push16(o_esp); @@ -746,7 +764,7 @@ call_code: for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) CPU_Push16(mem_readw(o_stack+i*2)); CPU_Push16(SegValue(cs)); - CPU_Push16(reg_eip); + CPU_Push16(oldeip); } cpu.cpl = n_cs_desc.DPL(); @@ -770,7 +788,7 @@ call_gate_same_privilege: if (call.DPL()DESC_DATA_ED_RW_A)) { - CPU_SetupException(0x0D,value & 0xfffc); - return true; + return CPU_PrepareException(0x0D,value & 0xfffc); } } } @@ -1191,6 +1205,14 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) { } } +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=2 << use32; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask); + return false; +} + void CPU_CPUID(void) { switch (reg_eax) { case 0: /* Vendor ID String and maximum level? */ @@ -1221,12 +1243,12 @@ static Bits HLT_Decode(void) { return 0; } -void CPU_HLT(Bitu opLen) { +void CPU_HLT(Bitu oldeip) { if (cpu.cpl) { - reg_eip-=opLen; CPU_Exception(13,0); return; } + reg_eip=oldeip; CPU_Cycles=0; cpu.hlt.cs=SegValue(cs); cpu.hlt.eip=reg_eip; @@ -1235,6 +1257,38 @@ void CPU_HLT(Bitu opLen) { return; } +void CPU_ENTER(bool use32,Bitu bytes,Bitu level) { + level&=0x1f; + Bitu sp_index=reg_esp&cpu.stack.mask; + Bitu bp_index=reg_ebp&cpu.stack.mask; + if (!use32) { + sp_index-=2; + mem_writew(SegPhys(ss)+sp_index,reg_bp); + reg_bp=(Bit16u)(reg_esp-2); + if (level) { + for (Bitu i=1;i(sec); reg_eax=0;