1 /*
2  *  Copyright (C) 2002-2021  The DOSBox Team
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdio.h>
20 
21 #include "dosbox.h"
22 #include "mem.h"
23 #include "cpu.h"
24 #include "lazyflags.h"
25 #include "inout.h"
26 #include "callback.h"
27 #include "pic.h"
28 #include "fpu.h"
29 #include "paging.h"
30 
31 #if C_DEBUG
32 #include "debug.h"
33 #endif
34 
35 #if (!C_CORE_INLINE)
36 #define LoadMb(off) mem_readb(off)
37 #define LoadMw(off) mem_readw(off)
38 #define LoadMd(off) mem_readd(off)
39 #define SaveMb(off,val)	mem_writeb(off,val)
40 #define SaveMw(off,val)	mem_writew(off,val)
41 #define SaveMd(off,val)	mem_writed(off,val)
42 #else
43 #include "paging.h"
44 #define LoadMb(off) mem_readb_inline(off)
45 #define LoadMw(off) mem_readw_inline(off)
46 #define LoadMd(off) mem_readd_inline(off)
47 #define SaveMb(off,val)	mem_writeb_inline(off,val)
48 #define SaveMw(off,val)	mem_writew_inline(off,val)
49 #define SaveMd(off,val)	mem_writed_inline(off,val)
50 #endif
51 
52 extern Bitu cycle_count;
53 
54 #if C_FPU
55 #define CPU_FPU	1						//Enable FPU escape instructions
56 #endif
57 
58 #define CPU_PIC_CHECK 1
59 #define CPU_TRAP_CHECK 1
60 
61 #define CPU_TRAP_DECODER	CPU_Core_Normal_Trap_Run
62 
63 #define OPCODE_NONE			0x000
64 #define OPCODE_0F			0x100
65 #define OPCODE_SIZE			0x200
66 
67 #define PREFIX_ADDR			0x1
68 #define PREFIX_REP			0x2
69 
70 #define TEST_PREFIX_ADDR	(core.prefixes & PREFIX_ADDR)
71 #define TEST_PREFIX_REP		(core.prefixes & PREFIX_REP)
72 
73 #define DO_PREFIX_SEG(_SEG)					\
74 	BaseDS=SegBase(_SEG);					\
75 	BaseSS=SegBase(_SEG);					\
76 	core.base_val_ds=_SEG;					\
77 	goto restart_opcode;
78 
79 #define DO_PREFIX_ADDR()								\
80 	core.prefixes=(core.prefixes & ~PREFIX_ADDR) |		\
81 	(cpu.code.big ^ PREFIX_ADDR);						\
82 	core.ea_table=&EATable[(core.prefixes&1) * 256];	\
83 	goto restart_opcode;
84 
85 #define DO_PREFIX_REP(_ZERO)				\
86 	core.prefixes|=PREFIX_REP;				\
87 	core.rep_zero=_ZERO;					\
88 	goto restart_opcode;
89 
90 typedef PhysPt (*GetEAHandler)(void);
91 
92 static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
93 
94 static struct {
95 	Bitu opcode_index;
96 	PhysPt cseip;
97 	PhysPt base_ds,base_ss;
98 	SegNames base_val_ds;
99 	bool rep_zero;
100 	Bitu prefixes;
101 	GetEAHandler * ea_table;
102 } core;
103 
104 #define GETIP		(core.cseip-SegBase(cs))
105 #define SAVEIP		reg_eip=GETIP;
106 #define LOADIP		core.cseip=(SegBase(cs)+reg_eip);
107 
108 #define SegBase(c)	SegPhys(c)
109 #define BaseDS		core.base_ds
110 #define BaseSS		core.base_ss
111 
Fetchb()112 static inline Bit8u Fetchb() {
113 	Bit8u temp=LoadMb(core.cseip);
114 	core.cseip+=1;
115 	return temp;
116 }
117 
Fetchw()118 static inline Bit16u Fetchw() {
119 	Bit16u temp=LoadMw(core.cseip);
120 	core.cseip+=2;
121 	return temp;
122 }
Fetchd()123 static inline Bit32u Fetchd() {
124 	Bit32u temp=LoadMd(core.cseip);
125 	core.cseip+=4;
126 	return temp;
127 }
128 
129 #define Push_16 CPU_Push16
130 #define Push_32 CPU_Push32
131 #define Pop_16 CPU_Pop16
132 #define Pop_32 CPU_Pop32
133 
134 #include "instructions.h"
135 #include "core_normal/support.h"
136 #include "core_normal/string.h"
137 
138 
139 #define EALookupTable (core.ea_table)
140 
CPU_Core_Normal_Run(void)141 Bits CPU_Core_Normal_Run(void) {
142 	while (CPU_Cycles-->0) {
143 		LOADIP;
144 		core.opcode_index=cpu.code.big*0x200;
145 		core.prefixes=cpu.code.big;
146 		core.ea_table=&EATable[cpu.code.big*256];
147 		BaseDS=SegBase(ds);
148 		BaseSS=SegBase(ss);
149 		core.base_val_ds=ds;
150 #if C_DEBUG
151 #if C_HEAVY_DEBUG
152 		if (DEBUG_HeavyIsBreakpoint()) {
153 			FillFlags();
154 			return debugCallback;
155 		};
156 #endif
157 		cycle_count++;
158 #endif
159 restart_opcode:
160 		switch (core.opcode_index+Fetchb()) {
161 		#include "core_normal/prefix_none.h"
162 		#include "core_normal/prefix_0f.h"
163 		#include "core_normal/prefix_66.h"
164 		#include "core_normal/prefix_66_0f.h"
165 		default:
166 		illegal_opcode:
167 #if C_DEBUG
168 			{
169 				Bitu len=(GETIP-reg_eip);
170 				LOADIP;
171 				if (len>16) len=16;
172 				char tempcode[16*2+1];char * writecode=tempcode;
173 				for (;len>0;len--) {
174 					sprintf(writecode,"%02X",mem_readb(core.cseip++));
175 					writecode+=2;
176 				}
177 				LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode);
178 			}
179 #endif
180 			CPU_Exception(6,0);
181 			continue;
182 		}
183 		SAVEIP;
184 	}
185 	FillFlags();
186 	return CBRET_NONE;
187 decode_end:
188 	SAVEIP;
189 	FillFlags();
190 	return CBRET_NONE;
191 }
192 
CPU_Core_Normal_Trap_Run(void)193 Bits CPU_Core_Normal_Trap_Run(void) {
194 	Bits oldCycles = CPU_Cycles;
195 	CPU_Cycles = 1;
196 	cpu.trap_skip = false;
197 
198 	Bits ret=CPU_Core_Normal_Run();
199 	if (!cpu.trap_skip) CPU_DebugException(DBINT_STEP,reg_eip);
200 	CPU_Cycles = oldCycles-1;
201 	cpudecoder = &CPU_Core_Normal_Run;
202 
203 	return ret;
204 }
205 
206 
207 
CPU_Core_Normal_Init(void)208 void CPU_Core_Normal_Init(void) {
209 
210 }
211 
212