1 #include "memoryspace.hpp"
7 template<typename T
, bool linear
> inline T
internal_read(memory_space
& m
, uint64_t addr
)
9 const int system_endian
= memory_space::get_system_endian();
10 std::pair
<memory_region
*, uint64_t> g
;
12 g
= m
.lookup_linear(addr
);
15 if(!g
.first
|| g
.second
+ sizeof(T
) > g
.first
->size
)
17 if((!g
.first
->endian
|| g
.first
->endian
== system_endian
) && memory_space::can_read_unaligned()) {
20 if(g
.first
->direct_map
)
21 return *reinterpret_cast<T
*>(g
.first
->direct_map
+ g
.second
);
23 g
.first
->read(g
.second
, &buf
, sizeof(T
));
25 } else if(g
.first
->endian
< 0 || (!g
.first
->endian
&& system_endian
< 0)) {
26 //The opposite endian (little).
27 unsigned char buf
[sizeof(T
)];
28 if(g
.first
->direct_map
)
29 memcpy(buf
, g
.first
->direct_map
+ g
.second
, sizeof(T
));
31 g
.first
->read(g
.second
, buf
, sizeof(T
));
33 for(unsigned i
= 0; i
< sizeof(T
); i
++)
34 v
|= (static_cast<T
>(buf
[i
]) << (8 * i
));
37 //The opposite endian (big).
38 unsigned char buf
[sizeof(T
)];
39 if(g
.first
->direct_map
)
40 memcpy(buf
, g
.first
->direct_map
+ g
.second
, sizeof(T
));
42 g
.first
->read(g
.second
, buf
, sizeof(T
));
44 for(unsigned i
= 0; i
< sizeof(T
); i
++)
45 v
|= (static_cast<T
>(buf
[i
]) << (8 * (sizeof(T
) - i
- 1)));
50 template<typename T
, bool linear
> inline bool internal_write(memory_space
& m
, uint64_t addr
, T value
)
52 const int system_endian
= memory_space::get_system_endian();
53 std::pair
<memory_region
*, uint64_t> g
;
55 g
= m
.lookup_linear(addr
);
58 if(!g
.first
|| g
.first
->readonly
|| g
.second
+ sizeof(T
) > g
.first
->size
)
60 if((!g
.first
->endian
|| g
.first
->endian
== system_endian
) && memory_space::can_read_unaligned()) {
62 if(g
.first
->direct_map
) {
63 *reinterpret_cast<T
*>(g
.first
->direct_map
+ g
.second
) = value
;
66 g
.first
->write(g
.second
, &value
, sizeof(T
));
67 } else if(g
.first
->endian
< 0 || (!g
.first
->endian
&& system_endian
< 0)) {
68 //The opposite endian (little).
69 unsigned char buf
[sizeof(T
)];
70 for(unsigned i
= 0; i
< sizeof(T
); i
++)
71 buf
[i
] = value
>> (8 * i
);
72 if(g
.first
->direct_map
)
73 memcpy(g
.first
->direct_map
+ g
.second
, buf
, sizeof(T
));
75 return g
.first
->write(g
.second
, buf
, sizeof(T
));
77 //The opposite endian (big).
78 unsigned char buf
[sizeof(T
)];
79 for(unsigned i
= 0; i
< sizeof(T
); i
++)
80 buf
[i
] = value
>> (8 * (sizeof(T
) - i
- 1));
81 if(g
.first
->direct_map
)
82 memcpy(g
.first
->direct_map
+ g
.second
, buf
, sizeof(T
));
84 return g
.first
->write(g
.second
, buf
, sizeof(T
));
89 void read_range_r(memory_region
& r
, uint64_t offset
, void* buffer
, size_t bsize
)
92 if(offset
>= r
.size
) {
93 memset(buffer
, 0, bsize
);
96 uint64_t maxcopy
= min(static_cast<uint64_t>(bsize
), r
.size
- offset
);
97 memcpy(buffer
, r
.direct_map
+ offset
, maxcopy
);
99 memset(reinterpret_cast<char*>(buffer
) + maxcopy
, 0, bsize
- maxcopy
);
101 r
.read(offset
, buffer
, bsize
);
104 bool write_range_r(memory_region
& r
, uint64_t offset
, const void* buffer
, size_t bsize
)
111 uint64_t maxcopy
= min(static_cast<uint64_t>(bsize
), r
.size
- offset
);
112 memcpy(r
.direct_map
+ offset
, buffer
, maxcopy
);
115 return r
.write(offset
, buffer
, bsize
);
119 memory_region::~memory_region() throw()
123 void memory_region::read(uint64_t offset
, void* buffer
, size_t tsize
)
125 if(!direct_map
|| offset
>= size
) {
126 memset(buffer
, 0, tsize
);
129 uint64_t maxcopy
= min(static_cast<uint64_t>(tsize
), size
- offset
);
130 memcpy(buffer
, direct_map
+ offset
, maxcopy
);
132 memset(reinterpret_cast<char*>(buffer
) + maxcopy
, 0, tsize
- maxcopy
);
135 bool memory_region::write(uint64_t offset
, const void* buffer
, size_t tsize
)
137 if(!direct_map
|| readonly
|| offset
>= size
)
139 uint64_t maxcopy
= min(static_cast<uint64_t>(tsize
), size
- offset
);
140 memcpy(direct_map
+ offset
, buffer
, maxcopy
);
144 std::pair
<memory_region
*, uint64_t> memory_space::lookup(uint64_t address
)
146 umutex_class
m(mutex
);
148 size_t ub
= u_regions
.size();
150 size_t mb
= (lb
+ ub
) / 2;
151 if(u_regions
[mb
]->base
> address
) {
155 if(u_regions
[mb
]->last_address() < address
) {
159 return std::make_pair(u_regions
[mb
], address
- u_regions
[mb
]->base
);
161 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
164 std::pair
<memory_region
*, uint64_t> memory_space::lookup_linear(uint64_t linear
)
166 umutex_class
m(mutex
);
167 if(linear
>= linear_size
)
168 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
170 size_t ub
= linear_bases
.size() - 1;
172 size_t mb
= (lb
+ ub
) / 2;
173 if(linear_bases
[mb
] > linear
) {
177 if(linear_bases
[mb
+ 1] <= linear
) {
181 return std::make_pair(u_lregions
[mb
], linear
- linear_bases
[mb
]);
183 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
186 #define MSR memory_space::read
187 #define MSW memory_space::write
188 #define MSRL memory_space::read_linear
189 #define MSWL memory_space::write_linear
191 template<> int8_t MSR (uint64_t address
) { return internal_read
<int8_t, false>(*this, address
); }
192 template<> uint8_t MSR (uint64_t address
) { return internal_read
<uint8_t, false>(*this, address
); }
193 template<> int16_t MSR (uint64_t address
) { return internal_read
<int16_t, false>(*this, address
); }
194 template<> uint16_t MSR (uint64_t address
) { return internal_read
<uint16_t, false>(*this, address
); }
195 template<> int32_t MSR (uint64_t address
) { return internal_read
<int32_t, false>(*this, address
); }
196 template<> uint32_t MSR (uint64_t address
) { return internal_read
<uint32_t, false>(*this, address
); }
197 template<> int64_t MSR (uint64_t address
) { return internal_read
<int64_t, false>(*this, address
); }
198 template<> uint64_t MSR (uint64_t address
) { return internal_read
<uint64_t, false>(*this, address
); }
199 template<> bool MSW (uint64_t a
, int8_t v
) { return internal_write
<int8_t, false>(*this, a
, v
); }
200 template<> bool MSW (uint64_t a
, uint8_t v
) { return internal_write
<uint8_t, false>(*this, a
, v
); }
201 template<> bool MSW (uint64_t a
, int16_t v
) { return internal_write
<int16_t, false>(*this, a
, v
); }
202 template<> bool MSW (uint64_t a
, uint16_t v
) { return internal_write
<uint16_t, false>(*this, a
, v
); }
203 template<> bool MSW (uint64_t a
, int32_t v
) { return internal_write
<int32_t, false>(*this, a
, v
); }
204 template<> bool MSW (uint64_t a
, uint32_t v
) { return internal_write
<uint32_t, false>(*this, a
, v
); }
205 template<> bool MSW (uint64_t a
, int64_t v
) { return internal_write
<int64_t, false>(*this, a
, v
); }
206 template<> bool MSW (uint64_t a
, uint64_t v
) { return internal_write
<uint64_t, false>(*this, a
, v
); }
207 template<> int8_t MSRL (uint64_t address
) { return internal_read
<int8_t, true>(*this, address
); }
208 template<> uint8_t MSRL (uint64_t address
) { return internal_read
<uint8_t, true>(*this, address
); }
209 template<> int16_t MSRL (uint64_t address
) { return internal_read
<int16_t, true>(*this, address
); }
210 template<> uint16_t MSRL (uint64_t address
) { return internal_read
<uint16_t, true>(*this, address
); }
211 template<> int32_t MSRL (uint64_t address
) { return internal_read
<int32_t, true>(*this, address
); }
212 template<> uint32_t MSRL (uint64_t address
) { return internal_read
<uint32_t, true>(*this, address
); }
213 template<> int64_t MSRL (uint64_t address
) { return internal_read
<int64_t, true>(*this, address
); }
214 template<> uint64_t MSRL (uint64_t address
) { return internal_read
<uint64_t, true>(*this, address
); }
215 template<> bool MSWL (uint64_t a
, int8_t v
) { return internal_write
<int8_t, true>(*this, a
, v
); }
216 template<> bool MSWL (uint64_t a
, uint8_t v
) { return internal_write
<uint8_t, true>(*this, a
, v
); }
217 template<> bool MSWL (uint64_t a
, int16_t v
) { return internal_write
<int16_t, true>(*this, a
, v
); }
218 template<> bool MSWL (uint64_t a
, uint16_t v
) { return internal_write
<uint16_t, true>(*this, a
, v
); }
219 template<> bool MSWL (uint64_t a
, int32_t v
) { return internal_write
<int32_t, true>(*this, a
, v
); }
220 template<> bool MSWL (uint64_t a
, uint32_t v
) { return internal_write
<uint32_t, true>(*this, a
, v
); }
221 template<> bool MSWL (uint64_t a
, int64_t v
) { return internal_write
<int64_t, true>(*this, a
, v
); }
222 template<> bool MSWL (uint64_t a
, uint64_t v
) { return internal_write
<uint64_t, true>(*this, a
, v
); }
224 void memory_space::read_range(uint64_t address
, void* buffer
, size_t bsize
)
226 auto g
= lookup(address
);
228 memset(buffer
, 0, bsize
);
231 read_range_r(*g
.first
, g
.second
, buffer
, bsize
);
234 bool memory_space::write_range(uint64_t address
, const void* buffer
, size_t bsize
)
236 auto g
= lookup(address
);
239 return write_range_r(*g
.first
, g
.second
, buffer
, bsize
);
242 void memory_space::read_range_linear(uint64_t address
, void* buffer
, size_t bsize
)
244 auto g
= lookup_linear(address
);
246 memset(buffer
, 0, bsize
);
249 read_range_r(*g
.first
, g
.second
, buffer
, bsize
);
252 bool memory_space::write_range_linear(uint64_t address
, const void* buffer
, size_t bsize
)
254 auto g
= lookup_linear(address
);
257 return write_range_r(*g
.first
, g
.second
, buffer
, bsize
);
260 memory_region
* memory_space::lookup_n(size_t n
)
262 umutex_class
m(mutex
);
263 if(n
>= u_regions
.size())
269 std::list
<memory_region
*> memory_space::get_regions()
271 umutex_class
m(mutex
);
272 std::list
<memory_region
*> r
;
273 for(auto i
: u_regions
)
278 void memory_space::set_regions(const std::list
<memory_region
*>& regions
)
280 umutex_class
m(mutex
);
281 std::vector
<memory_region
*> n_regions
;
282 std::vector
<memory_region
*> n_lregions
;
283 std::vector
<uint64_t> n_linear_bases
;
284 //Calculate array sizes.
285 n_regions
.resize(regions
.size());
287 for(auto i
: regions
)
288 if(!i
->readonly
&& !i
->special
)
290 n_lregions
.resize(linear_c
);
291 n_linear_bases
.resize(linear_c
+ 1);
293 //Fill the main array (it must be sorted!).
295 for(auto j
: regions
)
297 std::sort(n_regions
.begin(), n_regions
.end(),
298 [](memory_region
* a
, memory_region
* b
) -> bool { return a
->base
< b
->base
; });
300 //Fill linear address arrays from the main array.
303 for(auto j
: n_regions
) {
304 if(j
->readonly
|| j
->special
)
307 n_linear_bases
[i
] = base
;
308 base
= base
+ j
->size
;
311 n_linear_bases
[i
] = base
;
313 std::swap(u_regions
, n_regions
);
314 std::swap(u_lregions
, n_lregions
);
315 std::swap(linear_bases
, n_linear_bases
);
319 int memory_space::_get_system_endian()
323 uint16_t magic
= 258;
324 return (*reinterpret_cast<uint8_t*>(&magic
) == 1) ? 1 : -1;
327 int memory_space::sysendian
= 0;
329 memory_region_direct::memory_region_direct(const std::string
& _name
, uint64_t _base
, int _endian
,
330 unsigned char* _memory
, size_t _size
, bool _readonly
)
335 direct_map
= _memory
;
337 readonly
= _readonly
;
341 memory_region_direct::~memory_region_direct() throw() {}