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