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