DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 00022 #include "dosbox.h" 00023 #include "mem.h" 00024 #include "cpu.h" 00025 #include "lazyflags.h" 00026 #include "inout.h" 00027 #include "callback.h" 00028 #include "pic.h" 00029 #include "fpu.h" 00030 #include "mmx.h" 00031 00032 #define CPU_CORE CPU_ARCHTYPE_386 00033 00034 extern bool ignore_opcode_63; 00035 00036 #if C_DEBUG 00037 #include "debug.h" 00038 #endif 00039 00040 #include "paging.h" 00041 #define SegBase(c) SegPhys(c) 00042 #define LoadMb(off) mem_readb(off) 00043 #define LoadMw(off) mem_readw(off) 00044 #define LoadMd(off) mem_readd(off) 00045 #define LoadMq(off) ((Bit64u)((Bit64u)mem_readd(off+4)<<32 | (Bit64u)mem_readd(off))) 00046 00047 #define SaveMb(off,val) mem_writeb(off,val) 00048 #define SaveMw(off,val) mem_writew(off,val) 00049 #define SaveMd(off,val) mem_writed(off,val) 00050 #define SaveMq(off,val) {mem_writed(off,val&0xffffffff);mem_writed(off+4,(val>>32)&0xffffffff);} 00051 00052 extern Bitu cycle_count; 00053 00054 #if C_FPU 00055 #define CPU_FPU 1u //Enable FPU escape instructions 00056 #endif 00057 00058 #define CPU_PIC_CHECK 1u 00059 #define CPU_TRAP_CHECK 1u 00060 00061 #define CPU_TRAP_DECODER CPU_Core_Simple_Trap_Run 00062 00063 #define OPCODE_NONE 0x000u 00064 #define OPCODE_0F 0x100u 00065 #define OPCODE_SIZE 0x200u 00066 00067 #define PREFIX_ADDR 0x1u 00068 #define PREFIX_REP 0x2u 00069 00070 #define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) 00071 #define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) 00072 00073 #define DO_PREFIX_SEG(_SEG) \ 00074 BaseDS=SegBase(_SEG); \ 00075 BaseSS=SegBase(_SEG); \ 00076 core.base_val_ds=_SEG; \ 00077 goto restart_opcode; 00078 00079 #define DO_PREFIX_ADDR() \ 00080 core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ 00081 (cpu.code.big ^ PREFIX_ADDR); \ 00082 core.ea_table=&EATable[(core.prefixes&1u) * 256u]; \ 00083 goto restart_opcode; 00084 00085 #define DO_PREFIX_REP(_ZERO) \ 00086 core.prefixes|=PREFIX_REP; \ 00087 core.rep_zero=_ZERO; \ 00088 goto restart_opcode; 00089 00090 typedef PhysPt (*GetEAHandler)(void); 00091 00092 static const Bit32u AddrMaskTable[2]={0x0000ffffu,0xffffffffu}; 00093 00094 static struct { 00095 Bitu opcode_index; 00096 #if defined (_MSC_VER) 00097 volatile HostPt cseip; 00098 #else 00099 HostPt cseip; 00100 #endif 00101 PhysPt base_ds,base_ss; 00102 SegNames base_val_ds; 00103 bool rep_zero; 00104 Bitu prefixes; 00105 GetEAHandler* ea_table; 00106 } core; 00107 00108 #define GETIP ((Bit32u) ((uintptr_t)core.cseip - (uintptr_t)SegBase(cs) - (uintptr_t)MemBase)) 00109 #define SAVEIP reg_eip=GETIP; 00110 #define LOADIP core.cseip=((HostPt) ((uintptr_t)MemBase + (uintptr_t)SegBase(cs) + (uintptr_t)reg_eip)); 00111 00112 #define SegBase(c) SegPhys(c) 00113 #define BaseDS core.base_ds 00114 #define BaseSS core.base_ss 00115 00116 static INLINE void FetchDiscardb() { 00117 core.cseip+=1; 00118 } 00119 00120 static INLINE Bit8u FetchPeekb() { 00121 Bit8u temp=host_readb(core.cseip); 00122 return temp; 00123 } 00124 00125 static INLINE Bit8u Fetchb() { 00126 Bit8u temp=host_readb(core.cseip); 00127 core.cseip+=1; 00128 return temp; 00129 } 00130 00131 static INLINE Bit16u Fetchw() { 00132 Bit16u temp=host_readw(core.cseip); 00133 core.cseip+=2; 00134 return temp; 00135 } 00136 static INLINE Bit32u Fetchd() { 00137 Bit32u temp=host_readd(core.cseip); 00138 core.cseip+=4; 00139 return temp; 00140 } 00141 00142 #define Push_16 CPU_Push16 00143 #define Push_32 CPU_Push32 00144 #define Pop_16 CPU_Pop16 00145 #define Pop_32 CPU_Pop32 00146 00147 bool CPU_RDMSR(); 00148 bool CPU_WRMSR(); 00149 00150 #include "instructions.h" 00151 #include "core_normal/support.h" 00152 #include "core_normal/string.h" 00153 00154 00155 #define EALookupTable (core.ea_table) 00156 00157 /* NTS: This code fetches opcodes directly from MemBase plus an offset. 00158 * Because of this, the simple core cannot be used to execute directly 00159 * from ROM provided by an adapter since that requires memory I/O callbacks. */ 00160 Bits CPU_Core_Simple_Run(void) { 00161 HostPt safety_limit; 00162 00163 /* simple core is incompatible with paging */ 00164 if (paging.enabled) 00165 return CPU_Core_Normal_Run(); 00166 00167 safety_limit = (HostPt)((size_t)MemBase + ((size_t)MEM_TotalPages() * (size_t)4096) - (size_t)16384); /* safety margin */ 00168 00169 LOADIP; 00170 if (core.cseip >= safety_limit) /* beyond the safety limit, use the normal core */ 00171 return CPU_Core_Normal_Run(); 00172 00173 while (CPU_Cycles-->0) { 00174 LOADIP; 00175 00176 /* Simple core optimizes for non-paged linear memory access and can break (segfault) if beyond end of memory */ 00177 if (core.cseip >= safety_limit) break; 00178 00179 core.opcode_index=cpu.code.big*0x200u; 00180 core.prefixes=cpu.code.big; 00181 core.ea_table=&EATable[cpu.code.big*256u]; 00182 BaseDS=SegBase(ds); 00183 BaseSS=SegBase(ss); 00184 core.base_val_ds=ds; 00185 #if C_DEBUG 00186 #if C_HEAVY_DEBUG 00187 if (DEBUG_HeavyIsBreakpoint()) { 00188 FillFlags(); 00189 return (Bits)debugCallback; 00190 } 00191 #endif 00192 #endif 00193 cycle_count++; 00194 restart_opcode: 00195 switch (core.opcode_index+Fetchb()) { 00196 00197 #include "core_normal/prefix_none.h" 00198 #include "core_normal/prefix_0f.h" 00199 #include "core_normal/prefix_66.h" 00200 #include "core_normal/prefix_66_0f.h" 00201 default: 00202 illegal_opcode: 00203 CPU_Exception(6,0); 00204 continue; 00205 gp_fault: 00206 CPU_Exception(EXCEPTION_GP,0); 00207 continue; 00208 } 00209 SAVEIP; 00210 } 00211 FillFlags(); 00212 return CBRET_NONE; 00213 decode_end: 00214 SAVEIP; 00215 FillFlags(); 00216 return CBRET_NONE; 00217 } 00218 00219 Bits CPU_Core_Simple_Trap_Run(void) { 00220 Bits oldCycles = CPU_Cycles; 00221 CPU_Cycles = 1; 00222 cpu.trap_skip = false; 00223 00224 Bits ret=CPU_Core_Simple_Run(); 00225 if (!cpu.trap_skip) CPU_HW_Interrupt(1); 00226 CPU_Cycles = oldCycles-1; 00227 cpudecoder = &CPU_Core_Simple_Run; 00228 00229 return ret; 00230 } 00231 00232 void CPU_Core_Simple_Init(void) { 00233 00234 }