diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 7b4b03f27..2584d5c5e 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -204,6 +204,7 @@ public: void V_EXP_F32(const GcnInst& inst); void V_LOG_F32(const GcnInst& inst); void V_RCP_F32(const GcnInst& inst); + void V_RCP_LEGACY_F32(const GcnInst& inst); void V_RCP_F64(const GcnInst& inst); void V_RSQ_F32(const GcnInst& inst); void V_SQRT_F32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index fb3f52c7f..3b88e4dec 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -158,6 +158,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_LOG_F32(inst); case Opcode::V_RCP_F32: return V_RCP_F32(inst); + case Opcode::V_RCP_LEGACY_F32: + return V_RCP_LEGACY_F32(inst); case Opcode::V_RCP_F64: return V_RCP_F64(inst); case Opcode::V_RCP_IFLAG_F32: @@ -798,6 +800,20 @@ void Translator::V_RCP_F32(const GcnInst& inst) { SetDst(inst.dst[0], ir.FPRecip(src0)); } +void Translator::V_RCP_LEGACY_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const auto result = ir.FPRecip(src0); + const auto inf = ir.FPIsInf(result); + + const auto raw_result = ir.ConvertFToU(32, result); + const auto sign_bit = ir.ShiftRightLogical(raw_result, ir.Imm32(31u)); + const auto sign_bit_set = ir.INotEqual(sign_bit, ir.Imm32(0u)); + const IR::F32 inf_result{ir.Select(sign_bit_set, ir.Imm32(-0.0f), ir.Imm32(0.0f))}; + const IR::F32 val{ir.Select(inf, inf_result, result)}; + + SetDst(inst.dst[0], val); +} + void Translator::V_RCP_F64(const GcnInst& inst) { const IR::F64 src0{GetSrc64(inst.src[0])}; SetDst64(inst.dst[0], ir.FPRecip(src0));