Small fixes

This commit is contained in:
dingusdev 2024-09-27 21:37:32 -07:00
parent 11de987ea9
commit f1e6a2ce93
3 changed files with 49 additions and 30 deletions

View File

@ -16,3 +16,5 @@
#define OPCODESHIFTREC(op, __VA_ARGS__) template <field_direction isleft, field_rc rec > void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ } #define OPCODESHIFTREC(op, __VA_ARGS__) template <field_direction isleft, field_rc rec > void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ }
#define OPCODE601REC(op, __VA_ARGS__) template <field_601 for601, field_rc rec> void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ } #define OPCODE601REC(op, __VA_ARGS__) template <field_601 for601, field_rc rec> void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ }
#define OPCODEEXTSIGN(op, __VA_ARGS__) template <class T, field_rc rec> void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ } #define OPCODEEXTSIGN(op, __VA_ARGS__) template <class T, field_rc rec> void dppc_interpreter::ppc_##op(uint32_t instr) { __VA_ARGS__ }
#define ppc_store_iresult_reg(reg, ppc_result) ppc_state.gpr[reg] = ppc_result
#define ppc_set_xer(entry) ppc_state.spr[SPR::XER] |= entry

View File

@ -232,20 +232,26 @@ OPCODEOVREC (subfme,
uint32_t grab_ca = !!(ppc_state.spr[SPR::XER] & XER::CA); uint32_t grab_ca = !!(ppc_state.spr[SPR::XER] & XER::CA);
uint32_t ppc_result_d = ~ppc_result_a + grab_ca - 1; uint32_t ppc_result_d = ~ppc_result_a + grab_ca - 1;
if (ppc_result_a == 0xFFFFFFFFUL && !grab_ca) if (ppc_result_a == 0xFFFFFFFFUL && !grab_ca) {
ppc_unset_xer(XER::CA); ppc_unset_xer(XER::CA);
else }
else {
ppc_set_xer(XER::CA); ppc_set_xer(XER::CA);
if (ov) {
if (ppc_result_d == ppc_result_a && int32_t(ppc_result_d) > 0)
ppc_set_xer(XER::SO | XER::OV);
else
ppc_unset_xer(XER::OV);
} }
if (rec) if (ov) {
ppc_changecrf0(ppc_result_d); if (ppc_result_d == ppc_result_a && int32_t(ppc_result_d) > 0) {
ppc_set_xer(XER::SO | XER::OV);
}
else {
ppc_unset_xer(XER::OV);
}
}
if (rec) {
ppc_changecrf0(ppc_result_d);
}
ppc_store_iresult_reg(reg_d, ppc_result_d); ppc_store_iresult_reg(reg_d, ppc_result_d);
) )
@ -276,7 +282,7 @@ OPCODEOVREC (subfze,
} }
ppc_store_iresult_reg(reg_d, ppc_result_d); ppc_store_iresult_reg(reg_d, ppc_result_d);
) )
OPCODESHIFT (andirc, OPCODESHIFT (andirc,
ppc_grab_regssauimm(instr); ppc_grab_regssauimm(instr);
@ -442,16 +448,19 @@ OPCODEOVREC (divw,
ppc_result_d = 0; // tested on G4 in Mac OS X 10.4 and Open Firmware. ppc_result_d = 0; // tested on G4 in Mac OS X 10.4 and Open Firmware.
// ppc_result_d = (int32_t(ppc_result_a) < 0) ? -1 : 0; /* UNDOCUMENTED! */ // ppc_result_d = (int32_t(ppc_result_a) < 0) ? -1 : 0; /* UNDOCUMENTED! */
if (ov) if (ov) {
ppc_set_xer(XER::SO | XER::OV); ppc_set_xer(XER::SO | XER::OV);
}
} else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) { }
else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
ppc_result_d = 0; // tested on G4 in Mac OS X 10.4 and Open Firmware. ppc_result_d = 0; // tested on G4 in Mac OS X 10.4 and Open Firmware.
if (ov) if (ov)
ppc_set_xer(XER::SO | XER::OV); ppc_set_xer(XER::SO | XER::OV);
} else { // normal signed devision }
else { // normal signed devision
ppc_result_d = int32_t(ppc_result_a) / int32_t(ppc_result_b); ppc_result_d = int32_t(ppc_result_a) / int32_t(ppc_result_b);
if (ov) if (ov)
@ -470,21 +479,27 @@ OPCODEOVREC (divwu,
if (!ppc_result_b) { // division by zero if (!ppc_result_b) { // division by zero
if (ov) if (ov) {
ppc_set_xer(XER::SO | XER::OV); ppc_set_xer(XER::SO | XER::OV);
}
if (rec) if (rec) {
ppc_state.cr |= XER::CA; ppc_state.cr |= XER::CA;
}
} else { } else {
ppc_result_d = ppc_result_a / ppc_result_b; ppc_result_d = ppc_result_a / ppc_result_b;
if (ov) if (ov) {
ppc_unset_xer(XER::OV); ppc_unset_xer(XER::OV);
} }
if (rec) }
if (rec) {
ppc_changecrf0(ppc_result_d); ppc_changecrf0(ppc_result_d);
}
ppc_store_iresult_reg(reg_d, ppc_result_d); ppc_store_iresult_reg(reg_d, ppc_result_d);
) )
@ -496,13 +511,12 @@ OPCODESHIFTREC (shift,
ppc_result_a = 0; ppc_result_a = 0;
} }
else { else {
ppc_result_a = isleft ? (ppc_result_d << (ppc_result_b & 0x1F)) ppc_result_a = (isleft ? (ppc_result_d << (ppc_result_b & 0x1F))
: (ppc_result_d >> (ppc_result_b & 0x1F)); : (ppc_result_d >> (ppc_result_b & 0x1F)));
} }
if (rec) {
if (rec)
ppc_changecrf0(ppc_result_a); ppc_changecrf0(ppc_result_a);
}
ppc_store_iresult_reg(reg_a, ppc_result_a); ppc_store_iresult_reg(reg_a, ppc_result_a);
) )
@ -1007,10 +1021,12 @@ OPCODELKAA (bc,
cnd_ok = (br_bo & 0x10) | (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08)); cnd_ok = (br_bo & 0x10) | (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
if (ctr_ok && cnd_ok) { if (ctr_ok && cnd_ok) {
if (a) if (a) {
ppc_next_instruction_address = br_bd; ppc_next_instruction_address = br_bd;
else }
else {
ppc_next_instruction_address = uint32_t(ppc_state.pc + br_bd); ppc_next_instruction_address = uint32_t(ppc_state.pc + br_bd);
}
exec_flags = EXEF_BRANCH; exec_flags = EXEF_BRANCH;
} }
@ -1391,7 +1407,8 @@ OPCODEMEM (stux,
uint32_t ea = ppc_result_a + ppc_result_b; uint32_t ea = ppc_result_a + ppc_result_b;
mmu_write_vmem<T>(ea, instr, ppc_result_d); mmu_write_vmem<T>(ea, instr, ppc_result_d);
ppc_state.gpr[reg_a] = ea; ppc_state.gpr[reg_a] = ea;
} else { }
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
} }
) )

View File

@ -117,7 +117,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
void dppc_interpreter::ppc_##op(uint32_t instr) { \ void dppc_interpreter::ppc_##op(uint32_t instr) { \
__VA_ARGS__ \ __VA_ARGS__ \
} \ } \
template void dppc_interpreter::ppc_##op<ppc_and, RC0>(uint32_t instr) \ template void dppc_interpreter::ppc_##op<ppc_and, RC0>(uint32_t instr); \
template void dppc_interpreter::ppc_##op<ppc_andc, RC0>(uint32_t instr); \ template void dppc_interpreter::ppc_##op<ppc_andc, RC0>(uint32_t instr); \
template void dppc_interpreter::ppc_##op<ppc_eqv, RC0>(uint32_t instr); \ template void dppc_interpreter::ppc_##op<ppc_eqv, RC0>(uint32_t instr); \
template void dppc_interpreter::ppc_##op<ppc_nand, RC0>(uint32_t instr); \ template void dppc_interpreter::ppc_##op<ppc_nand, RC0>(uint32_t instr); \