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