openMSX
CPUCore.hh
Go to the documentation of this file.
1#ifndef CPUCORE_HH
2#define CPUCORE_HH
3
4#include "CPURegs.hh"
5#include "CacheLine.hh"
6#include "Probe.hh"
7#include "EmuTime.hh"
8#include "BooleanSetting.hh"
9#include "IntegerSetting.hh"
10#include "serialize_meta.hh"
11#include "openmsx.hh"
12#include <array>
13#include <atomic>
14#include <span>
15#include <string>
16
17namespace openmsx {
18
19class MSXCPUInterface;
20class Scheduler;
21class MSXMotherBoard;
22class TclCallback;
23class TclObject;
24class Interpreter;
25enum Reg8 : int;
26enum Reg16 : int;
27
28class CPUBase {}; // only for bw-compat savestates
29
30struct II { // InstructionInfo
31 // Number of instruction byte fetches since the last M1 cycle.
32 // In other words, at the end of an instruction the PC register should
33 // be incremented by this amount.
35
36 // Total duration of the instruction. At the end of the instruction
37 // this value is added to the total cycle counter. For efficiency
38 // reasons we only want to adjust this total once per instruction
39 // instead of small incremental updates after each micro-code.
40 int cycles;
41};
42
43enum class ExecIRQ {
44 NMI, // about to execute NMI routine
45 IRQ, // about to execute normal IRQ routine
46 NONE, // about to execute regular instruction
47};
48
49struct CacheLines {
50 std::span<const byte*, CacheLine::NUM> read;
51 std::span< byte*, CacheLine::NUM> write;
52};
53
54template<typename CPU_POLICY>
55class CPUCore final : public CPUBase, public CPURegs, public CPU_POLICY
56{
57public:
58 CPUCore(MSXMotherBoard& motherboard, const std::string& name,
59 const BooleanSetting& traceSetting,
60 TclCallback& diHaltCallback, EmuTime::param time);
61
62 void setInterface(MSXCPUInterface* interface_) { interface = interface_; }
63
67 void doReset(EmuTime::param time);
68
69 void execute(bool fastForward);
70
76 void exitCPULoopSync();
77
81 void exitCPULoopAsync();
82
83 void warp(EmuTime::param time);
84 [[nodiscard]] EmuTime::param getCurrentTime() const;
85 void wait(EmuTime::param time);
86 EmuTime waitCycles(EmuTime::param time, unsigned cycles);
87 void setNextSyncPoint(EmuTime::param time);
88 [[nodiscard]] CacheLines getCacheLines() {
89 return {readCacheLine, writeCacheLine};
90 }
91 [[nodiscard]] bool isM1Cycle(unsigned address) const;
92
93 void disasmCommand(Interpreter& interp,
94 std::span<const TclObject> tokens,
95 TclObject& result) const;
96
101 void raiseIRQ();
102
107 void lowerIRQ();
108
113 void raiseNMI();
114
119 void lowerNMI();
120
124 void setFreq(unsigned freq);
125
126 template<typename Archive>
127 void serialize(Archive& ar, unsigned version);
128
129private:
130 void execute2(bool fastForward);
131 [[nodiscard]] bool needExitCPULoop();
132 void setSlowInstructions();
133 void doSetFreq();
134
135 // Observer<Setting> !! non-virtual !!
136 void update(const Setting& setting) noexcept;
137
138private:
139 // memory cache
140 std::array<const byte*, CacheLine::NUM> readCacheLine;
141 std::array< byte*, CacheLine::NUM> writeCacheLine;
142
143 MSXMotherBoard& motherboard;
144 Scheduler& scheduler;
145 MSXCPUInterface* interface = nullptr;
146
147 const BooleanSetting& traceSetting;
148 TclCallback& diHaltCallback;
149
150 Probe<int> IRQStatus;
151 Probe<void> IRQAccept;
152
153 // dynamic freq
154 BooleanSetting freqLocked;
155 IntegerSetting freqValue;
156 unsigned freq;
157
158 // state machine variables
159 int slowInstructions;
160 int NMIStatus = 0;
161
167 bool nmiEdge = false;
168
169 std::atomic<bool> exitLoop = false;
170
172 bool tracingEnabled;
173
175 const bool isCMOS;
176
177private:
178 inline void cpuTracePre();
179 inline void cpuTracePost();
180 void cpuTracePost_slow();
181
182 inline byte READ_PORT(word port, unsigned cc);
183 inline void WRITE_PORT(word port, byte value, unsigned cc);
184
185 template<bool PRE_PB, bool POST_PB>
186 byte RDMEMslow(unsigned address, unsigned cc);
187 template<bool PRE_PB, bool POST_PB>
188 inline byte RDMEM_impl2(unsigned address, unsigned cc);
189 template<bool PRE_PB, bool POST_PB>
190 inline byte RDMEM_impl (unsigned address, unsigned cc);
191 template<unsigned PC_OFFSET>
192 inline byte RDMEM_OPCODE(unsigned cc);
193 inline byte RDMEM(unsigned address, unsigned cc);
194
195 template<bool PRE_PB, bool POST_PB>
196 word RD_WORD_slow(unsigned address, unsigned cc);
197 template<bool PRE_PB, bool POST_PB>
198 inline word RD_WORD_impl2(unsigned address, unsigned cc);
199 template<bool PRE_PB, bool POST_PB>
200 inline word RD_WORD_impl (unsigned address, unsigned cc);
201 template<unsigned PC_OFFSET>
202 inline word RD_WORD_PC(unsigned cc);
203 inline word RD_WORD(unsigned address, unsigned cc);
204
205 template<bool PRE_PB, bool POST_PB>
206 void WRMEMslow(unsigned address, byte value, unsigned cc);
207 template<bool PRE_PB, bool POST_PB>
208 inline void WRMEM_impl2(unsigned address, byte value, unsigned cc);
209 template<bool PRE_PB, bool POST_PB>
210 inline void WRMEM_impl (unsigned address, byte value, unsigned cc);
211 inline void WRMEM(unsigned address, byte value, unsigned cc);
212
213 void WR_WORD_slow(unsigned address, word value, unsigned cc);
214 inline void WR_WORD(unsigned address, word value, unsigned cc);
215
216 template<bool PRE_PB, bool POST_PB>
217 void WR_WORD_rev_slow(unsigned address, word value, unsigned cc);
218 template<bool PRE_PB, bool POST_PB>
219 inline void WR_WORD_rev2(unsigned address, word value, unsigned cc);
220 template<bool PRE_PB, bool POST_PB>
221 inline void WR_WORD_rev (unsigned address, word value, unsigned cc);
222
223 void executeInstructions();
224 inline void nmi();
225 inline void irq0();
226 inline void irq1();
227 inline void irq2();
228 [[nodiscard]] ExecIRQ getExecIRQ() const;
229 void executeSlow(ExecIRQ execIRQ);
230
231 template<Reg8> [[nodiscard]] inline byte get8() const;
232 template<Reg16> [[nodiscard]] inline word get16() const;
233 template<Reg8> inline void set8 (byte x);
234 template<Reg16> inline void set16(word x);
235
236 template<Reg8 DST, Reg8 SRC, int EE> inline II ld_R_R();
237 template<Reg16 REG, int EE> inline II ld_sp_SS();
238 template<Reg16 REG> inline II ld_SS_a();
239 template<Reg8 SRC> inline II ld_xhl_R();
240 template<Reg16 IXY, Reg8 SRC> inline II ld_xix_R();
241
242 inline II ld_xhl_byte();
243 template<Reg16 IXY> inline II ld_xix_byte();
244
245 template<int EE> inline II WR_NN_Y(word reg);
246 template<Reg16 REG, int EE> inline II ld_xword_SS();
247 template<Reg16 REG> inline II ld_xword_SS_ED();
248 template<Reg16 REG> inline II ld_a_SS();
249
250 inline II ld_xbyte_a();
251 inline II ld_a_xbyte();
252
253 template<Reg8 DST, int EE> inline II ld_R_byte();
254 template<Reg8 DST> inline II ld_R_xhl();
255 template<Reg8 DST, Reg16 IXY> inline II ld_R_xix();
256
257 template<int EE> inline word RD_P_XX();
258 template<Reg16 REG, int EE> inline II ld_SS_xword();
259 template<Reg16 REG> inline II ld_SS_xword_ED();
260
261 template<Reg16 REG, int EE> inline II ld_SS_word();
262
263 inline void ADC(byte reg);
264 inline II adc_a_a();
265 template<Reg8 SRC, int EE> inline II adc_a_R();
266 inline II adc_a_byte();
267 inline II adc_a_xhl();
268 template<Reg16 IXY> inline II adc_a_xix();
269
270 inline void ADD(byte reg);
271 inline II add_a_a();
272 template<Reg8 SRC, int EE> inline II add_a_R();
273 inline II add_a_byte();
274 inline II add_a_xhl();
275 template<Reg16 IXY> inline II add_a_xix();
276
277 inline void AND(byte reg);
278 inline II and_a();
279 template<Reg8 SRC, int EE> inline II and_R();
280 inline II and_byte();
281 inline II and_xhl();
282 template<Reg16 IXY> inline II and_xix();
283
284 inline void CP(byte reg);
285 inline II cp_a();
286 template<Reg8 SRC, int EE> inline II cp_R();
287 inline II cp_byte();
288 inline II cp_xhl();
289 template<Reg16 IXY> inline II cp_xix();
290
291 inline void OR(byte reg);
292 inline II or_a();
293 template<Reg8 SRC, int EE> inline II or_R();
294 inline II or_byte();
295 inline II or_xhl();
296 template<Reg16 IXY> inline II or_xix();
297
298 inline void SBC(byte reg);
299 inline II sbc_a_a();
300 template<Reg8 SRC, int EE> inline II sbc_a_R();
301 inline II sbc_a_byte();
302 inline II sbc_a_xhl();
303 template<Reg16 IXY> inline II sbc_a_xix();
304
305 inline void SUB(byte reg);
306 inline II sub_a();
307 template<Reg8 SRC, int EE> inline II sub_R();
308 inline II sub_byte();
309 inline II sub_xhl();
310 template<Reg16 IXY> inline II sub_xix();
311
312 inline void XOR(byte reg);
313 inline II xor_a();
314 template<Reg8 SRC, int EE> inline II xor_R();
315 inline II xor_byte();
316 inline II xor_xhl();
317 template<Reg16 IXY> inline II xor_xix();
318
319 inline byte DEC(byte reg);
320 template<Reg8 REG, int EE> inline II dec_R();
321 template<int EE> inline void DEC_X(unsigned x);
322 inline II dec_xhl();
323 template<Reg16 IXY> inline II dec_xix();
324
325 inline byte INC(byte reg);
326 template<Reg8 REG, int EE> inline II inc_R();
327 template<int EE> inline void INC_X(unsigned x);
328 inline II inc_xhl();
329 template<Reg16 IXY> inline II inc_xix();
330
331 template<Reg16 REG> inline II adc_hl_SS();
332 inline II adc_hl_hl();
333 template<Reg16 REG1, Reg16 REG2, int EE> inline II add_SS_TT();
334 template<Reg16 REG, int EE> inline II add_SS_SS();
335 template<Reg16 REG> inline II sbc_hl_SS();
336 inline II sbc_hl_hl();
337
338 template<Reg16 REG, int EE> inline II dec_SS();
339 template<Reg16 REG, int EE> inline II inc_SS();
340
341 template<unsigned N, Reg8 REG> inline II bit_N_R();
342 template<unsigned N> inline II bit_N_xhl();
343 template<unsigned N> inline II bit_N_xix(unsigned a);
344
345 template<unsigned N, Reg8 REG> inline II res_N_R();
346 template<int EE> inline byte RES_X(unsigned bit, unsigned addr);
347 template<unsigned N> inline II res_N_xhl();
348 template<unsigned N, Reg8 REG> inline II res_N_xix_R(unsigned a);
349
350 template<unsigned N, Reg8 REG> inline II set_N_R();
351 template<int EE> inline byte SET_X(unsigned bit, unsigned addr);
352 template<unsigned N> inline II set_N_xhl();
353 template<unsigned N, Reg8 REG> inline II set_N_xix_R(unsigned a);
354
355 inline byte RL(byte reg);
356 template<int EE> inline byte RL_X(unsigned x);
357 template<Reg8 REG> inline II rl_R();
358 inline II rl_xhl();
359 template<Reg8 REG> inline II rl_xix_R(unsigned a);
360
361 inline byte RLC(byte reg);
362 template<int EE> inline byte RLC_X(unsigned x);
363 template<Reg8 REG> inline II rlc_R();
364 inline II rlc_xhl();
365 template<Reg8 REG> inline II rlc_xix_R(unsigned a);
366
367 inline byte RR(byte reg);
368 template<int EE> inline byte RR_X(unsigned x);
369 template<Reg8 REG> inline II rr_R();
370 inline II rr_xhl();
371 template<Reg8 REG> inline II rr_xix_R(unsigned a);
372
373 inline byte RRC(byte reg);
374 template<int EE> inline byte RRC_X(unsigned x);
375 template<Reg8 REG> inline II rrc_R();
376 inline II rrc_xhl();
377 template<Reg8 REG> inline II rrc_xix_R(unsigned a);
378
379 inline byte SLA(byte reg);
380 template<int EE> inline byte SLA_X(unsigned x);
381 template<Reg8 REG> inline II sla_R();
382 inline II sla_xhl();
383 template<Reg8 REG> inline II sla_xix_R(unsigned a);
384
385 inline byte SLL(byte reg);
386 template<int EE> inline byte SLL_X(unsigned x);
387 template<Reg8 REG> inline II sll_R();
388 inline II sll_xhl();
389 template<Reg8 REG> inline II sll_xix_R(unsigned a);
390 inline II sll2();
391
392 inline byte SRA(byte reg);
393 template<int EE> inline byte SRA_X(unsigned x);
394 template<Reg8 REG> inline II sra_R();
395 inline II sra_xhl();
396 template<Reg8 REG> inline II sra_xix_R(unsigned a);
397
398 inline byte SRL(byte reg);
399 template<int EE> inline byte SRL_X(unsigned x);
400 template<Reg8 REG> inline II srl_R();
401 inline II srl_xhl();
402 template<Reg8 REG> inline II srl_xix_R(unsigned a);
403
404 inline II rla();
405 inline II rlca();
406 inline II rra();
407 inline II rrca();
408
409 inline II rld();
410 inline II rrd();
411
412 template<int EE> inline void PUSH(word reg);
413 template<Reg16 REG, int EE> inline II push_SS();
414 template<int EE> inline word POP();
415 template<Reg16 REG, int EE> inline II pop_SS();
416
417 template<typename COND> inline II call(COND cond);
418 template<unsigned ADDR> inline II rst();
419
420 template<int EE, typename COND> inline II RET(COND cond);
421 template<typename COND> inline II ret(COND cond);
422 inline II ret();
423 inline II retn();
424
425 template<Reg16 REG, int EE> inline II jp_SS();
426 template<typename COND> inline II jp(COND cond);
427 template<typename COND> inline II jr(COND cond);
428 inline II djnz();
429
430 template<Reg16 REG, int EE> inline II ex_xsp_SS();
431
432 template<Reg8 REG> inline II in_R_c();
433 inline II in_a_byte();
434 template<Reg8 REG> inline II out_c_R();
435 inline II out_c_0();
436 inline II out_byte_a();
437
438 inline II BLOCK_CP(int increase, bool repeat);
439 inline II cpd();
440 inline II cpi();
441 inline II cpdr();
442 inline II cpir();
443
444 inline II BLOCK_LD(int increase, bool repeat);
445 inline II ldd();
446 inline II ldi();
447 inline II lddr();
448 inline II ldir();
449
450 inline II BLOCK_IN(int increase, bool repeat);
451 inline II ind();
452 inline II ini();
453 inline II indr();
454 inline II inir();
455
456 inline II BLOCK_OUT(int increase, bool repeat);
457 inline II outd();
458 inline II outi();
459 inline II otdr();
460 inline II otir();
461
462 template<int EE = 0> inline II nop();
463 inline II ccf();
464 inline II cpl();
465 inline II daa();
466 inline II neg();
467 inline II scf();
468 inline II ex_af_af();
469 inline II ex_de_hl();
470 inline II exx();
471 inline II di();
472 inline II ei();
473 inline II halt();
474 template<unsigned N> inline II im_N();
475
476 template<Reg8 REG> inline II ld_a_IR();
477 inline II ld_r_a();
478 inline II ld_i_a();
479
480 template<Reg8 REG> inline II mulub_a_R();
481 template<Reg16 REG> inline II muluw_hl_SS();
482
483 friend class MSXCPU;
484 friend class Z80TYPE;
485 friend class R800TYPE;
486};
487
488class Z80TYPE;
489class R800TYPE;
491SERIALIZE_CLASS_VERSION(CPUCore<R800TYPE>, 5); // keep these two the same
492
493} // namespace openmsx
494
495#endif
BaseSetting * setting
Definition: Interpreter.cc:28
void setInterface(MSXCPUInterface *interface_)
Definition: CPUCore.hh:62
void lowerIRQ()
Lowers the maskable interrupt count.
Definition: CPUCore.cc:446
void setNextSyncPoint(EmuTime::param time)
Definition: CPUCore.cc:501
void disasmCommand(Interpreter &interp, std::span< const TclObject > tokens, TclObject &result) const
Definition: CPUCore.cc:517
void setFreq(unsigned freq)
Change the clock freq.
Definition: CPUCore.cc:544
void execute(bool fastForward)
Definition: CPUCore.cc:2560
void warp(EmuTime::param time)
Definition: CPUCore.cc:328
CPUCore(MSXMotherBoard &motherboard, const std::string &name, const BooleanSetting &traceSetting, TclCallback &diHaltCallback, EmuTime::param time)
Definition: CPUCore.cc:292
void lowerNMI()
Lowers the non-maskable interrupt count.
Definition: CPUCore.cc:462
void exitCPULoopSync()
Request to exit the main CPU emulation loop.
Definition: CPUCore.cc:407
EmuTime::param getCurrentTime() const
Definition: CPUCore.cc:334
void exitCPULoopAsync()
Similar to exitCPULoopSync(), but this method may be called from any thread.
Definition: CPUCore.cc:402
void raiseNMI()
Raises the non-maskable interrupt count.
Definition: CPUCore.cc:452
void serialize(Archive &ar, unsigned version)
Definition: CPUCore.cc:4419
void doReset(EmuTime::param time)
Reset the CPU.
Definition: CPUCore.cc:339
void wait(EmuTime::param time)
Definition: CPUCore.cc:484
EmuTime waitCycles(EmuTime::param time, unsigned cycles)
Definition: CPUCore.cc:491
bool isM1Cycle(unsigned address) const
Definition: CPUCore.cc:468
CacheLines getCacheLines()
Definition: CPUCore.hh:88
void raiseIRQ()
Raises the maskable interrupt count.
Definition: CPUCore.cc:437
A Setting with an integer value.
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
std::span< const byte *, CacheLine::NUM > read
Definition: CPUCore.hh:50
std::span< byte *, CacheLine::NUM > write
Definition: CPUCore.hh:51
word length
Definition: CPUCore.hh:34
int cycles
Definition: CPUCore.hh:40
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition: xrange.hh:147