diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 4522231e..f1619e81 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -190,6 +190,7 @@ public: void V_FFBL_B32(const GcnInst& inst); void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); void V_BFM_B32(const GcnInst& inst); + void V_FFBH_U32(const GcnInst& inst); // Vector Memory void BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 36fab906..e658456b 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -314,6 +314,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { case Opcode::V_BFM_B32: return V_BFM_B32(inst); + case Opcode::V_FFBH_U32: + return V_FFBH_U32(inst); default: LogMissingOpcode(inst); } @@ -976,4 +978,14 @@ void Translator::V_BFM_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.ShiftLeftLogical(ones, src1)); } +void Translator::V_FFBH_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) position + const IR::U32 msb_pos = ir.FindUMsb(src0); + const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 + const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); + SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); +} + } // namespace Shader::Gcn