Finish ELF loading, running actual code now

This commit is contained in:
wheremyfoodat 2022-09-15 17:35:59 +03:00
parent 51689af51f
commit 275c6dfd0c
7 changed files with 135 additions and 59 deletions

View file

@ -1,35 +1,15 @@
#ifdef CPU_DYNARMIC
#include "cpu_dynarmic.hpp"
CPU::CPU(Memory& mem) : mem(mem) {
// Execute at least 1 instruction.
// (Note: More than one instruction may be executed.)
env.ticks_left = 10;
// Write some code to memory.
env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2
env.MemoryWrite16(2, 0x3045); // adds r0, #69
env.MemoryWrite16(4, 0x3845); // subs r0, #69
env.MemoryWrite16(6, 0xE7FE); // b +#0 (infinite loop)
// Setup registers.
auto& regs = jit.Regs();
regs[0] = 1;
regs[1] = 2;
regs[15] = 0; // PC = 0
setCPSR(0x00000030); // Thumb mode
// Execute!
jit.Run();
// Here we would expect cpu.Regs()[0] == 77
printf("R0: %u\n", jit.Regs()[0]);
}
CPU::CPU(Memory& mem) : mem(mem), env(mem) {}
void CPU::reset() {
jit.Regs().fill(0);
// ARM mode, all flags disabled, interrupts and aborts all enabled, user mode
setCPSR(0x00000010);
jit.Reset();
jit.ClearCache();
jit.Regs().fill(0);
}
#endif // CPU_DYNARMIC

View file

@ -1,4 +1,6 @@
#include "memory.hpp"
#include <cstring>
#include "elfio/elfio.hpp"
using namespace ELFIO;
@ -10,14 +12,35 @@ std::optional<u32> Memory::loadELF(std::filesystem::path& path) {
return std::nullopt;
}
auto seg_num = reader.segments.size();
printf("Number of segments: %d\n", seg_num);
for (int i = 0; i < seg_num; ++i) {
const auto pseg = reader.segments[i];
std::cout << " [" << i << "] 0x" << std::hex << pseg->get_flags()
<< "\t0x" << pseg->get_virtual_address() << "\t0x"
<< pseg->get_file_size() << "\t0x" << pseg->get_memory_size()
<< std::endl;
auto segNum = reader.segments.size();
printf("Number of segments: %d\n", segNum);
for (int i = 0; i < segNum; ++i) {
const auto seg = reader.segments[i];
const auto flags = seg->get_flags();
const u32 vaddr = static_cast<u32>(seg->get_virtual_address()); // Vaddr the segment is loaded in
u32 fileSize = static_cast<u32>(seg->get_file_size()); // Size of segment in file
u32 memorySize = static_cast<u32>(seg->get_memory_size()); // Size of segment in memory
u8* data = (u8*)seg->get_data();
// Get read/write/execute permissions for segment
const bool r = (flags & 0b100) != 0;
const bool w = (flags & 0b010) != 0;
const bool x = (flags & 0b001) != 0;
printf(" # Perms Vaddr File Size Mem Size\n");
printf("[%d] (%c%c%c)\t%08X\t%08X\t%08X\n", i, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', vaddr, fileSize, memorySize);
// Assert that the segment will be loaded in the executable region. If it isn't then panic.
// The executable region starts at 0x00100000 and has a maximum size of 0x03F00000
u64 endAddress = (u64)vaddr + (u64)fileSize;
const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd;
if (!isGood) {
Helpers::panic("ELF is loaded at invalid place");
return std::nullopt;
}
u32 fcramAddr = vaddr - VirtualAddrs::ExecutableStart;
std::memcpy(&fcram[fcramAddr], data, fileSize);
}
return static_cast<u32>(reader.get_entry());

View file

@ -2,11 +2,66 @@
Memory::Memory() {
fcram = new uint8_t[128_MB]();
readTable.resize(totalPageCount, 0);
writeTable.resize(totalPageCount, 0);
// Map 63MB of FCRAM in the executable section as read/write
// TODO: This should probably be read-only, but making it r/w shouldn't hurt?
// Because if that were the case then writes would cause data aborts, so games wouldn't write to read-only memory
u32 executablePageCount = VirtualAddrs::MaxExeSize / pageSize;
u32 page = VirtualAddrs::ExecutableStart / pageSize;
for (u32 i = 0; i < executablePageCount; i++) {
const auto pointer = (uintptr_t)&fcram[i * pageSize];
readTable[page] = pointer;
writeTable[page++] = pointer;
}
}
u8 Memory::read8(u32 vaddr) {
Helpers::panic("Unimplemented 8-bit read, addr: %08X", vaddr);
}
u16 Memory::read16(u32 vaddr) {
Helpers::panic("Unimplemented 16-bit read, addr: %08X", vaddr);
}
u32 Memory::read32(u32 vaddr) {
const u32 page = vaddr >> pageShift;
const u32 offset = vaddr & pageMask;
uintptr_t pointer = readTable[page];
if (pointer != 0) [[likely]] {
printf("Read %08X from %08X\n", *(u32*)(pointer + offset), vaddr);
return *(u32*)(pointer + offset);
} else {
Helpers::panic("Unimplemented 32-bit read, addr: %08X", vaddr);
}
}
void Memory::write8(u32 vaddr, u8 value) {
Helpers::panic("Unimplemented 8-bit write, addr: %08X, val: %02X", vaddr, value);
}
void Memory::write16(u32 vaddr, u16 value) {
Helpers::panic("Unimplemented 16-bit write, addr: %08X, val: %04X", vaddr, value);
}
void Memory::write32(u32 vaddr, u32 value) {
const u32 page = vaddr >> pageShift;
const u32 offset = vaddr & pageMask;
uintptr_t pointer = writeTable[page];
if (pointer != 0) [[likely]] {
printf("Wrote %08X to %08X\n", value, vaddr);
*(u32*)(pointer + offset) = value;
} else {
Helpers::panic("Unimplemented 32-bit write, addr: %08X, val: %08X", vaddr, value);
}
}
void* Memory::getReadPointer(u32 address) {
const auto page = address >> pageShift;
const auto offset = address & pageMask;
const u32 page = address >> pageShift;
const u32 offset = address & pageMask;
uintptr_t pointer = readTable[page];
if (pointer == 0) return nullptr;
@ -14,8 +69,8 @@ void* Memory::getReadPointer(u32 address) {
}
void* Memory::getWritePointer(u32 address) {
const auto page = address >> pageShift;
const auto offset = address & pageMask;
const u32 page = address >> pageShift;
const u32 offset = address & pageMask;
uintptr_t pointer = writeTable[page];
if (pointer == 0) return nullptr;