no need for os_address, map find returns pointer
This commit is contained in:
parent
fea76d7347
commit
ae9d34b3d8
6 changed files with 108 additions and 139 deletions
|
|
@ -24,7 +24,7 @@ class Dynemu:
|
|||
...
|
||||
def dcc_write(self, value: typing.SupportsInt | typing.SupportsIndex) -> None:
|
||||
...
|
||||
def execute(self, pc: typing.SupportsInt | typing.SupportsIndex, stub_mode: bool = True) -> int:
|
||||
def execute(self, pc: typing.SupportsInt | typing.SupportsIndex, return_mode: bool = True) -> int:
|
||||
...
|
||||
def get_reg(self, reg_num: typing.SupportsInt | typing.SupportsIndex) -> int:
|
||||
...
|
||||
|
|
@ -67,11 +67,7 @@ class Dynemu:
|
|||
@typing.overload
|
||||
def upload_fls_memory(self, data: bytearray) -> None:
|
||||
...
|
||||
@typing.overload
|
||||
def upload_memstub(self, vaddr: typing.SupportsInt | typing.SupportsIndex, mem_start: typing.SupportsInt | typing.SupportsIndex = 2684354560, mem_size: typing.SupportsInt | typing.SupportsIndex = 33554432) -> None:
|
||||
...
|
||||
@typing.overload
|
||||
def upload_memstub(self, mem_start: typing.SupportsInt | typing.SupportsIndex = 2684354560, mem_size: typing.SupportsInt | typing.SupportsIndex = 33554432) -> None:
|
||||
def upload_memstub(self, vaddr: typing.SupportsInt | typing.SupportsIndex, mem_start: typing.SupportsInt | typing.SupportsIndex, mem_size: typing.SupportsInt | typing.SupportsIndex) -> None:
|
||||
...
|
||||
@typing.overload
|
||||
def write_bytes(self, vaddr: typing.SupportsInt | typing.SupportsIndex, data: bytes) -> None:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ extern "C" {
|
|||
DYNEMU_EXPORT size_t dynemu_upload_file(Emulator *e, const char *filename, int64_t dest, u32 size);
|
||||
DYNEMU_EXPORT bool dynemu_upload_fls_memory(Emulator *e, const u8 *fls);
|
||||
DYNEMU_EXPORT void dynemu_upload_memstub(Emulator *e, u32 dest, u32 mem_start, u32 mem_size);
|
||||
DYNEMU_EXPORT void dynemu_upload_memstub_nooffset(Emulator *e, u32 mem_start, u32 mem_size);
|
||||
DYNEMU_EXPORT void dynemu_mmio(Emulator *e, u32 vaddr, u32 size, DY_MMIO_Read read, DY_MMIO_Write write);
|
||||
DYNEMU_EXPORT u8 dynemu_read_u8(Emulator *e, u32 vaddr);
|
||||
DYNEMU_EXPORT u16 dynemu_read_u16(Emulator *e, u32 vaddr);
|
||||
|
|
@ -48,7 +47,7 @@ extern "C" {
|
|||
DYNEMU_EXPORT void dynemu_write_u64(Emulator *e, u32 vaddr, u64 value);
|
||||
DYNEMU_EXPORT void dynemu_read_bytes(Emulator *e, u32 vaddr, u8 *output, u32 size);
|
||||
DYNEMU_EXPORT void dynemu_write_bytes(Emulator *e, u32 vaddr, const u8 *input, u32 size);
|
||||
DYNEMU_EXPORT u32 dynemu_execute(Emulator *e, u32 pc, bool stub_mode);
|
||||
DYNEMU_EXPORT u32 dynemu_execute(Emulator *e, u32 pc, bool return_mode);
|
||||
DYNEMU_EXPORT u32 dynemu_read_reg(Emulator *e, u8 reg);
|
||||
DYNEMU_EXPORT void dynemu_write_reg(Emulator *e, u8 reg, u32 value);
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Dynemu {
|
|||
struct MemMap final {
|
||||
u32 start;
|
||||
u32 size;
|
||||
std::unique_ptr<u8[]> data;
|
||||
std::vector<u8> data;
|
||||
};
|
||||
|
||||
struct MMIO final {
|
||||
|
|
@ -52,37 +52,36 @@ namespace Dynemu {
|
|||
class DYNEMU_EXPORT MyEmulator final : public Dynarmic::A32::UserCallbacks {
|
||||
private:
|
||||
/* Memory map */
|
||||
std::optional<u8> find_memory_map_id(u32 vaddr);
|
||||
MemMap * find_memory_map_by_vaddr(u32 vaddr);
|
||||
|
||||
/* MMIO */
|
||||
std::optional<u8> find_mmio_id(u32 vaddr);
|
||||
MMIO * find_mmio_by_vaddr(u32 vaddr);
|
||||
std::optional<u32> handle_mmio_read(u32 vaddr, u8 access);
|
||||
bool handle_mmio_write(u32 vaddr, u32 value, u8 access);
|
||||
|
||||
/* Misc */
|
||||
bool check_memory_access(u32 vaddr);
|
||||
bool check_memory_access(u32 vaddr, u32 size);
|
||||
bool big_endian;
|
||||
bool thumb_mode;
|
||||
bool stub_mode;
|
||||
bool return_mode;
|
||||
u8 mem_map_index;
|
||||
u8 mmio_index;
|
||||
|
||||
public:
|
||||
/* Memory map */
|
||||
std::array<MemMap, 64> mem_map;
|
||||
u8 mem_map_index;
|
||||
|
||||
/* MMIO */
|
||||
std::array<MMIO, 64> mmio_map;
|
||||
u8 mmio_index;
|
||||
|
||||
/* state */
|
||||
Dynarmic::A32::Jit *cpu;
|
||||
u32 os_offset;
|
||||
|
||||
/*
|
||||
MyEmulator()
|
||||
Constructor
|
||||
*/
|
||||
MyEmulator(bool big_endian = false) : mem_map_index(0), mmio_index(0), os_offset(0xa8000000), mem_map(), mmio_map(), big_endian(big_endian) {};
|
||||
MyEmulator(bool big_endian = false) : mem_map_index(0), mmio_index(0), mem_map(), mmio_map(), big_endian(big_endian) {};
|
||||
|
||||
/*
|
||||
void CreateMemoryMap(u32 vaddr, u32 size)
|
||||
|
|
@ -140,15 +139,6 @@ namespace Dynemu {
|
|||
*/
|
||||
void UploadOSStub(u32 dest, u32 mem_start, u32 mem_size);
|
||||
|
||||
/*
|
||||
void UploadOSStub(u32 mem_start, u32 mem_size)
|
||||
This function uploads a stub libc to the configured os_offset parameter virtual address, along with setting up the regions assosiated with the dynamic memory functions.
|
||||
Endianness were determined by big_endian parameter.
|
||||
*/
|
||||
void UploadOSStub(u32 mem_start, u32 mem_size) {
|
||||
UploadOSStub(os_offset, mem_start, mem_size);
|
||||
}
|
||||
|
||||
/*
|
||||
void CreateMMIO(u32 addr_start, u32 addr_size, const MMIO_Read &read, const MMIO_Write &write)
|
||||
This function maps the virtual address to specific functions.
|
||||
|
|
@ -290,18 +280,18 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
/*
|
||||
u32 Execute(u32 pc, bool stub_mode)
|
||||
u32 Execute(u32 pc, bool return_mode)
|
||||
Executes from specific PC
|
||||
Returns: R0 register
|
||||
*/
|
||||
u32 Execute(u32 pc, bool stub_mode=true);
|
||||
u32 Execute(u32 pc, bool return_mode=true);
|
||||
|
||||
/*
|
||||
std::future<u32> Spawn(u32 pc, bool stub_mode)
|
||||
std::future<u32> Spawn(u32 pc, bool return_mode)
|
||||
Async version of Execute
|
||||
Returns: Future(R0 register)
|
||||
*/
|
||||
std::future<u32> Spawn(u32 pc, bool stub_mode=true);
|
||||
std::future<u32> Spawn(u32 pc, bool return_mode=true);
|
||||
|
||||
/*
|
||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception)
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@ extern "C" {
|
|||
return e->env.UploadOSStub(dest, mem_start, mem_size);
|
||||
}
|
||||
|
||||
void dynemu_upload_memstub_nooffset(Emulator *e, u32 mem_start, u32 mem_size) {
|
||||
return e->env.UploadOSStub(mem_start, mem_size);
|
||||
}
|
||||
|
||||
u8 dynemu_read_u8(Emulator *e, u32 vaddr) {
|
||||
return e->env.MemoryRead8(vaddr);
|
||||
}
|
||||
|
|
@ -79,8 +75,8 @@ extern "C" {
|
|||
e->env.MemoryWriteBytes(vaddr, input, size);
|
||||
}
|
||||
|
||||
u32 dynemu_execute(Emulator *e, u32 pc, bool stub_mode) {
|
||||
return e->env.Execute(pc, stub_mode);
|
||||
u32 dynemu_execute(Emulator *e, u32 pc, bool return_mode) {
|
||||
return e->env.Execute(pc, return_mode);
|
||||
}
|
||||
|
||||
u32 dynemu_read_reg(Emulator *e, u8 reg) {
|
||||
|
|
|
|||
|
|
@ -35,52 +35,64 @@ namespace Dynemu {
|
|||
};
|
||||
|
||||
/* 01 - Private */
|
||||
std::optional<u8> MyEmulator::find_memory_map_id(u32 vaddr) {
|
||||
MemMap * MyEmulator::find_memory_map_by_vaddr(u32 vaddr) {
|
||||
for (int i = 0; i < mem_map_index; i++) {
|
||||
if (vaddr >= mem_map[i].start && vaddr < (mem_map[i].start + mem_map[i].size))
|
||||
return i;
|
||||
return &mem_map[i];
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::optional<u8> MyEmulator::find_mmio_id(u32 vaddr) {
|
||||
MMIO * MyEmulator::find_mmio_by_vaddr(u32 vaddr) {
|
||||
for (int i = 0; i < mmio_index; i++) {
|
||||
if (vaddr >= mmio_map[i].start && vaddr < (mmio_map[i].start + mmio_map[i].size))
|
||||
return i;
|
||||
return &mmio_map[i];
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::optional<u32> MyEmulator::handle_mmio_read(u32 vaddr, u8 access) {
|
||||
if (auto id = find_mmio_id(vaddr); id.has_value()) {
|
||||
if (auto mmio = find_mmio_by_vaddr(vaddr); mmio != nullptr) {
|
||||
#if DEBUG
|
||||
printf("Handling MMIO READ for 0x%08x\n", vaddr);
|
||||
#endif
|
||||
return mmio_map[id.value()].read(vaddr - mmio_map[id.value()].start, access);
|
||||
return mmio->read(vaddr - mmio->start, access);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool MyEmulator::handle_mmio_write(u32 vaddr, u32 value, u8 access) {
|
||||
if (auto id = find_mmio_id(vaddr); id.has_value()) {
|
||||
if (auto mmio = find_mmio_by_vaddr(vaddr); mmio != nullptr) {
|
||||
#if DEBUG
|
||||
printf("Handling MMIO WRITE for 0x%08x\n", vaddr);
|
||||
#endif
|
||||
mmio_map[id.value()].write(vaddr - mmio_map[id.value()].start, value, access);
|
||||
mmio->write(vaddr - mmio->start, value, access);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MyEmulator::check_memory_access(u32 vaddr, u32 size) {
|
||||
if (auto mmio = find_mmio_by_vaddr(vaddr); mmio != nullptr) {
|
||||
return ((mmio->start + mmio->size) - vaddr) >= size;
|
||||
}
|
||||
|
||||
if (auto mmap = find_memory_map_by_vaddr(vaddr); mmap != nullptr) {
|
||||
return ((mmap->start + mmap->size) - vaddr) >= size;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 02 - Public */
|
||||
void MyEmulator::CreateMemoryMap(u32 vaddr, u32 size) {
|
||||
ASSERT_MSG(!find_mmio_id(vaddr).has_value(), "Cannot create memory map on MMIO-mapped addresses");
|
||||
if (!find_memory_map_id(vaddr).has_value())
|
||||
mem_map[mem_map_index++] = {vaddr, size, std::make_unique<u8[]>(size)};
|
||||
ASSERT_MSG(find_mmio_by_vaddr(vaddr) == nullptr, "Cannot create memory map on MMIO-mapped addresses");
|
||||
if (find_memory_map_by_vaddr(vaddr) == nullptr)
|
||||
mem_map[mem_map_index++] = {vaddr, size, std::vector<u8>(size)};
|
||||
}
|
||||
|
||||
size_t MyEmulator::UploadToMemory(const std::string &filename, std::int64_t dest, u32 size) {
|
||||
|
|
@ -99,13 +111,8 @@ namespace Dynemu {
|
|||
size_t fileSize = file.tellg();
|
||||
file.seekg(0, file.beg);
|
||||
|
||||
auto mmap_id = find_memory_map_id((u32)dest);
|
||||
bool fitsOnMemoryMap = !mmap_id.has_value() ? (size >= fileSize) : false;
|
||||
|
||||
if (!fitsOnMemoryMap && mmap_id.has_value()) {
|
||||
u32 max_range = mem_map[mmap_id.value()].start + mem_map[mmap_id.value()].size;
|
||||
fitsOnMemoryMap = (max_range - dest) >= fileSize;
|
||||
}
|
||||
auto mmap = find_memory_map_by_vaddr((u32)dest);
|
||||
bool fitsOnMemoryMap = mmap == nullptr ? (size >= fileSize) : (((mmap->start + mmap->size) - dest) >= fileSize);
|
||||
|
||||
if (!fitsOnMemoryMap) {
|
||||
std::cerr << "dynemu: code file too large to fit into memory" << std::endl;
|
||||
|
|
@ -130,7 +137,7 @@ namespace Dynemu {
|
|||
file.read((char *)&fl.count, sizeof(fl.count));
|
||||
|
||||
if (fl.magic != 0x4c46) {
|
||||
std::cerr << "dynemu: nvalid FL magic check" << std::endl;
|
||||
std::cerr << "dynemu: invalid FL magic check" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +166,7 @@ namespace Dynemu {
|
|||
memcpy(&fl.count, fls + sizeof(fl.magic), sizeof(fl.count));
|
||||
|
||||
if (fl.magic != 0x4c46) {
|
||||
std::cerr << "Invalid FL magic check" << std::endl;
|
||||
std::cerr << "dynemu: invalid FL magic check" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -191,13 +198,11 @@ namespace Dynemu {
|
|||
|
||||
MemoryWrite32(dest + MEM_INIT_REG_OFFSET, mem_start);
|
||||
MemoryWrite32(dest + MEM_INIT_REG_SIZE, mem_size);
|
||||
|
||||
os_offset = dest;
|
||||
}
|
||||
|
||||
void MyEmulator::CreateMMIO(u32 addr_start, u32 addr_size, const MMIO_Read &read, const MMIO_Write &write) {
|
||||
ASSERT_MSG(!find_memory_map_id(addr_start).has_value(), "Cannot create MMIO map on memory-mapped address");
|
||||
if (!find_mmio_id(addr_start).has_value())
|
||||
ASSERT_MSG(find_memory_map_by_vaddr(addr_start) == nullptr, "Cannot create MMIO map on memory-mapped address");
|
||||
if (find_mmio_by_vaddr(addr_start) == nullptr)
|
||||
mmio_map[mmio_index++] = {addr_start, addr_size, read, write};
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +218,7 @@ namespace Dynemu {
|
|||
|
||||
thumb_mode = is_thumb;
|
||||
|
||||
if (stub_mode && pc == (os_offset + ROUTE_EXIT)) {
|
||||
if (return_mode && pc == 0xfffffffc) {
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::Step);
|
||||
ir.SetTerm(Dynarmic::IR::Term::CheckHalt{Dynarmic::IR::Term::ReturnToDispatch{}});
|
||||
return false;
|
||||
|
|
@ -223,16 +228,16 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
std::optional<u32> MyEmulator::MemoryReadCode(u32 vaddr, bool is_thumb) {
|
||||
if (!check_memory_access(vaddr, 4)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory fetch at {:#010x}", vaddr) << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
u32 temp;
|
||||
|
||||
if (auto ret = handle_mmio_read(vaddr, 4); ret.has_value()) {
|
||||
return ret.value();
|
||||
} else {
|
||||
if (!find_memory_map_id(vaddr).has_value()) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory fetch at {:#010x}", vaddr) << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (big_endian && is_thumb) {
|
||||
temp = MemoryRead8(vaddr + 1);
|
||||
temp |= MemoryRead8(vaddr) << 8;
|
||||
|
|
@ -247,34 +252,33 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
u8 MyEmulator::MemoryRead8(u32 vaddr) {
|
||||
if (auto ret = handle_mmio_read(vaddr, 1); ret.has_value())
|
||||
return ret.value();
|
||||
if (!check_memory_access(vaddr, 1)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory read at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return -1; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (cpu->IsExecuting()) printf("Reading at 0x%08x\n", vaddr);
|
||||
#endif
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory read at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return -1; // Undefined behavior can occur
|
||||
}
|
||||
if (auto ret = handle_mmio_read(vaddr, 1); ret.has_value())
|
||||
return ret.value();
|
||||
|
||||
return mem_map[mmap.value()].data.get()[vaddr - mem_map[mmap.value()].start];
|
||||
auto mmap = find_memory_map_by_vaddr(vaddr);
|
||||
return mmap->data[vaddr - mmap->start];
|
||||
}
|
||||
|
||||
u16 MyEmulator::MemoryRead16(u32 vaddr) {
|
||||
if (auto ret = handle_mmio_read(vaddr, 2); ret.has_value())
|
||||
return ret.value();
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
if (!check_memory_access(vaddr, 2)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory read at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return -1; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
if (auto ret = handle_mmio_read(vaddr, 2); ret.has_value())
|
||||
return ret.value();
|
||||
|
||||
u16 temp;
|
||||
|
||||
if (big_endian) {
|
||||
|
|
@ -289,16 +293,15 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
u32 MyEmulator::MemoryRead32(u32 vaddr) {
|
||||
if (auto ret = handle_mmio_read(vaddr, 4); ret.has_value())
|
||||
return ret.value();
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
if (!check_memory_access(vaddr, 4)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory read at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return -1; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
if (auto ret = handle_mmio_read(vaddr, 4); ret.has_value())
|
||||
return ret.value();
|
||||
|
||||
u32 temp;
|
||||
|
||||
if (big_endian) {
|
||||
|
|
@ -321,34 +324,33 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
void MyEmulator::MemoryWrite8(u32 vaddr, u8 value) {
|
||||
if (handle_mmio_write(vaddr, value, 1))
|
||||
return;
|
||||
if (!check_memory_access(vaddr, 1)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory write at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (cpu->IsExecuting()) printf("Writing at 0x%08x 0x%02x\n", vaddr, value);
|
||||
#endif
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory write at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return; // Undefined behavior can occur
|
||||
}
|
||||
if (handle_mmio_write(vaddr, value, 1))
|
||||
return;
|
||||
|
||||
mem_map[mmap.value()].data.get()[vaddr - mem_map[mmap.value()].start] = value;
|
||||
auto mmap = find_memory_map_by_vaddr(vaddr);
|
||||
mmap->data[vaddr - mmap->start] = value;
|
||||
}
|
||||
|
||||
void MyEmulator::MemoryWrite16(u32 vaddr, u16 value) {
|
||||
if (handle_mmio_write(vaddr, value, 2))
|
||||
return;
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
if (!check_memory_access(vaddr, 2)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory write at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
if (handle_mmio_write(vaddr, value, 2))
|
||||
return;
|
||||
|
||||
if (big_endian) {
|
||||
MemoryWrite8(vaddr, value >> 8);
|
||||
MemoryWrite8(vaddr + 1, value);
|
||||
|
|
@ -359,16 +361,15 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
void MyEmulator::MemoryWrite32(u32 vaddr, u32 value) {
|
||||
if (handle_mmio_write(vaddr, value, 4))
|
||||
return;
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
if (!mmap.has_value()) {
|
||||
if (!check_memory_access(vaddr, 4)) {
|
||||
std::cerr << fmt::format("dynemu: Invalid memory write at {:#010x}", vaddr) << std::endl;
|
||||
cpu->HaltExecution(Dynarmic::HaltReason::MemoryAbort);
|
||||
return; // Undefined behavior can occur
|
||||
}
|
||||
|
||||
if (handle_mmio_write(vaddr, value, 4))
|
||||
return;
|
||||
|
||||
if (big_endian) {
|
||||
MemoryWrite8(vaddr, value >> 24);
|
||||
MemoryWrite8(vaddr + 1, value >> 16);
|
||||
|
|
@ -387,35 +388,27 @@ namespace Dynemu {
|
|||
}
|
||||
|
||||
void MyEmulator::MemoryReadBytes(u32 vaddr, u8 *output, u32 size) {
|
||||
ASSERT_MSG(!find_mmio_id(vaddr).has_value(), "You're trying to read a MMIO mapped address. Use coresponding MMIO routines instead.");
|
||||
ASSERT_MSG(find_mmio_by_vaddr(vaddr) == nullptr, "You're trying to read a MMIO mapped address. Use coresponding MMIO routines instead.");
|
||||
ASSERT_MSG(check_memory_access(vaddr, size), "Invalid memory read");
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
ASSERT_MSG(mmap.has_value(), "Invalid memory read");
|
||||
|
||||
u32 maddr = vaddr - mem_map[mmap.value()].start;
|
||||
|
||||
ASSERT_MSG((maddr + size) <= mem_map[mmap.value()].size, "Invalid memory read");
|
||||
memcpy(output, mem_map[mmap.value()].data.get() + maddr, size);
|
||||
auto mmap = find_memory_map_by_vaddr(vaddr);
|
||||
memcpy(output, &mmap->data[vaddr - mmap->start], size);
|
||||
}
|
||||
|
||||
|
||||
void MyEmulator::MemoryWriteBytes(u32 vaddr, const u8 *input, u32 size) {
|
||||
ASSERT_MSG(!find_mmio_id(vaddr).has_value(), "You're trying to write a MMIO mapped address. Use coresponding MMIO routines instead.");
|
||||
ASSERT_MSG(find_mmio_by_vaddr(vaddr) == nullptr, "You're trying to write a MMIO mapped address. Use coresponding MMIO routines instead.");
|
||||
ASSERT_MSG(check_memory_access(vaddr, size), "Invalid memory write");
|
||||
|
||||
auto mmap = find_memory_map_id(vaddr);
|
||||
ASSERT_MSG(mmap.has_value(), "Invalid memory write");
|
||||
|
||||
u32 maddr = vaddr - mem_map[mmap.value()].start;
|
||||
|
||||
ASSERT_MSG((maddr + size) <= mem_map[mmap.value()].size, "Invalid memory write");
|
||||
memcpy(mem_map[mmap.value()].data.get() + maddr, input, size);
|
||||
auto mmap = find_memory_map_by_vaddr(vaddr);
|
||||
memcpy(&mmap->data[vaddr - mmap->start], input, size);
|
||||
}
|
||||
|
||||
u32 MyEmulator::Execute(u32 pc, bool stub_mode) {
|
||||
if (stub_mode)
|
||||
cpu->Regs()[14] = os_offset + ROUTE_EXIT;
|
||||
u32 MyEmulator::Execute(u32 pc, bool return_mode) {
|
||||
if (return_mode)
|
||||
cpu->Regs()[14] = 0xfffffffc;
|
||||
|
||||
this->stub_mode = stub_mode;
|
||||
this->return_mode = return_mode;
|
||||
cpu->Regs()[15] = pc & ~1;
|
||||
cpu->SetCpsr((pc & 1) ? 0x30 : 0x1d0);
|
||||
|
||||
|
|
@ -428,9 +421,9 @@ namespace Dynemu {
|
|||
return cpu->Regs()[0];
|
||||
}
|
||||
|
||||
std::future<u32> MyEmulator::Spawn(u32 pc, bool stub_mode) {
|
||||
return std::async(std::launch::async, [this, pc, stub_mode] {
|
||||
return Execute(pc, stub_mode);
|
||||
std::future<u32> MyEmulator::Spawn(u32 pc, bool return_mode) {
|
||||
return std::async(std::launch::async, [this, pc, return_mode] {
|
||||
return Execute(pc, return_mode);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,14 +28,10 @@ struct Emu {
|
|||
emu.env.UploadFLSFromBytes((const u8 *)info.ptr);
|
||||
}
|
||||
|
||||
void upload_memstub(u32 vaddr, u32 mem_start = 0xa0000000, u32 mem_size = 0x2000000) {
|
||||
void upload_memstub(u32 vaddr, u32 mem_start, u32 mem_size) {
|
||||
emu.env.UploadOSStub(vaddr, mem_start, mem_size);
|
||||
}
|
||||
|
||||
void upload_memstub(u32 mem_start = 0xa0000000, u32 mem_size = 0x2000000) {
|
||||
emu.env.UploadOSStub(mem_start, mem_size);
|
||||
}
|
||||
|
||||
void mmio(u32 vaddr, u32 size, const MMIO_Read &read, const MMIO_Write &write) {
|
||||
emu.env.CreateMMIO(vaddr, size, read, write);
|
||||
}
|
||||
|
|
@ -109,8 +105,8 @@ struct Emu {
|
|||
emu.env.MemoryWriteBytes(vaddr, (const u8 *)info.ptr, info.size);
|
||||
}
|
||||
|
||||
u32 execute(u32 pc, bool stub_mode=true) {
|
||||
return emu.env.Execute(pc, stub_mode);
|
||||
u32 execute(u32 pc, bool return_mode=true) {
|
||||
return emu.env.Execute(pc, return_mode);
|
||||
}
|
||||
|
||||
void halt() {
|
||||
|
|
@ -152,8 +148,7 @@ PYBIND11_MODULE(_dynemu, module, py::mod_gil_not_used()) {
|
|||
.def("upload_file", &Emu::upload_file, py::arg("filename"), py::arg("vaddr"), py::arg("size"))
|
||||
.def("upload_fls_memory", static_cast<void (Emu::*)(py::bytes)>(&Emu::upload_fls_memory), py::arg("data"))
|
||||
.def("upload_fls_memory", static_cast<void (Emu::*)(py::bytearray)>(&Emu::upload_fls_memory), py::arg("data"))
|
||||
.def("upload_memstub", static_cast<void (Emu::*)(u32, u32, u32)>(&Emu::upload_memstub), py::arg("vaddr"), py::arg("mem_start") = 0xa0000000, py::arg("mem_size") = 0x2000000)
|
||||
.def("upload_memstub", static_cast<void (Emu::*)(u32, u32)>(&Emu::upload_memstub), py::arg("mem_start") = 0xa0000000, py::arg("mem_size") = 0x2000000)
|
||||
.def("upload_memstub", &Emu::upload_memstub, py::arg("vaddr"), py::arg("mem_start"), py::arg("mem_size"))
|
||||
.def("mmio", static_cast<void (Emu::*)(u32, u32)>(&Emu::mmio), py::arg("vaddr"), py::arg("size"))
|
||||
.def("mmio", static_cast<void (Emu::*)(u32, u32, const MMIO_Read &)>(&Emu::mmio), py::arg("vaddr"), py::arg("size"), py::arg("read"))
|
||||
.def("mmio", static_cast<void (Emu::*)(u32, u32, const MMIO_Write &)>(&Emu::mmio), py::arg("vaddr"), py::arg("size"), py::arg("write"))
|
||||
|
|
@ -171,7 +166,7 @@ PYBIND11_MODULE(_dynemu, module, py::mod_gil_not_used()) {
|
|||
.def("read_bytes", &Emu::read_bytes, py::arg("vaddr"), py::arg("size"))
|
||||
.def("write_bytes", static_cast<void (Emu::*)(u32, py::bytes)>(&Emu::write_bytes), py::arg("vaddr"), py::arg("data"))
|
||||
.def("write_bytes", static_cast<void (Emu::*)(u32, py::bytearray)>(&Emu::write_bytes), py::arg("vaddr"), py::arg("data"))
|
||||
.def("execute", &Emu::execute, py::arg("pc"), py::arg("stub_mode") = true)
|
||||
.def("execute", &Emu::execute, py::arg("pc"), py::arg("return_mode") = true)
|
||||
.def("halt", &Emu::halt)
|
||||
.def("get_reg", &Emu::get_reg, py::arg("reg_num"))
|
||||
.def("set_reg", &Emu::set_reg, py::arg("reg_num"), py::arg("value"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue