182 lines
4.9 KiB
C++
182 lines
4.9 KiB
C++
//---------------------------------------------------------------------------//
|
|
// 1100101 |_ mov #0, r4 __ //
|
|
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
|
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
|
// |_ base# + offset |_| /_\_\___/__/ //
|
|
//---------------------------------------------------------------------------//
|
|
|
|
#include <fxos/vspace.h>
|
|
#include <fxos/os.h>
|
|
#include <cstring>
|
|
|
|
namespace FxOS {
|
|
|
|
//=== AbstractMemory ===//
|
|
|
|
bool AbstractMemory::covers(uint32_t addr, int size) const
|
|
{
|
|
return (this->translate(addr, size) != nullptr);
|
|
}
|
|
|
|
bool AbstractMemory::covers(MemoryRegion const ®ion) const
|
|
{
|
|
return this->covers(region.start, region.size());
|
|
}
|
|
|
|
char const *AbstractMemory::translate(uint32_t addr, int size) const
|
|
{
|
|
int actual_size;
|
|
char const *ptr = this->translate_dynamic(addr, &actual_size);
|
|
return (ptr && actual_size >= size) ? ptr : nullptr;
|
|
}
|
|
|
|
Addressable<int8_t> AbstractMemory::read_i8(uint32_t addr) const
|
|
{
|
|
int8_t *i8 = (int8_t *)this->translate(addr, 1);
|
|
if(!i8)
|
|
return Addressable((int8_t)-1);
|
|
return Addressable(addr, *i8);
|
|
}
|
|
|
|
Addressable<uint8_t> AbstractMemory::read_u8(uint32_t addr) const
|
|
{
|
|
uint8_t *u8 = (uint8_t *)this->translate(addr, 1);
|
|
if(!u8)
|
|
return Addressable((uint8_t)-1);
|
|
return Addressable(addr, *u8);
|
|
}
|
|
|
|
Addressable<int16_t> AbstractMemory::read_i16(uint32_t addr) const
|
|
{
|
|
uint8_t *i16 = (uint8_t *)this->translate(addr, 2);
|
|
if(!i16)
|
|
return Addressable((int16_t)-1);
|
|
int16_t v = (i16[0] << 8) | i16[1];
|
|
return Addressable(addr, v);
|
|
}
|
|
|
|
Addressable<uint16_t> AbstractMemory::read_u16(uint32_t addr) const
|
|
{
|
|
uint8_t *u16 = (uint8_t *)this->translate(addr, 2);
|
|
if(!u16)
|
|
return Addressable((uint16_t)-1);
|
|
uint16_t v = (u16[0] << 8) | u16[1];
|
|
return Addressable(addr, v);
|
|
}
|
|
|
|
Addressable<int32_t> AbstractMemory::read_i32(uint32_t addr) const
|
|
{
|
|
uint8_t *i32 = (uint8_t *)this->translate(addr, 4);
|
|
if(!i32)
|
|
return Addressable((int32_t)-1);
|
|
int32_t v = (i32[0] << 24) | (i32[1] << 16) | (i32[2] << 8) | i32[3];
|
|
return Addressable(addr, v);
|
|
}
|
|
|
|
Addressable<uint32_t> AbstractMemory::read_u32(uint32_t addr) const
|
|
{
|
|
uint8_t *u32 = (uint8_t *)this->translate(addr, 4);
|
|
if(!u32)
|
|
return Addressable((uint32_t)-1);
|
|
uint32_t v = (u32[0] << 24) | (u32[1] << 16) | (u32[2] << 8) | u32[3];
|
|
return Addressable(addr, v);
|
|
}
|
|
|
|
Addressable<std::string> AbstractMemory::read_str(
|
|
uint32_t addr, size_t len) const
|
|
{
|
|
char const *str = this->translate(addr, len);
|
|
if(!str)
|
|
return Addressable(std::string());
|
|
return Addressable(addr, std::string(str, len));
|
|
}
|
|
|
|
uint32_t AbstractMemory::search(
|
|
uint32_t start, uint32_t end, void const *pattern, int size) const
|
|
{
|
|
void const *data = translate(start, end - start);
|
|
if(!data)
|
|
return end;
|
|
|
|
void const *occurrence = memmem(data, end - start, pattern, size);
|
|
if(!occurrence)
|
|
return end;
|
|
|
|
return start + ((char *)occurrence - (char *)data);
|
|
}
|
|
|
|
//=== Binding ===//
|
|
|
|
Binding::Binding(MemoryRegion source_region, Buffer const &source_buffer):
|
|
region {source_region}, buffer {source_buffer, region.size()}
|
|
{
|
|
}
|
|
|
|
BSON Binding::serialize() const
|
|
{
|
|
return BSON::mkDocument({
|
|
{"*", BSON::mkString("Binding")},
|
|
{"start", BSON::mkI32(region.start)},
|
|
{"end", BSON::mkI32(region.end)},
|
|
{"buffer", buffer.serialize()},
|
|
});
|
|
}
|
|
|
|
Binding::Binding(BSON const &b)
|
|
{
|
|
assert(b.isDocument() && b["*"].getString() == "Binding");
|
|
|
|
u32 start = b["start"].getI32();
|
|
u32 end = b["end"].getI32();
|
|
region = MemoryRegion("<anonymous>", start, end, false);
|
|
|
|
buffer.deserialize(b["buffer"]);
|
|
}
|
|
|
|
char const *Binding::translate_dynamic(uint32_t addr, int *size) const
|
|
{
|
|
if(addr >= region.start && addr < region.end) {
|
|
*size = region.end - addr;
|
|
return buffer.data.get() + (addr - region.start);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//=== VirtualSpace ===//
|
|
|
|
VirtualSpace::VirtualSpace(): bindings {}, disasm {*this}
|
|
{
|
|
}
|
|
|
|
BSON VirtualSpace::serialize() const
|
|
{
|
|
BSON b = BSON::mkArray(this->bindings.size());
|
|
for(uint i = 0; i < this->bindings.size(); i++)
|
|
b[i] = this->bindings[i].serialize();
|
|
return b;
|
|
}
|
|
|
|
void VirtualSpace::deserialize(BSON const &b)
|
|
{
|
|
assert(b.isArray());
|
|
for(uint i = 0; i < b.size(); i++)
|
|
this->bindings.push_back(Binding(b[i]));
|
|
}
|
|
|
|
void VirtualSpace::bind_region(MemoryRegion const ®ion, Buffer const &buf)
|
|
{
|
|
this->bindings.emplace(this->bindings.begin(), region, buf);
|
|
}
|
|
|
|
char const *VirtualSpace::translate_dynamic(uint32_t addr, int *size) const
|
|
{
|
|
for(auto &b: this->bindings) {
|
|
char const *ptr = b.translate_dynamic(addr, size);
|
|
if(ptr)
|
|
return ptr;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
} /* namespace FxOS */
|