openMSX
MSXMultiMemDevice.cc
Go to the documentation of this file.
1 #include "MSXMultiMemDevice.hh"
2 #include "DummyDevice.hh"
3 #include "MSXCPUInterface.hh"
4 #include "TclObject.hh"
5 #include "likely.hh"
6 #include "ranges.hh"
7 #include "stl.hh"
8 #include "unreachable.hh"
9 #include "view.hh"
10 #include <cassert>
11 
12 namespace openmsx {
13 
14 MSXMultiMemDevice::Range::Range(
15  unsigned base_, unsigned size_, MSXDevice& device_)
16  : base(base_), size(size_), device(&device_)
17 {
18 }
19 
20 bool MSXMultiMemDevice::Range::operator==(const Range& other) const
21 {
22  return (base == other.base) &&
23  (size == other.size) &&
24  (device == other.device);
25 }
26 
27 
28 MSXMultiMemDevice::MSXMultiMemDevice(const HardwareConfig& hwConf)
29  : MSXMultiDevice(hwConf)
30 {
31  // add sentinel at the end
32  ranges.emplace_back(0x0000, 0x10000, getCPUInterface().getDummyDevice());
33 }
34 
36 {
37  assert(empty());
38 }
39 
40 static constexpr bool isInside(unsigned x, unsigned start, unsigned size)
41 {
42  return (x - start) < size;
43 }
44 
45 static constexpr bool overlap(unsigned start1, unsigned size1,
46  unsigned start2, unsigned size2)
47 {
48  return (isInside(start1, start2, size2)) ||
49  (isInside(start1 + size1 - 1, start2, size2));
50 }
51 
52 bool MSXMultiMemDevice::canAdd(int base, int size)
53 {
54  return ranges::none_of(view::drop_back(ranges, 1), [&](auto& rn) {
55  return overlap(base, size, rn.base, rn.size);
56  });
57 }
58 
59 void MSXMultiMemDevice::add(MSXDevice& device, int base, int size)
60 {
61  assert(canAdd(base, size));
62  ranges.insert(begin(ranges), Range(base, size, device));
63 }
64 
65 void MSXMultiMemDevice::remove(MSXDevice& device, int base, int size)
66 {
67  ranges.erase(rfind_unguarded(ranges, Range(base, size, device)));
68 }
69 
70 std::vector<MSXDevice*> MSXMultiMemDevice::getDevices() const
71 {
73  [](auto& rn) { return rn.device; }));
74 }
75 
76 const std::string& MSXMultiMemDevice::getName() const
77 {
78  TclObject list;
79  getNameList(list);
80  const_cast<std::string&>(deviceName) = list.getString();
81  return deviceName;
82 }
84 {
85  for (const auto& r : ranges) {
86  const auto& name = r.device->getName();
87  if (!name.empty()) {
88  result.addListElement(name);
89  }
90  }
91 }
92 
93 const MSXMultiMemDevice::Range& MSXMultiMemDevice::searchRange(unsigned address) const
94 {
95  for (const auto& r : ranges) {
96  if (isInside(address, r.base, r.size)) {
97  return r;
98  }
99  }
100  UNREACHABLE; return ranges.back();
101 }
102 
103 MSXDevice* MSXMultiMemDevice::searchDevice(unsigned address) const
104 {
105  return searchRange(address).device;
106 }
107 
108 byte MSXMultiMemDevice::readMem(word address, EmuTime::param time)
109 {
110  return searchDevice(address)->readMem(address, time);
111 }
112 
113 byte MSXMultiMemDevice::peekMem(word address, EmuTime::param time) const
114 {
115  return searchDevice(address)->peekMem(address, time);
116 }
117 
118 void MSXMultiMemDevice::writeMem(word address, byte value, EmuTime::param time)
119 {
120  searchDevice(address)->writeMem(address, value, time);
121 }
122 
124 {
125  assert((start & CacheLine::HIGH) == start); // start is aligned
126  // Because start is aligned we don't need to worry about the begin
127  // address of the range. But we must make sure the end of the range
128  // doesn't only fill a partial cacheline.
129  const auto& range = searchRange(start);
130  if (unlikely(((range.base + range.size) & CacheLine::HIGH) == start)) {
131  // The end of this memory device only fills a partial
132  // cacheline. This can't be cached.
133  return nullptr;
134  }
135  return range.device->getReadCacheLine(start);
136 }
137 
139 {
140  assert((start & CacheLine::HIGH) == start);
141  const auto& range = searchRange(start);
142  if (unlikely(((range.base + range.size) & CacheLine::HIGH) == start)) {
143  return nullptr;
144  }
145  return range.device->getWriteCacheLine(start);
146 }
147 
148 } // namespace openmsx
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
virtual byte readMem(word address, EmuTime::param time)
Read a byte from a location at a certain time from this device.
Definition: MSXDevice.cc:420
std::string deviceName
Definition: MSXDevice.hh:321
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.
Definition: MSXDevice.cc:431
virtual byte peekMem(word address, EmuTime::param time) const
Read a byte from a given memory location.
Definition: MSXDevice.cc:437
MSXCPUInterface & getCPUInterface() const
Definition: MSXDevice.cc:134
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
void add(MSXDevice &device, int base, int size)
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
const std::string & getName() const override
Returns a human-readable name for this device.
bool canAdd(int base, int size)
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
std::vector< MSXDevice * > getDevices() const
void remove(MSXDevice &device, int base, int size)
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
void getNameList(TclObject &result) const override
Returns list of name(s) of this device.
void addListElement(const T &t)
Definition: TclObject.hh:129
zstring_view getString() const
Definition: TclObject.cc:111
#define unlikely(x)
Definition: likely.hh:15
constexpr unsigned HIGH
Definition: CacheLine.hh:10
This file implemented 3 utility functions:
Definition: Autofire.cc:9
bool operator==(const Event &x, const Event &y)
Definition: Event.cc:11
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118
Definition: ranges.hh:21
bool none_of(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:160
size_t size(std::string_view utf8)
constexpr auto transform(Range &&range, UnaryOp op)
Definition: view.hh:391
constexpr auto drop_back(Range &&range, size_t n)
Definition: view.hh:379
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.
Definition: stl.hh:108
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))>>
Definition: stl.hh:274
#define UNREACHABLE
Definition: unreachable.hh:38
constexpr auto begin(const zstring_view &x)
Definition: zstring_view.hh:83