DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_simple.cpp
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 }