1#ifndef MSXCPUINTERFACE_HH
2#define MSXCPUINTERFACE_HH
119 int ps,
int ss,
unsigned base,
unsigned size);
121 int ps,
int ss,
unsigned base,
unsigned size);
146 return readMemSlow(address, time);
148 return visibleDevices[address >> 14]->readMem(address, time);
157 writeMemSlow(address, value, time);
160 visibleDevices[address>>14]->writeMem(address, value, time);
168 return IO_In[port & 0xFF]->readIO(port, time);
176 IO_Out[port & 0xFF]->writeIO(port, value, time);
196 return visibleDevices[start >> 14]->getReadCacheLine(start);
216 return visibleDevices[start >> 14]->getWriteCacheLine(start);
237 void fillRWCache(
unsigned start,
unsigned size,
const byte* rData,
byte* wData,
int ps,
int ss);
238 void fillRCache (
unsigned start,
unsigned size,
const byte* rData,
int ps,
int ss);
239 void fillWCache (
unsigned start,
unsigned size,
byte* wData,
int ps,
int ss);
245 [[nodiscard]]
byte peekMem(
word address, EmuTime::param time)
const;
246 [[nodiscard]]
byte peekSlottedMem(
unsigned address, EmuTime::param time)
const;
249 EmuTime::param time);
254 std::span<
const std::unique_ptr<MSXDevice>> allowed)
const;
255 [[nodiscard]]
bool isExpanded(
int ps)
const {
return expanded[ps] != 0; }
258 [[nodiscard]]
auto getPrimarySlot (
int page)
const {
return primarySlotState[page]; }
269 void setWatchPoint(
const std::shared_ptr<WatchPoint>& watchPoint);
282 [[nodiscard]]
static bool isBreaked() {
return breaked; }
290 return !breakPoints.empty() || !conditions.empty();
295 if (conditions.empty() && (range.first == range.second)) {
315 template<
typename Archive>
316 void serialize(Archive& ar,
unsigned version);
319 byte readMemSlow(
word address, EmuTime::param time);
320 void writeMemSlow(
word address,
byte value, EmuTime::param time);
322 MSXDevice*& getDevicePtr(
byte port,
bool isIn);
324 void register_IO (
int port,
bool isIn,
327 void testRegisterSlot(
const MSXDevice& device,
328 int ps,
int ss,
unsigned base,
unsigned size);
330 int ps,
int ss,
unsigned base,
unsigned size);
332 int ps,
int ss,
unsigned base,
unsigned size);
336 BreakPoints::const_iterator> range);
338 void removeAllWatchPoints();
341 unsigned value = ~0u);
345 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
346 void write(
unsigned address,
byte value, EmuTime::param time)
override;
349 struct SlottedMemoryDebug final : SimpleDebuggable {
350 explicit SlottedMemoryDebug(MSXMotherBoard& motherBoard);
351 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
352 void write(
unsigned address,
byte value, EmuTime::param time)
override;
353 } slottedMemoryDebug;
355 struct IODebug final : SimpleDebuggable {
356 explicit IODebug(MSXMotherBoard& motherBoard);
357 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
358 void write(
unsigned address,
byte value, EmuTime::param time)
override;
361 struct SlotInfo final : InfoTopic {
362 explicit SlotInfo(InfoCommand& machineInfoCommand);
363 void execute(std::span<const TclObject> tokens,
364 TclObject& result)
const override;
365 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
368 struct SubSlottedInfo final : InfoTopic {
369 explicit SubSlottedInfo(InfoCommand& machineInfoCommand);
370 void execute(std::span<const TclObject> tokens,
371 TclObject& result)
const override;
372 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
375 struct ExternalSlotInfo final : InfoTopic {
376 explicit ExternalSlotInfo(InfoCommand& machineInfoCommand);
377 void execute(std::span<const TclObject> tokens,
378 TclObject& result)
const override;
379 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
382 struct IOInfo : InfoTopic {
383 IOInfo(InfoCommand& machineInfoCommand,
const char* name);
384 void helper(std::span<const TclObject> tokens,
385 TclObject& result, std::span<MSXDevice*, 256> devices)
const;
386 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
390 struct IInfo final : IOInfo {
391 explicit IInfo(InfoCommand& machineInfoCommand)
392 : IOInfo(machineInfoCommand,
"input_port") {}
393 void execute(std::span<const TclObject> tokens,
394 TclObject& result)
const override;
396 struct OInfo final : IOInfo {
397 explicit OInfo(InfoCommand& machineInfoCommand)
398 : IOInfo(machineInfoCommand,
"output_port") {}
399 void execute(std::span<const TclObject> tokens,
400 TclObject& result)
const override;
409 void updateVisible(
byte page);
410 inline void updateVisible(
byte page,
byte ps,
byte ss);
411 void setSubSlot(
byte primSlot,
byte value);
413 std::unique_ptr<DummyDevice> dummyDevice;
416 MSXMotherBoard& motherBoard;
417 BooleanSetting& pauseSetting;
419 std::unique_ptr<VDPIODelay> delayDevice;
421 std::array<byte, CacheLine::NUM> disallowReadCache;
422 std::array<byte, CacheLine::NUM> disallowWriteCache;
423 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> readWatchSet;
424 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> writeWatchSet;
426 struct GlobalRwInfo {
429 [[nodiscard]]
constexpr bool operator==(
const GlobalRwInfo&)
const =
default;
431 std::vector<GlobalRwInfo> globalReads;
432 std::vector<GlobalRwInfo> globalWrites;
434 std::array<MSXDevice*, 256> IO_In;
435 std::array<MSXDevice*, 256> IO_Out;
436 std::array<std::array<std::array<MSXDevice*, 4>, 4>, 4> slotLayout;
437 std::array<MSXDevice*, 4> visibleDevices;
438 std::array<byte, 4> subSlotRegister;
439 std::array<byte, 4> primarySlotState;
440 std::array<byte, 4> secondarySlotState;
441 byte initialPrimarySlots;
442 std::array<unsigned, 4> expanded;
444 bool fastForward =
false;
450 static inline bool breaked =
false;
456template<
unsigned BEGIN,
unsigned END = BEGIN + 1>
459 [[nodiscard]]
unsigned begin()
const {
return BEGIN; }
460 [[nodiscard]]
unsigned end()
const {
return END; }
466 for (
auto i = ct_interval.begin(); i != ct_interval.end(); ++i) {
471 auto front_interval,
auto... tail_intervals)
478template<
typename MSXDEVICE,
typename... CT_INTERVALS>
481 void execute(std::invocable<MSXCPUInterface&, MSXDevice&, unsigned>
auto action)
483 auto& dev =
static_cast<MSXDEVICE&
>(*this);
484 auto& cpu = dev.getCPUInterface();
486 [&](
unsigned addr) { action(cpu, dev, addr); },
491template<
typename MSXDEVICE,
typename... CT_INTERVALS>
514template<
typename MSXDEVICE,
typename... CT_INTERVALS>
void tick(CacheLineCounters e) const
Base class for CPU breakpoints.
General debugger condition Like breakpoints, but not tied to a specific address.
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
void unregister_IO_In_range(byte port, unsigned num, MSXDevice *device)
void setWatchPoint(const std::shared_ptr< WatchPoint > &watchPoint)
void invalidateRWCache(word start, unsigned size, int ps, int ss)
void insertBreakPoint(BreakPoint bp)
void unregister_IO_Out_range(byte port, unsigned num, MSXDevice *device)
std::vector< DebugCondition > Conditions
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
MSXDevice * getMSXDevice(int ps, int ss, int page)
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss)
auto getPrimarySlot(int page) const
void unregister_IO_In(byte port, MSXDevice *device)
DummyDevice & getDummyDevice()
void writeIO(word port, byte value, EmuTime::param time)
This writes a byte to the given IO-port.
bool replace_IO_Out(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
void changeExpanded(bool newExpanded)
byte * getWriteCacheLine(word start)
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
void unregister_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
void unregisterMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
void register_IO_In_range(byte port, unsigned num, MSXDevice *device)
void removeCondition(const DebugCondition &cond)
byte peekMem(word address, EmuTime::param time) const
Peek memory location.
byte readIRQVector() const
CPU uses this method to read 'extra' data from the data bus used in interrupt routines.
byte readIO(word port, EmuTime::param time)
This read a byte from the given IO-port.
void unregister_IO_InOut(byte port, MSXDevice *device)
void testUnsetExpanded(int ps, std::span< const std::unique_ptr< MSXDevice > > allowed) const
MSXCPUInterface & operator=(MSXCPUInterface &&)=delete
static const Conditions & getConditions()
void writeSlottedMem(unsigned address, byte value, EmuTime::param time)
void setPrimarySlots(byte value)
void invalidateRCache(word start, unsigned size, int ps, int ss)
void unregisterGlobalWrite(MSXDevice &device, word address)
void unregisterGlobalRead(MSXDevice &device, word address)
byte peekSlottedMem(unsigned address, EmuTime::param time) const
void removeWatchPoint(std::shared_ptr< WatchPoint > watchPoint)
std::vector< std::shared_ptr< WatchPoint > > WatchPoints
byte readMem(word address, EmuTime::param time)
This reads a byte from the currently selected device.
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss)
void reset()
Reset (the slot state)
void setCondition(DebugCondition cond)
void invalidateWCache(word start, unsigned size, int ps, int ss)
void unsetExpanded(int ps)
bool isFastForward() const
const WatchPoints & getWatchPoints() const
void register_IO_InOut(byte port, MSXDevice *device)
Convenience methods for {un}register_IO_{In,Out}.
bool checkBreakPoints(unsigned pc)
MSXCPUInterface & operator=(const MSXCPUInterface &)=delete
void serialize(Archive &ar, unsigned version)
void register_IO_Out_range(byte port, unsigned num, MSXDevice *device)
void registerGlobalRead(MSXDevice &device, word address)
(Un)register global read.
void writeMem(word address, byte value, EmuTime::param time)
This writes a byte to the currently selected device.
byte readSlottedMem(unsigned address, EmuTime::param time)
void registerMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
Devices can register themself in the MSX slot structure.
static const BreakPoints & getBreakPoints()
void removeBreakPoint(const BreakPoint &bp)
void unregister_IO_Out(byte port, MSXDevice *device)
void registerGlobalWrite(MSXDevice &device, word address)
(Un)register global writes.
MSXCPUInterface(MSXCPUInterface &&)=delete
std::vector< BreakPoint > BreakPoints
static bool anyBreakPoints()
MSXDevice * getVisibleMSXDevice(int page)
bool replace_IO_In(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
These methods replace a previously registered device with a new one.
void setFastForward(bool fastForward_)
const byte * getReadCacheLine(word start) const
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
MSXCPUInterface(const MSXCPUInterface &)=delete
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss)
bool isExpanded(int ps) const
auto getSecondarySlot(int page) const
void register_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
byte read(unsigned address) override
void write(unsigned address, byte value) override
This file implemented 3 utility functions:
bool operator==(const BooleanInput &x, const BooleanInput &y)
constexpr bool PROFILE_CACHELINES
std::ostream & operator<<(std::ostream &os, EnumTypeName< CacheLineCounters >)
uint16_t word
16 bit unsigned integer
void foreach_ct_interval(std::invocable< unsigned > auto action, auto ct_interval)
auto equal_range(ForwardRange &&range, const T &value, Compare comp={})
void execute(std::invocable< MSXCPUInterface &, MSXDevice &, unsigned > auto action)
GlobalReadClient & operator=(GlobalReadClient &&)=delete
GlobalReadClient(const GlobalReadClient &)=delete
GlobalReadClient & operator=(const GlobalReadClient &)=delete
GlobalReadClient(GlobalReadClient &&)=delete
GlobalWriteClient(const GlobalWriteClient &)=delete
GlobalWriteClient(GlobalWriteClient &&)=delete
GlobalWriteClient & operator=(GlobalWriteClient &&)=delete
GlobalWriteClient & operator=(const GlobalWriteClient &)=delete