i should implement DSP DMA...
This commit is contained in:
@@ -8,6 +8,31 @@ void broadway::add(ircolib::u32 instr) {
|
||||
cr0_update(instr & 1, gpr[utils::RD(instr)]);
|
||||
}
|
||||
|
||||
void broadway::addc(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
|
||||
cr0_update(instr & 1, sum);
|
||||
xer.ca = carry;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
void broadway::adde(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool c0 = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
|
||||
bool c1 = __builtin_add_overflow(sum, xer.ca, &sum);
|
||||
cr0_update(instr & 1, sum);
|
||||
xer.ca = c0 | c1;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
void broadway::addze(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool c1 = __builtin_add_overflow(gpr[utils::RA(instr)], xer.ca, &sum);
|
||||
cr0_update(instr & 1, sum);
|
||||
xer.ca = c1;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
void broadway::addi(ircolib::u32 instr) {
|
||||
if (utils::RA(instr) == 0) { // li
|
||||
gpr[utils::RD(instr)] = ircolib::s32(utils::SIMM(instr));
|
||||
@@ -17,13 +42,19 @@ 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) {
|
||||
ircolib::u32 sum;
|
||||
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum);
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
xer.ca = carry;
|
||||
}
|
||||
|
||||
void broadway::addic(ircolib::u32 instr) {
|
||||
gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr)));
|
||||
void broadway::addicr(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum);
|
||||
cr0_update(true, sum);
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
xer.ca = carry;
|
||||
}
|
||||
|
||||
void broadway::addis(ircolib::u32 instr) {
|
||||
@@ -167,6 +198,22 @@ void broadway::stwu(ircolib::u32 instr, mem &mem) {
|
||||
});
|
||||
}
|
||||
|
||||
void broadway::sthu(ircolib::u32 instr, mem &mem) {
|
||||
if (utils::RA(instr) == 0)
|
||||
ircolib::panic("broadway::sthu with ra == 0");
|
||||
|
||||
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
|
||||
auto _ = mem.write16(EA, gpr[utils::RS(instr)])
|
||||
.and_then([&] {
|
||||
gpr[utils::RA(instr)] = EA;
|
||||
return std::expected<void, std::string>();
|
||||
})
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("sthu broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<void, std::string>();
|
||||
});
|
||||
}
|
||||
|
||||
void broadway::stbu(ircolib::u32 instr, mem &mem) {
|
||||
if (utils::RA(instr) == 0)
|
||||
ircolib::panic("broadway::stbu with ra == 0");
|
||||
@@ -288,6 +335,22 @@ void broadway::lhz(ircolib::u32 instr, mem &mem) {
|
||||
.value();
|
||||
}
|
||||
|
||||
void broadway::lhzx(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.read16(ea)
|
||||
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
|
||||
.or_else([&](std::string e) {
|
||||
ircolib::panic("lhzx broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
|
||||
return std::expected<ircolib::u32, std::string>();
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
void broadway::lbz(ircolib::u32 instr, mem &mem) {
|
||||
ircolib::u32 b = gpr[utils::RA(instr)];
|
||||
if (utils::RA(instr) == 0)
|
||||
@@ -505,11 +568,39 @@ void broadway::subf(ircolib::u32 instr) {
|
||||
cr0_update(instr & 1, gpr[utils::RD(instr)]);
|
||||
}
|
||||
|
||||
void broadway::subfc(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum);
|
||||
bool c1 = __builtin_add_overflow(sum, gpr[utils::RB(instr)], &sum);
|
||||
cr0_update(instr & 1, sum);
|
||||
xer.ca = !c0 | c1;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
void broadway::subfic(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum);
|
||||
bool c1 = __builtin_add_overflow(sum, utils::SIMM(instr), &sum);
|
||||
xer.ca = !c0 | c1;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
void broadway::subfe(ircolib::u32 instr) {
|
||||
ircolib::u32 sum;
|
||||
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
|
||||
bool c1 = __builtin_add_overflow(sum, xer.ca, &sum);
|
||||
cr0_update(instr & 1, sum);
|
||||
xer.ca = c0 | c1;
|
||||
gpr[utils::RD(instr)] = sum;
|
||||
}
|
||||
|
||||
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::xori(ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] ^ utils::UIMM(instr); }
|
||||
|
||||
void broadway::mullw(ircolib::u32 instr) {
|
||||
gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(gpr[utils::RB(instr)]);
|
||||
}
|
||||
@@ -543,4 +634,27 @@ void broadway::divwu(ircolib::u32 instr) {
|
||||
gpr[utils::RD(instr)] = dividend / divisor;
|
||||
cr0_update(instr & 1, gpr[utils::RD(instr)]);
|
||||
}
|
||||
|
||||
void broadway::mftb(ircolib::u32 instr) {
|
||||
const ircolib::u32 tbr = (instr >> 11) & 0x3FF;
|
||||
|
||||
if (tbr != 392 && tbr != 424)
|
||||
ircolib::panic("broadway::mftb with tbr != 268 && != 269 ({})", tbr);
|
||||
|
||||
if (tbr == 392)
|
||||
gpr[utils::RD(instr)] = tbl;
|
||||
|
||||
if (tbr == 424)
|
||||
gpr[utils::RD(instr)] = tbu;
|
||||
}
|
||||
|
||||
void broadway::sraw(ircolib::u32 instr) {
|
||||
ircolib::u8 shift = std::min(gpr[utils::RB(instr)] & 0x3f, ircolib::u32(31));
|
||||
ircolib::s32 rs = gpr[utils::RS(instr)];
|
||||
ircolib::s32 result = rs >> shift;
|
||||
ircolib::u32 mask = (1 << shift) - 1;
|
||||
cr0_update(instr & 1, result);
|
||||
xer.ca = (rs < 0) & ((ircolib::u32(rs) & mask) != 0);
|
||||
gpr[utils::RA(instr)] = result;
|
||||
}
|
||||
} // namespace weee::core
|
||||
|
||||
Reference in New Issue
Block a user