there might be an off by 1 error...
This commit is contained in:
@@ -17,6 +17,7 @@ if(WIN32)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif()
|
||||
add_compile_options(-fno-operator-names)
|
||||
|
||||
set(CAPSTONE_ARCHITECTURE_DEFAULT OFF)
|
||||
set(CAPSTONE_PPC_SUPPORT ON)
|
||||
|
||||
+49
-1
@@ -17,27 +17,66 @@ void broadway::set_pc(ircolib::u32 value) { pc = value; }
|
||||
|
||||
void broadway::run(mem &mem) {
|
||||
for (int i = 0; i < 12150000; i++) {
|
||||
// std::println("pc: 0x{:08X}", pc);
|
||||
execute(fetch(mem), mem);
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::u32 broadway::fetch(mem &mem) {
|
||||
ircolib::u32 val = mem.read32(pc);
|
||||
ircolib::u32 val = mem.read32(pc)
|
||||
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc);
|
||||
return std::expected<ircolib::u32, std::string>();
|
||||
})
|
||||
.value();
|
||||
pc += 4;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void broadway::decode_special3(ircolib::u32 instr, mem &mem) {
|
||||
auto secondary = utils::secondary(instr);
|
||||
switch (secondary) {
|
||||
case 38:
|
||||
mtfsb1(instr);
|
||||
break;
|
||||
case 711:
|
||||
mtfsf(instr);
|
||||
break;
|
||||
default:
|
||||
ircolib::panic("broadway unknown special3 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4);
|
||||
}
|
||||
}
|
||||
|
||||
void broadway::decode_special2(ircolib::u32 instr, mem &mem) {
|
||||
auto secondary = utils::secondary(instr);
|
||||
switch (secondary) {
|
||||
case 0x000:
|
||||
cmp(instr);
|
||||
break;
|
||||
case 0x020:
|
||||
cmpl(instr);
|
||||
break;
|
||||
case 0x028:
|
||||
subf(instr);
|
||||
break;
|
||||
case 0x053:
|
||||
mfmsr(instr);
|
||||
break;
|
||||
case 0x0D2:
|
||||
ircolib::warn("broadway TODO mtsr (pc 0x{:08X})", pc - 4);
|
||||
break;
|
||||
case 0x1BC:
|
||||
or (instr);
|
||||
break;
|
||||
case 0x153:
|
||||
case 0x1D3:
|
||||
mftspr(ircolib::is_bit_set<ircolib::u32, 7>(secondary), instr);
|
||||
break;
|
||||
case 0x1DC:
|
||||
nand(instr);
|
||||
break;
|
||||
case 0x10A:
|
||||
add(instr);
|
||||
break;
|
||||
@@ -66,6 +105,9 @@ void broadway::decode_special1(ircolib::u32 instr, mem &mem) {
|
||||
|
||||
void broadway::execute(ircolib::u32 instr, mem &mem) {
|
||||
switch (utils::primary(instr)) {
|
||||
case 10:
|
||||
cmpli(instr);
|
||||
break;
|
||||
case 11:
|
||||
cmpi(instr);
|
||||
break;
|
||||
@@ -111,12 +153,18 @@ void broadway::execute(ircolib::u32 instr, mem &mem) {
|
||||
case 37:
|
||||
stwu(instr, mem);
|
||||
break;
|
||||
case 39:
|
||||
stbu(instr, mem);
|
||||
break;
|
||||
case 44:
|
||||
sth(instr, mem);
|
||||
break;
|
||||
case 50:
|
||||
lfd(instr, mem);
|
||||
break;
|
||||
case 63:
|
||||
decode_special3(instr, mem);
|
||||
break;
|
||||
default:
|
||||
std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b}", instr, instr);
|
||||
std::println("disassembly:");
|
||||
|
||||
+27
-2
@@ -17,7 +17,7 @@ struct broadway {
|
||||
void execute(ircolib::u32, mem &);
|
||||
|
||||
bool disasm_available = true;
|
||||
ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0;
|
||||
ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0 = 0, fpscr = 0, msr = 0;
|
||||
union {
|
||||
struct {
|
||||
unsigned bytecount : 7;
|
||||
@@ -43,7 +43,13 @@ struct broadway {
|
||||
|
||||
std::array<ircolib::u32, 16> ibat, dbat;
|
||||
std::array<ircolib::u32, 32> gpr{};
|
||||
std::array<double, 32> fpr{};
|
||||
|
||||
struct Fgr {
|
||||
ircolib::u64 ps0, ps1;
|
||||
};
|
||||
|
||||
std::array<Fgr, 32> fgrs{};
|
||||
|
||||
// ircolib::u32 const_gpr_lookup{};
|
||||
csh capstone;
|
||||
// Xbyak::CodeGenerator code;
|
||||
@@ -51,6 +57,7 @@ struct broadway {
|
||||
// instructions
|
||||
void decode_special1(ircolib::u32, mem &);
|
||||
void decode_special2(ircolib::u32, mem &);
|
||||
void decode_special3(ircolib::u32, mem &);
|
||||
|
||||
void branch(bool, bool, ircolib::u32);
|
||||
bool test_cond_and_ctr(ircolib::u32);
|
||||
@@ -66,14 +73,25 @@ struct broadway {
|
||||
void mftspr(bool, ircolib::u32);
|
||||
void stw(ircolib::u32, mem &);
|
||||
void stwu(ircolib::u32, mem &);
|
||||
void stbu(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 cmpli(ircolib::u32);
|
||||
void cmp(ircolib::u32);
|
||||
void cmpl(ircolib::u32);
|
||||
void rlwinm(ircolib::u32);
|
||||
void lwzu(ircolib::u32, mem &);
|
||||
void rfi(ircolib::u32);
|
||||
void mtfsf(ircolib::u32);
|
||||
void mtfsb1(ircolib::u32);
|
||||
void mtfsb0(ircolib::u32);
|
||||
void mfmsr(ircolib::u32);
|
||||
void nand(ircolib::u32);
|
||||
void subf(ircolib::u32);
|
||||
void or (ircolib::u32);
|
||||
|
||||
inline void cr0_update(bool condition, ircolib::s32 result) {
|
||||
if (condition) {
|
||||
@@ -84,5 +102,12 @@ struct broadway {
|
||||
set_cr((b0 << 3) | (b1 << 2) | (b2 << 1) | (b3 << 0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline void cr1_update(bool condition) {
|
||||
if (condition) {
|
||||
const ircolib::u8 field = (fpscr >> 28) & 0xf;
|
||||
set_cr(field, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace weee::core
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <broadway/utils.hpp>
|
||||
#include "ircolib/log.hpp"
|
||||
#include <broadway/utils.hpp>
|
||||
#include <mem.hpp>
|
||||
|
||||
namespace weee::core {
|
||||
@@ -49,6 +49,7 @@ void broadway::bx(ircolib::u32 instr) {
|
||||
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) || (get_cr_bit(0, bi) == ircolib::is_bit_set(bo, 3));
|
||||
|
||||
@@ -132,7 +133,8 @@ void broadway::mftspr(bool dir, ircolib::u32 instr) {
|
||||
move_to_or_from_spr(dbat[BAT_UPPER_OFFSET + 3]);
|
||||
break;
|
||||
default:
|
||||
ircolib::warn("broadway::m{}spr with unimplemented spr field of value 0b{:010b} (0x{:04X}) (pc 0x{:08X})",
|
||||
ircolib::warn("broadway::m{}spr with unimplemented spr field of value "
|
||||
"0b{:010b} (0x{:04X}) (pc 0x{:08X})",
|
||||
dir ? 't' : 'f', spr_field, spr_field, pc - 4);
|
||||
}
|
||||
}
|
||||
@@ -142,7 +144,26 @@ void broadway::stwu(ircolib::u32 instr, mem &mem) {
|
||||
ircolib::panic("broadway::stwu with ra == 0");
|
||||
|
||||
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
|
||||
mem.write32(EA, gpr[utils::RS(instr)]);
|
||||
auto _ = mem.write32(EA, gpr[utils::RS(instr)])
|
||||
.and_then([&] { return std::expected<void, std::string>(); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<void, std::string>();
|
||||
});
|
||||
gpr[utils::RA(instr)] = EA;
|
||||
}
|
||||
|
||||
void broadway::stbu(ircolib::u32 instr, mem &mem) {
|
||||
if (utils::RA(instr) == 0)
|
||||
ircolib::panic("broadway::stbu with ra == 0");
|
||||
|
||||
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
|
||||
auto _ = mem.write8(EA, gpr[utils::RS(instr)])
|
||||
.and_then([&] { return std::expected<void, std::string>(); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<void, std::string>();
|
||||
});
|
||||
gpr[utils::RA(instr)] = EA;
|
||||
}
|
||||
|
||||
@@ -152,7 +173,12 @@ void broadway::stw(ircolib::u32 instr, mem &mem) {
|
||||
b = 0;
|
||||
|
||||
const ircolib::u32 EA = b + utils::SIMM(instr);
|
||||
mem.write32(EA, gpr[utils::RS(instr)]);
|
||||
auto _ = mem.write32(EA, gpr[utils::RS(instr)])
|
||||
.and_then([&] { return std::expected<void, std::string>(); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<void, std::string>();
|
||||
});
|
||||
}
|
||||
|
||||
void broadway::sth(ircolib::u32 instr, mem &mem) {
|
||||
@@ -163,7 +189,12 @@ void broadway::sth(ircolib::u32 instr, mem &mem) {
|
||||
const ircolib::s32 d = utils::SIMM(instr);
|
||||
const ircolib::u32 EA = b + d;
|
||||
|
||||
mem.write16(EA, ircolib::u16(gpr[utils::RS(instr)]));
|
||||
auto _ = mem.write16(EA, ircolib::u16(gpr[utils::RS(instr)]))
|
||||
.and_then([&] { return std::expected<void, std::string>(); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<void, std::string>();
|
||||
});
|
||||
}
|
||||
|
||||
void broadway::lwz(ircolib::u32 instr, mem &mem) {
|
||||
@@ -172,7 +203,14 @@ void broadway::lwz(ircolib::u32 instr, mem &mem) {
|
||||
b = 0;
|
||||
|
||||
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
|
||||
gpr[utils::RD(instr)] = mem.read32(ea);
|
||||
|
||||
gpr[utils::RD(instr)] = mem.read32(ea)
|
||||
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<ircolib::u32, std::string>();
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
void broadway::lfd(ircolib::u32 instr, mem &mem) {
|
||||
@@ -182,9 +220,15 @@ void broadway::lfd(ircolib::u32 instr, mem &mem) {
|
||||
|
||||
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
|
||||
double val;
|
||||
ircolib::u64 read = mem.read64(ea);
|
||||
ircolib::u64 read = mem.read64(ea)
|
||||
.and_then([&](ircolib::u64 val) { return std::expected<ircolib::u64, std::string>(val); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<ircolib::u64, std::string>();
|
||||
})
|
||||
.value();
|
||||
memcpy(&val, &read, 8);
|
||||
fpr[utils::RD(instr)] = val;
|
||||
fgrs[utils::RD(instr)].ps0 = val;
|
||||
}
|
||||
|
||||
void broadway::bclrx(ircolib::u32 instr) {
|
||||
@@ -211,6 +255,51 @@ void broadway::cmpi(ircolib::u32 instr) {
|
||||
set_cr(result, utils::crfD(instr));
|
||||
}
|
||||
|
||||
void broadway::cmpli(ircolib::u32 instr) {
|
||||
const ircolib::u32 a = gpr[utils::RA(instr)];
|
||||
const ircolib::u32 uimm = utils::UIMM(instr);
|
||||
ircolib::u8 c;
|
||||
if (a < uimm)
|
||||
c = 0b001;
|
||||
else if (a > uimm)
|
||||
c = 0b010;
|
||||
else
|
||||
c = 0b100;
|
||||
|
||||
const ircolib::u8 result = (xer.so << 3) | c;
|
||||
set_cr(result, utils::crfD(instr));
|
||||
}
|
||||
|
||||
void broadway::cmp(ircolib::u32 instr) {
|
||||
const ircolib::s32 a = gpr[utils::RA(instr)];
|
||||
const ircolib::s32 b = gpr[utils::RB(instr)];
|
||||
ircolib::u8 c;
|
||||
if (a < b)
|
||||
c = 0b001;
|
||||
else if (a > b)
|
||||
c = 0b010;
|
||||
else
|
||||
c = 0b100;
|
||||
|
||||
const ircolib::u8 result = (xer.so << 3) | c;
|
||||
set_cr(result, utils::crfD(instr));
|
||||
}
|
||||
|
||||
void broadway::cmpl(ircolib::u32 instr) {
|
||||
const ircolib::u32 a = gpr[utils::RA(instr)];
|
||||
const ircolib::u32 b = gpr[utils::RB(instr)];
|
||||
ircolib::u8 c;
|
||||
if (a < b)
|
||||
c = 0b001;
|
||||
else if (a > b)
|
||||
c = 0b010;
|
||||
else
|
||||
c = 0b100;
|
||||
|
||||
const ircolib::u8 result = (xer.so << 3) | c;
|
||||
set_cr(result, utils::crfD(instr));
|
||||
}
|
||||
|
||||
void broadway::rlwinm(ircolib::u32 instr) {
|
||||
const ircolib::u8 sh = (instr >> 11) & 0x1f;
|
||||
ircolib::u32 r = std::rotl(gpr[utils::RS(instr)], sh);
|
||||
@@ -226,7 +315,13 @@ void broadway::lwzu(ircolib::u32 instr, mem &mem) {
|
||||
ircolib::panic("broadway::lwzu with ra == 0");
|
||||
|
||||
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
|
||||
gpr[utils::RD(instr)] = mem.read32(EA);
|
||||
gpr[utils::RD(instr)] = mem.read32(EA)
|
||||
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<ircolib::u32, std::string>();
|
||||
})
|
||||
.value();
|
||||
gpr[utils::RA(instr)] = EA;
|
||||
}
|
||||
|
||||
@@ -237,4 +332,50 @@ void broadway::andi(ircolib::u32 instr) {
|
||||
gpr[utils::RA(instr)] = result;
|
||||
cr0_update(true, result);
|
||||
}
|
||||
|
||||
void broadway::mtfsf(ircolib::u32 instr) {
|
||||
const ircolib::u8 fm = (instr >> 17) & 0xff;
|
||||
ircolib::u8 mask = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (ircolib::is_bit_set(fm, i)) {
|
||||
mask |= 0xf << (i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::u32 frb = fgrs[utils::RB(instr)].ps0;
|
||||
fpscr = (fpscr & ~mask) | (frb & mask);
|
||||
cr1_update(instr & 1);
|
||||
}
|
||||
|
||||
void broadway::mtfsb0(ircolib::u32 instr) {
|
||||
ircolib::u32 mask = ~(1 << utils::RD(instr));
|
||||
|
||||
fpscr = fpscr & mask;
|
||||
cr1_update(instr & 1);
|
||||
}
|
||||
|
||||
void broadway::mtfsb1(ircolib::u32 instr) {
|
||||
ircolib::u32 bit = 1 << utils::RD(instr);
|
||||
ircolib::u32 mask = ~bit;
|
||||
|
||||
fpscr = (fpscr & mask) | bit;
|
||||
cr1_update(instr & 1);
|
||||
}
|
||||
|
||||
void broadway::mfmsr(ircolib::u32 instr) { gpr[utils::RS(instr)] = msr; }
|
||||
|
||||
void broadway::nand(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::subf(ircolib::u32 instr) {
|
||||
gpr[utils::RD(instr)] = ~(gpr[utils::RA(instr)] + gpr[utils::RB(instr)] + 1);
|
||||
cr0_update(instr & 1, gpr[utils::RD(instr)]);
|
||||
}
|
||||
|
||||
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)]);
|
||||
}
|
||||
} // namespace weee::core
|
||||
|
||||
+29
-24
@@ -7,6 +7,9 @@ namespace weee::core {
|
||||
mem::mem() : vi(*this) {
|
||||
mem1.resize(24_mib);
|
||||
std::fill(mem1.begin(), mem1.end(), 0);
|
||||
|
||||
register_read8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr) { return mem1[addr]; });
|
||||
|
||||
register_read16_handler(0x00000000, 0x017fffff,
|
||||
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u16>(mem1, addr); });
|
||||
|
||||
@@ -16,6 +19,8 @@ mem::mem() : vi(*this) {
|
||||
register_read64_handler(0x00000000, 0x017fffff,
|
||||
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u64>(mem1, addr); });
|
||||
|
||||
register_write8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u8 value) { mem1[addr] = value; });
|
||||
|
||||
register_write16_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u16 value) {
|
||||
ircolib::write_access<ircolib::u16>(mem1, addr, value);
|
||||
});
|
||||
@@ -52,7 +57,7 @@ void mem::set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32
|
||||
memset(&mem1[offset], val, size);
|
||||
}
|
||||
|
||||
ircolib::u8 mem::read8(ircolib::u32 addr) {
|
||||
std::expected<ircolib::u8, std::string> mem::read8(ircolib::u32 addr) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : read8_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
@@ -60,11 +65,10 @@ ircolib::u8 mem::read8(ircolib::u32 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::read8 unimplemented addr 0x{:08X}", addr);
|
||||
return 0;
|
||||
return std::unexpected(std::format("mem::read8 unimplemented addr 0x{:08X}", addr));
|
||||
}
|
||||
|
||||
ircolib::u16 mem::read16(ircolib::u32 addr) {
|
||||
std::expected<ircolib::u16, std::string> mem::read16(ircolib::u32 addr) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : read16_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
@@ -72,11 +76,10 @@ ircolib::u16 mem::read16(ircolib::u32 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::read16 unimplemented addr 0x{:08X}", addr);
|
||||
return 0;
|
||||
return std::unexpected(std::format("mem::read16 unimplemented addr 0x{:08X}", addr));
|
||||
}
|
||||
|
||||
ircolib::u32 mem::read32(ircolib::u32 addr) {
|
||||
std::expected<ircolib::u32, std::string> mem::read32(ircolib::u32 addr) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : read32_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
@@ -84,11 +87,10 @@ ircolib::u32 mem::read32(ircolib::u32 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::read32 unimplemented addr 0x{:08X}", addr);
|
||||
return 0;
|
||||
return std::unexpected(std::format("mem::read32 unimplemented addr 0x{:08X}", addr));
|
||||
}
|
||||
|
||||
ircolib::u64 mem::read64(ircolib::u32 addr) {
|
||||
std::expected<ircolib::u64, std::string> mem::read64(ircolib::u32 addr) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : read64_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
@@ -96,51 +98,54 @@ ircolib::u64 mem::read64(ircolib::u32 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::read64 unimplemented addr 0x{:08X}", addr);
|
||||
return 0;
|
||||
return std::unexpected(std::format("mem::read64 unimplemented addr 0x{:08X}", addr));
|
||||
}
|
||||
|
||||
void mem::write8(ircolib::u32 addr, ircolib::u8 value) {
|
||||
std::expected<void, std::string> mem::write8(ircolib::u32 addr, ircolib::u8 value) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : write8_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
return handler.func(addr - handler.start, value);
|
||||
handler.func(addr - handler.start, value);
|
||||
return std::expected<void, std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::write8 unimplemented addr 0x{:08X} = 0x{:02X}", addr, value);
|
||||
return std::unexpected(std::format("mem::write8 unimplemented addr 0x{:08X} = 0x{:02X}", addr, value));
|
||||
}
|
||||
|
||||
void mem::write16(ircolib::u32 addr, ircolib::u16 value) {
|
||||
std::expected<void, std::string> mem::write16(ircolib::u32 addr, ircolib::u16 value) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : write16_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
return handler.func(addr - handler.start, value);
|
||||
handler.func(addr - handler.start, value);
|
||||
return std::expected<void, std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::write16 unimplemented addr 0x{:08X} = 0x{:04X}", addr, value);
|
||||
return std::unexpected(std::format("mem::write16 unimplemented addr 0x{:08X} = 0x{:04X}", addr, value));
|
||||
}
|
||||
|
||||
void mem::write32(ircolib::u32 addr, ircolib::u32 value) {
|
||||
std::expected<void, std::string> mem::write32(ircolib::u32 addr, ircolib::u32 value) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : write32_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
return handler.func(addr - handler.start, value);
|
||||
handler.func(addr - handler.start, value);
|
||||
return std::expected<void, std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::write32 unimplemented addr 0x{:08X} = 0x{:08X}", addr, value);
|
||||
return std::unexpected(std::format("mem::write32 unimplemented addr 0x{:08X} = 0x{:08X}", addr, value));
|
||||
}
|
||||
|
||||
void mem::write64(ircolib::u32 addr, ircolib::u64 value) {
|
||||
std::expected<void, std::string> mem::write64(ircolib::u32 addr, ircolib::u64 value) {
|
||||
addr &= 0x0FFFFFFF;
|
||||
for (const auto &handler : write64_handlers) {
|
||||
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
|
||||
return handler.func(addr - handler.start, value);
|
||||
handler.func(addr - handler.start, value);
|
||||
return std::expected<void, std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
ircolib::panic("mem::write64 unimplemented addr 0x{:08X} = 0x{:016X}", addr, value);
|
||||
return std::unexpected(std::format("mem::write64 unimplemented addr 0x{:08X} = 0x{:016X}", addr, value));
|
||||
}
|
||||
} // namespace weee::core
|
||||
|
||||
+10
-8
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ircolib/types.hpp>
|
||||
#include <broadway/mmio/vi.hpp>
|
||||
#include <functional>
|
||||
#include <expected>
|
||||
|
||||
namespace weee::core {
|
||||
template <typename T>
|
||||
@@ -53,14 +55,14 @@ struct mem {
|
||||
write64_handlers.push_back({std::move(func), start, end});
|
||||
}
|
||||
|
||||
ircolib::u8 read8(ircolib::u32);
|
||||
ircolib::u16 read16(ircolib::u32);
|
||||
ircolib::u32 read32(ircolib::u32);
|
||||
ircolib::u64 read64(ircolib::u32);
|
||||
void write8(ircolib::u32, ircolib::u8);
|
||||
void write16(ircolib::u32, ircolib::u16);
|
||||
void write32(ircolib::u32, ircolib::u32);
|
||||
void write64(ircolib::u32, ircolib::u64);
|
||||
std::expected<ircolib::u8, std::string> read8(ircolib::u32);
|
||||
std::expected<ircolib::u16, std::string> read16(ircolib::u32);
|
||||
std::expected<ircolib::u32, std::string> read32(ircolib::u32);
|
||||
std::expected<ircolib::u64, std::string> read64(ircolib::u32);
|
||||
std::expected<void, std::string> write8(ircolib::u32, ircolib::u8);
|
||||
std::expected<void, std::string> write16(ircolib::u32, ircolib::u16);
|
||||
std::expected<void, std::string> write32(ircolib::u32, ircolib::u32);
|
||||
std::expected<void, std::string> write64(ircolib::u32, ircolib::u64);
|
||||
|
||||
void copy(std::vector<ircolib::u8> &src, const ircolib::u32 offset);
|
||||
void copy(ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset);
|
||||
|
||||
Reference in New Issue
Block a user