diff --git a/core/broadway.cpp b/core/broadway.cpp index fdb2de6..6d198aa 100644 --- a/core/broadway.cpp +++ b/core/broadway.cpp @@ -31,7 +31,7 @@ ircolib::u32 broadway::fetch(mem &mem) { void broadway::decode_special2(ircolib::u32 instr, mem &mem) { auto secondary = utils::secondary(instr); switch (secondary) { - case 0x0D2: // mtsr + case 0x0D2: ircolib::warn("broadway TODO mtsr (pc 0x{:08X})", pc - 4); break; case 0x153: @@ -66,19 +66,19 @@ void broadway::decode_special1(ircolib::u32 instr, mem &mem) { void broadway::execute(ircolib::u32 instr, mem &mem) { switch (utils::primary(instr)) { - case 11: // cmpi crfD, L, rA, simm + case 11: cmpi(instr); break; - case 14: // addi rd, ra, simm + case 14: addi(instr); break; - case 15: // addis rd, ra, simm + case 15: addis(instr); break; - case 16: // bcx BO, BI, target + case 16: bcx(instr); break; - case 18: // bx target + case 18: bx(instr); break; case 19: @@ -87,7 +87,7 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 21: rlwinm(instr); break; - case 24: // ori ra, rs, uimm + case 24: ori(instr); break; case 25: @@ -99,21 +99,24 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 31: decode_special2(instr, mem); break; - case 32: // lwz rd, d(ra) + case 32: lwz(instr, mem); break; - case 33: // lwz rd, d(ra) + case 33: lwzu(instr, mem); break; - case 36: // stw rs, d(ra) + case 36: stw(instr, mem); break; - case 37: // stwu rs, d(ra) + case 37: stwu(instr, mem); break; - case 44: // stwu rs, d(ra) + case 44: sth(instr, mem); break; + case 50: + lfd(instr, mem); + break; default: std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b}", instr, instr); std::println("disassembly:"); diff --git a/core/broadway.hpp b/core/broadway.hpp index 2df70b2..c700a9c 100644 --- a/core/broadway.hpp +++ b/core/broadway.hpp @@ -30,12 +30,20 @@ struct broadway { ircolib::u32 raw; } xer; + void set_cr(ircolib::u8 value, ircolib::u8 index) { + cr &= ~(0xffff << index * 4); + cr |= (value << index * 4); + } + + bool get_cr_bit(ircolib::u8 index, ircolib::u8 bit) { return (cr >> index * 4) & (1 << (4 - bit)); } + // bat registers indexes static constexpr std::size_t BAT_LOWER_OFFSET = 0; static constexpr std::size_t BAT_UPPER_OFFSET = 8; std::array ibat, dbat; std::array gpr{}; + std::array fpr{}; // ircolib::u32 const_gpr_lookup{}; csh capstone; // Xbyak::CodeGenerator code; @@ -60,10 +68,21 @@ struct broadway { void stwu(ircolib::u32, mem &); void sth(ircolib::u32, mem &); void lwz(ircolib::u32, mem &); + void lfd(ircolib::u32, mem &); void bclrx(ircolib::u32); void cmpi(ircolib::u32); void rlwinm(ircolib::u32); void lwzu(ircolib::u32, mem &); void rfi(ircolib::u32); + + inline void cr0_update(bool condition, ircolib::s32 result) { + if (condition) { + const bool b0 = result < 0; + const bool b1 = result >= 0; + const bool b2 = result == 0; + const bool b3 = xer.so; + set_cr((b0 << 3) | (b1 << 2) | (b2 << 1) | (b3 << 0), 0); + } + } }; } // namespace weee::core diff --git a/core/broadway/instructions.cpp b/core/broadway/instructions.cpp index 79f608c..ba4f3cd 100644 --- a/core/broadway/instructions.cpp +++ b/core/broadway/instructions.cpp @@ -50,7 +50,7 @@ bool broadway::test_cond_and_ctr(ircolib::u32 instr) { const ircolib::u8 bo = (instr >> 21) & 0x1f; const ircolib::u8 bi = (instr >> 16) & 0x1f; const bool ctr_ok = ircolib::is_bit_set(bo, 2) || ((--ctr == 0) == (ircolib::is_bit_set(bo, 1))); - const bool cond_ok = ircolib::is_bit_set(bo, 4) || (ircolib::is_bit_set(cr, 32 - bi) == ircolib::is_bit_set(bo, 3)); + const bool cond_ok = ircolib::is_bit_set(bo, 4) || (get_cr_bit(0, bi) == ircolib::is_bit_set(bo, 3)); return cond_ok && ctr_ok; } @@ -175,6 +175,18 @@ void broadway::lwz(ircolib::u32 instr, mem &mem) { gpr[utils::RD(instr)] = mem.read32(ea); } +void broadway::lfd(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); + double val; + ircolib::u64 read = mem.read64(ea); + memcpy(&val, &read, 8); + fpr[utils::RD(instr)] = val; +} + void broadway::bclrx(ircolib::u32 instr) { const bool link = instr & 1; @@ -195,9 +207,8 @@ void broadway::cmpi(ircolib::u32 instr) { else c = 0b100; - const ircolib::u32 result = ((xer.so << 3) | c) << (28 - 4 * utils::crfD(instr)); - cr &= ~(0xffff << (28 - 4 * utils::crfD(instr))); - cr |= result; + const ircolib::u8 result = (xer.so << 3) | c; + set_cr(result, utils::crfD(instr)); } void broadway::rlwinm(ircolib::u32 instr) { @@ -222,6 +233,8 @@ void broadway::lwzu(ircolib::u32 instr, mem &mem) { void broadway::rfi(ircolib::u32 instr) { pc = srr0; } void broadway::andi(ircolib::u32 instr) { - gpr[utils::RA(instr)] = gpr[utils::RS(instr)] & (ircolib::u32(utils::UIMM(instr)) << 16); + const ircolib::s32 result = gpr[utils::RS(instr)] & utils::UIMM(instr); + gpr[utils::RA(instr)] = result; + cr0_update(true, result); } } // namespace weee::core diff --git a/core/broadway/mmio/vi.cpp b/core/broadway/mmio/vi.cpp index 40b2a74..f8b70fc 100644 --- a/core/broadway/mmio/vi.cpp +++ b/core/broadway/mmio/vi.cpp @@ -55,10 +55,10 @@ void video_interface::write32(ircolib::u32 addr, ircolib::u32 value) { bboi.raw = value; break; case 0x1c: - tfbl.raw = value; + tfbl.raw = value & 0x1ffffe00; break; case 0x24: - bfbl.raw = value; + bfbl.raw = value & 0x10fffe00; break; case 0x4c: case 0x50: diff --git a/core/broadway/mmio/vi.hpp b/core/broadway/mmio/vi.hpp index 3e6defb..080b0eb 100644 --- a/core/broadway/mmio/vi.hpp +++ b/core/broadway/mmio/vi.hpp @@ -8,6 +8,14 @@ struct video_interface { video_interface(mem &); void write16(ircolib::u32, ircolib::u16); void write32(ircolib::u32, ircolib::u32); + ircolib::u32 xfb_top_addr() { + auto addr = tfbl.fbb; + if (tfbl.page) { + addr <<= 5; + } + + return addr + tfbl.xof; + } union DCR { struct { @@ -80,26 +88,15 @@ struct video_interface { ircolib::u32 raw; } bbei, bboi; - union TFBL { + union FBR { struct { - unsigned : 9; - unsigned fbb : 15; + unsigned : 3; + unsigned page : 1; unsigned xof : 4; - unsigned : 4; + unsigned fbb : 24; }; - ircolib::u32 raw; - } tfbl; - - union BFBL { - struct { - unsigned : 9; - unsigned fbb : 15; - unsigned y : 8; - }; - - ircolib::u32 raw; - } bfbl; + } tfbl, bfbl; union FCT012 { struct { diff --git a/core/mem.cpp b/core/mem.cpp index 6d39b36..8e38fc1 100644 --- a/core/mem.cpp +++ b/core/mem.cpp @@ -13,6 +13,9 @@ mem::mem() : vi(*this) { register_read32_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr) { return ircolib::read_access(mem1, addr); }); + register_read64_handler(0x00000000, 0x017fffff, + [&](ircolib::u32 addr) { return ircolib::read_access(mem1, addr); }); + register_write16_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u16 value) { ircolib::write_access(mem1, addr, value); }); @@ -20,6 +23,10 @@ mem::mem() : vi(*this) { register_write32_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) { ircolib::write_access(mem1, addr, value); }); + + register_write64_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) { + ircolib::write_access(mem1, addr, value); + }); } void mem::copy(std::vector &src, const ircolib::u32 offset) { diff --git a/core/mem.hpp b/core/mem.hpp index 2287ccd..b0aae3f 100644 --- a/core/mem.hpp +++ b/core/mem.hpp @@ -78,6 +78,7 @@ struct mem { std::vector> write32_handlers{}; std::vector> write64_handlers{}; + public: video_interface vi; }; } // namespace weee::core diff --git a/main.cpp b/main.cpp index 7382867..a5c1857 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ namespace fs = std::filesystem; int main(int argc, char **argv) { weee::core::mem mem; weee::core::broadway broadway; + weee::core::video_interface &vi = mem.vi; std::string binName; cflags::cflags flags; @@ -68,7 +69,7 @@ int main(int argc, char **argv) { open = false; } - SDL_ConvertPixels(640, 240, SDL_PIXELFORMAT_UYVY, &mem.mem1[0x104000], 640 * 4, SDL_PIXELFORMAT_BGR24, + SDL_ConvertPixels(640, 240, SDL_PIXELFORMAT_UYVY, &mem.mem1[vi.xfb_top_addr()], 640 * 4, SDL_PIXELFORMAT_BGR24, rgbTexture.data(), 640 * 3); SDL_RenderClear(renderer);