VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
CPU.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "CPUTypes.h"
16#include "Peddle.h"
17// #include "SubComponent.h"
18#include "CmdQueue.h"
19
20using namespace vc64::peddle;
21
22namespace vc64 {
23
24class CPU final : public Peddle, public Inspectable<CPUInfo> {
25
26 friend class C64;
27
28 Descriptions descriptions = {{
29
30 .name = "CPU",
31 .description = "Central Processing Unit"
32 }};
33
34 // Result of the latest inspection
35 mutable CPUInfo info = { };
36
37public:
38
39 /* Processor port
40 *
41 * Clock cycles when floating pins reach zero. Bit 3, 6, and 7 of the
42 * processor port need special attention. When the direction of these bits
43 * changes from output to input, there will be no external signal driving
44 * them. As a result, these bits will be in a floating state and act as
45 * capacitors. They will discharge slowly and eventually reach zero. These
46 * variables are used to indicate when the zero level is reached. All three
47 * variables are queried in externalPortBits() and comply to the following
48 * rules:
49 *
50 * dischargeCycleBit > current cycle => bit reads as 1
51 * (if configured as input)
52 * otherwise => bit reads as 0
53 * (if configured as input)
54 */
55 i64 dischargeCycleBit3;
56 i64 dischargeCycleBit6;
57 i64 dischargeCycleBit7;
58
59 /* Discharging times for bit 3, 6, and 7 as seen in other emulators. In
60 * reality, the discharge delay depend on both CPU temperature and how
61 * long the output was 1 befor the bit became an input.
62 */
63 static constexpr i64 dischargeCyclesVICE = 350000;
64 static constexpr i64 dischargeCyclesHOXS = 246312;
65
66
67 //
68 // Methods
69 //
70
71public:
72
73 CPU(C64& ref);
74 CPU(CPURevision cpuModel, C64& ref);
75
76 bool isC64CPU() const { return cpuModel == MOS_6510; }
77 bool isDriveCPU() const { return cpuModel == MOS_6502; }
78
79 void setID(isize id) { this->id = id; }
80
81 CPU& operator= (const CPU& other) {
82
83 CLONE(flags)
84 CLONE(next)
85
86 CLONE(reg)
87
88 CLONE(rdyLine)
89 CLONE(rdyLineUp)
90 CLONE(rdyLineDown)
91 CLONE(nmiLine)
92 CLONE(irqLine)
93 CLONE(edgeDetector)
94 CLONE(levelDetector)
95 CLONE(doNmi)
96 CLONE(doIrq)
97 CLONE(dischargeCycleBit3)
98 CLONE(dischargeCycleBit6)
99 CLONE(dischargeCycleBit7)
100
101 CLONE(clock)
102
103 return *this;
104 }
105
106
107 //
108 // Methods from Serializable
109 //
110
111public:
112
113 template <class T>
114 void serialize(T& worker)
115 {
116 worker
117
118 << flags
119 << next
120
121 << reg.pc
122 << reg.pc0
123 << reg.sp
124 << reg.a
125 << reg.x
126 << reg.y
127 << reg.adl
128 << reg.adh
129 << reg.idl
130 << reg.d
131 << reg.ovl
132 << reg.sr.n
133 << reg.sr.v
134 << reg.sr.b
135 << reg.sr.d
136 << reg.sr.i
137 << reg.sr.z
138 << reg.sr.c
139 << reg.pport.data
140 << reg.pport.direction
141
142 << rdyLine
143 << rdyLineUp
144 << rdyLineDown
145 << nmiLine
146 << irqLine
147 << edgeDetector
148 << levelDetector
149 << doNmi
150 << doIrq
151 << dischargeCycleBit3
152 << dischargeCycleBit6
153 << dischargeCycleBit7;
154
155 if (isSoftResetter(worker)) return;
156
157 worker
158
159 << clock;
160
161 } SERIALIZERS(serialize);
162
163
164 //
165 // Methods from CoreComponent
166 //
167
168public:
169
170 const Descriptions &getDescriptions() const override { return descriptions; }
171
172private:
173
174 void _dump(Category category, std::ostream& os) const override;
175 void _reset(bool hard) override;
176 void _trackOn() override;
177 void _trackOff() override;
178
179
180 //
181 // Methods from Inspectable
182 //
183
184public:
185
186 void cacheInfo(CPUInfo &result) const override;
187
188
189 //
190 // Methods from Peddle
191 //
192
193public:
194
195 virtual u8 read(u16 addr) override;
196 virtual void write(u16 addr, u8 val) override;
197 virtual u16 readResetVector() override;
198 virtual u8 readDasm(u16 addr) const override;
199
200 virtual void writePort(u8 val) override;
201 virtual void writePortDir(u8 val) override;
202 virtual u8 externalPortBits() const override;
203
204 virtual void cpuDidJam() override;
205 virtual void nmiWillTrigger() override;
206 virtual void nmiDidTrigger() override;
207 virtual void breakpointReached(u16 addr) const override;
208 virtual void watchpointReached(u16 addr) const override;
209 virtual void instructionLogged() const override;
210 virtual void jumpedTo(u16 addr) const override;
211
212
213 //
214 // Changing state
215 //
216
217 // Continues program execution at the specified address
218 void jump(u16 addr);
219
220
221 //
222 // Interpreting processor port bits
223 //
224
225public:
226
227 bool getLoram() const { return readPort() & 0x1; }
228 bool getHiram() const { return readPort() & 0x2; }
229 bool getCharen() const { return readPort() & 0x4; }
230
231
232 //
233 // Processing commands
234 //
235
236public:
237
238 // Processes a command from the command queue
239 void processCommand(const Cmd &cmd);
240
241
242 //
243 // Debugging (Breakpoints)
244 //
245
246public:
247
248 void setBreakpoint(u32 addr, isize ignores = 0) throws;
249 void moveBreakpoint(isize nr, u32 newAddr) throws;
250
251 void deleteBreakpoint(isize nr) throws;
252 void deleteBreakpointAt(u32 addr) throws;
253 void deleteAllBreakpoints() throws;
254
255 void enableBreakpoint(isize nr) throws { setEnableBreakpoint(nr, true); }
256 void enableBreakpointAt(u32 addr) throws { setEnableBreakpointAt(addr, true); }
257 void enableAllBreakpoints() throws { setEnableAllBreakpoints(true); }
258
259 void disableBreakpoint(isize nr) throws { setEnableBreakpoint(nr, false); }
260 void disableBreakpointAt(u32 addr) throws { setEnableBreakpointAt(addr, false); }
261 void disableAllBreakpoints() throws { setEnableAllBreakpoints(false); }
262
263 void toggleBreakpoint(isize nr) throws;
264
265private:
266
267 void setEnableBreakpoint(isize nr, bool value) throws;
268 void setEnableBreakpointAt(u32 addr, bool value) throws;
269 void setEnableAllBreakpoints(bool value) throws;
270
271
272 //
273 // Debugging (Watchpoints)
274 //
275
276public:
277
278 void setWatchpoint(u32 addr, isize ignores = 0) throws;
279 void moveWatchpoint(isize nr, u32 newAddr) throws;
280
281 void deleteWatchpoint(isize nr) throws;
282 void deleteWatchpointAt(u32 addr) throws;
283 void deleteAllWatchpoints() throws;
284
285 void enableWatchpoint(isize nr) throws { setEnableWatchpoint(nr, true); }
286 void enableWatchpointAt(u32 addr) throws { setEnableWatchpointAt(addr, true); }
287 void enableAllWatchpoints() throws { setEnableAllWatchpoints(true); }
288
289 void disableWatchpoint(isize nr) throws { setEnableWatchpoint(nr, false); }
290 void disableWatchpointAt(u32 addr) throws { setEnableWatchpointAt(addr, false); }
291 void disableAllWatchpoints() throws { setEnableAllWatchpoints(false); }
292
293 void toggleWatchpoint(isize nr) throws;
294
295private:
296
297 void setEnableWatchpoint(isize nr, bool value) throws;
298 void setEnableWatchpointAt(u32 addr, bool value) throws;
299 void setEnableAllWatchpoints(bool value) throws;
300};
301
302}
Inspection interface.
Definition Inspectable.h:32
VirtualC64 project namespace.
Definition CmdQueue.cpp:16