1#ifndef MSXCPUINTERFACE_HH
2#define MSXCPUINTERFACE_HH
107 int ps,
int ss,
unsigned base,
unsigned size);
109 int ps,
int ss,
unsigned base,
unsigned size);
134 return readMemSlow(address, time);
136 return visibleDevices[address >> 14]->readMem(address, time);
145 writeMemSlow(address, value, time);
148 visibleDevices[address>>14]->writeMem(address, value, time);
156 return IO_In[port & 0xFF]->readIO(port, time);
164 IO_Out[port & 0xFF]->writeIO(port, value, time);
184 return visibleDevices[start >> 14]->getReadCacheLine(start);
204 return visibleDevices[start >> 14]->getWriteCacheLine(start);
225 void fillRWCache(
unsigned start,
unsigned size,
const byte* rData,
byte* wData,
int ps,
int ss);
226 void fillRCache (
unsigned start,
unsigned size,
const byte* rData,
int ps,
int ss);
227 void fillWCache (
unsigned start,
unsigned size,
byte* wData,
int ps,
int ss);
233 [[nodiscard]]
byte peekMem(
word address, EmuTime::param time)
const;
234 [[nodiscard]]
byte peekSlottedMem(
unsigned address, EmuTime::param time)
const;
237 EmuTime::param time);
242 std::span<
const std::unique_ptr<MSXDevice>> allowed)
const;
243 [[nodiscard]]
bool isExpanded(
int ps)
const {
return expanded[ps] != 0; }
246 [[nodiscard]]
auto getPrimarySlot (
int page)
const {
return primarySlotState[page]; }
257 void setWatchPoint(
const std::shared_ptr<WatchPoint>& watchPoint);
270 [[nodiscard]]
static bool isBreaked() {
return breaked; }
278 return !breakPoints.empty() || !conditions.empty();
283 if (conditions.empty() && (range.first == range.second)) {
303 template<
typename Archive>
304 void serialize(Archive& ar,
unsigned version);
307 byte readMemSlow(
word address, EmuTime::param time);
308 void writeMemSlow(
word address,
byte value, EmuTime::param time);
310 MSXDevice*& getDevicePtr(
byte port,
bool isIn);
312 void register_IO (
int port,
bool isIn,
315 void testRegisterSlot(
const MSXDevice& device,
316 int ps,
int ss,
unsigned base,
unsigned size);
318 int ps,
int ss,
unsigned base,
unsigned size);
320 int ps,
int ss,
unsigned base,
unsigned size);
324 BreakPoints::const_iterator> range);
326 void removeAllWatchPoints();
329 unsigned value = ~0u);
333 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
334 void write(
unsigned address,
byte value, EmuTime::param time)
override;
337 struct SlottedMemoryDebug final : SimpleDebuggable {
338 explicit SlottedMemoryDebug(MSXMotherBoard& motherBoard);
339 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
340 void write(
unsigned address,
byte value, EmuTime::param time)
override;
341 } slottedMemoryDebug;
343 struct IODebug final : SimpleDebuggable {
344 explicit IODebug(MSXMotherBoard& motherBoard);
345 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
346 void write(
unsigned address,
byte value, EmuTime::param time)
override;
349 struct SlotInfo final : InfoTopic {
350 explicit SlotInfo(InfoCommand& machineInfoCommand);
351 void execute(std::span<const TclObject> tokens,
352 TclObject& result)
const override;
353 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
356 struct SubSlottedInfo final : InfoTopic {
357 explicit SubSlottedInfo(InfoCommand& machineInfoCommand);
358 void execute(std::span<const TclObject> tokens,
359 TclObject& result)
const override;
360 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
363 struct ExternalSlotInfo final : InfoTopic {
364 explicit ExternalSlotInfo(InfoCommand& machineInfoCommand);
365 void execute(std::span<const TclObject> tokens,
366 TclObject& result)
const override;
367 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
370 struct IOInfo : InfoTopic {
371 IOInfo(InfoCommand& machineInfoCommand,
const char* name);
372 void helper(std::span<const TclObject> tokens,
373 TclObject& result, std::span<MSXDevice*, 256> devices)
const;
374 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
378 struct IInfo final : IOInfo {
379 explicit IInfo(InfoCommand& machineInfoCommand)
380 : IOInfo(machineInfoCommand,
"input_port") {}
381 void execute(std::span<const TclObject> tokens,
382 TclObject& result)
const override;
384 struct OInfo final : IOInfo {
385 explicit OInfo(InfoCommand& machineInfoCommand)
386 : IOInfo(machineInfoCommand,
"output_port") {}
387 void execute(std::span<const TclObject> tokens,
388 TclObject& result)
const override;
397 void updateVisible(
byte page);
398 inline void updateVisible(
byte page,
byte ps,
byte ss);
399 void setSubSlot(
byte primSlot,
byte value);
401 std::unique_ptr<DummyDevice> dummyDevice;
404 MSXMotherBoard& motherBoard;
405 BooleanSetting& pauseSetting;
407 std::unique_ptr<VDPIODelay> delayDevice;
409 std::array<byte, CacheLine::NUM> disallowReadCache;
410 std::array<byte, CacheLine::NUM> disallowWriteCache;
411 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> readWatchSet;
412 std::array<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> writeWatchSet;
414 struct GlobalRwInfo {
417 [[nodiscard]]
constexpr bool operator==(
const GlobalRwInfo&)
const =
default;
419 std::vector<GlobalRwInfo> globalReads;
420 std::vector<GlobalRwInfo> globalWrites;
422 std::array<MSXDevice*, 256> IO_In;
423 std::array<MSXDevice*, 256> IO_Out;
424 std::array<std::array<std::array<MSXDevice*, 4>, 4>, 4> slotLayout;
425 std::array<MSXDevice*, 4> visibleDevices;
426 std::array<byte, 4> subSlotRegister;
427 std::array<byte, 4> primarySlotState;
428 std::array<byte, 4> secondarySlotState;
429 byte initialPrimarySlots;
430 std::array<unsigned, 4> expanded;
432 bool fastForward =
false;
438 static inline bool breaked =
false;
444template<
unsigned BEGIN,
unsigned END = BEGIN + 1>
447 [[nodiscard]]
unsigned begin()
const {
return BEGIN; }
448 [[nodiscard]]
unsigned end()
const {
return END; }
454 for (
auto i = ct_interval.begin(); i != ct_interval.end(); ++i) {
459 auto front_interval,
auto... tail_intervals)
466template<
typename MSXDEVICE,
typename... CT_INTERVALS>
469 void execute(std::invocable<MSXCPUInterface&, MSXDevice&, unsigned>
auto action)
471 auto& dev =
static_cast<MSXDEVICE&
>(*this);
472 auto& cpu = dev.getCPUInterface();
474 [&](
unsigned addr) { action(cpu, dev, addr); },
479template<
typename MSXDEVICE,
typename... CT_INTERVALS>
502template<
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 setWatchPoint(const std::shared_ptr< WatchPoint > &watchPoint)
void invalidateRWCache(word start, unsigned size, int ps, int ss)
void insertBreakPoint(BreakPoint bp)
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 unregisterMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
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 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
bool checkBreakPoints(unsigned pc)
MSXCPUInterface & operator=(const MSXCPUInterface &)=delete
void serialize(Archive &ar, unsigned version)
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
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