PPU: Stop inverting float-to-int saturation on ARM64

- This was breaking armored core 4/4a on ARM
- Original fix credit to jpolo1224 of armsx3 https://github.com/ARMSX2/ARMSX3/commit/87ccdb85152a707f5d0c8122ed39344b4648501e

Co-authored-by: jpolo1224 <[email protected]>
This commit is contained in:
Malcolm
2026-08-18 03:12:13 +02:00
committed by Ani
co-authored by jpolo1224
parent de33fda28c
commit 6161ecd7aa
+12 -8
View File
@@ -4760,13 +4760,14 @@ void PPUTranslator::FRSP(ppu_opcode_t op)
void PPUTranslator::FCTIW(ppu_opcode_t op)
{
const auto b = GetFpr(op.frb);
#if defined(ARCH_X64)
const auto xormask = m_ir->CreateSExt(m_ir->CreateFCmpOGE(b, ConstantFP::get(GetType<f64>(), std::exp2l(31.))), GetType<s32>());
// fix result saturation (0x80000000 -> 0x7fffffff)
#if defined(ARCH_X64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s32>(), "llvm.x86.sse2.cvtsd2si", m_ir->CreateInsertElement(GetUndef<f64[2]>(), b, u64{0}))));
#elif defined(ARCH_ARM64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s32>(), "llvm.aarch64.neon.fcvtns.i32.f64", b)));
SetFpr(op.frd, Call(GetType<s32>(), "llvm.aarch64.neon.fcvtns.i32.f64", b));
#endif
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fctiw_get_fr", b));
@@ -4780,13 +4781,14 @@ void PPUTranslator::FCTIW(ppu_opcode_t op)
void PPUTranslator::FCTIWZ(ppu_opcode_t op)
{
const auto b = GetFpr(op.frb);
#if defined(ARCH_X64)
const auto xormask = m_ir->CreateSExt(m_ir->CreateFCmpOGE(b, ConstantFP::get(GetType<f64>(), std::exp2l(31.))), GetType<s32>());
// fix result saturation (0x80000000 -> 0x7fffffff)
#if defined(ARCH_X64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s32>(), "llvm.x86.sse2.cvttsd2si", m_ir->CreateInsertElement(GetUndef<f64[2]>(), b, u64{0}))));
#elif defined(ARCH_ARM64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s32>(), "llvm.aarch64.neon.fcvtzs.i32.f64", b)));
SetFpr(op.frd, Call(GetType<s32>(), "llvm.aarch64.neon.fcvtzs.i32.f64", b));
#endif
}
@@ -5062,13 +5064,14 @@ void PPUTranslator::FABS(ppu_opcode_t op)
void PPUTranslator::FCTID(ppu_opcode_t op)
{
const auto b = GetFpr(op.frb);
#if defined(ARCH_X64)
const auto xormask = m_ir->CreateSExt(m_ir->CreateFCmpOGE(b, ConstantFP::get(GetType<f64>(), std::exp2l(63.))), GetType<s64>());
// fix result saturation (0x8000000000000000 -> 0x7fffffffffffffff)
#if defined(ARCH_X64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s64>(), "llvm.x86.sse2.cvtsd2si64", m_ir->CreateInsertElement(GetUndef<f64[2]>(), b, u64{0}))));
#elif defined(ARCH_ARM64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s64>(), "llvm.aarch64.neon.fcvtns.i64.f64", b)));
SetFpr(op.frd, Call(GetType<s64>(), "llvm.aarch64.neon.fcvtns.i64.f64", b));
#endif
@@ -5083,13 +5086,14 @@ void PPUTranslator::FCTID(ppu_opcode_t op)
void PPUTranslator::FCTIDZ(ppu_opcode_t op)
{
const auto b = GetFpr(op.frb);
#if defined(ARCH_X64)
const auto xormask = m_ir->CreateSExt(m_ir->CreateFCmpOGE(b, ConstantFP::get(GetType<f64>(), std::exp2l(63.))), GetType<s64>());
// fix result saturation (0x8000000000000000 -> 0x7fffffffffffffff)
#if defined(ARCH_X64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s64>(), "llvm.x86.sse2.cvttsd2si64", m_ir->CreateInsertElement(GetUndef<f64[2]>(), b, u64{0}))));
#elif defined(ARCH_ARM64)
SetFpr(op.frd, m_ir->CreateXor(xormask, Call(GetType<s64>(), "llvm.aarch64.neon.fcvtzs.i64.f64", b)));
SetFpr(op.frd, Call(GetType<s64>(), "llvm.aarch64.neon.fcvtzs.i64.f64", b));
#endif
}