diff --git a/rpcs3/Emu/Cell/PPUDisAsm.cpp b/rpcs3/Emu/Cell/PPUDisAsm.cpp index 29378c015c..a176716cad 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.cpp +++ b/rpcs3/Emu/Cell/PPUDisAsm.cpp @@ -1328,7 +1328,18 @@ void PPUDisAsm::MFOCRF(ppu_opcode_t op) { if (op.l11) { - DisAsm_R1_IMM("mfocrf", op.rd, op.crm); + const u8 crm = static_cast(op.crm); + const int cr = std::countl_zero(crm); + + if (cr >= 8 || crm & (crm - 1)) + { + // Note: invalid form + DisAsm_R1_IMM("mfocrf", op.rd, crm); + } + else + { + DisAsm_R1_CR1("mfocrf", op.rd, cr); + } } else { @@ -1495,13 +1506,24 @@ void PPUDisAsm::ADDE(ppu_opcode_t op) void PPUDisAsm::MTOCRF(ppu_opcode_t op) { - if (op.l11) + const u8 crm = static_cast(op.crm); + + if (!op.l11 && crm == 0xff) { - DisAsm_INT1_R1("mtocrf", op.crm, op.rs); + DisAsm_R1("mtcr", op.rs); + return; + } + + const int cr = std::countl_zero(crm); + const auto name = op.l11 ? "mtocrf" : "mtcrf"; + + if (cr >= 8 || crm & (crm - 1)) + { + DisAsm_INT1_R1(name, crm, op.rs); } else { - DisAsm_INT1_R1("mtcrf", op.crm, op.rs); + DisAsm_CR1_R1(name, cr, op.rs); } } diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index 11070d3c2c..049915df42 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -219,6 +219,14 @@ private: { Write(fmt::format("%s%s cr%d,r%d,r%d", FixOp(op), (rc ? "." : ""), cr0, r0, r1)); } + void DisAsm_CR1_R1(const std::string& op, u32 cr0, u32 r0) + { + Write(fmt::format("%s cr%d,r%d", FixOp(op), cr0, r0)); + } + void DisAsm_R1_CR1(const std::string& op, u32 r0, u32 cr0) + { + Write(fmt::format("%s r%d,cr%d", FixOp(op), r0, cr0)); + } void DisAsm_CR1_R2(const std::string& op, u32 cr0, u32 r0, u32 r1) { DisAsm_CR1_R2_RC(op, cr0, r0, r1, false);