Files
weee/core/broadway.cpp
T
2026-05-14 12:16:43 +02:00

117 lines
2.8 KiB
C++

#include <broadway/utils.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 < 12150000; i++) {
execute(fetch(mem), mem);
}
}
ircolib::u32 broadway::fetch(mem &mem) {
ircolib::u32 val = mem.read32(pc);
pc += 4;
return val;
}
void broadway::decode_special(ircolib::u32 instr, mem &mem) {
switch (utils::secondary(instr)) {
case 0x153:
mfspr(instr);
break;
case 0x1D3:
mtspr(instr);
break;
case 0x10A:
add(instr);
break;
default:
ircolib::panic("broadway unknown special 0x{:04X}", utils::secondary(instr));
}
}
void broadway::execute(ircolib::u32 instr, mem &mem) {
switch (utils::primary(instr)) {
case 11: // cmpi crfD, L, rA, simm
cmpi(instr);
break;
case 14: // addi rd, ra, simm
addi(instr);
break;
case 15: // addis rd, ra, simm
addis(instr);
break;
case 16: // bcx BO, BI, target
bcx(instr);
break;
case 18: // bx target
bx(instr);
break;
case 19:
bclrx(instr);
break;
case 21:
rlwinm(instr);
break;
case 24: // ori ra, rs, uimm
ori(instr);
break;
case 31:
decode_special(instr, mem);
break;
case 32: // lwz rd, d(ra)
lwz(instr, mem);
break;
case 33: // lwz rd, d(ra)
lwzu(instr, mem);
break;
case 36: // stw rs, d(ra)
stw(instr, mem);
break;
case 37: // stwu rs, d(ra)
stwu(instr, mem);
break;
case 44: // stwu rs, d(ra)
sth(instr, mem);
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++) {
std::println("\t0x{:x}:\t{}\t\t{}", insn[j].address, insn[j].mnemonic, insn[j].op_str);
}
cs_free(insn, count);
}
} // namespace weee::core