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