mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
PPU: Fix DIVW, DIVWU, MULHW, MULLW, MULHWU when op.rc is set (#8630)
This commit is contained in:
parent
be4b71b805
commit
da44d5f10d
@ -3332,7 +3332,7 @@ bool ppu_interpreter::MULHWU(ppu_thread& ppu, ppu_opcode_t op)
|
||||
u32 a = static_cast<u32>(ppu.gpr[op.ra]);
|
||||
u32 b = static_cast<u32>(ppu.gpr[op.rb]);
|
||||
ppu.gpr[op.rd] = (u64{a} * b) >> 32;
|
||||
if (op.rc) [[unlikely]] ppu_cr_set(ppu, 0, false, false, false, ppu.xer.so);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3515,7 +3515,7 @@ bool ppu_interpreter::MULHW(ppu_thread& ppu, ppu_opcode_t op)
|
||||
s32 a = static_cast<s32>(ppu.gpr[op.ra]);
|
||||
s32 b = static_cast<s32>(ppu.gpr[op.rb]);
|
||||
ppu.gpr[op.rd] = (s64{a} * b) >> 32;
|
||||
if (op.rc) [[unlikely]] ppu_cr_set(ppu, 0, false, false, false, ppu.xer.so);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3785,7 +3785,7 @@ bool ppu_interpreter::MULLW(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
ppu.gpr[op.rd] = s64{static_cast<s32>(ppu.gpr[op.ra])} * static_cast<s32>(ppu.gpr[op.rb]);
|
||||
if (op.oe) [[unlikely]] ppu_ov_set(ppu, s64(ppu.gpr[op.rd]) < INT32_MIN || s64(ppu.gpr[op.rd]) > INT32_MAX);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3981,7 +3981,7 @@ bool ppu_interpreter::DIVWU(ppu_thread& ppu, ppu_opcode_t op)
|
||||
const u32 RB = static_cast<u32>(ppu.gpr[op.rb]);
|
||||
ppu.gpr[op.rd] = RB == 0 ? 0 : RA / RB;
|
||||
if (op.oe) [[unlikely]] ppu_ov_set(ppu, RB == 0);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set(ppu, 0, false, false, false, ppu.xer.so);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4046,7 +4046,7 @@ bool ppu_interpreter::DIVW(ppu_thread& ppu, ppu_opcode_t op)
|
||||
const bool o = RB == 0 || (RA == INT32_MIN && RB == -1);
|
||||
ppu.gpr[op.rd] = o ? 0 : static_cast<u32>(RA / RB);
|
||||
if (op.oe) [[unlikely]] ppu_ov_set(ppu, o);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set(ppu, 0, false, false, false, ppu.xer.so);
|
||||
if (op.rc) [[unlikely]] ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2399,7 +2399,7 @@ void PPUTranslator::MULHWU(ppu_opcode_t op)
|
||||
const auto a = ZExt(GetGpr(op.ra, 32));
|
||||
const auto b = ZExt(GetGpr(op.rb, 32));
|
||||
SetGpr(op.rd, m_ir->CreateLShr(m_ir->CreateMul(a, b), 32));
|
||||
if (op.rc) SetCrField(0, GetUndef<bool>(), GetUndef<bool>(), GetUndef<bool>());
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
}
|
||||
|
||||
void PPUTranslator::MFOCRF(ppu_opcode_t op)
|
||||
@ -2586,7 +2586,7 @@ void PPUTranslator::MULHW(ppu_opcode_t op)
|
||||
const auto a = SExt(GetGpr(op.ra, 32));
|
||||
const auto b = SExt(GetGpr(op.rb, 32));
|
||||
SetGpr(op.rd, m_ir->CreateAShr(m_ir->CreateMul(a, b), 32));
|
||||
if (op.rc) SetCrField(0, GetUndef<bool>(), GetUndef<bool>(), GetUndef<bool>());
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
}
|
||||
|
||||
void PPUTranslator::LDARX(ppu_opcode_t op)
|
||||
@ -3034,7 +3034,7 @@ void PPUTranslator::DIVDU(ppu_opcode_t op)
|
||||
const auto o = IsZero(b);
|
||||
const auto result = m_ir->CreateUDiv(a, m_ir->CreateSelect(o, m_ir->getInt64(-1), b));
|
||||
SetGpr(op.rd, m_ir->CreateSelect(o, m_ir->getInt64(0), result));
|
||||
if (op.rc) SetCrFieldSignedCmp(0, result, m_ir->getInt64(0));
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
if (op.oe) SetOverflow(o);
|
||||
}
|
||||
|
||||
@ -3045,7 +3045,7 @@ void PPUTranslator::DIVWU(ppu_opcode_t op)
|
||||
const auto o = IsZero(b);
|
||||
const auto result = m_ir->CreateUDiv(a, m_ir->CreateSelect(o, m_ir->getInt32(0xffffffff), b));
|
||||
SetGpr(op.rd, m_ir->CreateSelect(o, m_ir->getInt32(0), result));
|
||||
if (op.rc) SetCrField(0, GetUndef<bool>(), GetUndef<bool>(), GetUndef<bool>());
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
if (op.oe) SetOverflow(o);
|
||||
}
|
||||
|
||||
@ -3095,7 +3095,7 @@ void PPUTranslator::DIVD(ppu_opcode_t op)
|
||||
const auto o = m_ir->CreateOr(IsZero(b), m_ir->CreateAnd(m_ir->CreateICmpEQ(a, m_ir->getInt64(1ull << 63)), IsOnes(b)));
|
||||
const auto result = m_ir->CreateSDiv(a, m_ir->CreateSelect(o, m_ir->getInt64(1ull << 63), b));
|
||||
SetGpr(op.rd, m_ir->CreateSelect(o, m_ir->getInt64(0), result));
|
||||
if (op.rc) SetCrFieldSignedCmp(0, result, m_ir->getInt64(0));
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
if (op.oe) SetOverflow(o);
|
||||
}
|
||||
|
||||
@ -3106,7 +3106,7 @@ void PPUTranslator::DIVW(ppu_opcode_t op)
|
||||
const auto o = m_ir->CreateOr(IsZero(b), m_ir->CreateAnd(m_ir->CreateICmpEQ(a, m_ir->getInt32(INT32_MIN)), IsOnes(b)));
|
||||
const auto result = m_ir->CreateSDiv(a, m_ir->CreateSelect(o, m_ir->getInt32(INT32_MIN), b));
|
||||
SetGpr(op.rd, m_ir->CreateSelect(o, m_ir->getInt32(0), result));
|
||||
if (op.rc) SetCrField(0, GetUndef<bool>(), GetUndef<bool>(), GetUndef<bool>());
|
||||
if (op.rc) SetCrFieldSignedCmp(0, GetGpr(op.rd), m_ir->getInt64(0));
|
||||
if (op.oe) SetOverflow(o);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user