DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_normal_8086.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 "paging.h"
00030 #include "mmx.h"
00031 
00032 #define CPU_CORE CPU_ARCHTYPE_8086
00033 #define CPU_Core_Normal_Trap_Run CPU_Core8086_Normal_Trap_Run
00034 
00035 #define DoString DoString_Normal8086
00036 
00037 extern bool ignore_opcode_63;
00038 
00039 #if C_DEBUG
00040 #include "debug.h"
00041 #endif
00042 
00043 static Bit16u last_ea86_offset;
00044 
00045 /* NTS: we special case writes to seg:ffff to emulate 8086 behavior where word read/write wraps around the 64KB segment */
00046 #if (!C_CORE_INLINE)
00047 
00048 #define LoadMb(off) mem_readb(off)
00049 
00050 static inline Bit16u LoadMw(Bitu off) {
00051         if (last_ea86_offset == 0xffff)
00052                 return (mem_readb(off) | (mem_readb(off-0xffff) << 8));
00053 
00054         return mem_readw(off);  
00055 }
00056 
00057 #define LoadMd(off) mem_readd(off)
00058 
00059 #define SaveMb(off,val) mem_writeb(off,val)
00060 
00061 static void SaveMw(Bitu off,Bitu val) {
00062         if (last_ea86_offset == 0xffff) {
00063                 mem_writeb(off,val);
00064                 mem_writeb(off-0xffff,val>>8);
00065         }
00066         else {
00067                 mem_writew(off,val);
00068         }
00069 }
00070 
00071 #define SaveMd(off,val) mem_writed(off,val)
00072 
00073 #else 
00074 
00075 #include "paging.h"
00076 
00077 #define LoadMb(off) mem_readb_inline(off)
00078 
00079 static inline Bit16u LoadMw(Bitu off) {
00080         if (last_ea86_offset == 0xffff)
00081                 return (mem_readb_inline(off) | (mem_readb_inline(off-0xffff) << 8));
00082 
00083         return mem_readw_inline(off);   
00084 }
00085 
00086 #define LoadMd(off) mem_readd_inline(off)
00087 
00088 #define SaveMb(off,val) mem_writeb_inline(off,val)
00089 
00090 static void SaveMw(Bitu off,Bitu val) {
00091         if (last_ea86_offset == 0xffff) {
00092                 mem_writeb_inline(off,val);
00093                 mem_writeb_inline(off-0xffff,val>>8);
00094         }
00095         else {
00096                 mem_writew_inline(off,val);
00097         }
00098 }
00099 
00100 #define SaveMd(off,val) mem_writed_inline(off,val)
00101 
00102 #endif
00103 
00104 extern Bitu cycle_count;
00105 
00106 #if C_FPU
00107 #define CPU_FPU 1u                                              //Enable FPU escape instructions
00108 #endif
00109 
00110 #define CPU_PIC_CHECK 1u
00111 #define CPU_TRAP_CHECK 1u
00112 
00113 #define OPCODE_NONE                     0x000u
00114 #define OPCODE_0F                       0x100u
00115 
00116 #define OPCODE_SIZE                     0u                      //DISABLED
00117 
00118 #define PREFIX_ADDR                     0u                      //DISABLED
00119 
00120 #define PREFIX_REP                      0x2u
00121 
00122 #define TEST_PREFIX_ADDR        (0u)                            //DISABLED
00123 #define TEST_PREFIX_REP         (core.prefixes & PREFIX_REP)
00124 
00125 #define DO_PREFIX_SEG(_SEG)                                     \
00126         BaseDS=SegBase(_SEG);                                   \
00127         BaseSS=SegBase(_SEG);                                   \
00128         core.base_val_ds=_SEG;                                  \
00129         goto restart_opcode;
00130 
00131 // it's the core's job not to decode 0x66-0x67 when compiled for 286
00132 #define DO_PREFIX_ADDR()                                                                \
00133         abort();                                                                        
00134 
00135 #define DO_PREFIX_REP(_ZERO)                            \
00136         core.prefixes|=PREFIX_REP;                              \
00137         core.rep_zero=_ZERO;                                    \
00138         goto restart_opcode;
00139 
00140 typedef PhysPt (*GetEAHandler)(void);
00141 
00142 static const Bit32u AddrMaskTable[2]={0x0000ffffu,0x0000ffffu};
00143 
00144 static struct {
00145         Bitu opcode_index;
00146         PhysPt cseip;
00147         PhysPt base_ds,base_ss;
00148         SegNames base_val_ds;
00149         bool rep_zero;
00150         Bitu prefixes;
00151         GetEAHandler * ea_table;
00152 } core;
00153 
00154 /* FIXME: Someone at Microsoft tell how subtracting PhysPt - PhysPt = __int64, or PhysPt + PhysPt = __int64 */
00155 #define GETIP           ((PhysPt)(core.cseip-SegBase(cs)))
00156 #define SAVEIP          reg_eip=GETIP;
00157 #define LOADIP          core.cseip=((PhysPt)(SegBase(cs)+reg_eip));
00158 
00159 #define SegBase(c)      SegPhys(c)
00160 #define BaseDS          core.base_ds
00161 #define BaseSS          core.base_ss
00162 
00163 static INLINE Bit8u Fetchb() {
00164         Bit8u temp=LoadMb(core.cseip);
00165         core.cseip+=1;
00166         return temp;
00167 }
00168 
00169 static INLINE Bit16u Fetchw() {
00170         Bit16u temp=LoadMw(core.cseip);
00171         core.cseip+=2;
00172         return temp;
00173 }
00174 
00175 static INLINE Bit32u Fetchd() {
00176         Bit32u temp=LoadMd(core.cseip);
00177         core.cseip+=4;
00178         return temp;
00179 }
00180 
00181 #define Push_16 CPU_Push16
00182 #define Pop_16 CPU_Pop16
00183 
00184 #include "instructions.h"
00185 #include "core_normal/support.h"
00186 #include "core_normal/string.h"
00187 
00188 
00189 #define EALookupTable (core.ea_table)
00190 
00191 Bits CPU_Core8086_Normal_Run(void) {
00192         while (CPU_Cycles-->0) {
00193                 LOADIP;
00194                 core.prefixes=0;
00195                 core.opcode_index=0;
00196                 last_ea86_offset=0;
00197                 core.ea_table=&EATable[0];
00198                 BaseDS=SegBase(ds);
00199                 BaseSS=SegBase(ss);
00200                 core.base_val_ds=ds;
00201 #if C_DEBUG
00202 #if C_HEAVY_DEBUG
00203                 if (DEBUG_HeavyIsBreakpoint()) {
00204                         FillFlags();
00205                         return (Bits)debugCallback;
00206                 };
00207 #endif
00208 #endif
00209                 cycle_count++;
00210 restart_opcode:
00211                 switch (core.opcode_index+Fetchb()) {
00212                 #include "core_normal/prefix_none.h"
00213                 default:
00214                 illegal_opcode:
00215 #if C_DEBUG     
00216                         {
00217                                 bool ignore=false;
00218                                 Bitu len=(GETIP-reg_eip);
00219                                 LOADIP;
00220                                 if (len>16) len=16;
00221                                 char tempcode[16*2+1];char * writecode=tempcode;
00222                                 if (ignore_opcode_63 && mem_readb(core.cseip) == 0x63)
00223                                         ignore = true;
00224                                 for (;len>0;len--) {
00225                                         sprintf(writecode,"%02X",mem_readb(core.cseip++));
00226                                         writecode+=2;
00227                                 }
00228                                 if (!ignore)
00229                                         LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode);
00230                         }
00231 #endif
00232                         /* there is no invalid opcode instruction. */
00233                         reg_eip += 2;
00234                         continue;
00235                 }
00236                 SAVEIP;
00237         }
00238         FillFlags();
00239         return CBRET_NONE;
00240 decode_end:
00241         SAVEIP;
00242         FillFlags();
00243         return CBRET_NONE;
00244 }
00245 
00246 Bits CPU_Core8086_Normal_Trap_Run(void) {
00247         Bits oldCycles = CPU_Cycles;
00248         CPU_Cycles = 1;
00249         cpu.trap_skip = false;
00250 
00251         Bits ret=CPU_Core8086_Normal_Run();
00252         if (!cpu.trap_skip) CPU_HW_Interrupt(1);
00253         CPU_Cycles = oldCycles-1;
00254         cpudecoder = &CPU_Core8086_Normal_Run;
00255 
00256         return ret;
00257 }
00258 
00259 
00260 
00261 void CPU_Core8086_Normal_Init(void) {
00262 
00263 }
00264