openMSX
MSXCPUInterface.hh
Go to the documentation of this file.
1 #ifndef MSXCPUINTERFACE_HH
2 #define MSXCPUINTERFACE_HH
3 
4 #include "CacheLine.hh"
5 #include "MSXDevice.hh"
6 #include "WatchPoint.hh"
7 #include "openmsx.hh"
8 #include "noncopyable.hh"
9 #include "likely.hh"
10 #include <bitset>
11 #include <vector>
12 #include <map>
13 #include <memory>
14 
15 namespace openmsx {
16 
17 class VDPIODelay;
18 class DummyDevice;
19 class MSXMotherBoard;
20 class MSXCPU;
21 class CliComm;
22 class MemoryDebug;
23 class SlottedMemoryDebug;
24 class IODebug;
25 class SlotInfo;
26 class SubSlottedInfo;
27 class ExternalSlotInfo;
28 class IOInfo;
29 class BreakPoint;
30 class DebugCondition;
31 
33 {
34 public:
35  explicit MSXCPUInterface(MSXMotherBoard& motherBoard);
37 
43  void register_IO_In(byte port, MSXDevice* device);
44  void unregister_IO_In(byte port, MSXDevice* device);
45 
51  void register_IO_Out(byte port, MSXDevice* device);
52  void unregister_IO_Out(byte port, MSXDevice* device);
53 
60  void registerMemDevice(MSXDevice& device,
61  int primSl, int secSL, int base, int size);
62  void unregisterMemDevice(MSXDevice& device,
63  int primSl, int secSL, int base, int size);
64 
68  void registerGlobalWrite(MSXDevice& device, word address);
69  void unregisterGlobalWrite(MSXDevice& device, word address);
70 
74  void reset();
75 
79  inline byte readMem(word address, EmuTime::param time) {
80  if (unlikely(disallowReadCache[address >> CacheLine::BITS])) {
81  return readMemSlow(address, time);
82  }
83  return visibleDevices[address >> 14]->readMem(address, time);
84  }
85 
89  inline void writeMem(word address, byte value, EmuTime::param time) {
90  if (unlikely(disallowWriteCache[address >> CacheLine::BITS])) {
91  writeMemSlow(address, value, time);
92  }
93  visibleDevices[address>>14]->writeMem(address, value, time);
94  }
95 
100  inline byte readIO(word port, EmuTime::param time) {
101  return IO_In[port & 0xFF]->readIO(port, time);
102  }
103 
108  inline void writeIO(word port, byte value, EmuTime::param time) {
109  IO_Out[port & 0xFF]->writeIO(port, value, time);
110  }
111 
124  inline const byte* getReadCacheLine(word start) const {
125  if (unlikely(disallowReadCache[start >> CacheLine::BITS])) {
126  return nullptr;
127  }
128  return visibleDevices[start >> 14]->getReadCacheLine(start);
129  }
130 
143  inline byte* getWriteCacheLine(word start) const {
144  if (unlikely(disallowWriteCache[start >> CacheLine::BITS])) {
145  return nullptr;
146  }
147  return visibleDevices[start >> 14]->getWriteCacheLine(start);
148  }
149 
155 
156  /*
157  * Should only be used by PPI
158  * TODO: make private / friend
159  */
160  void setPrimarySlots(byte value);
161 
166  byte peekMem(word address, EmuTime::param time) const;
167  byte peekSlottedMem(unsigned address, EmuTime::param time) const;
168  byte readSlottedMem(unsigned address, EmuTime::param time);
169  void writeSlottedMem(unsigned address, byte value,
170  EmuTime::param time);
171 
172  void setExpanded(int ps);
173  void unsetExpanded(int ps);
174  void testUnsetExpanded(int ps, std::vector<MSXDevice*> allowed) const;
175  inline bool isExpanded(int ps) const { return expanded[ps] != 0; }
176  void changeExpanded(bool isExpanded);
177 
179 
180  static void insertBreakPoint(const std::shared_ptr<BreakPoint>& bp);
181  static void removeBreakPoint(const BreakPoint& bp);
182  // note: must be shared_ptr (not unique_ptr), see checkBreakPoints()
183  // TODO use multi_set sorted on BreakPoint->getAddress()
184  typedef std::multimap<word, std::shared_ptr<BreakPoint>> BreakPoints;
185  static const BreakPoints& getBreakPoints();
186 
187  void setWatchPoint(const std::shared_ptr<WatchPoint>& watchPoint);
188  void removeWatchPoint(std::shared_ptr<WatchPoint> watchPoint);
189  // note: must be shared_ptr (not unique_ptr), see WatchIO::doReadCallback()
190  typedef std::vector<std::shared_ptr<WatchPoint>> WatchPoints;
191  const WatchPoints& getWatchPoints() const;
192 
193  static void setCondition(const std::shared_ptr<DebugCondition>& cond);
194  static void removeCondition(const DebugCondition& cond);
195  // note: must be shared_ptr (not unique_ptr), see checkBreakPoints()
196  typedef std::vector<std::shared_ptr<DebugCondition>> Conditions;
197  static const Conditions& getConditions();
198 
199  static bool isBreaked() { return breaked; }
200  void doBreak();
201  void doStep();
202  void doContinue();
203 
204  // should only be used by CPUCore
205  static bool isStep() { return step; }
206  static void setStep (bool x) { step = x; }
207  static bool isContinue() { return continued; }
208  static void setContinue(bool x) { continued = x; }
209 
210  // breakpoint methods used by CPUCore
211  static bool anyBreakPoints()
212  {
213  return !breakPoints.empty() || !conditions.empty();
214  }
215  static bool checkBreakPoints(unsigned pc)
216  {
217  auto range = breakPoints.equal_range(pc);
218  if (conditions.empty() && (range.first == range.second)) {
219  return false;
220  }
221 
222  // slow path non-inlined
223  checkBreakPoints(range);
224  return isBreaked();
225  }
226 
227  // cleanup global variables
228  static void cleanup();
229 
230  // In fast-forward mode, breakpoints, watchpoints and conditions should
231  // not trigger.
232  void setFastForward(bool fastForward_) { fastForward = fastForward_; }
233  bool isFastForward() const { return fastForward; }
234 
235  template<typename Archive>
236  void serialize(Archive& ar, unsigned version);
237 
238 private:
239  byte readMemSlow(word address, EmuTime::param time);
240  void writeMemSlow(word address, byte value, EmuTime::param time);
241 
242  MSXDevice*& getDevicePtr(byte port, bool isIn);
243 
244  void register_IO (int port, bool isIn,
245  MSXDevice*& devicePtr, MSXDevice* device);
246  void unregister_IO(MSXDevice*& devicePtr, MSXDevice* device);
247  void testRegisterSlot(MSXDevice& device,
248  int ps, int ss, int base, int size);
249  void registerSlot(MSXDevice& device,
250  int ps, int ss, int base, int size);
251  void unregisterSlot(MSXDevice& device,
252  int ps, int ss, int base, int size);
253 
254 
255  static void checkBreakPoints(std::pair<BreakPoints::const_iterator,
256  BreakPoints::const_iterator> range);
257 
258  void removeAllWatchPoints();
259  void registerIOWatch (WatchPoint& watchPoint, MSXDevice** devices);
260  void unregisterIOWatch(WatchPoint& watchPoint, MSXDevice** devices);
261  void updateMemWatch(WatchPoint::Type type);
262  void executeMemWatch(WatchPoint::Type type, unsigned address,
263  unsigned value = ~0u);
264 
265  void doContinue2();
266 
267  friend class SlotInfo;
268  friend class IODebug;
269  friend class IOInfo;
270  const std::unique_ptr<MemoryDebug> memoryDebug;
271  const std::unique_ptr<SlottedMemoryDebug> slottedMemoryDebug;
272  const std::unique_ptr<IODebug> ioDebug;
273  const std::unique_ptr<SlotInfo> slotInfo;
274  const std::unique_ptr<SubSlottedInfo> subSlottedInfo;
275  const std::unique_ptr<ExternalSlotInfo> externalSlotInfo;
276  const std::unique_ptr<IOInfo> inputPortInfo;
277  const std::unique_ptr<IOInfo> outputPortInfo;
278 
285  void updateVisible(int page);
286  inline void updateVisible(int page, int ps, int ss);
287  void setSubSlot(byte primSlot, byte value);
288 
289  std::unique_ptr<DummyDevice> dummyDevice;
290  MSXCPU& msxcpu;
291  CliComm& cliComm;
292  MSXMotherBoard& motherBoard;
293 
294  std::unique_ptr<VDPIODelay> delayDevice;
295 
296  byte disallowReadCache [CacheLine::NUM];
297  byte disallowWriteCache[CacheLine::NUM];
298  std::bitset<CacheLine::SIZE> readWatchSet [CacheLine::NUM];
299  std::bitset<CacheLine::SIZE> writeWatchSet[CacheLine::NUM];
300 
301  struct GlobalWriteInfo {
302  MSXDevice* device;
303  word addr;
304  bool operator==(const GlobalWriteInfo& rhs) const {
305  return (device == rhs.device) &&
306  (addr == rhs.addr);
307  }
308  };
309  std::vector<GlobalWriteInfo> globalWrites;
310 
311  MSXDevice* IO_In [256];
312  MSXDevice* IO_Out[256];
313  MSXDevice* slotLayout[4][4][4];
314  MSXDevice* visibleDevices[4];
315  byte subSlotRegister[4];
316  byte primarySlotState[4];
317  byte secondarySlotState[4];
318  unsigned expanded[4];
319 
320  bool fastForward; // no need to serialize
321 
322  // All CPUs (Z80 and R800) of all MSX machines share this state.
323  static BreakPoints breakPoints;
324  WatchPoints watchPoints; // TODO must also be static
325  static Conditions conditions;
326  static bool breaked;
327  static bool continued;
328  static bool step;
329 };
330 
331 } // namespace openmsx
332 
333 #endif