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