diff --git a/src/cpu/core_16/main.h b/src/cpu/core_16/main.h index fc03e3d5..4926826e 100644 --- a/src/cpu/core_16/main.h +++ b/src/cpu/core_16/main.h @@ -293,7 +293,16 @@ restart: #include "prefix_66.h" break; case 0x67: /* Address Size Prefix */ +#ifdef CPU_PREFIX_67 + prefix.mark|=PREFIX_ADDR; +#ifdef CPU_PREFIX_COUNT + prefix.count++; +#endif + lookupEATable=EAPrefixTable[prefix.mark]; + goto restart; +#else NOTDONE; +#endif break; #endif case 0x68: /* PUSH Iw */ @@ -657,26 +666,22 @@ restart: } case 0xa0: /* MOV AL,Ob */ { - GetEADirect; - reg_al=LoadMb(eaa); + reg_al=LoadMb(GetEADirect[prefix.mark]()); } break; case 0xa1: /* MOV AX,Ow */ { - GetEADirect; - reg_ax=LoadMw(eaa); + reg_ax=LoadMw(GetEADirect[prefix.mark]()); } break; case 0xa2: /* MOV Ob,AL */ { - GetEADirect; - SaveMb(eaa,reg_al); + SaveMb(GetEADirect[prefix.mark](),reg_al); } break; case 0xa3: /* MOV Ow,AX */ { - GetEADirect; - SaveMw(eaa,reg_ax); + SaveMw(GetEADirect[prefix.mark](),reg_ax); } break; case 0xa4: /* MOVSB */ @@ -956,6 +961,7 @@ restart: case 0xde: /* FPU ESC 6 */ case 0xdf: /* FPU ESC 7 */ { + LOG_WARN("FPU used"); Bit8u rm=Fetchb(); if (rm<0xc0) GetEAa; } @@ -974,9 +980,15 @@ restart: else ADDIPFAST(1); break; case 0xe3: /* JCXZ */ - if (!reg_cx) ADDIPFAST(Fetchbs()); - else ADDIPFAST(1); - break; + { + Bitu test; + if (prefix.mark & PREFIX_ADDR) { + test=reg_ecx;PrefixReset; + } else test=reg_cx; + if (!test) ADDIPFAST(Fetchbs()); + else ADDIPFAST(1); + break; + } case 0xe4: /* IN AL,Ib */ { Bit16u port=Fetchb();reg_al=IO_Read(port);} break; diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h index 0379490f..340be2db 100644 --- a/src/cpu/core_16/prefix_66.h +++ b/src/cpu/core_16/prefix_66.h @@ -149,12 +149,23 @@ switch(Fetchb()) { reg_edi=Pop_32();reg_edi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); break; - case 0x68: /* PUSH Id */ - Push_32(Fetchd());break; case 0x64: /* SEG FS: */ SegPrefix_66(fs);break; case 0x65: /* SEG GS: */ SegPrefix_66(gs);break; + case 0x67: /* Address Size Prefix */ +#ifdef CPU_PREFIX_67 + prefix.mark|=PREFIX_ADDR; +#ifdef CPU_PREFIX_COUNT + prefix.count++; +#endif + lookupEATable=EAPrefixTable[prefix.mark]; + goto restart_66; +#else + NOTDONE; +#endif + case 0x68: /* PUSH Id */ + Push_32(Fetchd());break; case 0x69: /* IMUL Gd,Ed,Id */ { GetRMrd; @@ -267,6 +278,15 @@ switch(Fetchb()) { case 0x8c: LOG_WARN("CPU:66:8c looped back"); break; + case 0x8d: /* LEA */ + { + prefix.segbase=0; + prefix.mark|=PREFIX_SEG; + lookupEATable=EAPrefixTable[prefix.mark]; + GetRMrd;GetEAa; + *rmrd=(Bit32u)eaa; + break; + } case 0x8f: /* POP Ed */ { GetRM; @@ -321,14 +341,12 @@ switch(Fetchb()) { } case 0xa1: /* MOV EAX,Ow */ { - GetEADirect; - reg_eax=LoadMd(eaa); + reg_eax=LoadMd(GetEADirect[prefix.mark]()); } break; case 0xa3: /* MOV Ow,EAX */ { - GetEADirect; - SaveMd(eaa,reg_eax); + SaveMd(GetEADirect[prefix.mark](),reg_eax); } break; case 0xa5: /* MOVSD */ @@ -383,6 +401,18 @@ switch(Fetchb()) { reg_edi=Fetchd();break; case 0xc1: /* GRP2 Ed,Ib */ GRP2D(Fetchb());break; + case 0xc4: /* LES */ + { + GetRMrd;GetEAa; + *rmrd=LoadMd(eaa);SegSet16(es,LoadMw(eaa+4)); + break; + } + case 0xc5: /* LDS */ + { + GetRMrd;GetEAa; + *rmrd=LoadMd(eaa);SegSet16(ds,LoadMw(eaa+4)); + break; + } case 0xc7: /* MOV Ed,Id */ { GetRM; diff --git a/src/cpu/core_16/prefix_66_of.h b/src/cpu/core_16/prefix_66_of.h index c7b0f81f..fa972dca 100644 --- a/src/cpu/core_16/prefix_66_of.h +++ b/src/cpu/core_16/prefix_66_of.h @@ -33,6 +33,14 @@ switch (Fetchb()) { else {GetEAa;DSHRD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);} break; } + case 0xad: /* SHRD Ed,Gd,Cl */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,reg_cl,LoadRd,SaveRd);} + else {GetEAa;DSHRD(eaa,*rmrd,reg_cl,LoadMd,SaveMd);} + break; + } + case 0xb6: /* MOVZX Gd,Eb */ { GetRMrd; @@ -44,8 +52,8 @@ switch (Fetchb()) { { GetRMrd; Bit64s res; - if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*rmrd) * (Bit64s)(*eards);} - else {GetEAa;res=(Bit64s)(*rmrd) * (Bit64s)LoadMds(eaa);} + if (rm >= 0xc0 ) {GetEArd;res=((Bit64s)((Bit32s)*rmrd) * (Bit64s)((Bit32s)*eards));} + else {GetEAa;res=((Bit64s)((Bit32s)*rmrd) * (Bit64s)LoadMds(eaa));} *rmrd=(Bit32s)(res); flags.type=t_MUL; if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} @@ -108,6 +116,56 @@ switch (Fetchb()) { flags.type=t_CF; break; } + case 0xbb: /* BTC Ed,Gd */ + { + GetRMrd; + Bit32u mask=1 << (*rmrd & 31); + if (rm >= 0xc0 ) { + GetEArd; + flags.cf=(*eard & mask)>0; + *eard^=mask; + } else { + GetEAa;Bit32u old=LoadMd(eaa); + flags.cf=(old & mask)>0; + SaveMd(eaa,old ^ mask); + } + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } + break; + } + case 0xbc: /* BSF Gd,Ed */ + { + GetRMrd; + Bit32u result,value; + if (rm >= 0xc0) { GetEArd; value=*eard; } + else { GetEAa; value=LoadMd(eaa); } + if (value==0) { + flags.zf = true; + } else { + result = 0; + while ((value & 0x01)==0) { result++; value>>=1; } + flags.zf = false; + *rmrd = result; + } + flags.type=t_UNKNOWN; + break; + } + case 0xbd: /* BSR Gd,Ed */ + { + GetRMrd; + Bit32u result,value; + if (rm >= 0xc0) { GetEArd; value=*eard; } + else { GetEAa; value=LoadMd(eaa); } + if (value==0) { + flags.zf = true; + } else { + result = 35; // Operandsize-1 + while ((value & 0x80000000)==0) { result--; value<<=1; } + flags.zf = false; + *rmrd = result; + } + flags.type=t_UNKNOWN; + break; + } case 0xbe: /* MOVSX Gd,Eb */ { GetRMrd; diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h index dc99459c..ebac6f2a 100644 --- a/src/cpu/core_16/prefix_of.h +++ b/src/cpu/core_16/prefix_of.h @@ -59,6 +59,12 @@ switch(Fetchb()) { /* 0x21 MOV Rd,DRx (386) */ /* 0x22 MOV CRx,Rd (386) */ /* 0x23 MOV DRx,Rd (386) */ + case 0x23: /* MOV DRx,Rd */ + { + GetRM; + LOG_DEBUG("CPU:0F:23 does nothing"); + } + break; /* 0x24 MOV Rd,TRx (386) */ /* 0x26 MOV TRx,Rd (386) */ /* 0x30 WRMSR (P5) */ @@ -394,7 +400,6 @@ switch(Fetchb()) { flags.type=t_UNKNOWN; break; } - /* 0xbd BSR Gw,Ew */ case 0xbe: /* MOVSX Gw,Eb */ { GetRMrw; diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h index 4468693f..5f540a0a 100644 --- a/src/cpu/core_16/support.h +++ b/src/cpu/core_16/support.h @@ -95,13 +95,17 @@ static INLINE Bit32u Pop_32() { from=SegBase(ds)+reg_si; \ } - #include "helpers.h" #include "table_ea.h" #include "../modrm.h" #include "instructions.h" +static Bit8s table_df_8[2]={1,-1}; +static Bit16s table_df_16[2]={2,-2}; +static Bit32s table_df_32[2]={4,-4}; + + static void Repeat_Normal(bool testz,bool prefix_66) { PhysPt base_si,base_di; @@ -110,6 +114,7 @@ static void Repeat_Normal(bool testz,bool prefix_66) { if (flags.df) direct=-1; else direct=1; base_di=SegBase(es); + if (prefix.mark & PREFIX_ADDR) E_Exit("Unhandled 0x67 prefixed string op"); rep_again: if (prefix.mark & PREFIX_SEG) { base_si=(prefix.segbase); @@ -137,6 +142,16 @@ rep_again: prefix.mark|=PREFIX_SEG; prefix.count++; goto rep_again; + case 0x64: /* FS Prefix */ + prefix.segbase=SegBase(fs); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; + case 0x65: /* GS Prefix */ + prefix.segbase=SegBase(gs); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; case 0x66: /* Size Prefix */ prefix.count++; prefix_66=!prefix_66; diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h index e5aef7e7..d702fe1a 100644 --- a/src/cpu/core_16/table_ea.h +++ b/src/cpu/core_16/table_ea.h @@ -19,6 +19,8 @@ /* Some variables for EA Loolkup */ typedef EAPoint (*GetEATable[256])(void); +typedef EAPoint (*EA_LookupHandler)(void); + static GetEATable * lookupEATable; #define PREFIX_NONE 0x0 @@ -35,6 +37,7 @@ static struct { /* Gets initialized at the bottem, can't seem to declare forward references */ static GetEATable * EAPrefixTable[4]; + #define SegPrefix(blah) \ prefix.segbase=SegBase(blah); \ prefix.mark|=PREFIX_SEG; \ @@ -55,29 +58,6 @@ static GetEATable * EAPrefixTable[4]; prefix.count=0; \ lookupEATable=EAPrefixTable[PREFIX_NONE]; -#if 1 - -#define GetEADirect \ -EAPoint eaa;switch (prefix.mark) { \ -case PREFIX_NONE:eaa=SegBase(ds)+Fetchw();break; \ -case PREFIX_SEG:eaa=prefix.segbase+Fetchw();PrefixReset;break; \ -case PREFIX_ADDR:eaa=SegBase(ds)+Fetchd();PrefixReset;break; \ -case PREFIX_SEG_ADDR:eaa=prefix.segbase+Fetchd();PrefixReset;break; \ -} - -#else - -#define GetEADirect \ -EAPoint eaa; \ -if (!prefix.mark) { eaa=SegBase(ds)+Fetchw();} \ -else if (prefix.mark == PREFIX_SEG) { eaa=prefix.segbase+Fetchw();PrefixReset;} \ -else if (prefix.mark == PREFIX_ADDR) { eaa=SegBase(ds)+Fetchd();PrefixReset;} \ -else if (prefix.mark == PREFIX_SEG_ADDR) { eaa=prefix.segbase+Fetchd();PrefixReset;} - -#endif - - - /* The MOD/RM Decoder for EA for this decoder's addressing modes */ static EAPoint EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } @@ -240,32 +220,32 @@ INLINE EAPoint Sib(Bitu mode) { }; -static EAPoint EA_32_00_n(void) { return SegBase(ds)+reg_eax; } -static EAPoint EA_32_01_n(void) { return SegBase(ds)+reg_ecx; } -static EAPoint EA_32_02_n(void) { return SegBase(ds)+reg_edx; } -static EAPoint EA_32_03_n(void) { return SegBase(ds)+reg_ebx; } -static EAPoint EA_32_04_n(void) { return Sib(0);} -static EAPoint EA_32_05_n(void) { return SegBase(ds)+Fetchd(); } -static EAPoint EA_32_06_n(void) { return SegBase(ds)+reg_esi; } -static EAPoint EA_32_07_n(void) { return SegBase(ds)+reg_edi; } +static EAPoint EA_32_00_n(void) { PrefixReset;return SegBase(ds)+reg_eax; } +static EAPoint EA_32_01_n(void) { PrefixReset;return SegBase(ds)+reg_ecx; } +static EAPoint EA_32_02_n(void) { PrefixReset;return SegBase(ds)+reg_edx; } +static EAPoint EA_32_03_n(void) { PrefixReset;return SegBase(ds)+reg_ebx; } +static EAPoint EA_32_04_n(void) { PrefixReset;return Sib(0);} +static EAPoint EA_32_05_n(void) { PrefixReset;return SegBase(ds)+Fetchd(); } +static EAPoint EA_32_06_n(void) { PrefixReset;return SegBase(ds)+reg_esi; } +static EAPoint EA_32_07_n(void) { PrefixReset;return SegBase(ds)+reg_edi; } -static EAPoint EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); } -static EAPoint EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); } -static EAPoint EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); } -static EAPoint EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); } -static EAPoint EA_32_44_n(void) { return Sib(1)+Fetchbs();} -static EAPoint EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); } -static EAPoint EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); } -static EAPoint EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); } +static EAPoint EA_32_40_n(void) { PrefixReset;return SegBase(ds)+reg_eax+Fetchbs(); } +static EAPoint EA_32_41_n(void) { PrefixReset;return SegBase(ds)+reg_ecx+Fetchbs(); } +static EAPoint EA_32_42_n(void) { PrefixReset;return SegBase(ds)+reg_edx+Fetchbs(); } +static EAPoint EA_32_43_n(void) { PrefixReset;return SegBase(ds)+reg_ebx+Fetchbs(); } +static EAPoint EA_32_44_n(void) { PrefixReset;return Sib(1)+Fetchbs();} +static EAPoint EA_32_45_n(void) { PrefixReset;return SegBase(ss)+reg_ebp+Fetchbs(); } +static EAPoint EA_32_46_n(void) { PrefixReset;return SegBase(ds)+reg_esi+Fetchbs(); } +static EAPoint EA_32_47_n(void) { PrefixReset;return SegBase(ds)+reg_edi+Fetchbs(); } -static EAPoint EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); } -static EAPoint EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); } -static EAPoint EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); } -static EAPoint EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); } -static EAPoint EA_32_84_n(void) { return Sib(2)+Fetchds();} -static EAPoint EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); } -static EAPoint EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); } -static EAPoint EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); } +static EAPoint EA_32_80_n(void) { PrefixReset;return SegBase(ds)+reg_eax+Fetchds(); } +static EAPoint EA_32_81_n(void) { PrefixReset;return SegBase(ds)+reg_ecx+Fetchds(); } +static EAPoint EA_32_82_n(void) { PrefixReset;return SegBase(ds)+reg_edx+Fetchds(); } +static EAPoint EA_32_83_n(void) { PrefixReset;return SegBase(ds)+reg_ebx+Fetchds(); } +static EAPoint EA_32_84_n(void) { PrefixReset;return Sib(2)+Fetchds();} +static EAPoint EA_32_85_n(void) { PrefixReset;return SegBase(ss)+reg_ebp+Fetchds(); } +static EAPoint EA_32_86_n(void) { PrefixReset;return SegBase(ds)+reg_esi+Fetchds(); } +static EAPoint EA_32_87_n(void) { PrefixReset;return SegBase(ds)+reg_edi+Fetchds(); } static GetEATable GetEA_32_n={ /* 00 */ @@ -327,7 +307,8 @@ INLINE EAPoint Sib_s(Bitu mode) { case 7: /* EDI Base */ base=prefix.segbase+reg_edi;break; } - base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); PrefixReset; + base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); + PrefixReset; return base; }; @@ -396,4 +377,21 @@ static GetEATable GetEA_32_s={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static EAPoint GetEADirect_NONE(void) { + EAPoint result=SegBase(ds)+Fetchw(); + return result; +} +static EAPoint GetEADirect_SEG(void) { + EAPoint result=prefix.segbase+Fetchw();PrefixReset; + return result; +} +static EAPoint GetEADirect_ADDR(void) { + EAPoint result=SegBase(ds)+Fetchd();PrefixReset; + return result; +} +static EAPoint GetEADirect_SEG_ADDR(void) { + EAPoint result=prefix.segbase+Fetchd();PrefixReset; + return result; +} +static EA_LookupHandler GetEADirect[4]={GetEADirect_NONE,GetEADirect_SEG,GetEADirect_ADDR,GetEADirect_SEG_ADDR}; diff --git a/src/cpu/slow_16.cpp b/src/cpu/slow_16.cpp index 5f997f98..40146a3b 100644 --- a/src/cpu/slow_16.cpp +++ b/src/cpu/slow_16.cpp @@ -55,10 +55,14 @@ extern Bitu cycle_count; /* Enable parts of the cpu emulation */ #define CPU_386 //Enable 386 instructions +#define CPU_PREFIX_67 //Enable the 0x67 prefix +#define CPU_PREFIX_COUNT //Enable counting of prefixes + #if C_FPU #define CPU_FPU //Enable FPU escape instructions #endif + #include "core_16/support.h" static Bitu CPU_Real_16_Slow_Decode_Trap(void); @@ -73,7 +77,11 @@ static Bitu CPU_Real_16_Slow_Decode(void) { if (DEBUG_HeavyIsBreakpoint()) return 1; #endif #include "core_16/main.h" -// if (prefix.count) LOG_DEBUG("Prefix for non prefixed instruction"); + if (prefix.count) { + PrefixReset; + //DEBUG_HeavyWriteLogInstruction(); + LOG_DEBUG("Prefix for non prefixed instruction"); + } CPU_Cycles--; } #include "core_16/stop.h"