shader: implement S_WQM_B32

Co-authored-by: Brandon Strong <brandostrong@gmail.com>
This commit is contained in:
nmzik
2026-09-09 19:17:45 +04:00
parent c913951f7b
commit c3546577b6
7 changed files with 101 additions and 6 deletions
@@ -41,6 +41,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
{0x06u, Opcode::S_CMOV_B64},
{0x07u, Opcode::S_NOT_B32},
{0x08u, Opcode::S_NOT_B64},
{0x09u, Opcode::S_WQM_B32},
{0x0au, Opcode::S_WQM_B64},
{0x0bu, Opcode::S_BREV_B32},
{0x0fu, Opcode::S_BCNT1_I32_B32},
@@ -487,6 +487,7 @@ std::string InstructionToString(const Instruction& inst) {
case Opcode::S_BITSET0_B64:
case Opcode::S_BITSET1_B64:
case Opcode::S_NOT_B64:
case Opcode::S_WQM_B32:
case Opcode::S_WQM_B64:
case Opcode::S_QUADMASK_B64:
case Opcode::S_AND_SAVEEXEC_B32:
@@ -63,6 +63,7 @@ enum class Opcode {
S_ANDN1_SAVEEXEC_B64,
S_NOT_B32,
S_NOT_B64,
S_WQM_B32,
S_WQM_B64,
S_ADD_U32,
S_ADDC_U32,
@@ -301,10 +301,19 @@ void Translator::S_MOV_B64(const Decoder::Instruction& inst) {
}
}
void Translator::S_WQM_B64(const Decoder::Instruction& inst) {
const auto mask_valid = ReadMaskValid(inst.src0);
const auto result =
IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {ReadOperand(inst.src0, IR::Type::U64)}));
void Translator::S_WQM(const Decoder::Instruction& inst, bool wide) {
const auto source = wide ? ReadU64(inst.src0)
: ir.ConstructU64(ReadU32(inst.src0), IR::U32(IR::Value(0u)));
const auto result = IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {source}));
if (!wide) {
const auto low = ir.CompositeExtract(result, 0);
// A 32-bit write preserves the other EXEC/VCC half and invalidates any
// overlapping SGPR-pair mask provenance through the ordinary scalar path.
WriteRawU32(inst.dst, low);
ir.SetScc(ir.INotEqual(low, IR::U32(IR::Value(0u))));
return;
}
const auto mask_valid = ReadMaskValid(inst.src0);
WriteOperand(DestinationOperand(inst), result);
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
@@ -8,7 +8,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
case O::S_MOV_B32:
case O::S_MOVK_I32: MOV_B32(inst, false); return true;
case O::S_MOV_B64: S_MOV_B64(inst); return true;
case O::S_WQM_B64: S_WQM_B64(inst); return true;
case O::S_WQM_B32: S_WQM(inst, false); return true;
case O::S_WQM_B64: S_WQM(inst, true); return true;
case O::S_GETPC_B64: S_GETPC_B64(inst); return true;
case O::S_SETPC_B64: return true;
case O::S_SUBVECTOR_LOOP_BEGIN: S_SUBVECTOR_LOOP(inst, true); return true;
@@ -234,7 +234,7 @@ private:
void ScalarSelect64(const Decoder::Instruction& inst, const Decoder::Operand& false_source);
void MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers);
void S_MOV_B64(const Decoder::Instruction& inst);
void S_WQM_B64(const Decoder::Instruction& inst);
void S_WQM(const Decoder::Instruction& inst, bool wide);
void V_MOVRELS_B32(const Decoder::Instruction& inst);
void V_MOVRELD_B32(const Decoder::Instruction& inst);
void V_READFIRSTLANE_B32(const Decoder::Instruction& inst);