diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 2b0367d6..ca648f88 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -519,7 +519,38 @@ void Translator::V_CVT_FLR_I32_F32(const GcnInst& inst) { } void Translator::V_CMP_CLASS_F32(const GcnInst& inst) { - UNREACHABLE(); + constexpr u32 SIGNALING_NAN = 1 << 0; + constexpr u32 QUIET_NAN = 1 << 1; + constexpr u32 NEGATIVE_INFINITY = 1 << 2; + constexpr u32 NEGATIVE_NORMAL = 1 << 3; + constexpr u32 NEGATIVE_DENORM = 1 << 4; + constexpr u32 NEGATIVE_ZERO = 1 << 5; + constexpr u32 POSITIVE_ZERO = 1 << 6; + constexpr u32 POSITIVE_DENORM = 1 << 7; + constexpr u32 POSITIVE_NORMAL = 1 << 8; + constexpr u32 POSITIVE_INFINITY = 1 << 9; + + const IR::F32F64 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + if (src1.IsImmediate()) { + const u32 class_mask = src1.U32(); + IR::U1 value; + if ((class_mask & (SIGNALING_NAN | QUIET_NAN)) == (SIGNALING_NAN | QUIET_NAN)) { + value = ir.FPIsNan(src0); + } else if ((class_mask & (POSITIVE_INFINITY | NEGATIVE_INFINITY)) == + (POSITIVE_INFINITY | NEGATIVE_INFINITY)) { + value = ir.FPIsInf(src0); + } else { + UNREACHABLE(); + } + if (inst.dst[1].field == OperandField::VccLo) { + return ir.SetVcc(value); + } else { + UNREACHABLE(); + } + } else { + UNREACHABLE(); + } } } // namespace Shader::Gcn