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 : interface(interface_), wp(
std::move(wp_)) {
283 interface.unregisterWatchPoint(*wp);
286 interface.registerWatchPoint(*wp);
290 std::shared_ptr<WatchPoint> wp;
302 [[nodiscard]]
static bool isBreaked() {
return breaked; }
310 return !breakPoints.empty() || !conditions.empty();
325 template<
typename Archive>
326 void serialize(Archive& ar,
unsigned version);
329 byte readMemSlow(
word address, EmuTime::param time);
330 void writeMemSlow(
word address,
byte value, EmuTime::param time);
332 MSXDevice*& getDevicePtr(
byte port,
bool isIn);
334 void register_IO (
int port,
bool isIn,
337 void testRegisterSlot(
const MSXDevice& device,
338 int ps,
int ss,
unsigned base,
unsigned size);
340 int ps,
int ss,
unsigned base,
unsigned size);
342 int ps,
int ss,
unsigned base,
unsigned size);
347 void removeAllWatchPoints();
350 unsigned value = ~0u);
354 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
355 void write(
unsigned address,
byte value, EmuTime::param time)
override;
358 struct SlottedMemoryDebug final : SimpleDebuggable {
359 explicit SlottedMemoryDebug(MSXMotherBoard& motherBoard);
360 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
361 void write(
unsigned address,
byte value, EmuTime::param time)
override;
362 } slottedMemoryDebug;
364 struct IODebug final : SimpleDebuggable {
365 explicit IODebug(MSXMotherBoard& motherBoard);
366 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
367 void write(
unsigned address,
byte value, EmuTime::param time)
override;
370 struct SlotInfo final : InfoTopic {
371 explicit SlotInfo(InfoCommand& machineInfoCommand);
372 void execute(std::span<const TclObject> tokens,
373 TclObject& result)
const override;
374 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
377 struct SubSlottedInfo final : InfoTopic {
378 explicit SubSlottedInfo(InfoCommand& machineInfoCommand);
379 void execute(std::span<const TclObject> tokens,
380 TclObject& result)
const override;
381 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
384 struct ExternalSlotInfo final : InfoTopic {
385 explicit ExternalSlotInfo(InfoCommand& machineInfoCommand);
386 void execute(std::span<const TclObject> tokens,
387 TclObject& result)
const override;
388 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
391 struct IOInfo : InfoTopic {
392 IOInfo(InfoCommand& machineInfoCommand,
const char* name);
393 void helper(std::span<const TclObject> tokens,
394 TclObject& result, std::span<MSXDevice*, 256> devices)
const;
395 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
399 struct IInfo final : IOInfo {
400 explicit IInfo(InfoCommand& machineInfoCommand)
401 : IOInfo(machineInfoCommand,
"input_port") {}
402 void execute(std::span<const TclObject> tokens,
403 TclObject& result)
const override;
405 struct OInfo final : IOInfo {
406 explicit OInfo(InfoCommand& machineInfoCommand)
407 : IOInfo(machineInfoCommand,
"output_port") {}
408 void execute(std::span<const TclObject> tokens,
409 TclObject& result)
const override;
418 void updateVisible(
byte page);
419 inline void updateVisible(
byte page,
byte ps,
byte ss);
420 void setSubSlot(
byte primSlot,
byte value);
422 std::unique_ptr<DummyDevice> dummyDevice;
425 MSXMotherBoard& motherBoard;
426 BooleanSetting& pauseSetting;
428 std::unique_ptr<VDPIODelay> delayDevice;
430 std::array<byte, CacheLine::NUM> disallowReadCache;
431 std::array<byte, CacheLine::NUM> disallowWriteCache;
432 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> readWatchSet;
433 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> writeWatchSet;
435 struct GlobalRwInfo {
438 [[nodiscard]]
constexpr bool operator==(
const GlobalRwInfo&)
const =
default;
440 std::vector<GlobalRwInfo> globalReads;
441 std::vector<GlobalRwInfo> globalWrites;
443 std::array<MSXDevice*, 256> IO_In;
444 std::array<MSXDevice*, 256> IO_Out;
445 std::array<std::array<std::array<MSXDevice*, 4>, 4>, 4> slotLayout;
446 std::array<MSXDevice*, 4> visibleDevices;
447 std::array<byte, 4> subSlotRegister;
448 std::array<byte, 4> primarySlotState;
449 std::array<byte, 4> secondarySlotState;
450 byte initialPrimarySlots;
451 std::array<unsigned, 4> expanded;
453 bool fastForward =
false;
459 static inline bool breaked =
false;
465template<
unsigned BEGIN,
unsigned END = BEGIN + 1>
468 [[nodiscard]]
unsigned begin()
const {
return BEGIN; }
469 [[nodiscard]]
unsigned end()
const {
return END; }
475 for (
auto i = ct_interval.begin(); i != ct_interval.end(); ++i) {
480 auto front_interval,
auto... tail_intervals)
487template<
typename MSXDEVICE,
typename... CT_INTERVALS>
490 void execute(std::invocable<MSXCPUInterface&, MSXDevice&, unsigned>
auto action)
492 auto& dev =
static_cast<MSXDEVICE&
>(*this);
493 auto& cpu = dev.getCPUInterface();
495 [&](
unsigned addr) { action(cpu, dev, addr); },
500template<
typename MSXDEVICE,
typename... CT_INTERVALS>
523template<
typename MSXDEVICE,
typename... CT_INTERVALS>
void tick(CacheLineCounters e) const
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)
auto getScopedChangeWatchpoint(std::shared_ptr< WatchPoint > wp)
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.
static BreakPoints & getBreakPoints()
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
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
WatchPoints & getWatchPoints()
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.
void removeBreakPoint(const BreakPoint &bp)
static Conditions & getConditions()
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)
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
ScopedChangeWatchpoint(MSXCPUInterface &interface_, std::shared_ptr< WatchPoint > wp_)
~ScopedChangeWatchpoint()