diff --git a/src/graphics/shader/recompiler/frontend/translate/Convert.cpp b/src/graphics/shader/recompiler/frontend/translate/Convert.cpp index 7417f2e72..3bc13bf46 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Convert.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Convert.cpp @@ -89,7 +89,7 @@ void Translator::V_CVT_16_F16(const Decoder::Instruction& inst, bool signed_valu if (signed_value) { const auto converted = ConvertF32ToI32Saturated(value, -32768.0f, 32768.0f, 32767.0f, 0xffff8000u, 0x7fffu); - Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(converted, IR::U32(IR::Value(0xffffu)))); + Write16Bits(DestinationOperand(inst), converted); return; } Write16Bits(DestinationOperand(inst), diff --git a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp index ffa2a92e1..7fe8967c6 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp @@ -9,7 +9,7 @@ void Translator::Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcod const auto value = ReadU16AsU32(inst.src1, arithmetic); const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u))); const auto result = IR::U32(ir.Emit(opcode, {value, count})); - Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); + Write16Bits(DestinationOperand(inst), result); } void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, @@ -17,7 +17,7 @@ void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpco const auto lhs = ReadU16AsU32(inst.src0, sign); const auto rhs = ReadU16AsU32(inst.src1, sign); const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs})); - Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); + Write16Bits(DestinationOperand(inst), result); } void Translator::V_MAD_I16(const Decoder::Instruction& inst) { @@ -28,7 +28,7 @@ void Translator::V_MAD_I16(const Decoder::Instruction& inst) { result = IR::U32(ir.Emit(IR::ValueOpcode::SMax32, {result, IR::Value(0xffff8000u)})); result = IR::U32(ir.Emit(IR::ValueOpcode::SMin32, {result, IR::Value(0x7fffu)})); } - Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); + Write16Bits(DestinationOperand(inst), result); } void Translator::Integer16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp index 15a09a10f..318dfde4b 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp @@ -296,15 +296,11 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) { value = ir.ShiftLeftLogical(extended, IR::U32(IR::Value(offset))); break; } - case 2: { - const uint32_t field_mask = width == 32u ? 0xffffffffu : (1u << width) - 1u; - const auto inserted = - ir.ShiftLeftLogical(ir.BitwiseAnd(value, IR::U32(IR::Value(field_mask))), - IR::U32(IR::Value(offset))); - const auto cleared = ir.BitwiseAnd(ReadRawU32(PlainOperand(operand)), - IR::U32(IR::Value(~(field_mask << offset)))); - value = ir.BitwiseOr(cleared, inserted); - } break; + case 2: + value = IR::U32(ir.Emit(IR::ValueOpcode::BitFieldInsert, + {ReadRawU32(PlainOperand(operand)), value, IR::Value(offset), + IR::Value(width)})); + break; default: EXIT("reserved SDWA DST_U mode"); } } @@ -453,7 +449,10 @@ void Translator::Write16Bits(const Decoder::Operand& operand, IR::U32 value) { destination.omod = 0u; destination.op_sel = false; destination.clamp = false; - WriteRawU32(destination, ir.BitwiseAnd(value, IR::U32(IR::Value(0xffffu)))); + // A field selector keeps only the field's bits; a full-dword SDWA selector zero-extends. + WriteRawU32(destination, destination.sdwa_sel == 6u + ? ir.BitwiseAnd(value, IR::U32(IR::Value(0xffffu))) + : value); } void Translator::WriteF16(const Decoder::Operand& operand, IR::F32 value) { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index bf69e15d8..97caf606a 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -24676,7 +24676,7 @@ TestCase Vop1SdwaMovByteDestinations() { test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; test.decoded_counts = {{"V_MOV_B32 v1.sdwa(sel=2,sext=0), 0", 1}}; - test.required_spirv = {"OpBitFieldInsert", "OpBitFieldSExtract", "OpBitwiseOr"}; + test.required_spirv = {"OpBitFieldInsert", "OpBitFieldSExtract"}; return test; } @@ -24793,7 +24793,7 @@ TestCase Vop2SdwaAddNcCapturedHighWordDestination() { test.expected = {0x00010002u, 0x0006c3d4u}; test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_READFIRSTLANE_B32, O::V_MOV_B32, O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; - test.required_spirv = {"OpIAdd", "OpShiftLeftLogical", "OpBitwiseOr"}; + test.required_spirv = {"OpIAdd", "OpBitFieldInsert"}; return test; }