start executing
This commit is contained in:
+3
-1
@@ -20,6 +20,8 @@ set(CAPSTONE_PPC_SUPPORT ON)
|
||||
add_subdirectory(external/capstone)
|
||||
|
||||
add_executable(weee main.cpp core/mem.cpp core/loaders/elf.cpp
|
||||
core/loaders/dol.cpp)
|
||||
core/loaders/dol.cpp
|
||||
core/broadway.cpp
|
||||
core/broadway/instructions.cpp)
|
||||
target_link_libraries(weee PUBLIC capstone)
|
||||
target_include_directories(weee PUBLIC core)
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <broadway.hpp>
|
||||
#include <mem.hpp>
|
||||
#include <print>
|
||||
#include <ircolib/log.hpp>
|
||||
#include <ircolib/mem_access.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace weee::core {
|
||||
broadway::broadway() {
|
||||
if (cs_open(CS_ARCH_PPC, cs_mode(CS_MODE_BIG_ENDIAN | CS_MODE_32), &capstone) != CS_ERR_OK) {
|
||||
std::println("warning: could not initialize capstone. Disassembly is disabled");
|
||||
disasm_available = false;
|
||||
}
|
||||
}
|
||||
|
||||
void broadway::set_pc(ircolib::u32 value) { pc = value; }
|
||||
|
||||
void broadway::run(mem &mem) {
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
execute(fetch(mem), mem);
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::u32 broadway::fetch(mem &mem) {
|
||||
ircolib::u32 val = mem.read(pc);
|
||||
pc += 4;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void broadway::execute(ircolib::u32 instr, mem &mem) {
|
||||
ircolib::u8 primary = (instr >> 26) & 0x3f;
|
||||
switch (primary) {
|
||||
case 15: // addis rd, ra, simm
|
||||
addis(instr);
|
||||
break;
|
||||
default:
|
||||
std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b}", instr, instr);
|
||||
std::println("disassembly:");
|
||||
print_disasm(instr);
|
||||
ircolib::panic("");
|
||||
}
|
||||
}
|
||||
|
||||
void broadway::print_disasm(ircolib::u32 instr) {
|
||||
if (!disasm_available)
|
||||
return;
|
||||
|
||||
cs_insn *insn;
|
||||
auto instr_buff = ircolib::integral_to_slice(std::byteswap(instr));
|
||||
size_t count = cs_disasm(capstone, instr_buff.data(), instr_buff.size(), pc - 4, 1, &insn);
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
size_t j;
|
||||
for (j = 0; j < count; j++) {
|
||||
printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
|
||||
}
|
||||
|
||||
cs_free(insn, count);
|
||||
}
|
||||
} // namespace weee::core
|
||||
+20
-1
@@ -1,7 +1,26 @@
|
||||
#pragma once
|
||||
#include <ircolib/types.hpp>
|
||||
#include <capstone/capstone.h>
|
||||
#include <array>
|
||||
|
||||
namespace weee::core {
|
||||
struct mem;
|
||||
struct broadway {
|
||||
|
||||
broadway();
|
||||
void set_pc(ircolib::u32);
|
||||
void run(mem &);
|
||||
|
||||
private:
|
||||
ircolib::u32 fetch(mem &);
|
||||
void print_disasm(ircolib::u32);
|
||||
void execute(ircolib::u32, mem &);
|
||||
|
||||
bool disasm_available = true;
|
||||
ircolib::u32 pc = 0;
|
||||
std::array<ircolib::u32, 32> gpr{};
|
||||
csh capstone;
|
||||
|
||||
// instructions
|
||||
void addis(ircolib::u32);
|
||||
};
|
||||
} // namespace weee::core
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <broadway.hpp>
|
||||
|
||||
namespace weee::core {
|
||||
void broadway::addis(ircolib::u32 instr) {
|
||||
|
||||
}
|
||||
} // namespace weee::core
|
||||
@@ -1,12 +1,13 @@
|
||||
#include <loaders/dol.hpp>
|
||||
#include <mem.hpp>
|
||||
#include <broadway.hpp>
|
||||
#include <ircolib/file.hpp>
|
||||
#include <ircolib/mem_access.hpp>
|
||||
#include <array>
|
||||
#include <print>
|
||||
|
||||
namespace weee::core {
|
||||
bool load_dol(const std::string &path, mem &mem) {
|
||||
bool load_dol(const std::string &path, mem &mem, broadway &broadway) {
|
||||
auto bin = ircolib::read_file_binary(path);
|
||||
if (bin.size() <= 0)
|
||||
return false;
|
||||
@@ -45,6 +46,7 @@ bool load_dol(const std::string &path, mem &mem) {
|
||||
mem.set(0, hdr.bss_size, hdr.bss_address & 0x0FFFFFFF);
|
||||
|
||||
hdr.entry_point = std::byteswap(ircolib::read_access<ircolib::u32>(bin, 0xE0));
|
||||
broadway.set_pc(hdr.entry_point);
|
||||
|
||||
for (const auto §ion : hdr.text) {
|
||||
if (section.offset == 0)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace weee::core {
|
||||
struct mem;
|
||||
struct broadway;
|
||||
|
||||
bool load_dol(const std::string &, mem &);
|
||||
bool load_dol(const std::string &, mem &, broadway &);
|
||||
} // namespace weee::core
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include <loaders/elf.hpp>
|
||||
#include <mem.hpp>
|
||||
#include <broadway.hpp>
|
||||
#include <elfio/elfio.hpp>
|
||||
#include <print>
|
||||
|
||||
namespace weee::core {
|
||||
bool load_elf(const std::string &path, mem &mem) {
|
||||
bool load_elf(const std::string &path, mem &mem, broadway &broadway) {
|
||||
ELFIO::elfio reader;
|
||||
if (!reader.load(path))
|
||||
return false;
|
||||
@@ -39,10 +40,12 @@ bool load_elf(const std::string &path, mem &mem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mem.copy((const ircolib::u8 *)segment->get_data(), segment->get_file_size(),
|
||||
mem.copy((ircolib::u8 *)segment->get_data(), segment->get_file_size(),
|
||||
segment->get_virtual_address() & 0x0FFFFFFF);
|
||||
}
|
||||
|
||||
broadway.set_pc(reader.get_entry());
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace weee::core
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace weee::core {
|
||||
struct mem;
|
||||
struct broadway;
|
||||
|
||||
bool load_elf(const std::string &, mem &);
|
||||
bool load_elf(const std::string &, mem &, broadway &);
|
||||
} // namespace weee::core
|
||||
|
||||
+21
-2
@@ -1,6 +1,7 @@
|
||||
#include <cstring>
|
||||
#include <mem.hpp>
|
||||
#include <ircolib/log.hpp>
|
||||
#include "ircolib/mem_access.hpp"
|
||||
|
||||
namespace weee::core {
|
||||
mem::mem() {
|
||||
@@ -8,18 +9,20 @@ mem::mem() {
|
||||
std::fill(mem1.begin(), mem1.end(), 0);
|
||||
}
|
||||
|
||||
void mem::copy(const std::vector<ircolib::u8> &src, const ircolib::u32 offset) {
|
||||
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::println("Copying {} bytes to mem1[{}]", src.size(), offset);
|
||||
std::copy(src.begin(), src.end(), mem1.begin() + offset);
|
||||
}
|
||||
|
||||
void mem::copy(const ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 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);
|
||||
std::println("Copying {} bytes to mem1[{}]", size, offset);
|
||||
memcpy(&mem1[offset], src, size);
|
||||
}
|
||||
@@ -31,4 +34,20 @@ void mem::set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32
|
||||
std::println("Setting {} bytes to {} from mem1[{}]", size, val, offset);
|
||||
memset(&mem1[offset], val, size);
|
||||
}
|
||||
|
||||
ircolib::u32 mem::read(ircolib::u32 addr) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
if (addr > 0x017FFFFF)
|
||||
ircolib::panic("mem::read unimplemented outside mem1 (0x{:08X})", addr);
|
||||
|
||||
return ircolib::read_access<ircolib::u32>(mem1, addr);
|
||||
}
|
||||
|
||||
void mem::write(ircolib::u32 addr, ircolib::u32 value) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
if (addr > 0x017FFFFF)
|
||||
ircolib::panic("mem::write unimplemented outside mem1 (0x{:08X} = 0x{:08X})", addr, value);
|
||||
|
||||
ircolib::write_access<ircolib::u32>(mem1, addr, value);
|
||||
}
|
||||
} // namespace weee::core
|
||||
|
||||
+4
-2
@@ -6,8 +6,10 @@ namespace weee::core {
|
||||
struct mem {
|
||||
mem();
|
||||
|
||||
void copy(const std::vector<ircolib::u8> &src, const ircolib::u32 offset);
|
||||
void copy(const ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset);
|
||||
ircolib::u32 read(ircolib::u32);
|
||||
void write(ircolib::u32, ircolib::u32);
|
||||
void copy(std::vector<ircolib::u8> &src, const ircolib::u32 offset);
|
||||
void copy(ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset);
|
||||
void set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32 offset);
|
||||
|
||||
private:
|
||||
|
||||
Vendored
+8
@@ -144,6 +144,14 @@ static constexpr inline void swap_buffer(std::array<u8, Size> &data) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr inline void swap_buffer(u8 *data, size_t size) {
|
||||
for (size_t i = 0; i < size; i += sizeof(T)) {
|
||||
const T original = *reinterpret_cast<T *>(&data[i]);
|
||||
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
inline void *aligned_alloc(const size_t alignment, const size_t size) { return _aligned_malloc(size, alignment); }
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
#include <loaders/dol.hpp>
|
||||
#include <ircolib/log.hpp>
|
||||
#include <mem.hpp>
|
||||
#include <broadway.hpp>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
weee::core::mem mem;
|
||||
weee::core::broadway broadway;
|
||||
|
||||
cflags::cflags flags;
|
||||
flags.add_string_callback(
|
||||
'\0', "elf",
|
||||
[&](const std::string &v) {
|
||||
if (!weee::core::load_elf(v, mem))
|
||||
if (!weee::core::load_elf(v, mem, broadway))
|
||||
ircolib::panic("Could not load '{}'", v);
|
||||
},
|
||||
"ELF binary to load");
|
||||
@@ -20,7 +22,7 @@ int main(int argc, char **argv) {
|
||||
flags.add_string_callback(
|
||||
'\0', "dol",
|
||||
[&](const std::string &v) {
|
||||
if (!weee::core::load_dol(v, mem))
|
||||
if (!weee::core::load_dol(v, mem, broadway))
|
||||
ircolib::panic("Could not load '{}'", v);
|
||||
},
|
||||
"DOL binary to load");
|
||||
@@ -28,5 +30,8 @@ int main(int argc, char **argv) {
|
||||
if (!flags.parse(argc, argv))
|
||||
return -1;
|
||||
|
||||
while (true)
|
||||
broadway.run(mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user