152 lines
5.7 KiB
C++
152 lines
5.7 KiB
C++
#include <cstring>
|
|
#include <mem.hpp>
|
|
#include <ircolib/log.hpp>
|
|
#include <ircolib/mem_access.hpp>
|
|
|
|
namespace weee::core {
|
|
mem::mem() : vi(*this) {
|
|
mem1.resize(24_mib);
|
|
std::fill(mem1.begin(), mem1.end(), 0);
|
|
|
|
register_read8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr) { return mem1[addr]; });
|
|
|
|
register_read16_handler(0x00000000, 0x017fffff,
|
|
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u16>(mem1, addr); });
|
|
|
|
register_read32_handler(0x00000000, 0x017fffff,
|
|
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u32>(mem1, addr); });
|
|
|
|
register_read64_handler(0x00000000, 0x017fffff,
|
|
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u64>(mem1, addr); });
|
|
|
|
register_write8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u8 value) { mem1[addr] = value; });
|
|
|
|
register_write16_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u16 value) {
|
|
ircolib::write_access<ircolib::u16>(mem1, addr, value);
|
|
});
|
|
|
|
register_write32_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) {
|
|
ircolib::write_access<ircolib::u32>(mem1, addr, value);
|
|
});
|
|
|
|
register_write64_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) {
|
|
ircolib::write_access<ircolib::u64>(mem1, addr, value);
|
|
});
|
|
}
|
|
|
|
void mem::copy(std::vector<ircolib::u8> &src, const ircolib::u32 offset) {
|
|
if (offset + src.size() >= mem1.size())
|
|
ircolib::panic("mem::copy outside mem1 range (src @ 0x{:08} for size 0x{:08X})", offset, src.size());
|
|
|
|
ircolib::swap_buffer<ircolib::u32>(src);
|
|
std::copy(src.begin(), src.end(), mem1.begin() + offset);
|
|
}
|
|
|
|
void mem::copy(ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset) {
|
|
if (offset + size >= mem1.size())
|
|
ircolib::panic("mem::copy outside mem1 range (src @ 0x{:08} for size 0x{:08X})", offset, size);
|
|
|
|
ircolib::swap_buffer<ircolib::u32>(src, size);
|
|
memcpy(&mem1[offset], src, size);
|
|
}
|
|
|
|
void mem::set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32 offset) {
|
|
if (offset + size >= mem1.size())
|
|
ircolib::panic("mem::set outside mem1 range (@ 0x{:08} for size 0x{:08X})", offset, size);
|
|
|
|
memset(&mem1[offset], val, size);
|
|
}
|
|
|
|
std::expected<ircolib::u8, std::string> mem::read8(ircolib::u32 addr) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : read8_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
return handler.func(addr - handler.start);
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::read8 unimplemented addr 0x{:08X}", addr));
|
|
}
|
|
|
|
std::expected<ircolib::u16, std::string> mem::read16(ircolib::u32 addr) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : read16_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
return handler.func(addr - handler.start);
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::read16 unimplemented addr 0x{:08X}", addr));
|
|
}
|
|
|
|
std::expected<ircolib::u32, std::string> mem::read32(ircolib::u32 addr) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : read32_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
return handler.func(addr - handler.start);
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::read32 unimplemented addr 0x{:08X}", addr));
|
|
}
|
|
|
|
std::expected<ircolib::u64, std::string> mem::read64(ircolib::u32 addr) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : read64_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
return handler.func(addr - handler.start);
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::read64 unimplemented addr 0x{:08X}", addr));
|
|
}
|
|
|
|
std::expected<void, std::string> mem::write8(ircolib::u32 addr, ircolib::u8 value) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : write8_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
handler.func(addr - handler.start, value);
|
|
return std::expected<void, std::string>();
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::write8 unimplemented addr 0x{:08X} = 0x{:02X}", addr, value));
|
|
}
|
|
|
|
std::expected<void, std::string> mem::write16(ircolib::u32 addr, ircolib::u16 value) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : write16_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
handler.func(addr - handler.start, value);
|
|
return std::expected<void, std::string>();
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::write16 unimplemented addr 0x{:08X} = 0x{:04X}", addr, value));
|
|
}
|
|
|
|
std::expected<void, std::string> mem::write32(ircolib::u32 addr, ircolib::u32 value) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : write32_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
handler.func(addr - handler.start, value);
|
|
return std::expected<void, std::string>();
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::write32 unimplemented addr 0x{:08X} = 0x{:08X}", addr, value));
|
|
}
|
|
|
|
std::expected<void, std::string> mem::write64(ircolib::u32 addr, ircolib::u64 value) {
|
|
addr &= 0x0FFFFFFF;
|
|
for (const auto &handler : write64_handlers) {
|
|
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
|
handler.func(addr - handler.start, value);
|
|
return std::expected<void, std::string>();
|
|
}
|
|
}
|
|
|
|
return std::unexpected(std::format("mem::write64 unimplemented addr 0x{:08X} = 0x{:016X}", addr, value));
|
|
}
|
|
} // namespace weee::core
|