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