From 15033b27a4926212305e00513bc98c5d18d55074 Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Fri, 25 Oct 2002 21:25:35 +0000 Subject: [PATCH] New prefix variables and a new string repeat function. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@427 --- src/cpu/core_16/support.h | 317 +++++++++++++++++++++++++++++++++----- 1 file changed, 276 insertions(+), 41 deletions(-) diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h index 095f585a..ace3a10f 100644 --- a/src/cpu/core_16/support.h +++ b/src/cpu/core_16/support.h @@ -88,8 +88,8 @@ static INLINE Bit32u Pop_32() { #define stringSI \ EAPoint from; \ - if (prefixes & PREFIX_SEG) { \ - from=(segprefix_base+reg_si); \ + if (prefix.mark & PREFIX_SEG) { \ + from=(prefix.segbase+reg_si); \ PrefixReset; \ } else { \ from=SegBase(ds)+reg_si; \ @@ -102,48 +102,265 @@ static INLINE Bit32u Pop_32() { #include "instructions.h" -static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) { - bool again; - do { - again=false; - Bit8u repcode=Fetchb(); - switch (repcode) { - case 0x26: /* ES Prefix */ - again=true; - from=SegBase(es); - break; - case 0x2e: /* CS Prefix */ - again=true; - from=SegBase(cs); - break; - case 0x36: /* SS Prefix */ - again=true; - from=SegBase(ss); - break; - case 0x3e: /* DS Prefix */ - again=true; - from=SegBase(ds); - break; - case 0xa5: /* REP MOVSD */ - for (;reg_cx>0;reg_cx--) { - SaveMd(to+reg_di,LoadMd(from+reg_si)); - reg_di+=direct*4; - reg_si+=direct*4; - } - break; - case 0xab: /* REP STOSW */ - for (;reg_cx>0;reg_cx--) { - SaveMd(to+reg_di,reg_eax); - reg_di+=direct*4; - } - break; - default: - E_Exit("CPU:Opcode 66:Illegal REP prefix %2X",repcode); +static Bits Repeat_Normal(bool testz,bool prefix_66,Bits count_remain) { + + Bits count=count_remain; + PhysPt base_si,base_di; + + Bit16s direct; + if (flags.df) direct=-1; + else direct=1; + base_di=SegBase(es); +rep_again: + if (prefix.mark & PREFIX_SEG) { + base_si=(prefix.segbase); + } else { + base_si=SegBase(ds); + } + switch (Fetchb()) { + case 0x26: /* ES Prefix */ + prefix.segbase=SegBase(es); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; + case 0x2e: /* CS Prefix */ + prefix.segbase=SegBase(cs); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; + case 0x36: /* SS Prefix */ + prefix.segbase=SegBase(ss); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; + case 0x3e: /* DS Prefix */ + prefix.segbase=SegBase(ds); + prefix.mark|=PREFIX_SEG; + prefix.count++; + goto rep_again; + case 0x66: /* Size Prefix */ + prefix.count++; + prefix_66=!prefix_66; + goto rep_again; + case 0x6c: /* REP INSB */ + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMb(base_di+reg_di,IO_Read(reg_dx)); + reg_di+=direct; } - } while (again); + if (reg_cx && count<=0) goto countzero; + break; + case 0x6d: /* REP INSW/D */ + if (prefix_66) { + direct*=4; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0)); + SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1)); + SaveMb(base_di+reg_di+2,IO_Read(reg_dx+2)); + SaveMb(base_di+reg_di+3,IO_Read(reg_dx+3)); + reg_di+=direct; + } + } else { + direct*=2; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0)); + SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1)); + reg_di+=direct; + } + } + if (reg_cx && count<=0) goto countzero; + break; + case 0x6e: /* REP OUTSB */ + for (;(reg_cx && count>0);reg_cx--,count--) { + IO_Write(reg_dx,LoadMb(base_si+reg_si)); + reg_si+=direct; + } + if (reg_cx && count<=0) goto countzero; + break; + case 0x6f: /* REP OUTSW/D */ + if (prefix_66) { + direct*=4; + for (;(reg_cx && count>0);reg_cx--,count--) { + IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0)); + IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1)); + IO_Write(reg_dx+2,LoadMb(base_si+reg_si+2)); + IO_Write(reg_dx+3,LoadMb(base_si+reg_si+3)); + reg_si+=direct; + } + } else { + direct*=2; + for (;(reg_cx && count>0);reg_cx--,count--) { + IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0)); + IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1)); + reg_si+=direct; + } + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xa4: /* REP MOVSB */ + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMb(base_di+reg_di,LoadMb(base_si+reg_si)); + reg_si+=direct;reg_di+=direct; + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xa5: /* REP MOVSW/D */ + if (prefix_66) { + direct*=4; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMd(base_di+reg_di,LoadMd(base_si+reg_si)); + reg_si+=direct;reg_di+=direct; + } + } else { + direct*=2; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMw(base_di+reg_di,LoadMw(base_si+reg_si)); + reg_si+=direct;reg_di+=direct; + } + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xa6: /* REP CMPSB */ + { + if (!reg_cx) goto stopit;Bit8u op1,op2; + for (;(reg_cx && count>0);) { + op1=LoadMb(base_si+reg_si);op2=LoadMb(base_di+reg_di); + reg_cx--,count--;reg_si+=direct;reg_di+=direct; + if ((op1==op2)!=testz) break; + } + CMPB(op1,op2,LoadRb,0); + if ((op1==op2)!=testz) goto stopit; + if (reg_cx && count<=0) goto countzero; + } + break; + case 0xa7: /* REP CMPSW */ + { + if (!reg_cx) goto stopit; + if (prefix_66) { + direct*=4; + Bit32u op1,op2; + for (;(reg_cx && count>0);) { + op1=LoadMd(base_si+reg_si);op2=LoadMd(base_di+reg_di); + reg_cx--,count--;reg_si+=direct;reg_di+=direct; + if ((op1==op2)!=testz) break; + } + CMPD(op1,op2,LoadRd,0); + if ((op1==op2)!=testz) goto stopit; + } else { + direct*=2; + Bit16u op1,op2; + for (;(reg_cx && count>0);) { + op1=LoadMw(base_si+reg_si);op2=LoadMw(base_di+reg_di); + reg_cx--,count--;reg_si+=direct;reg_di+=direct; + if ((op1==op2)!=testz) break; + } + CMPW(op1,op2,LoadRw,0); + if ((op1==op2)!=testz) goto stopit; + } + if (reg_cx && count<=0) goto countzero; + } + break; + case 0xaa: /* REP STOSB */ + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMb(base_di+reg_di,reg_al); + reg_di+=direct; + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xab: /* REP STOSW */ + if (prefix_66) { + direct*=4; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMd(base_di+reg_di,reg_eax); + reg_di+=direct; + } + } else { + direct*=2; + for (;(reg_cx && count>0);reg_cx--,count--) { + SaveMw(base_di+reg_di,reg_ax); + reg_di+=direct; + } + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xac: /* REP LODSB */ + for (;(reg_cx && count>0);reg_cx--,count--) { + reg_al=LoadMb(base_si+reg_si); + reg_si+=direct; + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xad: /* REP LODSW */ + if (prefix_66) { + direct*=4; + for (;(reg_cx && count>0);reg_cx--,count--) { + reg_eax=LoadMd(base_si+reg_si); + reg_si+=direct; + } + } else { + direct*=2; + for (;(reg_cx && count>0);reg_cx--,count--) { + reg_ax=LoadMw(base_si+reg_si); + reg_si+=direct; + } + } + if (reg_cx && count<=0) goto countzero; + break; + case 0xae: /* REP SCASB */ + { + if (!reg_cx) goto stopit;Bit8u op2; + for (;(reg_cx && count>0);) { + op2=LoadMb(base_di+reg_di); + reg_cx--,count--;reg_di+=direct; + if ((reg_al==op2)!=testz) break; + } + CMPB(reg_al,op2,LoadRb,0); + if ((reg_al==op2)!=testz) goto stopit; + if (reg_cx && count<=0) goto countzero; + } + break; + case 0xaf: /* REP SCASW */ + { + if (!reg_cx) goto stopit; + if (prefix_66) { + direct*=4; + Bit32u op2; + for (;(reg_cx && count>0);) { + op2=LoadMd(base_di+reg_di); + reg_cx--,count--;reg_di+=direct; + if ((reg_eax==op2)!=testz) break; + } + CMPD(reg_eax,op2,LoadRd,0); + if ((reg_eax==op2)!=testz) goto stopit; + } else { + direct*=2; + Bit16u op2; + for (;(reg_cx && count>0);) { + op2=LoadMw(base_di+reg_di); + reg_cx--,count--;reg_di+=direct; + if ((reg_ax==op2)!=testz) break; + } + CMPW(reg_ax,op2,LoadRw,0); + if ((reg_ax==op2)!=testz) goto stopit; + } + if (reg_cx && count<=0) goto countzero; + } + break; + default: + IPPoint--; + LOG_DEBUG("Unhandled REP Prefix %X",Fetchb()); + + } +stopit: + PrefixReset; + return count_remain-count; +countzero: + IPPoint-=(prefix.count+2); /* Rep instruction and whatever string instruction */ + PrefixReset; + return count_remain; } //flags.io and nt shouldn't be compiled for 386 +#ifdef CPU_386 #define Save_Flagsw(FLAGW) \ { \ flags.type=t_UNKNOWN; \ @@ -159,7 +376,25 @@ static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) { PIC_runIRQs(); \ LOADIP; \ } \ - if (flags.tf) E_Exit("CPU:Trap Flag not supported"); \ + if (flags.tf) LOG_DEBUG("CPU:Trap Flag not supported"); \ } +#else +#define Save_Flagsw(FLAGW) \ +{ \ + flags.type=t_UNKNOWN; \ + flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \ + flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \ + flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \ + flags.intf =(FLAGW & 0x200)>0; \ + flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \ + if (flags.intf && PIC_IRQCheck) { \ + SAVEIP; \ + PIC_runIRQs(); \ + LOADIP; \ + } \ + if (flags.tf) LOG_DEBUG("CPU:Trap Flag not supported"); \ +} + +#endif