38 static std::optional<ReadOnlySetting> breakedSetting;
39 static unsigned breakedSettingCount = 0;
49 return os <<
"CacheLineCounters";
63 "InvalidateReadWrite",
70 return os << names[size_t(evn.
e)];
74 : memoryDebug (motherBoard_)
75 , slottedMemoryDebug(motherBoard_)
76 , ioDebug (motherBoard_)
77 , slotInfo(motherBoard_.getMachineInfoCommand())
78 , subSlottedInfo(motherBoard_.getMachineInfoCommand())
79 , externalSlotInfo(motherBoard_.getMachineInfoCommand())
80 , inputPortInfo (motherBoard_.getMachineInfoCommand())
81 , outputPortInfo(motherBoard_.getMachineInfoCommand())
83 *motherBoard_.getMachineConfig()))
84 , msxcpu(motherBoard_.getCPU())
85 , cliComm(motherBoard_.getMSXCliComm())
86 , motherBoard(motherBoard_)
96 for (
auto& sub1 : slotLayout) {
97 for (
auto& sub2 : sub1) {
103 memset(disallowReadCache, 0,
sizeof(disallowReadCache));
104 memset(disallowWriteCache, 0,
sizeof(disallowWriteCache));
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());
177 void MSXCPUInterface::removeAllWatchPoints()
179 while (!watchPoints.empty()) {
185 byte 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);
211 void 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;
325 MSXDevice*& 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);
362 void 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,
440 void MSXCPUInterface::testRegisterSlot(
443 int 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);
466 void MSXCPUInterface::registerSlot(
469 int page = 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);
495 void MSXCPUInterface::unregisterSlot(
498 int page = 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,
int base_,
int size_)
521 "Slot ", ps,
'.', ss,
522 " does not exist because slot is not expanded.");
530 int partialSize =
std::min(
size, ((base + 0x4000) & ~0x3FFF) - base);
531 testRegisterSlot(device, ps, ss, base, partialSize);
539 int partialSize =
std::min(
size, ((base + 0x4000) & ~0x3FFF) - base);
540 registerSlot(device, ps, ss, base, partialSize);
551 int 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) {
606 ALWAYS_INLINE void MSXCPUInterface::updateVisible(
int page,
int ps,
int ss)
608 MSXDevice* newDevice = slotLayout[ps][ss][page];
609 if (visibleDevices[page] != newDevice) {
610 visibleDevices[page] = newDevice;
614 void MSXCPUInterface::updateVisible(
int page)
616 updateVisible(page, primarySlotState[page], secondarySlotState[page]);
638 msxcpu.
fillRWCache(start,
size, rData, wData, ps, ss, disallowReadCache, disallowWriteCache);
648 msxcpu.
fillWCache(start,
size, wData, ps, ss, disallowWriteCache);
653 for (
auto i :
xrange(4)) {
678 int ps0 = (value >> 0) & 3;
679 if (primarySlotState[0] != ps0) [[unlikely]] {
680 primarySlotState[0] = ps0;
681 int ss0 = (subSlotRegister[ps0] >> 0) & 3;
682 secondarySlotState[0] = ss0;
683 updateVisible(0, ps0, ss0);
685 int ps1 = (value >> 2) & 3;
686 if (primarySlotState[1] != ps1) [[unlikely]] {
687 primarySlotState[1] = ps1;
688 int ss1 = (subSlotRegister[ps1] >> 2) & 3;
689 secondarySlotState[1] = ss1;
690 updateVisible(1, ps1, ss1);
692 int ps2 = (value >> 4) & 3;
693 if (primarySlotState[2] != ps2) [[unlikely]] {
694 primarySlotState[2] = ps2;
695 int ss2 = (subSlotRegister[ps2] >> 4) & 3;
696 secondarySlotState[2] = ss2;
697 updateVisible(2, ps2, ss2);
699 int ps3 = (value >> 6) & 3;
700 if (primarySlotState[3] != ps3) [[unlikely]] {
701 bool oldExpanded =
isExpanded(primarySlotState[3]);
703 primarySlotState[3] = ps3;
704 int ss3 = (subSlotRegister[ps3] >> 6) & 3;
705 secondarySlotState[3] = ss3;
706 updateVisible(3, ps3, ss3);
707 if (oldExpanded != newExpanded) [[unlikely]] {
713 void MSXCPUInterface::setSubSlot(
byte primSlot,
byte value)
715 subSlotRegister[primSlot] = value;
716 for (
int 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);
835 static void registerIOWatch(WatchPoint& watchPoint,
MSXDevice** devices)
837 assert(
dynamic_cast<WatchIO*
>(&watchPoint));
838 auto& ioWatch =
static_cast<WatchIO&
>(watchPoint);
839 unsigned beginPort = ioWatch.getBeginAddress();
840 unsigned endPort = ioWatch.getEndAddress();
841 assert(beginPort <= endPort);
842 assert(endPort < 0x100);
843 for (
unsigned port = beginPort; port <= endPort; ++port) {
844 ioWatch.getDevice(port).getDevicePtr() = devices[port];
845 devices[port] = &ioWatch.getDevice(port);
852 watchPoints.push_back(watchPoint);
856 registerIOWatch(*watchPoint, IO_In);
859 registerIOWatch(*watchPoint, IO_Out);
863 updateMemWatch(type);
872 assert(
dynamic_cast<WatchIO*
>(&watchPoint));
873 auto& ioWatch =
static_cast<WatchIO&
>(watchPoint);
875 unsigned endPort = ioWatch.getEndAddress();
876 assert(beginPort <= endPort);
877 assert(endPort < 0x100);
879 for (
unsigned port = beginPort; port <= endPort; ++port) {
882 while (*prev != &ioWatch.getDevice(port)) {
883 prev = &checked_cast<MSXWatchIODevice*>(*prev)->getDevicePtr();
886 *prev = checked_cast<MSXWatchIODevice*>(*prev)->getDevicePtr();
896 it !=
end(watchPoints)) {
899 watchPoints.erase(it);
903 unregisterIOWatch(*watchPoint, IO_In);
906 unregisterIOWatch(*watchPoint, IO_Out);
910 updateMemWatch(type);
921 conditions.push_back(std::move(cond));
928 [](
auto&
e) {
return &
e; }));
935 it != conditions.end()) {
937 conditions.erase(it);
943 std::bitset<CacheLine::SIZE>* watchSet =
948 for (
auto& w : watchPoints) {
949 if (w->getType() == type) {
950 unsigned beginAddr = w->getBeginAddress();
951 unsigned endAddr = w->getEndAddress();
952 assert(beginAddr <= endAddr);
953 assert(endAddr < 0x10000);
954 for (
unsigned addr = beginAddr; addr <= endAddr; ++addr) {
961 if (readWatchSet [i].any()) {
966 if (writeWatchSet[i].any()) {
976 unsigned address,
unsigned value)
978 assert(!watchPoints.empty());
984 TclObject(
int(address)));
986 interp.setVariable(TclObject(
"wp_last_value"),
987 TclObject(
int(value)));
990 auto wpCopy = watchPoints;
991 for (
auto& w : wpCopy) {
992 if ((w->getBeginAddress() <= address) &&
993 (w->getEndAddress() >= address) &&
994 (w->getType() == type)) {
995 bool remove = w->checkAndExecute(globalCliComm, interp);
1002 interp.unsetVariable(
"wp_last_address");
1003 interp.unsetVariable(
"wp_last_value");
1010 if (breaked)
return;
1016 breakedSetting->setReadOnlyValue(
TclObject(
"true"));
1019 Event::create<BreakEvent>());
1037 breakedSetting->setReadOnlyValue(
TclObject(
"false"));
1051 breakPoints.clear();
1058 MSXCPUInterface::MemoryDebug::MemoryDebug(
MSXMotherBoard& motherBoard_)
1060 "The memory currently visible for the CPU.", 0x10000)
1064 byte MSXCPUInterface::MemoryDebug::read(
unsigned address, EmuTime::param time)
1067 return interface.peekMem(address, time);
1070 void MSXCPUInterface::MemoryDebug::write(
unsigned address,
byte value,
1071 EmuTime::param time)
1074 return interface.writeMem(address, value, time);
1080 MSXCPUInterface::SlottedMemoryDebug::SlottedMemoryDebug(
1081 MSXMotherBoard& motherBoard_)
1082 : SimpleDebuggable(motherBoard_,
"slotted memory",
1083 "The memory in slots and subslots.", 0x10000 * 4 * 4)
1087 byte MSXCPUInterface::SlottedMemoryDebug::read(
unsigned address, EmuTime::param time)
1090 return interface.peekSlottedMem(address, time);
1093 void MSXCPUInterface::SlottedMemoryDebug::write(
unsigned address,
byte value,
1094 EmuTime::param time)
1097 return interface.writeSlottedMem(address, value, time);
1103 static unsigned getSlot(
1104 Interpreter& interp,
const TclObject& token,
const std::string& itemName)
1106 unsigned slot = token.getInt(interp);
1108 throw CommandException(itemName,
" must be in range 0..3");
1113 MSXCPUInterface::SlotInfo::SlotInfo(
1114 InfoCommand& machineInfoCommand)
1115 : InfoTopic(machineInfoCommand,
"slot")
1119 void MSXCPUInterface::SlotInfo::execute(std::span<const TclObject> tokens,
1120 TclObject& result)
const
1122 checkNumArgs(tokens, 5, Prefix{2},
"primary secondary page");
1123 auto& interp = getInterpreter();
1124 unsigned ps = getSlot(interp, tokens[2],
"Primary slot");
1125 unsigned ss = getSlot(interp, tokens[3],
"Secondary slot");
1126 unsigned page = getSlot(interp, tokens[4],
"Page");
1128 if (!interface.isExpanded(ps)) {
1131 interface.slotLayout[ps][ss][page]->getNameList(result);
1134 std::string MSXCPUInterface::SlotInfo::help(std::span<const TclObject> )
const
1136 return "Retrieve name of the device inserted in given "
1137 "primary slot / secondary slot / page.";
1143 MSXCPUInterface::SubSlottedInfo::SubSlottedInfo(
1144 InfoCommand& machineInfoCommand)
1145 : InfoTopic(machineInfoCommand,
"issubslotted")
1149 void MSXCPUInterface::SubSlottedInfo::execute(std::span<const TclObject> tokens,
1150 TclObject& result)
const
1152 checkNumArgs(tokens, 3,
"primary");
1154 result = interface.isExpanded(
1155 getSlot(getInterpreter(), tokens[2],
"Slot"));
1158 std::string MSXCPUInterface::SubSlottedInfo::help(
1159 std::span<const TclObject> )
const
1161 return "Indicates whether a certain primary slot is expanded.";
1167 MSXCPUInterface::ExternalSlotInfo::ExternalSlotInfo(
1168 InfoCommand& machineInfoCommand)
1169 : InfoTopic(machineInfoCommand,
"isexternalslot")
1173 void MSXCPUInterface::ExternalSlotInfo::execute(
1174 std::span<const TclObject> tokens, TclObject& result)
const
1176 checkNumArgs(tokens, Between{3, 4},
"primary ?secondary?");
1179 auto& interp = getInterpreter();
1180 switch (tokens.size()) {
1182 ss = getSlot(interp, tokens[3],
"Secondary slot");
1185 ps = getSlot(interp, tokens[2],
"Primary slot");
1189 auto& manager = interface.motherBoard.getSlotManager();
1190 result = manager.isExternalSlot(ps, ss,
true);
1193 std::string MSXCPUInterface::ExternalSlotInfo::help(
1194 std::span<const TclObject> )
const
1196 return "Indicates whether a certain slot is external or internal.";
1202 MSXCPUInterface::IODebug::IODebug(MSXMotherBoard& motherBoard_)
1203 : SimpleDebuggable(motherBoard_,
"ioports",
"IO ports.", 0x100)
1207 byte MSXCPUInterface::IODebug::read(
unsigned address, EmuTime::param time)
1210 return interface.IO_In[address & 0xFF]->peekIO(address, time);
1213 void MSXCPUInterface::IODebug::write(
unsigned address,
byte value, EmuTime::param time)
1216 interface.writeIO(
word(address), value, time);
1222 MSXCPUInterface::IOInfo::IOInfo(InfoCommand& machineInfoCommand,
const char* name_)
1223 : InfoTopic(machineInfoCommand, name_)
1227 void MSXCPUInterface::IOInfo::helper(
1228 std::span<const TclObject> tokens, TclObject& result,
MSXDevice** devices)
const
1230 checkNumArgs(tokens, 3,
"port");
1231 unsigned port = tokens[2].getInt(getInterpreter());
1233 throw CommandException(
"Port must be in range 0..255");
1235 devices[port]->getNameList(result);
1237 void MSXCPUInterface::IInfo::execute(
1238 std::span<const TclObject> tokens, TclObject& result)
const
1241 helper(tokens, result, interface.IO_In);
1243 void MSXCPUInterface::OInfo::execute(
1244 std::span<const TclObject> tokens, TclObject& result)
const
1247 helper(tokens, result, interface.IO_Out);
1250 std::string MSXCPUInterface::IOInfo::help(std::span<const TclObject> )
const
1252 return "Return the name of the device connected to the given IO port.";
1256 template<
typename Archive>
1263 if constexpr (!Archive::IS_LOADER) {
1264 for (
auto i :
xrange(4)) {
1265 prim |= primarySlotState[i] << (2 * i);
1268 ar.serialize(
"primarySlots", prim,
1269 "subSlotRegs", subSlotRegister);
1270 if constexpr (Archive::IS_LOADER) {
1272 for (
auto i :
xrange(4)) {
1273 setSubSlot(i, subSlotRegister[i]);
1278 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 specifc 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.
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss)
void testUnsetExpanded(int ps, std::span< const std::unique_ptr< MSXDevice >> allowed) const
void unregister_IO_In(byte port, MSXDevice *device)
bool replace_IO_Out(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
void changeExpanded(bool newExpanded)
void removeCondition(const DebugCondition &cond)
byte peekMem(word address, EmuTime::param time) const
Peek memory location.
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 registerMemDevice(MSXDevice &device, int ps, int ss, int base, int size)
Devices can register themself in the MSX slotstructure.
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 databus used in interrupt routines.
bool checkBreakPoints(unsigned pc)
void serialize(Archive &ar, unsigned version)
void unregisterMemDevice(MSXDevice &device, int ps, int ss, int base, int size)
void registerGlobalRead(MSXDevice &device, word address)
(Un)register global read.
byte readSlottedMem(unsigned address, EmuTime::param time)
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 fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss, const byte *disallowWrite)
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss, const byte *disallowRead, const byte *disallowWrite)
Fill the read and write cache lines for a specific slot with the specified value.
void invalidateAllSlotsRWCache(word start, unsigned size)
Invalidate the CPU its cache for the interval [start, start + size) For example MSXMemoryMapper and M...
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss, const byte *disallowRead)
void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
Inform CPU of bank switch.
void invalidateRWCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowRead, const byte *disallowWrite)
Similar to the method above, but only invalidates one specific slot.
void exitCPULoopSync()
See CPUCore::exitCPULoopsync()
void invalidateRCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowRead)
void setInterface(MSXCPUInterface *interf)
void invalidateWCache(unsigned start, unsigned size, int ps, int ss, const byte *disallowWrite)
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
virtual byte readMem(word address, EmuTime::param time)
Read a byte from a location at a certain time from this device.
virtual void writeMem(word address, byte value, EmuTime::param time)
Write a given byte to a given location at a certain time to this device.
virtual byte peekMem(word address, EmuTime::param time) const
Read a byte from a given memory location.
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()
EventDistributor & getEventDistributor()
GlobalCliComm & getGlobalCliComm()
Interpreter & getInterpreter()
Base class for CPU breakpoints.
unsigned getBeginAddress() const
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
This file implemented 3 utility functions:
constexpr byte GLOBAL_RW_BIT
constexpr byte SECONDARY_SLOT_BIT
std::ostream & operator<<(std::ostream &os, EnumTypeName< CacheLineCounters >)
uint16_t word
16 bit unsigned integer
constexpr byte MEMORY_WATCH_BIT
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)