diff --git a/include/cpu.h b/include/cpu.h index 5544f93f..23f1aa5e 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.h,v 1.53 2008-05-18 13:10:42 c2woody Exp $ */ +/* $Id: cpu.h,v 1.54 2008-05-21 21:29:15 c2woody Exp $ */ #ifndef DOSBOX_CPU_H #define DOSBOX_CPU_H @@ -62,6 +62,8 @@ extern Bitu CPU_AutoDetermineMode; extern Bitu CPU_ArchitectureType; +extern Bitu CPU_PrefetchQueueSize; + /* Some common Defines */ /* A CPU Handler */ typedef Bits (CPU_Decoder)(void); @@ -75,6 +77,8 @@ Bits CPU_Core_Dyn_X86_Run(void); Bits CPU_Core_Dyn_X86_Trap_Run(void); Bits CPU_Core_Dynrec_Run(void); Bits CPU_Core_Dynrec_Trap_Run(void); +Bits CPU_Core_Prefetch_Run(void); +Bits CPU_Core_Prefetch_Trap_Run(void); void CPU_Enable_SkipAutoAdjust(void); void CPU_Disable_SkipAutoAdjust(void); diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 0d6c542f..5c63a9a4 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -3,5 +3,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ - paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \ + paging.cpp lazyflags.h core_normal.cpp core_simple.cpp core_prefetch.cpp \ core_dyn_x86.cpp core_dynrec.cpp diff --git a/src/cpu/core_prefetch.cpp b/src/cpu/core_prefetch.cpp new file mode 100644 index 00000000..ebbd3f02 --- /dev/null +++ b/src/cpu/core_prefetch.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2002-2008 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: core_prefetch.cpp,v 1.1 2008-05-21 21:29:32 c2woody Exp $ */ + +#include + +#include "dosbox.h" +#include "mem.h" +#include "cpu.h" +#include "lazyflags.h" +#include "inout.h" +#include "callback.h" +#include "pic.h" +#include "fpu.h" +#include "paging.h" + +#if C_DEBUG +#include "debug.h" +#endif + +#if (!C_CORE_INLINE) +#define LoadMb(off) mem_readb(off) +#define LoadMw(off) mem_readw(off) +#define LoadMd(off) mem_readd(off) +#define SaveMb(off,val) mem_writeb(off,val) +#define SaveMw(off,val) mem_writew(off,val) +#define SaveMd(off,val) mem_writed(off,val) +#else +#include "paging.h" +#define LoadMb(off) mem_readb_inline(off) +#define LoadMw(off) mem_readw_inline(off) +#define LoadMd(off) mem_readd_inline(off) +#define SaveMb(off,val) mem_writeb_inline(off,val) +#define SaveMw(off,val) mem_writew_inline(off,val) +#define SaveMd(off,val) mem_writed_inline(off,val) +#endif + +extern Bitu cycle_count; + +#if C_FPU +#define CPU_FPU 1 //Enable FPU escape instructions +#endif + +#define CPU_PIC_CHECK 1 +#define CPU_TRAP_CHECK 1 + +#define OPCODE_NONE 0x000 +#define OPCODE_0F 0x100 +#define OPCODE_SIZE 0x200 + +#define PREFIX_ADDR 0x1 +#define PREFIX_REP 0x2 + +#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) +#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) + +#define DO_PREFIX_SEG(_SEG) \ + BaseDS=SegBase(_SEG); \ + BaseSS=SegBase(_SEG); \ + core.base_val_ds=_SEG; \ + goto restart_opcode; + +#define DO_PREFIX_ADDR() \ + core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ + (cpu.code.big ^ PREFIX_ADDR); \ + core.ea_table=&EATable[(core.prefixes&1) * 256]; \ + goto restart_opcode; + +#define DO_PREFIX_REP(_ZERO) \ + core.prefixes|=PREFIX_REP; \ + core.rep_zero=_ZERO; \ + goto restart_opcode; + +typedef PhysPt (*GetEAHandler)(void); + +static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff}; + +static struct { + Bitu opcode_index; + PhysPt cseip; + PhysPt base_ds,base_ss; + SegNames base_val_ds; + bool rep_zero; + Bitu prefixes; + GetEAHandler * ea_table; +} core; + +#define GETIP (core.cseip-SegBase(cs)) +#define SAVEIP reg_eip=GETIP; +#define LOADIP core.cseip=(SegBase(cs)+reg_eip); + +#define SegBase(c) SegPhys(c) +#define BaseDS core.base_ds +#define BaseSS core.base_ss + + +#define MAX_PQ_SIZE 32 +static Bit8u prefetch_buffer[MAX_PQ_SIZE]; +static bool pq_valid=false; +static Bitu pq_start; + +static INLINE Bit8u Fetchb() { + Bit8u temp; + if (pq_valid && (core.cseip>=pq_start) && (core.cseip=pq_start+CPU_PrefetchQueueSize-4) && + (core.cseip+1=pq_start) && (core.cseip+2=pq_start+CPU_PrefetchQueueSize-4) && + (core.cseip+2=pq_start) && (core.cseip+4=pq_start+CPU_PrefetchQueueSize-4) && + (core.cseip+40) { + if (invalidate_pq) { + pq_valid=false; + invalidate_pq=false; + } + LOADIP; + core.opcode_index=cpu.code.big*0x200; + core.prefixes=cpu.code.big; + core.ea_table=&EATable[cpu.code.big*256]; + BaseDS=SegBase(ds); + BaseSS=SegBase(ss); + core.base_val_ds=ds; +#if C_DEBUG +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) { + FillFlags(); + return debugCallback; + }; +#endif + cycle_count++; +#endif +restart_opcode: + Bit8u next_opcode=Fetchb(); + invalidate_pq=false; + if (core.opcode_index&OPCODE_0F) invalidate_pq=true; + else switch (next_opcode) { + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: // jcc + case 0x9a: // call + case 0xc2: case 0xc3: // retn + case 0xc8: // enter + case 0xc9: // leave + case 0xca: case 0xcb: // retf + case 0xcc: // int3 + case 0xcd: // int + case 0xce: // into + case 0xcf: // iret + case 0xe0: // loopnz + case 0xe1: // loopz + case 0xe2: // loop + case 0xe3: // jcxz + case 0xe8: // call + case 0xe9: case 0xea: case 0xeb: // jmp + case 0xff: + invalidate_pq=true; + break; + default: + break; + } + switch (core.opcode_index+next_opcode) { + #include "core_normal/prefix_none.h" + #include "core_normal/prefix_0f.h" + #include "core_normal/prefix_66.h" + #include "core_normal/prefix_66_0f.h" + default: + illegal_opcode: +#if C_DEBUG + { + 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.cseip++)); + writecode+=2; + } + LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); + } +#endif + CPU_Exception(6,0); + invalidate_pq=true; + continue; + } + SAVEIP; + } + FillFlags(); + return CBRET_NONE; +decode_end: + SAVEIP; + FillFlags(); + return CBRET_NONE; +} + +Bits CPU_Core_Prefetch_Trap_Run(void) { + Bits oldCycles = CPU_Cycles; + CPU_Cycles = 1; + cpu.trap_skip = false; + + Bits ret=CPU_Core_Prefetch_Run(); + if (!cpu.trap_skip) CPU_HW_Interrupt(1); + CPU_Cycles = oldCycles-1; + cpudecoder = &CPU_Core_Prefetch_Run; + + return ret; +} + + + +void CPU_Core_Prefetch_Init(void) { + +} + diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index e5c8991a..0ed6800f 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.111 2008-05-18 13:11:14 c2woody Exp $ */ +/* $Id: cpu.cpp,v 1.112 2008-05-21 21:29:32 c2woody Exp $ */ #include #include @@ -65,6 +65,8 @@ Bitu CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; Bitu CPU_flag_id_toggle=0; +Bitu CPU_PrefetchQueueSize=0; + void CPU_Core_Full_Init(void); void CPU_Core_Normal_Init(void); void CPU_Core_Simple_Init(void); @@ -2313,10 +2315,34 @@ public: CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; } else if (cputype == "386") { CPU_ArchitectureType = CPU_ARCHTYPE_386FAST; + } else if (cputype == "386_prefetch") { + CPU_ArchitectureType = CPU_ARCHTYPE_386FAST; + if (core == "normal") { + cpudecoder=&CPU_Core_Prefetch_Run; + CPU_PrefetchQueueSize = 16; + } else if (core == "auto") { + cpudecoder=&CPU_Core_Prefetch_Run; + CPU_PrefetchQueueSize = 16; + CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE); + } else { + E_Exit("prefetch queue emulation requires the normal core setting."); + } } else if (cputype == "386_slow") { CPU_ArchitectureType = CPU_ARCHTYPE_386SLOW; } else if (cputype == "486_slow") { CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW; + } else if (cputype == "486_prefetch") { + CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW; + if (core == "normal") { + cpudecoder=&CPU_Core_Prefetch_Run; + CPU_PrefetchQueueSize = 32; + } else if (core == "auto") { + cpudecoder=&CPU_Core_Prefetch_Run; + CPU_PrefetchQueueSize = 32; + CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE); + } else { + E_Exit("prefetch queue emulation requires the normal core setting."); + } } else if (cputype == "pentium_slow") { CPU_ArchitectureType = CPU_ARCHTYPE_PENTIUMSLOW; } diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 81975831..57a68c6f 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dosbox.cpp,v 1.136 2008-05-18 13:10:42 c2woody Exp $ */ +/* $Id: dosbox.cpp,v 1.137 2008-05-21 21:29:16 c2woody Exp $ */ #include #include @@ -393,7 +393,7 @@ void DOSBOX_Init(void) { Pstring->Set_values(cores); Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and appropriate."); - const char* cputype_values[] = { "auto", "386", "386_slow", "486_slow", "pentium_slow", 0}; + const char* cputype_values[] = { "auto", "386", "386_slow", "486_slow", "pentium_slow", "386_prefetch", 0}; Pstring = secprop->Add_string("cputype",Property::Changeable::Always,"auto"); Pstring->Set_values(cputype_values); Pstring->Set_help("CPU Type used in emulation. auto is the fastest choice."); diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj index f2257ce0..0e7a1f22 100644 --- a/visualc_net/dosbox.vcproj +++ b/visualc_net/dosbox.vcproj @@ -179,6 +179,9 @@ + +