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