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 "paging.h" 00031 #include "mmx.h" 00032 00033 bool CPU_RDMSR(); 00034 bool CPU_WRMSR(); 00035 00036 #define CPU_CORE CPU_ARCHTYPE_386 00037 00038 #define DoString DoString_Normal 00039 00040 extern bool ignore_opcode_63; 00041 00042 #if C_DEBUG 00043 #include "debug.h" 00044 #endif 00045 00046 #if (!C_CORE_INLINE) 00047 #define LoadMb(off) mem_readb(off) 00048 #define LoadMw(off) mem_readw(off) 00049 #define LoadMd(off) mem_readd(off) 00050 #define LoadMq(off) ((Bit64u)((Bit64u)mem_readd(off+4)<<32 | (Bit64u)mem_readd(off))) 00051 #define SaveMb(off,val) mem_writeb(off,val) 00052 #define SaveMw(off,val) mem_writew(off,val) 00053 #define SaveMd(off,val) mem_writed(off,val) 00054 #define SaveMq(off,val) {mem_writed(off,val&0xffffffff);mem_writed(off+4,(val>>32)&0xffffffff);} 00055 #else 00056 #include "paging.h" 00057 #define LoadMb(off) mem_readb_inline(off) 00058 #define LoadMw(off) mem_readw_inline(off) 00059 #define LoadMd(off) mem_readd_inline(off) 00060 #define LoadMq(off) ((Bit64u)((Bit64u)mem_readd_inline(off+4)<<32 | (Bit64u)mem_readd_inline(off))) 00061 #define SaveMb(off,val) mem_writeb_inline(off,val) 00062 #define SaveMw(off,val) mem_writew_inline(off,val) 00063 #define SaveMd(off,val) mem_writed_inline(off,val) 00064 #define SaveMq(off,val) {mem_writed_inline(off,val&0xffffffff);mem_writed_inline(off+4,(val>>32)&0xffffffff);} 00065 #endif 00066 00067 Bitu cycle_count; 00068 00069 #if C_FPU 00070 #define CPU_FPU 1u //Enable FPU escape instructions 00071 #endif 00072 00073 #define CPU_PIC_CHECK 1u 00074 #define CPU_TRAP_CHECK 1u 00075 00076 #define CPU_TRAP_DECODER CPU_Core_Normal_Trap_Run 00077 00078 #define OPCODE_NONE 0x000u 00079 #define OPCODE_0F 0x100u 00080 #define OPCODE_SIZE 0x200u 00081 00082 #define PREFIX_ADDR 0x1u 00083 #define PREFIX_REP 0x2u 00084 00085 #define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) 00086 #define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) 00087 00088 #define DO_PREFIX_SEG(_SEG) \ 00089 BaseDS=SegBase(_SEG); \ 00090 BaseSS=SegBase(_SEG); \ 00091 core.base_val_ds=_SEG; \ 00092 goto restart_opcode; 00093 00094 #define DO_PREFIX_ADDR() \ 00095 core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ 00096 (cpu.code.big ^ PREFIX_ADDR); \ 00097 core.ea_table=&EATable[(core.prefixes&1u) * 256u]; \ 00098 goto restart_opcode; 00099 00100 #define DO_PREFIX_REP(_ZERO) \ 00101 core.prefixes|=PREFIX_REP; \ 00102 core.rep_zero=_ZERO; \ 00103 goto restart_opcode; 00104 00105 typedef PhysPt (*GetEAHandler)(void); 00106 00107 static const Bit32u AddrMaskTable[2]={0x0000ffffu,0xffffffffu}; 00108 00109 static struct { 00110 Bitu opcode_index; 00111 PhysPt cseip; 00112 PhysPt base_ds,base_ss; 00113 SegNames base_val_ds; 00114 bool rep_zero; 00115 Bitu prefixes; 00116 GetEAHandler * ea_table; 00117 } core; 00118 00119 /* FIXME: Someone at Microsoft tell how subtracting PhysPt - PhysPt = __int64, or PhysPt + PhysPt = __int64 */ 00120 #define GETIP ((PhysPt)(core.cseip-SegBase(cs))) 00121 #define SAVEIP reg_eip=GETIP; 00122 #define LOADIP core.cseip=((PhysPt)(SegBase(cs)+reg_eip)); 00123 00124 #define SegBase(c) SegPhys(c) 00125 #define BaseDS core.base_ds 00126 #define BaseSS core.base_ss 00127 00128 static INLINE void FetchDiscardb() { 00129 core.cseip+=1; 00130 } 00131 00132 static INLINE Bit8u FetchPeekb() { 00133 Bit8u temp=LoadMb(core.cseip); 00134 return temp; 00135 } 00136 00137 static INLINE Bit8u Fetchb() { 00138 Bit8u temp=LoadMb(core.cseip); 00139 core.cseip+=1; 00140 return temp; 00141 } 00142 00143 static INLINE Bit16u Fetchw() { 00144 Bit16u temp=LoadMw(core.cseip); 00145 core.cseip+=2; 00146 return temp; 00147 } 00148 static INLINE Bit32u Fetchd() { 00149 Bit32u temp=LoadMd(core.cseip); 00150 core.cseip+=4; 00151 return temp; 00152 } 00153 00154 #define Push_16 CPU_Push16 00155 #define Push_32 CPU_Push32 00156 #define Pop_16 CPU_Pop16 00157 #define Pop_32 CPU_Pop32 00158 00159 #include "instructions.h" 00160 #include "core_normal/support.h" 00161 #include "core_normal/string.h" 00162 00163 00164 #define EALookupTable (core.ea_table) 00165 00166 Bits CPU_Core_Normal_Run(void) { 00167 if (CPU_Cycles <= 0) 00168 return CBRET_NONE; 00169 00170 while (CPU_Cycles-->0) { 00171 LOADIP; 00172 core.opcode_index=cpu.code.big*(Bitu)0x200u; 00173 core.prefixes=cpu.code.big; 00174 core.ea_table=&EATable[cpu.code.big*256u]; 00175 BaseDS=SegBase(ds); 00176 BaseSS=SegBase(ss); 00177 core.base_val_ds=ds; 00178 #if C_DEBUG 00179 #if C_HEAVY_DEBUG 00180 if (DEBUG_HeavyIsBreakpoint()) { 00181 FillFlags(); 00182 return (Bits)debugCallback; 00183 } 00184 #endif 00185 #endif 00186 cycle_count++; 00187 restart_opcode: 00188 switch (core.opcode_index+Fetchb()) { 00189 #include "core_normal/prefix_none.h" 00190 #include "core_normal/prefix_0f.h" 00191 #include "core_normal/prefix_66.h" 00192 #include "core_normal/prefix_66_0f.h" 00193 default: 00194 illegal_opcode: 00195 #if C_DEBUG 00196 { 00197 bool ignore=false; 00198 Bitu len=(GETIP-reg_eip); 00199 LOADIP; 00200 if (len>16) len=16; 00201 char tempcode[16*2+1];char * writecode=tempcode; 00202 if (ignore_opcode_63 && mem_readb(core.cseip) == 0x63) 00203 ignore = true; 00204 for (;len>0;len--) { 00205 sprintf(writecode,"%02X",mem_readb(core.cseip++)); 00206 writecode+=2; 00207 } 00208 if (!ignore) 00209 LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); 00210 } 00211 #endif 00212 CPU_Exception(6,0); 00213 continue; 00214 gp_fault: 00215 LOG_MSG("Segment limit violation"); 00216 CPU_Exception(EXCEPTION_GP,0); 00217 continue; 00218 } 00219 SAVEIP; 00220 } 00221 FillFlags(); 00222 return CBRET_NONE; 00223 decode_end: 00224 SAVEIP; 00225 FillFlags(); 00226 return CBRET_NONE; 00227 } 00228 00229 Bits CPU_Core_Normal_Trap_Run(void) { 00230 Bits oldCycles = CPU_Cycles; 00231 CPU_Cycles = 1; 00232 cpu.trap_skip = false; 00233 00234 Bits ret=CPU_Core_Normal_Run(); 00235 if (!cpu.trap_skip) CPU_HW_Interrupt(1); 00236 CPU_Cycles = oldCycles-1; 00237 cpudecoder = &CPU_Core_Normal_Run; 00238 00239 return ret; 00240 } 00241 00242 00243 00244 void CPU_Core_Normal_Init(void) { 00245 00246 } 00247