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