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