diff --git a/CMakeLists.txt b/CMakeLists.txt index 312f969..08424c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,11 @@ add_executable(weee main.cpp core/mem.cpp core/loaders/elf.cpp core/loaders/dol.cpp core/broadway.cpp core/broadway/instructions.cpp - core/broadway/mmio/vi.cpp) + core/broadway/mmio/vi.cpp + core/broadway/mmio/pi.cpp + core/broadway/mmio/mi.cpp + core/broadway/mmio/dsp.cpp + core/broadway/mmio/ai.cpp + core/broadway/mmio/exi.cpp) target_link_libraries(weee PUBLIC SDL3::SDL3 capstone) target_include_directories(weee PUBLIC core) \ No newline at end of file diff --git a/core/broadway.cpp b/core/broadway.cpp index a775858..be628b3 100644 --- a/core/broadway.cpp +++ b/core/broadway.cpp @@ -45,7 +45,10 @@ void broadway::decode_special3(ircolib::u32 instr, mem &mem) { mtfsf(instr); break; default: - ircolib::panic("broadway unknown special3 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4); + std::println("broadway unknown special3 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4); + std::println("disassembly:"); + print_disasm(instr); + ircolib::panic("LR: 0x{:08X}", lr); } } @@ -55,6 +58,15 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x000: cmp(instr); break; + case 0x013: + mfcr(instr); + break; + case 0x017: + lwzx(instr, mem); + break; + case 0x01C: + and(instr); + break; case 0x020: cmpl(instr); break; @@ -64,9 +76,21 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x053: mfmsr(instr); break; + case 0x090: + mtcrf(instr); + break; + case 0x092: + mtmsr(instr); + break; + case 0x097: + stwx(instr, mem); + break; case 0x0D2: ircolib::warn("broadway TODO mtsr (pc 0x{:08X})", pc - 4); break; + case 0x0EB: + mullw(instr); + break; case 0x1BC: or (instr); break; @@ -80,10 +104,16 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x10A: add(instr); break; + case 0x1CB: + divwu(instr); + break; case 0x256: // sync break; default: - ircolib::panic("broadway unknown special2 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4); + std::println("broadway unknown special2 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4); + std::println("disassembly:"); + print_disasm(instr); + ircolib::panic("LR: 0x{:08X}", lr); } } @@ -98,19 +128,32 @@ void broadway::decode_special1(ircolib::u32 instr, mem &mem) { case 0x96: // isync break; default: - ircolib::panic("broadway unknown special1 {} (0x{:04X}) (pc 0x{:08X})", utils::secondary(instr), - utils::secondary(instr), pc - 4); + std::println("broadway unknown special1 {} (0x{:04X}) (pc 0x{:08X})", utils::secondary(instr), + utils::secondary(instr), pc - 4); + std::println("disassembly:"); + print_disasm(instr); + ircolib::panic("LR: 0x{:08X}", lr); } } void broadway::execute(ircolib::u32 instr, mem &mem) { - switch (utils::primary(instr)) { + const auto primary = utils::primary(instr); + switch (primary) { + case 7: + mulli(instr); + break; case 10: cmpli(instr); break; case 11: cmpi(instr); break; + case 12: + addic(instr); + break; + case 13: + addicr(instr); + break; case 14: addi(instr); break; @@ -126,6 +169,9 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 19: decode_special1(instr, mem); break; + case 20: + rlwimi(instr); + break; case 21: rlwinm(instr); break; @@ -138,6 +184,9 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 28: andi(instr); break; + case 29: + andis(instr); + break; case 31: decode_special2(instr, mem); break; @@ -156,9 +205,15 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 37: stwu(instr, mem); break; + case 38: + stb(instr, mem); + break; case 39: stbu(instr, mem); break; + case 40: + lhz(instr, mem); + break; case 44: sth(instr, mem); break; @@ -169,7 +224,7 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { decode_special3(instr, mem); break; default: - std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b}", instr, instr); + std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b} ({})", instr, instr, primary); std::println("disassembly:"); print_disasm(instr); ircolib::panic("LR: 0x{:08X}", lr); diff --git a/core/broadway.hpp b/core/broadway.hpp index a24ceff..00ad1cf 100644 --- a/core/broadway.hpp +++ b/core/broadway.hpp @@ -63,20 +63,29 @@ struct broadway { bool test_cond_and_ctr(ircolib::u32); void andi(ircolib::u32); + void andis(ircolib::u32); + void and(ircolib::u32); void add(ircolib::u32); void addis(ircolib::u32); void addi(ircolib::u32); + void addic(ircolib::u32); + void addicr(ircolib::u32); void ori(ircolib::u32); void oris(ircolib::u32); void bx(ircolib::u32); void bcx(ircolib::u32); void mftspr(bool, ircolib::u32); + void mtcrf(ircolib::u32); void stw(ircolib::u32, mem &); + void stb(ircolib::u32, mem &); void stwu(ircolib::u32, mem &); + void stwx(ircolib::u32, mem &); void stbu(ircolib::u32, mem &); void sth(ircolib::u32, mem &); void lbz(ircolib::u32, mem &); void lwz(ircolib::u32, mem &); + void lwzx(ircolib::u32, mem &); + void lhz(ircolib::u32, mem &); void lfd(ircolib::u32, mem &); void bclrx(ircolib::u32); void cmpi(ircolib::u32); @@ -84,15 +93,21 @@ struct broadway { void cmp(ircolib::u32); void cmpl(ircolib::u32); void rlwinm(ircolib::u32); + void rlwimi(ircolib::u32); void lwzu(ircolib::u32, mem &); void rfi(ircolib::u32); + void mfcr(ircolib::u32); void mtfsf(ircolib::u32); void mtfsb1(ircolib::u32); void mtfsb0(ircolib::u32); void mfmsr(ircolib::u32); + void mtmsr(ircolib::u32); + void mullw(ircolib::u32); + void mulli(ircolib::u32); void nand(ircolib::u32); void subf(ircolib::u32); void or (ircolib::u32); + void divwu(ircolib::u32); inline void cr0_update(bool condition, ircolib::s32 result) { if (condition) { diff --git a/core/broadway/instructions.cpp b/core/broadway/instructions.cpp index 01ded14..c1e42bd 100644 --- a/core/broadway/instructions.cpp +++ b/core/broadway/instructions.cpp @@ -17,6 +17,15 @@ void broadway::addi(ircolib::u32 instr) { gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); } +void broadway::addicr(ircolib::u32 instr) { + gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); + cr0_update(true, gpr[utils::RD(instr)]); +} + +void broadway::addic(ircolib::u32 instr) { + gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); +} + void broadway::addis(ircolib::u32 instr) { if (utils::RA(instr) == 0) { // lis gpr[utils::RD(instr)] = ircolib::s32(utils::SIMM(instr)) << 16; @@ -188,6 +197,20 @@ void broadway::stw(ircolib::u32 instr, mem &mem) { }); } +void broadway::stb(ircolib::u32 instr, mem &mem) { + ircolib::s32 b = gpr[utils::RA(instr)]; + if (utils::RA(instr) == 0) + b = 0; + + const ircolib::u32 EA = b + utils::SIMM(instr); + auto _ = mem.write8(EA, gpr[utils::RS(instr)]) + .and_then([&] { return std::expected(); }) + .or_else([&](std::string e) { + ircolib::panic("stw broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }); +} + void broadway::sth(ircolib::u32 instr, mem &mem) { ircolib::u32 b = gpr[utils::RA(instr)]; if (utils::RA(instr) == 0) @@ -203,6 +226,20 @@ void broadway::sth(ircolib::u32 instr, mem &mem) { }); } +void broadway::stwx(ircolib::u32 instr, mem &mem) { + ircolib::u32 b = gpr[utils::RA(instr)]; + if (utils::RA(instr) == 0) + b = 0; + + const ircolib::u32 EA = b + gpr[utils::RB(instr)]; + auto _ = mem.write32(EA, gpr[utils::RS(instr)]) + .and_then([&] { return std::expected(); }) + .or_else([&](std::string e) { + ircolib::panic("stwx broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }); +} + void broadway::lwz(ircolib::u32 instr, mem &mem) { ircolib::u32 b = gpr[utils::RA(instr)]; if (utils::RA(instr) == 0) @@ -213,7 +250,39 @@ void broadway::lwz(ircolib::u32 instr, mem &mem) { gpr[utils::RD(instr)] = mem.read32(ea) .and_then([&](ircolib::u32 val) { return std::expected(val); }) .or_else([&](std::string e) { - ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + ircolib::panic("lwz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }) + .value(); +} + +void broadway::lwzx(ircolib::u32 instr, mem &mem) { + ircolib::u32 b = gpr[utils::RA(instr)]; + if (utils::RA(instr) == 0) + b = 0; + + ircolib::u32 ea = ircolib::s32(b) + gpr[utils::RB(instr)]; + + gpr[utils::RD(instr)] = mem.read32(ea) + .and_then([&](ircolib::u32 val) { return std::expected(val); }) + .or_else([&](std::string e) { + ircolib::panic("lwz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }) + .value(); +} + +void broadway::lhz(ircolib::u32 instr, mem &mem) { + ircolib::u32 b = gpr[utils::RA(instr)]; + if (utils::RA(instr) == 0) + b = 0; + + ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr); + + gpr[utils::RD(instr)] = mem.read16(ea) + .and_then([&](ircolib::u32 val) { return std::expected(val); }) + .or_else([&](std::string e) { + ircolib::panic("lhz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); return std::expected(); }) .value(); @@ -229,7 +298,7 @@ void broadway::lbz(ircolib::u32 instr, mem &mem) { gpr[utils::RD(instr)] = mem.read8(ea) .and_then([&](ircolib::u32 val) { return std::expected(val); }) .or_else([&](std::string e) { - ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + ircolib::panic("lbz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); return std::expected(); }) .value(); @@ -246,7 +315,7 @@ void broadway::lfd(ircolib::u32 instr, mem &mem) { mem.read64(ea) .and_then([&](ircolib::u64 val) { return std::expected(val); }) .or_else([&](std::string e) { - ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + ircolib::panic("lfd broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); return std::expected(); }) .value(); @@ -337,6 +406,23 @@ void broadway::rlwinm(ircolib::u32 instr) { cr0_update(instr & 1, r); } +void broadway::rlwimi(ircolib::u32 instr) { + const ircolib::u8 sh = (instr >> 11) & 0x1f; + ircolib::u32 r = std::rotl(gpr[utils::RS(instr)], sh); + const ircolib::u8 mb = (instr >> 6) & 0x1f; + const ircolib::u8 me = (instr >> 1) & 0x1f; + const ircolib::u32 start = 0xffffffff >> mb; + const ircolib::u32 end = 0x7fffffff >> me; + ircolib::u32 mask = start ^ end; + if (mb > me) + mask = ~mask; + + r &= mask; + r |= (gpr[utils::RA(instr)] & ~mask); + gpr[utils::RA(instr)] = r; + cr0_update(instr & 1, r); +} + void broadway::lwzu(ircolib::u32 instr, mem &mem) { if (utils::RA(instr) == 0 || utils::RA(instr) == utils::RD(instr)) ircolib::panic("broadway::lwzu with ra == 0"); @@ -348,7 +434,7 @@ void broadway::lwzu(ircolib::u32 instr, mem &mem) { return std::expected(val); }) .or_else([&](std::string e) { - ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + ircolib::panic("lwzu broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); return std::expected(); }) .value(); @@ -365,6 +451,18 @@ void broadway::andi(ircolib::u32 instr) { cr0_update(true, result); } +void broadway::andis(ircolib::u32 instr) { + const ircolib::s32 result = gpr[utils::RS(instr)] & (ircolib::u32(utils::UIMM(instr)) << 16); + gpr[utils::RA(instr)] = result; + cr0_update(true, result); +} + +void broadway::and(ircolib::u32 instr) { + const ircolib::s32 result = gpr[utils::RS(instr)] & gpr[utils::RB(instr)]; + gpr[utils::RA(instr)] = result; + cr0_update(instr & 1, result); +} + void broadway::mtfsf(ircolib::u32 instr) { const ircolib::u8 fm = (instr >> 17) & 0xff; ircolib::u8 mask = 0; @@ -395,6 +493,7 @@ void broadway::mtfsb1(ircolib::u32 instr) { } void broadway::mfmsr(ircolib::u32 instr) { gpr[utils::RS(instr)] = msr; } +void broadway::mtmsr(ircolib::u32 instr) { msr = gpr[utils::RS(instr)]; } void broadway::nand(ircolib::u32 instr) { gpr[utils::RA(instr)] = ~(gpr[utils::RS(instr)] & gpr[utils::RB(instr)]); @@ -410,4 +509,38 @@ void broadway:: or (ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] | gpr[utils::RB(instr)]; cr0_update(instr & 1, gpr[utils::RA(instr)]); } + +void broadway::mullw(ircolib::u32 instr) { + gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(gpr[utils::RB(instr)]); +} + +void broadway::mulli(ircolib::u32 instr) { + gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(utils::SIMM(instr)); +} + +void broadway::mfcr(ircolib::u32 instr) { gpr[utils::RD(instr)] = cr; } + +void broadway::mtcrf(ircolib::u32 instr) { + ircolib::u32 mask = 0; + const ircolib::u8 crm = (instr >> 13) & 0xff; + for (int i = 0; i < 7; i++) { + if (ircolib::is_bit_set(crm, i)) { + set_cr(gpr[utils::RS(instr)] & (0xffff << i * 4), i); + } + } +} + +void broadway::divwu(ircolib::u32 instr) { + ircolib::u32 dividend = gpr[utils::RA(instr)]; + ircolib::u32 divisor = gpr[utils::RB(instr)]; + if (divisor == 0) { + if ((instr >> 11) & 1) + xer.ov = true; + + return; + } + + gpr[utils::RD(instr)] = dividend / divisor; + cr0_update(instr & 1, gpr[utils::RD(instr)]); +} } // namespace weee::core diff --git a/core/broadway/mmio/ai.cpp b/core/broadway/mmio/ai.cpp new file mode 100644 index 0000000..5e6d119 --- /dev/null +++ b/core/broadway/mmio/ai.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +namespace weee::core { +ai::ai(mem &mem) { + mem.register_read32_handler(0x0c006c00, 0x0c006c1f, [&](ircolib::u32 addr) { return read32(addr); }); + mem.register_write32_handler(0x0c006c00, 0x0c006c1f, + [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); +} + +ircolib::u32 ai::read32(ircolib::u32 addr) { + switch (addr) { + case 0: + return ctrl.raw; + default: + ircolib::panic("ai::read32 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} + +void ai::write32(ircolib::u32 addr, ircolib::u32 value) { + switch (addr) { + case 0: + ctrl.raw = value; + break; + default: + ircolib::panic("ai::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/ai.hpp b/core/broadway/mmio/ai.hpp new file mode 100644 index 0000000..d4ead02 --- /dev/null +++ b/core/broadway/mmio/ai.hpp @@ -0,0 +1,26 @@ +#pragma once +#include + +namespace weee::core { +struct mem; +struct ai { + ai(mem &); + + ircolib::u32 read32(ircolib::u32); + void write32(ircolib::u32, ircolib::u32); + + union { + struct { + unsigned pstat : 1; + unsigned afr : 1; + unsigned aiintmsk : 1; + unsigned aiint : 1; + unsigned aiintvld : 1; + unsigned screset : 1; + unsigned dsp_sr : 1; + unsigned : 25; + }; + ircolib::u32 raw; + } ctrl; +}; +} // namespace weee::core diff --git a/core/broadway/mmio/dsp.cpp b/core/broadway/mmio/dsp.cpp new file mode 100644 index 0000000..381e673 --- /dev/null +++ b/core/broadway/mmio/dsp.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +namespace weee::core { +dsp::dsp(mem &mem) { + mem.register_read16_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr) { return read16(addr); }); + mem.register_write16_handler(0x0c005000, 0x0c0051ff, + [&](ircolib::u32 addr, ircolib::u16 value) { return write16(addr, value); }); +} + +ircolib::u16 dsp::read16(ircolib::u32 addr) { + switch (addr) { + case 0x0a: + return csr.raw; + default: + ircolib::panic("dsp::read16 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} + +void dsp::write16(ircolib::u32 addr, ircolib::u16 value) { + switch (addr) { + case 0x0a: + csr.raw = value; + break; + default: + ircolib::panic("dsp::read16 from unimplemented addr 0x{:08X}", addr); + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/dsp.hpp b/core/broadway/mmio/dsp.hpp new file mode 100644 index 0000000..d18f4a7 --- /dev/null +++ b/core/broadway/mmio/dsp.hpp @@ -0,0 +1,30 @@ +#pragma once +#include + +namespace weee::core { +struct mem; +struct dsp { + dsp(mem &); + ircolib::u16 read16(ircolib::u32); + void write16(ircolib::u32, ircolib::u16); + + union { + struct { + unsigned res : 1; + unsigned piint : 1; + unsigned halt : 1; + unsigned aidint : 1; + unsigned aidint_mask : 1; + unsigned arint : 1; + unsigned arint_mask : 1; + unsigned dspint : 1; + unsigned dspint_mask : 1; + unsigned int_status : 1; + unsigned : 1; + unsigned res2 : 1; + unsigned : 4; + }; + ircolib::u16 raw; + } csr; +}; +} // namespace weee::core diff --git a/core/broadway/mmio/exi.cpp b/core/broadway/mmio/exi.cpp new file mode 100644 index 0000000..8651756 --- /dev/null +++ b/core/broadway/mmio/exi.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +namespace weee::core { +exi::exi(mem &mem) { + mem.register_read32_handler(0x0c006800, 0x0c00683f, [&](ircolib::u32 addr) { return read32(addr); }); + mem.register_write32_handler(0x0c006800, 0x0c00683f, + [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); +} + +ircolib::u32 exi::read32(ircolib::u32 addr) { + switch (addr) { + case 0: + return param0.raw; + case 0x14: + return param1.raw; + case 0x28: + return param2.raw; + default: + ircolib::panic("exi::read32 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} + +void exi::write32(ircolib::u32 addr, ircolib::u32 value) { + switch (addr) { + case 0: + param0.raw = value; + break; + case 0x14: + param1.raw = value; + break; + case 0x28: + param2.raw = value; + break; + default: + ircolib::panic("exi::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/exi.hpp b/core/broadway/mmio/exi.hpp new file mode 100644 index 0000000..5244b4d --- /dev/null +++ b/core/broadway/mmio/exi.hpp @@ -0,0 +1,30 @@ +#pragma once +#include + +namespace weee::core { +struct mem; +struct exi { + exi(mem &); + + ircolib::u32 read32(ircolib::u32); + void write32(ircolib::u32, ircolib::u32); + + union { + struct { + unsigned ext_int_mask : 1; + unsigned ext_int : 1; + unsigned tc_int_mask : 1; + unsigned tc_int : 1; + unsigned clk : 3; + unsigned cs : 3; + unsigned ext_int_mask2 : 1; + unsigned ext_int2 : 1; + unsigned ext : 1; + unsigned romdis : 1; + unsigned : 18; + }; + + ircolib::u32 raw; + } param0, param1, param2; +}; +} // namespace weee::core diff --git a/core/broadway/mmio/mi.cpp b/core/broadway/mmio/mi.cpp new file mode 100644 index 0000000..7d082c5 --- /dev/null +++ b/core/broadway/mmio/mi.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +namespace weee::core { +memory_interface::memory_interface(mem &mem) { + mem.register_write16_handler(0x0c004000, 0x0c00407f, + [&](ircolib::u32 addr, ircolib::u16 value) { write16(addr, value); }); +} + +void memory_interface::write16(ircolib::u32 addr, ircolib::u16 value) { + switch (addr) { + case 0x1C: + int_mask.raw = value; + break; + default: + ircolib::panic("memory_interface::write16 to unimplemented addr 0x{:08X} with value 0x{:04X}", addr, value); + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/mi.hpp b/core/broadway/mmio/mi.hpp new file mode 100644 index 0000000..b32978c --- /dev/null +++ b/core/broadway/mmio/mi.hpp @@ -0,0 +1,23 @@ +#pragma once +#include + +namespace weee::core { +struct mem; + +struct memory_interface { + union { + struct { + unsigned mem0 : 1; + unsigned mem1 : 1; + unsigned mem2 : 1; + unsigned mem3 : 1; + unsigned all : 1; + unsigned : 27; + }; + ircolib::u32 raw; + } int_mask; + + memory_interface(mem &); + void write16(ircolib::u32, ircolib::u16); +}; +} // namespace weee::core diff --git a/core/broadway/mmio/pi.cpp b/core/broadway/mmio/pi.cpp new file mode 100644 index 0000000..740855a --- /dev/null +++ b/core/broadway/mmio/pi.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +namespace weee::core { +processor_interface::processor_interface(mem &mem) { + mem.register_write32_handler(0x0c003000, 0x0c0030ff, + [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); + mem.register_read32_handler(0x0c003000, 0x0c0030ff, [&](ircolib::u32 addr) { return read32(addr); }); +} + +void processor_interface::write32(ircolib::u32 addr, ircolib::u32 value) { + switch (addr) { + case 0x04: + intmr.raw = value; + break; + default: + ircolib::panic("processor_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + } +} + +ircolib::u32 processor_interface::read32(ircolib::u32 addr) { + switch (addr) { + case 0x2c: + return 2; + default: + ircolib::panic("processor_interface::read32 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/pi.hpp b/core/broadway/mmio/pi.hpp new file mode 100644 index 0000000..236e367 --- /dev/null +++ b/core/broadway/mmio/pi.hpp @@ -0,0 +1,33 @@ +#pragma once +#include + +namespace weee::core { +struct mem; + +struct processor_interface { + union { + struct { + unsigned error : 1; + unsigned rsw : 1; + unsigned di : 1; + unsigned si : 1; + unsigned exi : 1; + unsigned ai : 1; + unsigned dsp : 1; + unsigned mem : 1; + unsigned vi : 1; + unsigned pe_token : 1; + unsigned pe_finish : 1; + unsigned cp : 1; + unsigned debug : 1; + unsigned hsp : 1; + unsigned : 18; + }; + ircolib::u32 raw; + } intmr; + + processor_interface(mem &); + void write32(ircolib::u32, ircolib::u32); + ircolib::u32 read32(ircolib::u32); +}; +} // namespace weee::core diff --git a/core/mem.cpp b/core/mem.cpp index 0ea7344..f0c8afa 100644 --- a/core/mem.cpp +++ b/core/mem.cpp @@ -4,9 +4,11 @@ #include namespace weee::core { -mem::mem() : vi(*this) { +mem::mem() : vi(*this), pi(*this), mi(*this), dsp(*this), ai(*this), exi(*this) { mem1.resize(24_mib); std::fill(mem1.begin(), mem1.end(), 0); + ipl.resize(1_mib); + std::fill(ipl.begin(), ipl.end(), 0); register_read8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr) { return mem1[addr]; }); @@ -29,9 +31,34 @@ mem::mem() : vi(*this) { ircolib::write_access(mem1, addr, value); }); - register_write64_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) { + register_write64_handler(0x00000000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) { ircolib::write_access(mem1, addr, value); }); + + register_read8_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr) { return ipl[addr]; }); + + register_read16_handler(0x0ff00000, 0x0fffffff, + [&](ircolib::u32 addr) { return ircolib::read_access(ipl, addr); }); + + register_read32_handler(0x0ff00000, 0x0fffffff, + [&](ircolib::u32 addr) { return ircolib::read_access(ipl, addr); }); + + register_read64_handler(0x0ff00000, 0x0fffffff, + [&](ircolib::u32 addr) { return ircolib::read_access(ipl, addr); }); + + register_write8_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u8 value) { ipl[addr] = value; }); + + register_write16_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u16 value) { + ircolib::write_access(ipl, addr, value); + }); + + register_write32_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) { + ircolib::write_access(ipl, addr, value); + }); + + register_write64_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) { + ircolib::write_access(ipl, addr, value); + }); } void mem::copy(std::vector &src, const ircolib::u32 offset) { diff --git a/core/mem.hpp b/core/mem.hpp index a436069..0b7a742 100644 --- a/core/mem.hpp +++ b/core/mem.hpp @@ -3,6 +3,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -69,6 +74,7 @@ struct mem { void set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32 offset); std::vector mem1; + std::vector ipl{}; private: std::vector> read8_handlers{}; @@ -82,5 +88,10 @@ struct mem { public: video_interface vi; + processor_interface pi; + memory_interface mi; + dsp dsp; + exi exi; + ai ai; }; } // namespace weee::core diff --git a/main.cpp b/main.cpp index a5c1857..d6a1afb 100644 --- a/main.cpp +++ b/main.cpp @@ -1,14 +1,12 @@ #include #include +#include #include #include #include #include #include #include -#include - -namespace fs = std::filesystem; int main(int argc, char **argv) { weee::core::mem mem; @@ -20,7 +18,7 @@ int main(int argc, char **argv) { flags.add_string_callback( '\0', "elf", [&](const std::string &v) { - binName = fs::path(v).filename().string(); + binName = ircolib::fs::path(v).filename().string(); if (!weee::core::load_elf(v, mem, broadway)) ircolib::panic("Could not load '{}'", v); }, @@ -29,7 +27,7 @@ int main(int argc, char **argv) { flags.add_string_callback( '\0', "dol", [&](const std::string &v) { - binName = fs::path(v).filename().string(); + binName = ircolib::fs::path(v).filename().string(); if (!weee::core::load_dol(v, mem, broadway)) ircolib::panic("Could not load '{}'", v); },