39static std::optional<ReadOnlySetting> breakedSetting;
40static unsigned breakedSettingCount = 0;
44static constexpr byte SECONDARY_SLOT_BIT = 0x01;
45static constexpr byte MEMORY_WATCH_BIT = 0x02;
46static constexpr byte GLOBAL_RW_BIT = 0x04;
50 return os <<
"CacheLineCounters";
64 "InvalidateReadWrite",
71 return os << names[size_t(evn.
e)];
75 : memoryDebug (motherBoard_)
76 , slottedMemoryDebug(motherBoard_)
77 , ioDebug (motherBoard_)
78 , slotInfo(motherBoard_.getMachineInfoCommand())
79 , subSlottedInfo(motherBoard_.getMachineInfoCommand())
80 , externalSlotInfo(motherBoard_.getMachineInfoCommand())
81 , inputPortInfo (motherBoard_.getMachineInfoCommand())
82 , outputPortInfo(motherBoard_.getMachineInfoCommand())
84 *motherBoard_.getMachineConfig()))
85 , msxcpu(motherBoard_.getCPU())
86 , cliComm(motherBoard_.getMSXCliComm())
87 , motherBoard(motherBoard_)
96 for (
auto& sub1 : slotLayout) {
97 for (
auto& sub2 : sub1) {
115 for (
auto port :
xrange(0x98, 0x9c)) {
116 assert(IO_In [port] == dummyDevice.get());
117 assert(IO_Out[port] == dummyDevice.get());
118 IO_In [port] = delayDevice.get();
119 IO_Out[port] = delayDevice.get();
123 if (breakedSettingCount++ == 0) {
124 assert(!breakedSetting);
125 breakedSetting.emplace(
127 "breaked",
"Similar to 'debug breaked'",
135 if (--breakedSettingCount == 0) {
136 assert(breakedSetting);
137 breakedSetting.reset();
140 removeAllWatchPoints();
143 for (
auto port :
xrange(0x98, 0x9c)) {
144 assert(IO_In [port] == delayDevice.get());
145 assert(IO_Out[port] == delayDevice.get());
146 IO_In [port] = dummyDevice.get();
147 IO_Out[port] = dummyDevice.get();
154 for (
auto port :
xrange(256)) {
155 if (IO_In[port] != dummyDevice.get()) {
156 std::cout <<
"In-port " << port <<
" still registered "
157 << IO_In[port]->getName() <<
'\n';
160 if (IO_Out[port] != dummyDevice.get()) {
161 std::cout <<
"Out-port " << port <<
" still registered "
162 << IO_Out[port]->getName() <<
'\n';
166 for (
auto primSlot :
xrange(4)) {
168 for (
auto secSlot :
xrange(4)) {
169 for (
auto page :
xrange(4)) {
170 assert(slotLayout[primSlot][secSlot][page] == dummyDevice.get());
177void MSXCPUInterface::removeAllWatchPoints()
179 while (!watchPoints.empty()) {
185byte MSXCPUInterface::readMemSlow(
word address, EmuTime::param time)
191 for (
auto&
g : globalReads) {
194 if (
g.addr == address) [[unlikely]] {
195 g.device->globalRead(address, time);
204 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) [[unlikely]] {
205 return 0xFF ^ subSlotRegister[primarySlotState[3]];
207 return visibleDevices[address >> 14]->readMem(address, time);
211void MSXCPUInterface::writeMemSlow(
word address,
byte value, EmuTime::param time)
214 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) [[unlikely]] {
215 setSubSlot(primarySlotState[3], value);
220 visibleDevices[address>>14]->writeMem(address, value, time);
225 for (
auto&
g : globalWrites) {
228 if (
g.addr == address) [[unlikely]] {
229 g.device->globalWrite(address, value, time);
242 if (expanded[ps] == 0) {
243 for (
auto page :
xrange(4)) {
244 if (slotLayout[ps][0][page] != dummyDevice.get()) {
246 "it's already in use.");
256 std::span<
const std::unique_ptr<MSXDevice>> allowed)
const
259 if (expanded[ps] != 1)
return;
261 std::vector<MSXDevice*> inUse;
264 return (dev == dummyDevice.get()) ||
265 contains(allowed, dev, [](
const auto& d) {
return d.get(); });
268 if (!isAllowed(dev)) {
270 inUse.push_back(dev);
275 for (
auto ss :
xrange(4)) {
276 for (
auto page :
xrange(4)) {
277 MSXDevice* device = slotLayout[ps][ss][page];
279 for (
auto* dev : memDev->getDevices()) {
288 if (inUse.empty())
return;
290 auto msg =
strCat(
"Can't remove slot expander from slot ", ps,
291 " because the following devices are still inserted:");
292 for (
auto& d : inUse) {
303 std::span<const std::unique_ptr<MSXDevice>> dummy;
316 disallowReadCache [0xFF] |= SECONDARY_SLOT_BIT;
317 disallowWriteCache[0xFF] |= SECONDARY_SLOT_BIT;
319 disallowReadCache [0xFF] &= ~SECONDARY_SLOT_BIT;
320 disallowWriteCache[0xFF] &= ~SECONDARY_SLOT_BIT;
325MSXDevice*& MSXCPUInterface::getDevicePtr(
byte port,
bool isIn)
327 MSXDevice** devicePtr = isIn ? &IO_In[port] : &IO_Out[port];
329 devicePtr = &watch->getDevicePtr();
331 if (*devicePtr == delayDevice.get()) {
332 devicePtr = isIn ? &delayDevice->getInDevicePtr (port)
333 : &delayDevice->getOutDevicePtr(port);
340 MSXDevice*& devicePtr = getDevicePtr(port,
true);
341 register_IO(port,
true, devicePtr, device);
346 MSXDevice*& devicePtr = getDevicePtr(port,
true);
347 unregister_IO(devicePtr, device);
352 MSXDevice*& devicePtr = getDevicePtr(port,
false);
353 register_IO(port,
false, devicePtr, device);
358 MSXDevice*& devicePtr = getDevicePtr(port,
false);
359 unregister_IO(devicePtr, device);
362void MSXCPUInterface::register_IO(
int port,
bool isIn,
365 if (devicePtr == dummyDevice.get()) {
369 if (
auto* multi =
dynamic_cast<MSXMultiIODevice*
>(devicePtr)) {
371 multi->addDevice(device);
375 multi->addDevice(devicePtr);
376 multi->addDevice(device);
381 if (devices.getAttributeValueAsBool(
"overlap_warning",
true)) {
383 "Conflicting input port 0x",
385 " for devices ", devicePtr->
getName());
393 if (
auto* multi =
dynamic_cast<MSXMultiIODevice*
>(devicePtr)) {
395 multi->removeDevice(device);
396 auto& devices = multi->getDevices();
397 if (devices.size() == 1) {
399 devicePtr = devices.front();
405 assert(devicePtr == device);
406 devicePtr = dummyDevice.get();
413 MSXDevice*& devicePtr = getDevicePtr(port,
true);
414 if (devicePtr != oldDevice) {
418 devicePtr = newDevice;
424 MSXDevice*& devicePtr = getDevicePtr(port,
false);
425 if (devicePtr != oldDevice) {
429 devicePtr = newDevice;
436 "Overlapping memory devices in slot ", ps,
'.', ss,
440void MSXCPUInterface::testRegisterSlot(
441 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
443 auto page = base >> 14;
444 MSXDevice*& slot = slotLayout[ps][ss][page];
445 if (
size == 0x4000) {
447 if (slot != dummyDevice.get()) {
448 reportMemOverlap(ps, ss, *slot, device);
452 if (slot == dummyDevice.get()) {
454 }
else if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
456 if (!multi->canAdd(base,
size)) {
457 reportMemOverlap(ps, ss, *slot, device);
461 reportMemOverlap(ps, ss, *slot, device);
466void MSXCPUInterface::registerSlot(
467 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
469 auto page = narrow<byte>(base >> 14);
470 MSXDevice*& slot = slotLayout[ps][ss][page];
471 if (
size == 0x4000) {
473 assert(slot == dummyDevice.get());
477 if (slot == dummyDevice.get()) {
479 auto* multi =
new MSXMultiMemDevice(device.getHardwareConfig());
480 multi->add(device, base,
size);
482 }
else if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
484 assert(multi->canAdd(base,
size));
485 multi->add(device, base,
size);
495void MSXCPUInterface::unregisterSlot(
496 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
498 auto page = narrow<byte>(base >> 14);
499 MSXDevice*& slot = slotLayout[ps][ss][page];
500 if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
502 multi->remove(device, base,
size);
503 if (multi->empty()) {
505 slot = dummyDevice.get();
509 assert(slot == &device);
510 slot = dummyDevice.get();
517 MSXDevice& device,
int ps,
int ss,
unsigned base_,
unsigned size_)
521 "Slot ", ps,
'.', ss,
522 " does not exist because slot is not expanded.");
530 auto partialSize =
std::min(
size, ((base + 0x4000) & ~0x3FFF) - base);
531 testRegisterSlot(device, ps, ss, base, partialSize);
539 auto partialSize =
std::min(
size, ((base + 0x4000) & ~0x3FFF) - base);
540 registerSlot(device, ps, ss, base, partialSize);
547 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
551 auto partialSize =
std::min(
size, ((base + 0x4000) & ~0x3FFF) - base);
552 unregisterSlot(device, ps, ss, base, partialSize);
560 globalWrites.push_back({&device, address});
568 GlobalRwInfo info = { &device, address };
571 for (
auto&
g : globalWrites) {
584 globalReads.push_back({&device, address});
592 GlobalRwInfo info = { &device, address };
595 for (
auto&
g : globalReads) {
606ALWAYS_INLINE void MSXCPUInterface::updateVisible(
byte page,
byte ps,
byte ss)
608 MSXDevice* newDevice = slotLayout[ps][ss][page];
609 if (visibleDevices[page] != newDevice) {
610 visibleDevices[page] = newDevice;
614void MSXCPUInterface::updateVisible(
byte page)
616 updateVisible(page, primarySlotState[page], secondarySlotState[page]);
638 msxcpu.
fillRWCache(start,
size, rData, wData, ps, ss, disallowReadCache, disallowWriteCache);
643 msxcpu.
fillRCache(start,
size, rData, ps, ss, disallowReadCache, disallowWriteCache);
648 msxcpu.
fillWCache(start,
size, wData, ps, ss, disallowReadCache, disallowWriteCache);
653 for (
auto i :
xrange(
byte(4))) {
678 byte ps0 = (value >> 0) & 3;
679 if (primarySlotState[0] != ps0) [[unlikely]] {
680 primarySlotState[0] = ps0;
681 byte ss0 = (subSlotRegister[ps0] >> 0) & 3;
682 secondarySlotState[0] = ss0;
683 updateVisible(0, ps0, ss0);
685 byte ps1 = (value >> 2) & 3;
686 if (primarySlotState[1] != ps1) [[unlikely]] {
687 primarySlotState[1] = ps1;
688 byte ss1 = (subSlotRegister[ps1] >> 2) & 3;
689 secondarySlotState[1] = ss1;
690 updateVisible(1, ps1, ss1);
692 byte ps2 = (value >> 4) & 3;
693 if (primarySlotState[2] != ps2) [[unlikely]] {
694 primarySlotState[2] = ps2;
695 byte ss2 = (subSlotRegister[ps2] >> 4) & 3;
696 secondarySlotState[2] = ss2;
697 updateVisible(2, ps2, ss2);
699 byte ps3 = (value >> 6) & 3;
700 if (primarySlotState[3] != ps3) [[unlikely]] {
701 bool oldExpanded =
isExpanded(primarySlotState[3]);
703 primarySlotState[3] = ps3;
704 byte ss3 = (subSlotRegister[ps3] >> 6) & 3;
705 secondarySlotState[3] = ss3;
706 updateVisible(3, ps3, ss3);
707 if (oldExpanded != newExpanded) [[unlikely]] {
713void MSXCPUInterface::setSubSlot(
byte primSlot,
byte value)
715 subSlotRegister[primSlot] = value;
716 for (
byte page = 0; page < 4; ++page, value >>= 2) {
717 if (primSlot == primarySlotState[page]) {
718 secondarySlotState[page] = value & 3;
727 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) {
728 return 0xFF ^ subSlotRegister[primarySlotState[3]];
730 return visibleDevices[address >> 14]->peekMem(address, time);
736 byte primSlot = (address & 0xC0000) >> 18;
737 byte subSlot = (address & 0x30000) >> 16;
738 byte page = (address & 0x0C000) >> 14;
739 word offset = (address & 0xFFFF);
744 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
745 return 0xFF ^ subSlotRegister[primSlot];
747 return slotLayout[primSlot][subSlot][page]->peekMem(offset, time);
753 byte primSlot = (address & 0xC0000) >> 18;
754 byte subSlot = (address & 0x30000) >> 16;
755 byte page = (address & 0x0C000) >> 14;
756 word offset = (address & 0xFFFF);
761 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
762 return 0xFF ^ subSlotRegister[primSlot];
764 return slotLayout[primSlot][subSlot][page]->peekMem(offset, time);
771 byte primSlot = (address & 0xC0000) >> 18;
772 byte subSlot = (address & 0x30000) >> 16;
773 byte page = (address & 0x0C000) >> 14;
774 word offset = (address & 0xFFFF);
779 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
780 setSubSlot(primSlot, value);
782 slotLayout[primSlot][subSlot][page]->writeMem(offset, value, time);
790 breakPoints.insert(it, std::move(bp));
804 it != breakPoints.end()) {
806 breakPoints.erase(it);
811 std::pair<BreakPoints::const_iterator,
812 BreakPoints::const_iterator> range)
820 for (
auto& p : bpCopy) {
821 bool remove = p.checkAndExecute(globalCliComm, interp);
826 auto condCopy = conditions;
827 for (
auto& c : condCopy) {
828 bool remove = c.checkAndExecute(globalCliComm, interp);
835static void registerIOWatch(WatchPoint& watchPoint, std::span<MSXDevice*, 256> devices)
837 auto& ioWatch = checked_cast<WatchIO&>(watchPoint);
838 unsigned beginPort = ioWatch.getBeginAddress();
839 unsigned endPort = ioWatch.getEndAddress();
840 assert(beginPort <= endPort);
841 assert(endPort < 0x100);
842 for (
unsigned port = beginPort; port <= endPort; ++port) {
843 ioWatch.getDevice(narrow_cast<byte>(port)).getDevicePtr() = devices[port];
844 devices[port] = &ioWatch.getDevice(narrow_cast<byte>(port));
851 watchPoints.push_back(watchPoint);
855 registerIOWatch(*watchPoint, IO_In);
858 registerIOWatch(*watchPoint, IO_Out);
862 updateMemWatch(type);
869static void unregisterIOWatch(
WatchPoint& watchPoint, std::span<MSXDevice*, 256> devices)
871 auto& ioWatch = checked_cast<WatchIO&>(watchPoint);
872 unsigned beginPort = ioWatch.getBeginAddress();
873 unsigned endPort = ioWatch.getEndAddress();
874 assert(beginPort <= endPort);
875 assert(endPort < 0x100);
877 for (
unsigned port = beginPort; port <= endPort; ++port) {
880 while (*prev != &ioWatch.getDevice(narrow_cast<byte>(port))) {
881 prev = &checked_cast<MSXWatchIODevice*>(*prev)->getDevicePtr();
884 *prev = checked_cast<MSXWatchIODevice*>(*prev)->getDevicePtr();
894 it !=
end(watchPoints)) {
897 watchPoints.erase(it);
901 unregisterIOWatch(*watchPoint, IO_In);
904 unregisterIOWatch(*watchPoint, IO_Out);
908 updateMemWatch(type);
919 it != watchPoints.end()) {
927 conditions.push_back(std::move(cond));
934 [](
auto&
e) {
return &
e; }));
941 it != conditions.end()) {
943 conditions.erase(it);
949 std::span<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> watchSet =
954 for (
auto& w : watchPoints) {
955 if (w->getType() == type) {
956 unsigned beginAddr = w->getBeginAddress();
957 unsigned endAddr = w->getEndAddress();
958 assert(beginAddr <= endAddr);
959 assert(endAddr < 0x10000);
960 for (
unsigned addr = beginAddr; addr <= endAddr; ++addr) {
967 if (readWatchSet [i].any()) {
968 disallowReadCache [i] |= MEMORY_WATCH_BIT;
970 disallowReadCache [i] &= ~MEMORY_WATCH_BIT;
972 if (writeWatchSet[i].any()) {
973 disallowWriteCache[i] |= MEMORY_WATCH_BIT;
975 disallowWriteCache[i] &= ~MEMORY_WATCH_BIT;
982 unsigned address,
unsigned value)
984 assert(!watchPoints.empty());
990 TclObject(
int(address)));
992 interp.setVariable(TclObject(
"wp_last_value"),
993 TclObject(
int(value)));
996 auto wpCopy = watchPoints;
997 for (
auto& w : wpCopy) {
998 if ((w->getBeginAddress() <= address) &&
999 (w->getEndAddress() >= address) &&
1000 (w->getType() == type)) {
1001 bool remove = w->checkAndExecute(globalCliComm, interp);
1008 interp.unsetVariable(
"wp_last_address");
1009 interp.unsetVariable(
"wp_last_value");
1016 if (breaked)
return;
1022 breakedSetting->setReadOnlyValue(
TclObject(
"true"));
1042 breakedSetting->setReadOnlyValue(
TclObject(
"false"));
1056 breakPoints.clear();
1062 assert(0 <= ps && ps < 4);
1063 assert(0 <= ss && ss < 4);
1064 assert(0 <= page && page < 4);
1065 return slotLayout[ps][ss][page];
1070MSXCPUInterface::MemoryDebug::MemoryDebug(
MSXMotherBoard& motherBoard_)
1072 "The memory currently visible for the CPU.", 0x10000)
1076byte MSXCPUInterface::MemoryDebug::read(
unsigned address, EmuTime::param time)
1079 return interface.peekMem(narrow<word>(address), time);
1082void MSXCPUInterface::MemoryDebug::write(
unsigned address,
byte value,
1083 EmuTime::param time)
1086 return interface.writeMem(narrow<word>(address), value, time);
1092MSXCPUInterface::SlottedMemoryDebug::SlottedMemoryDebug(
1093 MSXMotherBoard& motherBoard_)
1094 : SimpleDebuggable(motherBoard_,
"slotted memory",
1095 "The memory in slots and subslots.", 0x10000 * 4 * 4)
1099byte MSXCPUInterface::SlottedMemoryDebug::read(
unsigned address, EmuTime::param time)
1102 return interface.peekSlottedMem(address, time);
1105void MSXCPUInterface::SlottedMemoryDebug::write(
unsigned address,
byte value,
1106 EmuTime::param time)
1109 return interface.writeSlottedMem(address, value, time);
1115static unsigned getSlot(
1116 Interpreter& interp,
const TclObject& token,
const std::string& itemName)
1118 unsigned slot = token.getInt(interp);
1120 throw CommandException(itemName,
" must be in range 0..3");
1125MSXCPUInterface::SlotInfo::SlotInfo(
1126 InfoCommand& machineInfoCommand)
1127 : InfoTopic(machineInfoCommand,
"slot")
1131void MSXCPUInterface::SlotInfo::execute(std::span<const TclObject> tokens,
1132 TclObject& result)
const
1134 checkNumArgs(tokens, 5, Prefix{2},
"primary secondary page");
1135 auto& interp = getInterpreter();
1136 unsigned ps = getSlot(interp, tokens[2],
"Primary slot");
1137 unsigned ss = getSlot(interp, tokens[3],
"Secondary slot");
1138 unsigned page = getSlot(interp, tokens[4],
"Page");
1140 if (!interface.isExpanded(narrow<int>(ps))) {
1143 interface.slotLayout[ps][ss][page]->getNameList(result);
1146std::string MSXCPUInterface::SlotInfo::help(std::span<const TclObject> )
const
1148 return "Retrieve name of the device inserted in given "
1149 "primary slot / secondary slot / page.";
1155MSXCPUInterface::SubSlottedInfo::SubSlottedInfo(
1156 InfoCommand& machineInfoCommand)
1157 : InfoTopic(machineInfoCommand,
"issubslotted")
1161void MSXCPUInterface::SubSlottedInfo::execute(std::span<const TclObject> tokens,
1162 TclObject& result)
const
1164 checkNumArgs(tokens, 3,
"primary");
1166 result = interface.isExpanded(narrow<int>(
1167 getSlot(getInterpreter(), tokens[2],
"Slot")));
1170std::string MSXCPUInterface::SubSlottedInfo::help(
1171 std::span<const TclObject> )
const
1173 return "Indicates whether a certain primary slot is expanded.";
1179MSXCPUInterface::ExternalSlotInfo::ExternalSlotInfo(
1180 InfoCommand& machineInfoCommand)
1181 : InfoTopic(machineInfoCommand,
"isexternalslot")
1185void MSXCPUInterface::ExternalSlotInfo::execute(
1186 std::span<const TclObject> tokens, TclObject& result)
const
1188 checkNumArgs(tokens, Between{3, 4},
"primary ?secondary?");
1191 auto& interp = getInterpreter();
1192 switch (tokens.size()) {
1194 ss = narrow<int>(getSlot(interp, tokens[3],
"Secondary slot"));
1197 ps = narrow<int>(getSlot(interp, tokens[2],
"Primary slot"));
1201 auto& manager = interface.motherBoard.getSlotManager();
1202 result = manager.isExternalSlot(ps, ss,
true);
1205std::string MSXCPUInterface::ExternalSlotInfo::help(
1206 std::span<const TclObject> )
const
1208 return "Indicates whether a certain slot is external or internal.";
1214MSXCPUInterface::IODebug::IODebug(MSXMotherBoard& motherBoard_)
1215 : SimpleDebuggable(motherBoard_,
"ioports",
"IO ports.", 0x100)
1219byte MSXCPUInterface::IODebug::read(
unsigned address, EmuTime::param time)
1222 return interface.IO_In[address & 0xFF]->peekIO(narrow<word>(address), time);
1225void MSXCPUInterface::IODebug::write(
unsigned address,
byte value, EmuTime::param time)
1228 interface.writeIO(
word(address), value, time);
1234MSXCPUInterface::IOInfo::IOInfo(InfoCommand& machineInfoCommand,
const char* name_)
1235 : InfoTopic(machineInfoCommand, name_)
1239void MSXCPUInterface::IOInfo::helper(
1240 std::span<const TclObject> tokens, TclObject& result, std::span<MSXDevice*, 256> devices)
const
1242 checkNumArgs(tokens, 3,
"port");
1243 unsigned port = tokens[2].getInt(getInterpreter());
1245 throw CommandException(
"Port must be in range 0..255");
1247 devices[port]->getNameList(result);
1249void MSXCPUInterface::IInfo::execute(
1250 std::span<const TclObject> tokens, TclObject& result)
const
1253 helper(tokens, result, interface.IO_In);
1255void MSXCPUInterface::OInfo::execute(
1256 std::span<const TclObject> tokens, TclObject& result)
const
1259 helper(tokens, result, interface.IO_Out);
1262std::string MSXCPUInterface::IOInfo::help(std::span<const TclObject> )
const
1264 return "Return the name of the device connected to the given IO port.";
1268template<
typename Archive>
1275 if constexpr (!Archive::IS_LOADER) {
1276 for (
auto i :
xrange(4)) {
1277 prim |=
byte(primarySlotState[i] << (2 * i));
1280 ar.serialize(
"primarySlots", prim,
1281 "subSlotRegs", subSlotRegister);
1282 if constexpr (Archive::IS_LOADER) {
1284 for (
auto i :
xrange(
byte(4))) {
1285 setSubSlot(i, subSlotRegister[i]);
1290 ar.serialize(
"vdpDelay", *delayDevice);
void tick(CacheLineCounters e) const
Base class for CPU breakpoints.
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
void printWarning(std::string_view message)
General debugger condition Like breakpoints, but not tied to a specific address.
static std::unique_ptr< VDPIODelay > createVDPIODelay(const HardwareConfig &hwConf, MSXCPUInterface &cpuInterface)
void distributeEvent(Event &&event)
Schedule the given event for delivery.
byte parseSlotMap() const
Parses a slot mapping.
const XMLElement & getDevicesElem() const
void setVariable(const TclObject &name, const TclObject &value)
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)
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)
void unregister_IO_In(byte port, MSXDevice *device)
bool replace_IO_Out(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
void changeExpanded(bool newExpanded)
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.
void testUnsetExpanded(int ps, std::span< const std::unique_ptr< MSXDevice > > allowed) const
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)
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
byte readIRQVector()
CPU uses this method to read 'extra' data from the data bus used in interrupt routines.
bool checkBreakPoints(unsigned pc)
void serialize(Archive &ar, unsigned version)
void registerGlobalRead(MSXDevice &device, word address)
(Un)register global read.
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)
void unregister_IO_Out(byte port, MSXDevice *device)
void registerGlobalWrite(MSXDevice &device, word address)
(Un)register global writes.
std::vector< BreakPoint > BreakPoints
bool replace_IO_In(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
These methods replace a previously registered device with a new one.
MSXCPUInterface(const MSXCPUInterface &)=delete
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss)
bool isExpanded(int ps) const
void invalidateAllSlotsRWCache(word start, unsigned size)
Invalidate the CPU its cache for the interval [start, start + size) For example MSXMemoryMapper and M...
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
Inform CPU of bank switch.
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
Fill the read and write cache lines for a specific slot with the specified value.
void invalidateRCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void exitCPULoopSync()
See CPUCore::exitCPULoopSync()
void invalidateRWCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
Similar to the method above, but only invalidates one specific slot.
void setInterface(MSXCPUInterface *interface)
void invalidateWCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
const HardwareConfig & getHardwareConfig() const
Returns the hardwareconfig this device belongs to.
virtual const std::string & getName() const
Returns a human-readable name for this device.
const HardwareConfig * getMachineConfig() const
Contains the main loop of openMSX.
CommandController & getCommandController()
GlobalCliComm & getGlobalCliComm()
Interpreter & getInterpreter()
EventDistributor & getEventDistributor()
Base class for CPU breakpoints.
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
This file implemented 3 utility functions:
uint8_t byte
8 bit unsigned integer
std::ostream & operator<<(std::ostream &os, EnumTypeName< CacheLineCounters >)
uint16_t word
16 bit unsigned integer
constexpr void fill(ForwardRange &&range, const T &value)
auto remove(ForwardRange &&range, const T &value)
auto find(InputRange &&range, const T &value)
auto upper_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
auto equal_range(ForwardRange &&range, const T &value, Compare comp={})
size_t size(std::string_view utf8)
#define OUTER(type, member)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
ITER find_unguarded(ITER first, ITER last, const VAL &val, Proj proj={})
Faster alternative to 'find' when it's guaranteed that the value will be found (if not the behavior i...
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
TemporaryString tmpStrCat(Ts &&... ts)
std::string strCat(Ts &&...ts)
void strAppend(std::string &result, Ts &&...ts)
constexpr auto xrange(T e)
constexpr auto end(const zstring_view &x)