From 7c40dbc36c7a0b6a1a39c54f90a8a1f2030a6cba Mon Sep 17 00:00:00 2001 From: nmzik Date: Wed, 21 Oct 2026 23:16:17 +0200 Subject: [PATCH] shader: build the S_BFE_U64 mask from clamped halves and remove RightMask64 --- .../recompiler/frontend/translate/Integer.cpp | 22 +++++++------------ .../frontend/translate/Translator.h | 1 - 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp index fa37f84c1..c035f83d5 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp @@ -388,15 +388,6 @@ IR::U32 Translator::RightMask32(IR::U32 count) { {IR::Value(0u), IR::Value(0xffffffffu), IR::Value(0u), count})); } -IR::U64 Translator::RightMask64(IR::U32 count) { - const auto below32 = IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {count, IR::Value(32u)})); - const auto above32 = IR::U1(ir.Emit(IR::ValueOpcode::UGreaterThan32, {count, IR::Value(32u)})); - const auto low_count = ir.Select(below32, count, IR::U32(IR::Value(32u))); - const auto high_count = - ir.Select(above32, ir.ISub(count, IR::U32(IR::Value(32u))), IR::U32(IR::Value(0u))); - return ir.ConstructU64(RightMask32(low_count), RightMask32(high_count)); -} - void Translator::S_BFM_B64(const Decoder::Instruction& inst) { const auto count = ReadU32(inst.src0); const auto offset = ReadU32(inst.src1); @@ -428,12 +419,15 @@ void Translator::S_BFE_U64(const Decoder::Instruction& inst) { const auto field = ReadU32(inst.src1); const auto offset = IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {field, IR::Value(0u), IR::Value(6u)})); - const auto raw_count = + const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {field, IR::Value(16u), IR::Value(7u)})); - const auto available = ir.ISub(IR::U32(IR::Value(64u)), offset); - const auto count = IR::U32(ir.Emit(IR::ValueOpcode::UMin32, {raw_count, available})); - const auto shifted = IR::U64(ir.Emit(IR::ValueOpcode::ShiftRightLogical64, {source, offset})); - const auto result = ir.Emit(IR::ValueOpcode::BitwiseAnd64, {shifted, RightMask64(count)}); + // The shift already clears bits past the source; widths of 64 and more keep every bit. + const auto low_count = IR::U32(ir.Emit(IR::ValueOpcode::UMin32, {count, IR::Value(32u)})); + const auto high_count = + IR::U32(ir.Emit(IR::ValueOpcode::UMin32, {ir.ISub(count, low_count), IR::Value(32u)})); + const auto mask = ir.ConstructU64(RightMask32(low_count), RightMask32(high_count)); + const auto shifted = IR::U64(ir.Emit(IR::ValueOpcode::ShiftRightLogical64, {source, offset})); + const auto result = ir.Emit(IR::ValueOpcode::BitwiseAnd64, {shifted, mask}); WriteOperand(DestinationOperand(inst), result); ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}))); } diff --git a/src/graphics/shader/recompiler/frontend/translate/Translator.h b/src/graphics/shader/recompiler/frontend/translate/Translator.h index eb8c14770..ed3c60cd4 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translator.h +++ b/src/graphics/shader/recompiler/frontend/translate/Translator.h @@ -201,7 +201,6 @@ private: void S_QUADMASK_B64(const Decoder::Instruction& inst); void BFM_B32(const Decoder::Instruction& inst); IR::U32 RightMask32(IR::U32 count); - IR::U64 RightMask64(IR::U32 count); void S_BFM_B64(const Decoder::Instruction& inst); void S_BFE_U32(const Decoder::Instruction& inst, bool sign); void S_BFE_U64(const Decoder::Instruction& inst);