openMSX
MSXCPU.cc
Go to the documentation of this file.
1 #include "MSXCPU.hh"
2 #include "MSXCPUInterface.hh"
3 #include "MSXMotherBoard.hh"
4 #include "Debugger.hh"
5 #include "Scheduler.hh"
6 #include "IntegerSetting.hh"
7 #include "CPUCore.hh"
8 #include "Z80.hh"
9 #include "R800.hh"
10 #include "TclObject.hh"
11 #include "outer.hh"
12 #include "ranges.hh"
13 #include "serialize.hh"
14 #include "unreachable.hh"
15 #include <cassert>
16 #include <memory>
17 
18 using std::string;
19 using std::vector;
20 
21 namespace openmsx {
22 
24  : motherboard(motherboard_)
25  , traceSetting(
26  motherboard.getCommandController(), "cputrace",
27  "CPU tracing on/off", false, Setting::DONT_SAVE)
28  , diHaltCallback(
29  motherboard.getCommandController(), "di_halt_callback",
30  "Tcl proc called when the CPU executed a DI/HALT sequence")
31  , z80(std::make_unique<CPUCore<Z80TYPE>>(
32  motherboard, "z80", traceSetting,
33  diHaltCallback, EmuTime::zero()))
34  , r800(motherboard.isTurboR()
35  ? std::make_unique<CPUCore<R800TYPE>>(
36  motherboard, "r800", traceSetting,
37  diHaltCallback, EmuTime::zero())
38  : nullptr)
39  , timeInfo(motherboard.getMachineInfoCommand())
40  , z80FreqInfo(motherboard.getMachineInfoCommand(), "z80_freq", *z80)
41  , r800FreqInfo(r800
42  ? std::make_unique<CPUFreqInfoTopic>(
43  motherboard.getMachineInfoCommand(), "r800_freq", *r800)
44  : nullptr)
45  , debuggable(motherboard_)
46  , reference(EmuTime::zero())
47 {
48  z80Active = true; // setActiveCPU(CPU_Z80);
49  newZ80Active = z80Active;
50 
51  motherboard.getDebugger().setCPU(this);
52  motherboard.getScheduler().setCPU(this);
53  traceSetting.attach(*this);
54 
55  z80->freqLocked.attach(*this);
56  z80->freqValue.attach(*this);
57  if (r800) {
58  r800->freqLocked.attach(*this);
59  r800->freqValue.attach(*this);
60  }
61  invalidateMemCacheSlot();
62 }
63 
65 {
66  traceSetting.detach(*this);
67  z80->freqLocked.detach(*this);
68  z80->freqValue.detach(*this);
69  if (r800) {
70  r800->freqLocked.detach(*this);
71  r800->freqValue.detach(*this);
72  }
73  motherboard.getScheduler().setCPU(nullptr);
74  motherboard.getDebugger() .setCPU(nullptr);
75 }
76 
78 {
79  interface = interface_;
80  z80 ->setInterface(interface);
81  if (r800) r800->setInterface(interface);
82 }
83 
84 void MSXCPU::doReset(EmuTime::param time)
85 {
86  z80 ->doReset(time);
87  if (r800) r800->doReset(time);
88 
89  invalidateAllSlotsRWCache(0x0000, 0x10000);
90 
91  reference = time;
92 }
93 
95 {
96  if (cpu == CPU_R800) assert(r800);
97 
98  bool tmp = cpu == CPU_Z80;
99  if (tmp != z80Active) {
100  exitCPULoopSync();
101  newZ80Active = tmp;
102  }
103 }
104 
105 void MSXCPU::setDRAMmode(bool dram)
106 {
107  assert(r800);
108  r800->setDRAMmode(dram);
109 }
110 
111 void MSXCPU::execute(bool fastForward)
112 {
113  if (z80Active != newZ80Active) {
114  EmuTime time = getCurrentTime();
115  z80Active = newZ80Active;
116  z80Active ? z80 ->warp(time)
117  : r800->warp(time);
118  // copy Z80/R800 cache lines
119  auto zCache = z80 ->getCacheLines();
120  auto rCache = r800->getCacheLines();
121  auto from = z80Active ? rCache : zCache;
122  auto to = z80Active ? zCache : rCache;
123  std::copy_n(from.first, CacheLine::NUM, to.first );
124  std::copy_n(from.second, CacheLine::NUM, to.second);
125  }
126  z80Active ? z80 ->execute(fastForward)
127  : r800->execute(fastForward);
128 }
129 
131 {
132  z80Active ? z80 ->exitCPULoopSync()
133  : r800->exitCPULoopSync();
134 }
136 {
137  z80Active ? z80 ->exitCPULoopAsync()
138  : r800->exitCPULoopAsync();
139 }
140 
141 EmuTime::param MSXCPU::getCurrentTime() const
142 {
143  return z80Active ? z80 ->getCurrentTime()
144  : r800->getCurrentTime();
145 }
146 
147 void MSXCPU::setNextSyncPoint(EmuTime::param time)
148 {
149  z80Active ? z80 ->setNextSyncPoint(time)
150  : r800->setNextSyncPoint(time);
151 }
152 
153 void MSXCPU::invalidateMemCacheSlot()
154 {
155  ranges::fill(slots, 0);
156 
157  // nullptr: means not a valid entry and not yet attempted to fill this entry
158  for (int i = 0; i < 16; ++i) {
159  ranges::fill(slotReadLines[i], nullptr);
160  ranges::fill(slotWriteLines[i], nullptr);
161  }
162 }
163 
164 void MSXCPU::updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
165 {
166  byte from = slots[page];
167  byte to = 4 * primarySlot + secondarySlot;
168  slots[page] = to;
169 
170  auto [cpuReadLines, cpuWriteLines] = z80Active ? z80->getCacheLines() : r800->getCacheLines();
171 
172  unsigned first = page * (0x4000 / CacheLine::SIZE);
173  unsigned num = 0x4000 / CacheLine::SIZE;
174  std::copy_n(&cpuReadLines [first], num, &slotReadLines [from][first]);
175  std::copy_n(&slotReadLines [to][first], num, &cpuReadLines [first]);
176  std::copy_n(&cpuWriteLines [first], num, &slotWriteLines[from][first]);
177  std::copy_n(&slotWriteLines[to][first], num, &cpuWriteLines [first]);
178 
179  if (r800) r800->updateVisiblePage(page, primarySlot, secondarySlot);
180 }
181 
183 {
184  if (interface) interface->tick(CacheLineCounters::InvalidateAllSlots);
185  auto [cpuReadLines, cpuWriteLines] = z80Active ? z80->getCacheLines() : r800->getCacheLines();
186 
187  unsigned first = start / CacheLine::SIZE;
188  unsigned num = (size + CacheLine::SIZE - 1) / CacheLine::SIZE;
189  std::fill_n(cpuReadLines + first, num, nullptr); // nullptr: means not a valid entry and not
190  std::fill_n(cpuWriteLines + first, num, nullptr); // yet attempted to fill this entry
191 
192  for (int i = 0; i < 16; ++i) {
193  std::fill_n(slotReadLines[i] + first, num, nullptr);
194  std::fill_n(slotWriteLines[i] + first, num, nullptr);
195  }
196 }
197 
198 template<bool READ, bool WRITE, bool SUB_START>
199 void MSXCPU::setRWCache(unsigned start, unsigned size, const byte* rData, byte* wData, int ps, int ss,
200  const byte* disallowRead, const byte* disallowWrite)
201 {
202  if (!SUB_START) {
203  assert(rData == nullptr);
204  assert(wData == nullptr);
205  }
206 
207  // aligned on cache lines
208  assert((start & CacheLine::LOW) == 0);
209  assert((size & CacheLine::LOW) == 0);
210 
211  int slot = 4 * ps + ss;
212  unsigned page = start >> 14;
213  assert(((start + size - 1) >> 14) == page); // all in same page
214  if (SUB_START && READ) rData -= start;
215  if (SUB_START && WRITE) wData -= start;
216 
217  // select between 'active' or 'shadow' cache lines
218  const byte** readLines;
219  byte** writeLines;
220  if (slot == slots[page]) {
221  auto cache = z80Active ? z80->getCacheLines() : r800->getCacheLines();
222  readLines = cache.first;
223  writeLines = cache.second;
224  } else {
225  readLines = slotReadLines [slot];
226  writeLines = slotWriteLines[slot];
227  }
228 
229  unsigned first = start / CacheLine::SIZE;
230  readLines += first;
231  writeLines += first;
232  disallowRead += first;
233  disallowWrite += first;
234  unsigned num = size / CacheLine::SIZE;
235 
236  static const auto NON_CACHEABLE = reinterpret_cast<byte*>(1);
237  for (unsigned i = 0; i < num; ++i) {
238  if (READ) readLines [i] = disallowRead [i] ? NON_CACHEABLE : rData;
239  if (WRITE) writeLines[i] = disallowWrite[i] ? NON_CACHEABLE : wData;
240  }
241 }
242 
243 static void extendForAlignment(unsigned& start, unsigned& size)
244 {
245  static constexpr unsigned MASK = ~(CacheLine::LOW); // not CacheLine::HIGH because 0x0000ff00 != 0xffffff00
246 
247  auto end = start + size;
248  start &= MASK; // round down to cacheline
249  end = (end + CacheLine::SIZE - 1) & MASK; // round up to cacheline
250  size = end - start;
251 }
252 
253 void MSXCPU::invalidateRWCache(unsigned start, unsigned size, int ps, int ss,
254  const byte* disallowRead, const byte* disallowWrite)
255 {
256  // unaligned [start, start+size) is OK for invalidate, then simply invalidate a little more.
257  extendForAlignment(start, size);
258  setRWCache<true, true, false>(start, size, nullptr, nullptr, ps, ss, disallowRead, disallowWrite);
259 }
260 void MSXCPU::invalidateRCache(unsigned start, unsigned size, int ps, int ss,
261  const byte* disallowRead)
262 {
263  extendForAlignment(start, size);
264  setRWCache<true, false, false>(start, size, nullptr, nullptr, ps, ss, disallowRead, nullptr);
265 }
266 void MSXCPU::invalidateWCache(unsigned start, unsigned size, int ps, int ss,
267  const byte* disallowWrite)
268 {
269  extendForAlignment(start, size);
270  setRWCache<false, true, false>(start, size, nullptr, nullptr, ps, ss, nullptr, disallowWrite);
271 }
272 
273 void MSXCPU::fillRWCache(unsigned start, unsigned size, const byte* rData, byte* wData, int ps, int ss,
274  const byte* disallowRead, const byte* disallowWrite)
275 {
276  setRWCache<true, true, true>(start, size, rData, wData, ps, ss, disallowRead, disallowWrite);
277 }
278 void MSXCPU::fillRCache(unsigned start, unsigned size, const byte* rData, int ps, int ss,
279  const byte* disallowRead)
280 {
281  setRWCache<true, false, true>(start, size, rData, nullptr, ps, ss, disallowRead, nullptr);
282 }
283 void MSXCPU::fillWCache(unsigned start, unsigned size, byte* wData, int ps, int ss,
284  const byte* disallowWrite)
285 {
286  setRWCache<false, true, true>(start, size, nullptr, wData, ps, ss, nullptr, disallowWrite);
287 }
288 
290 {
291  z80 ->raiseIRQ();
292  if (r800) r800->raiseIRQ();
293 }
295 {
296  z80 ->lowerIRQ();
297  if (r800) r800->lowerIRQ();
298 }
300 {
301  z80 ->raiseNMI();
302  if (r800) r800->raiseNMI();
303 }
305 {
306  z80 ->lowerNMI();
307  if (r800) r800->lowerNMI();
308 }
309 
310 bool MSXCPU::isM1Cycle(unsigned address) const
311 {
312  return z80Active ? z80 ->isM1Cycle(address)
313  : r800->isM1Cycle(address);
314 }
315 
316 void MSXCPU::setZ80Freq(unsigned freq)
317 {
318  z80->setFreq(freq);
319 }
320 
321 void MSXCPU::wait(EmuTime::param time)
322 {
323  z80Active ? z80 ->wait(time)
324  : r800->wait(time);
325 }
326 
327 EmuTime MSXCPU::waitCyclesZ80(EmuTime::param time, unsigned cycles)
328 {
329  return z80Active ? z80 ->waitCycles(time, cycles)
330  : time;
331 }
332 
333 EmuTime MSXCPU::waitCyclesR800(EmuTime::param time, unsigned cycles)
334 {
335  return z80Active ? time
336  : r800->waitCycles(time, cycles);
337 }
338 
340 {
341  if (z80Active) {
342  return *z80;
343  } else {
344  return *r800;
345  }
346 }
347 
348 void MSXCPU::update(const Setting& setting)
349 {
350  z80 ->update(setting);
351  if (r800) r800->update(setting);
352  exitCPULoopSync();
353 }
354 
355 // Command
356 
358  Interpreter& interp, span<const TclObject> tokens,
359  TclObject& result) const
360 {
361  z80Active ? z80 ->disasmCommand(interp, tokens, result)
362  : r800->disasmCommand(interp, tokens, result);
363 }
364 
365 void MSXCPU::setPaused(bool paused)
366 {
367  if (z80Active) {
368  z80 ->setExtHALT(paused);
369  z80 ->exitCPULoopSync();
370  } else {
371  r800->setExtHALT(paused);
372  r800->exitCPULoopSync();
373  }
374 }
375 
376 
377 // class TimeInfoTopic
378 
379 MSXCPU::TimeInfoTopic::TimeInfoTopic(InfoCommand& machineInfoCommand)
380  : InfoTopic(machineInfoCommand, "time")
381 {
382 }
383 
384 void MSXCPU::TimeInfoTopic::execute(
385  span<const TclObject> /*tokens*/, TclObject& result) const
386 {
387  auto& cpu = OUTER(MSXCPU, timeInfo);
388  EmuDuration dur = cpu.getCurrentTime() - cpu.reference;
389  result = dur.toDouble();
390 }
391 
392 string MSXCPU::TimeInfoTopic::help(const vector<string>& /*tokens*/) const
393 {
394  return "Prints the time in seconds that the MSX is powered on\n";
395 }
396 
397 
398 // class CPUFreqInfoTopic
399 
400 MSXCPU::CPUFreqInfoTopic::CPUFreqInfoTopic(
401  InfoCommand& machineInfoCommand,
402  const string& name_, CPUClock& clock_)
403  : InfoTopic(machineInfoCommand, name_)
404  , clock(clock_)
405 {
406 }
407 
408 void MSXCPU::CPUFreqInfoTopic::execute(
409  span<const TclObject> /*tokens*/, TclObject& result) const
410 {
411  result = clock.getFreq();
412 }
413 
414 string MSXCPU::CPUFreqInfoTopic::help(const vector<string>& /*tokens*/) const
415 {
416  return "Returns the actual frequency of this CPU.\n"
417  "This frequency can vary because:\n"
418  " - the user has overridden the freq via the '{z80,r800}_freq' setting\n"
419  " - (only on some MSX machines) the MSX software can switch the Z80 between 2 frequencies\n"
420  "See also the '{z80,r800}_freq_locked' setting.\n";
421 }
422 
423 
424 // class Debuggable
425 
426 constexpr const char* const CPU_REGS_DESC =
427  "Registers of the active CPU (Z80 or R800).\n"
428  "Each byte in this debuggable represents one 8 bit register:\n"
429  " 0 -> A 1 -> F 2 -> B 3 -> C\n"
430  " 4 -> D 5 -> E 6 -> H 7 -> L\n"
431  " 8 -> A' 9 -> F' 10 -> B' 11 -> C'\n"
432  " 12 -> D' 13 -> E' 14 -> H' 15 -> L'\n"
433  " 16 -> IXH 17 -> IXL 18 -> IYH 19 -> IYL\n"
434  " 20 -> PCH 21 -> PCL 22 -> SPH 23 -> SPL\n"
435  " 24 -> I 25 -> R 26 -> IM 27 -> IFF1/2\n"
436  "The last position (27) contains the IFF1 and IFF2 flags in respectively\n"
437  "bit 0 and 1. Bit 2 contains 'IFF1 AND last-instruction-was-not-EI', so\n"
438  "this effectively indicates that the CPU could accept an interrupt at\n"
439  "the start of the current instruction.\n";
440 
441 MSXCPU::Debuggable::Debuggable(MSXMotherBoard& motherboard_)
442  : SimpleDebuggable(motherboard_, "CPU regs", CPU_REGS_DESC, 28)
443 {
444 }
445 
446 byte MSXCPU::Debuggable::read(unsigned address)
447 {
448  auto& cpu = OUTER(MSXCPU, debuggable);
449  const CPURegs& regs = cpu.getRegisters();
450  switch (address) {
451  case 0: return regs.getA();
452  case 1: return regs.getF();
453  case 2: return regs.getB();
454  case 3: return regs.getC();
455  case 4: return regs.getD();
456  case 5: return regs.getE();
457  case 6: return regs.getH();
458  case 7: return regs.getL();
459  case 8: return regs.getA2();
460  case 9: return regs.getF2();
461  case 10: return regs.getB2();
462  case 11: return regs.getC2();
463  case 12: return regs.getD2();
464  case 13: return regs.getE2();
465  case 14: return regs.getH2();
466  case 15: return regs.getL2();
467  case 16: return regs.getIXh();
468  case 17: return regs.getIXl();
469  case 18: return regs.getIYh();
470  case 19: return regs.getIYl();
471  case 20: return regs.getPCh();
472  case 21: return regs.getPCl();
473  case 22: return regs.getSPh();
474  case 23: return regs.getSPl();
475  case 24: return regs.getI();
476  case 25: return regs.getR();
477  case 26: return regs.getIM();
478  case 27: return 1 * regs.getIFF1() +
479  2 * regs.getIFF2() +
480  4 * (regs.getIFF1() && !regs.prevWasEI());
481  default: UNREACHABLE; return 0;
482  }
483 }
484 
485 void MSXCPU::Debuggable::write(unsigned address, byte value)
486 {
487  auto& cpu = OUTER(MSXCPU, debuggable);
488  CPURegs& regs = cpu.getRegisters();
489  switch (address) {
490  case 0: regs.setA(value); break;
491  case 1: regs.setF(value); break;
492  case 2: regs.setB(value); break;
493  case 3: regs.setC(value); break;
494  case 4: regs.setD(value); break;
495  case 5: regs.setE(value); break;
496  case 6: regs.setH(value); break;
497  case 7: regs.setL(value); break;
498  case 8: regs.setA2(value); break;
499  case 9: regs.setF2(value); break;
500  case 10: regs.setB2(value); break;
501  case 11: regs.setC2(value); break;
502  case 12: regs.setD2(value); break;
503  case 13: regs.setE2(value); break;
504  case 14: regs.setH2(value); break;
505  case 15: regs.setL2(value); break;
506  case 16: regs.setIXh(value); break;
507  case 17: regs.setIXl(value); break;
508  case 18: regs.setIYh(value); break;
509  case 19: regs.setIYl(value); break;
510  case 20: regs.setPCh(value); break;
511  case 21: regs.setPCl(value); break;
512  case 22: regs.setSPh(value); break;
513  case 23: regs.setSPl(value); break;
514  case 24: regs.setI(value); break;
515  case 25: regs.setR(value); break;
516  case 26:
517  if (value < 3) regs.setIM(value);
518  break;
519  case 27:
520  regs.setIFF1((value & 0x01) != 0);
521  regs.setIFF2((value & 0x02) != 0);
522  // can't change afterEI
523  break;
524  default:
525  UNREACHABLE;
526  }
527 }
528 
529 // version 1: initial version
530 // version 2: activeCPU,newCPU -> z80Active,newZ80Active
531 template<typename Archive>
532 void MSXCPU::serialize(Archive& ar, unsigned version)
533 {
534  if (ar.versionAtLeast(version, 2)) {
535  ar.serialize("z80", *z80);
536  if (r800) ar.serialize("r800", *r800);
537  ar.serialize("z80Active", z80Active,
538  "newZ80Active", newZ80Active);
539  } else {
540  // backwards-compatibility
541  assert(ar.isLoader());
542 
543  ar.serializeWithID("z80", *z80);
544  if (r800) ar.serializeWithID("r800", *r800);
545  CPUBase* activeCPU = nullptr;
546  CPUBase* newCPU = nullptr;
547  ar.serializePointerID("activeCPU", activeCPU);
548  ar.serializePointerID("newCPU", newCPU);
549  z80Active = activeCPU == z80.get();
550  if (newCPU) {
551  newZ80Active = newCPU == z80.get();
552  } else {
553  newZ80Active = z80Active;
554  }
555  }
556  ar.serialize("resetTime", reference);
557 
558  if (ar.isLoader()) {
559  invalidateMemCacheSlot();
560  invalidateAllSlotsRWCache(0x0000, 0x10000);
561  }
562 }
564 
565 } // namespace openmsx
openmsx::MSXCPU::waitCyclesR800
EmuTime waitCyclesR800(EmuTime::param time, unsigned cycles)
Definition: MSXCPU.cc:333
openmsx::CPU_REGS_DESC
constexpr const char *const CPU_REGS_DESC
Definition: MSXCPU.cc:426
openmsx::CPURegs
CPURegs
Definition: CPURegs.cc:50
IntegerSetting.hh
openmsx::Scheduler::setCPU
void setCPU(MSXCPU *cpu_)
Definition: Scheduler.hh:41
openmsx::CPUClock
CPUClock
Definition: CPUClock.cc:26
openmsx::Subject::detach
void detach(Observer< T > &observer)
Definition: Subject.hh:56
serialize.hh
openmsx::MSXCPU::exitCPULoopAsync
void exitCPULoopAsync()
See CPUCore::exitCPULoopAsync()
Definition: MSXCPU.cc:135
TclObject.hh
openmsx::MSXCPU::MSXCPU
MSXCPU(MSXMotherBoard &motherboard)
Definition: MSXCPU.cc:23
openmsx::InfoTopic
Definition: InfoTopic.hh:16
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
openmsx::MSXCPU::invalidateRWCache
void invalidateRWCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowRead, const byte *disallowWrite)
Similar to the method above, but only invalidates one specific slot.
Definition: MSXCPU.cc:253
openmsx::MSXCPU::setPaused
void setPaused(bool paused)
(un)pause CPU.
Definition: MSXCPU.cc:365
openmsx::MSXCPU::setInterface
void setInterface(MSXCPUInterface *interf)
Definition: MSXCPU.cc:77
openmsx::MSXCPU::waitCyclesZ80
EmuTime waitCyclesZ80(EmuTime::param time, unsigned cycles)
Definition: MSXCPU.cc:327
MSXCPU.hh
openmsx::MSXCPU::fillRWCache
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss, const byte *disallowRead, const byte *disallowWrite)
Fill the read and write cache lines for a specific slot with the specified value.
Definition: MSXCPU.cc:273
openmsx::MSXCPU::lowerNMI
void lowerNMI()
This methods lowers the non-maskable interrupt again.
Definition: MSXCPU.cc:304
openmsx::SimpleDebuggable
Definition: SimpleDebuggable.hh:12
openmsx::MSXCPU::CPUType
CPUType
Definition: MSXCPU.hh:31
openmsx::MSXCPU::wait
void wait(EmuTime::param time)
Definition: MSXCPU.cc:321
ranges.hh
openmsx::MSXCPU::doReset
void doReset(EmuTime::param time)
Reset CPU.
Definition: MSXCPU.cc:84
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
openmsx::MSXCPU
MSXCPU
Definition: MSXCPU.cc:563
openmsx::Setting
Definition: Setting.hh:120
openmsx::MSXCPUInterface
Definition: MSXCPUInterface.hh:64
openmsx::Debugger::setCPU
void setCPU(MSXCPU *cpu_)
Definition: Debugger.hh:40
openmsx::MSXCPU::invalidateWCache
void invalidateWCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowWrite)
Definition: MSXCPU.cc:266
span
Definition: span.hh:126
openmsx::InvalidateAllSlots
@ InvalidateAllSlots
Definition: MSXCPUInterface.hh:51
openmsx::MSXCPU::isM1Cycle
bool isM1Cycle(unsigned address) const
Should only be used from within a MSXDevice::readMem() method.
Definition: MSXCPU.cc:310
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
UNREACHABLE
#define UNREACHABLE
Definition: unreachable.hh:38
openmsx::CacheLine::NUM
constexpr unsigned NUM
Definition: CacheLine.hh:8
openmsx::MSXCPU::invalidateAllSlotsRWCache
void invalidateAllSlotsRWCache(word start, unsigned size)
Invalidate the CPU its cache for the interval [start, start + size) For example MSXMemoryMapper and M...
Definition: MSXCPU.cc:182
openmsx::MSXCPU::CPU_Z80
@ CPU_Z80
Definition: MSXCPU.hh:31
openmsx::InfoCommand
Definition: InfoCommand.hh:12
openmsx::MSXMotherBoard
Definition: MSXMotherBoard.hh:60
openmsx::MSXCPU
Definition: MSXCPU.hh:29
openmsx::MSXCPU::CPU_R800
@ CPU_R800
Definition: MSXCPU.hh:31
openmsx::CPUBase
Definition: CPUCore.hh:27
openmsx::MSXCPU::raiseNMI
void raiseNMI()
This method raises a non-maskable interrupt.
Definition: MSXCPU.cc:299
openmsx::MSXCPU::~MSXCPU
~MSXCPU()
Definition: MSXCPU.cc:64
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::MSXCPU::setActiveCPU
void setActiveCPU(CPUType cpu)
Switch between Z80/R800.
Definition: MSXCPU.cc:94
openmsx::CacheLine::SIZE
constexpr unsigned SIZE
Definition: CacheLine.hh:7
openmsx::MSXMotherBoard::getScheduler
Scheduler & getScheduler()
Definition: MSXMotherBoard.hh:118
openmsx::MSXCPU::invalidateRCache
void invalidateRCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowRead)
Definition: MSXCPU.cc:260
openmsx::MSXCPU::getRegisters
CPURegs & getRegisters()
Definition: MSXCPU.cc:339
openmsx::MSXCPU::lowerIRQ
void lowerIRQ()
This methods lowers the maskable interrupt again.
Definition: MSXCPU.cc:294
Scheduler.hh
openmsx::CacheLine::LOW
constexpr unsigned LOW
Definition: CacheLine.hh:9
outer.hh
openmsx::MSXCPU::updateVisiblePage
void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
Inform CPU of bank switch.
Definition: MSXCPU.cc:164
ProfileCounters::tick
void tick(ENUM e) const
Definition: ProfileCounters.hh:97
openmsx::MSXCPU::raiseIRQ
void raiseIRQ()
This method raises a maskable interrupt.
Definition: MSXCPU.cc:289
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
openmsx::MSXCPU::setZ80Freq
void setZ80Freq(unsigned freq)
Switch the Z80 clock freq.
Definition: MSXCPU.cc:316
MSXCPUInterface.hh
openmsx::Z80TYPE
Definition: Z80.hh:13
openmsx::MSXCPU::setDRAMmode
void setDRAMmode(bool dram)
Sets DRAM or ROM mode (influences memory access speed for R800).
Definition: MSXCPU.cc:105
Z80.hh
openmsx::R800TYPE
Definition: R800.hh:14
openmsx::TclObject
Definition: TclObject.hh:22
openmsx::MSXCPU::fillWCache
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss, const byte *disallowWrite)
Definition: MSXCPU.cc:283
openmsx::MSXCPU::exitCPULoopSync
void exitCPULoopSync()
See CPUCore::exitCPULoopsync()
Definition: MSXCPU.cc:130
CPUCore.hh
unreachable.hh
openmsx::MSXMotherBoard::getDebugger
Debugger & getDebugger()
Definition: MSXMotherBoard.hh:123
openmsx::serialize
void serialize(Archive &ar, T &t, unsigned version)
Definition: serialize_core.hh:41
ranges::fill
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:191
openmsx::CPURegs
Definition: CPURegs.hh:20
R800.hh
openmsx::Interpreter
Definition: Interpreter.hh:17
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
MSXMotherBoard.hh
openmsx::MSXCPU::disasmCommand
void disasmCommand(Interpreter &interp, span< const TclObject > tokens, TclObject &result) const
Definition: MSXCPU.cc:357
openmsx::MSXCPU::setNextSyncPoint
void setNextSyncPoint(EmuTime::param time)
Definition: MSXCPU.cc:147
Debugger.hh
openmsx::MSXCPU::fillRCache
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss, const byte *disallowRead)
Definition: MSXCPU.cc:278
openmsx::CPUCore
Definition: CPUCore.hh:50