|
|
|
@@ -13,6 +13,7 @@ enum class Vop2SdwaProfile {
|
|
|
|
|
None,
|
|
|
|
|
Float32,
|
|
|
|
|
Float16,
|
|
|
|
|
PackedFloat16,
|
|
|
|
|
IntegerFullDestination,
|
|
|
|
|
IntegerPartialDestination,
|
|
|
|
|
ReverseRightShift,
|
|
|
|
@@ -66,7 +67,7 @@ constexpr Vop2OpcodeInfo VOP2_OPCODE_LIST[] = {
|
|
|
|
|
{0x2bu, Opcode::V_MAC_F32},
|
|
|
|
|
{0x2cu, Opcode::V_MADMK_F32},
|
|
|
|
|
{0x2du, Opcode::V_MADAK_F32},
|
|
|
|
|
{0x2fu, Opcode::V_CVT_PKRTZ_F16_F32},
|
|
|
|
|
{0x2fu, Opcode::V_CVT_PKRTZ_F16_F32, Vop2SdwaProfile::PackedFloat16},
|
|
|
|
|
{0x32u, Opcode::V_ADD_F16, Vop2SdwaProfile::Float16},
|
|
|
|
|
{0x33u, Opcode::V_SUB_F16, Vop2SdwaProfile::Float16},
|
|
|
|
|
{0x34u, Opcode::V_SUBREV_F16, Vop2SdwaProfile::Float16},
|
|
|
|
@@ -417,14 +418,6 @@ bool IsPermlaneOpcode(Opcode opcode) {
|
|
|
|
|
return opcode == Opcode::V_PERMLANE16_B32 || opcode == Opcode::V_PERMLANEX16_B32;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsVop2LowHalfF16Opcode(Opcode opcode) {
|
|
|
|
|
return opcode == Opcode::V_ADD_F16 || opcode == Opcode::V_SUB_F16 ||
|
|
|
|
|
opcode == Opcode::V_SUBREV_F16 || opcode == Opcode::V_MUL_F16 ||
|
|
|
|
|
opcode == Opcode::V_FMAC_F16 || opcode == Opcode::V_FMAMK_F16 ||
|
|
|
|
|
opcode == Opcode::V_FMAAK_F16 || opcode == Opcode::V_MAX_F16 ||
|
|
|
|
|
opcode == Opcode::V_MIN_F16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsNativeVop3F16TernaryOpcode(Opcode opcode) {
|
|
|
|
|
return opcode == Opcode::V_MIN3_F16 || opcode == Opcode::V_MAX3_F16 ||
|
|
|
|
|
opcode == Opcode::V_MED3_F16 || opcode == Opcode::V_FMA_F16;
|
|
|
|
@@ -451,12 +444,6 @@ bool IsNativeVop3B16BinaryOpcode(Opcode opcode) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ApplyDefaultVop2F16Destination(Instruction& inst) {
|
|
|
|
|
if (IsVop2LowHalfF16Opcode(inst.opcode)) {
|
|
|
|
|
inst.dst.sdwa_sel = 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsVop1FloatResultOpcode(Opcode opcode);
|
|
|
|
|
bool IsVopcCompareExec(Opcode opcode);
|
|
|
|
|
|
|
|
|
@@ -471,6 +458,8 @@ bool IsVop1FloatSourceOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_FREXP_EXP_I32_F32:
|
|
|
|
|
case Opcode::V_FREXP_MANT_F32:
|
|
|
|
|
case Opcode::V_CVT_F16_F32:
|
|
|
|
|
case Opcode::V_CVT_U16_F16:
|
|
|
|
|
case Opcode::V_CVT_I16_F16:
|
|
|
|
|
case Opcode::V_RCP_F32:
|
|
|
|
|
case Opcode::V_RCP_IFLAG_F32:
|
|
|
|
|
case Opcode::V_FRACT_F32:
|
|
|
|
@@ -482,7 +471,11 @@ bool IsVop1FloatSourceOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_LOG_F32:
|
|
|
|
|
case Opcode::V_RSQ_F32:
|
|
|
|
|
case Opcode::V_SQRT_F32:
|
|
|
|
|
case Opcode::V_RCP_F16:
|
|
|
|
|
case Opcode::V_SQRT_F16:
|
|
|
|
|
case Opcode::V_RSQ_F16:
|
|
|
|
|
case Opcode::V_LOG_F16:
|
|
|
|
|
case Opcode::V_EXP_F16:
|
|
|
|
|
case Opcode::V_FLOOR_F16:
|
|
|
|
|
case Opcode::V_CEIL_F16:
|
|
|
|
|
case Opcode::V_TRUNC_F16:
|
|
|
|
@@ -528,33 +521,34 @@ constexpr Vop1SdwaRule VOP1_SDWA_RULES[] = {
|
|
|
|
|
{Opcode::V_NOT_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
|
|
|
|
|
{Opcode::V_FFBL_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
|
|
|
|
|
{Opcode::V_CVT_F32_F16, SdwaSelWords() | SdwaSelFull(), 0, 0, true},
|
|
|
|
|
{Opcode::V_CVT_F16_F32, SdwaSelFull(), SdwaSelWords(), SdwaSelFull(), false},
|
|
|
|
|
{Opcode::V_CVT_F16_F32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_CVT_F16_U16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
{Opcode::V_CVT_U16_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_CVT_F16_I16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
{Opcode::V_CVT_I16_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_RCP_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_SQRT_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_RSQ_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_LOG_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_EXP_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_FLOOR_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_CEIL_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_TRUNC_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_RNDNE_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), false},
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_SIN_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
|
SdwaSelWords() | SdwaSelFull(), true},
|
|
|
|
|
{Opcode::V_COS_F16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),
|
|
|
|
@@ -586,7 +580,7 @@ bool IsValidFullSdwaDestinationUnused(uint32_t dst_u) {
|
|
|
|
|
|
|
|
|
|
bool IsVop1SdwaSourceSupported(Opcode opcode, uint32_t src_sel, bool src_neg, bool src_abs) {
|
|
|
|
|
if (src_sel == 6u) {
|
|
|
|
|
return true;
|
|
|
|
|
return IsVop1FloatSourceOpcode(opcode) || (!src_neg && !src_abs);
|
|
|
|
|
}
|
|
|
|
|
const auto* rule = FindVop1SdwaRule(opcode);
|
|
|
|
|
if (rule == nullptr || !HasSdwaSelector(rule->source_selectors, src_sel)) {
|
|
|
|
@@ -597,29 +591,24 @@ bool IsVop1SdwaSourceSupported(Opcode opcode, uint32_t src_sel, bool src_neg, bo
|
|
|
|
|
|
|
|
|
|
bool IsVop1SdwaDestinationSupported(Opcode opcode, uint32_t dst_sel, uint32_t dst_u,
|
|
|
|
|
uint32_t src_sel) {
|
|
|
|
|
if ((opcode == Opcode::V_CVT_U16_F16 || opcode == Opcode::V_CVT_I16_F16) && dst_sel == 6u) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (dst_sel == 6u) {
|
|
|
|
|
return IsValidFullSdwaDestinationUnused(dst_u);
|
|
|
|
|
}
|
|
|
|
|
const auto* rule = FindVop1SdwaRule(opcode);
|
|
|
|
|
if (rule == nullptr || dst_u != 2u) {
|
|
|
|
|
if (rule == nullptr || dst_u == 3u) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return HasSdwaSelector(rule->partial_dst_selectors, dst_sel) &&
|
|
|
|
|
HasSdwaSelector(rule->partial_dst_source_selectors, src_sel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool HasUnsupportedVop1SdwaSourceModifiers(Opcode opcode, bool src_neg, bool src_abs) {
|
|
|
|
|
switch (opcode) {
|
|
|
|
|
case Opcode::V_CVT_U16_F16:
|
|
|
|
|
case Opcode::V_CVT_I16_F16:
|
|
|
|
|
case Opcode::V_SQRT_F16:
|
|
|
|
|
case Opcode::V_RSQ_F16: return src_neg || src_abs;
|
|
|
|
|
case Opcode::V_LOG_F16: return src_neg;
|
|
|
|
|
default: return false;
|
|
|
|
|
}
|
|
|
|
|
bool UsesInexactClampControl(Opcode opcode) {
|
|
|
|
|
return opcode == Opcode::V_CVT_U32_F32 || opcode == Opcode::V_CVT_I32_F32 ||
|
|
|
|
|
opcode == Opcode::V_CVT_U16_F16 || opcode == Opcode::V_CVT_I16_F16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SupportsVop1Clamp(Opcode opcode) {
|
|
|
|
|
return IsVop1FloatResultOpcode(opcode) || UsesInexactClampControl(opcode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ValidateVop1Sdwa(Instruction& inst, uint32_t opcode, uint32_t modifier) {
|
|
|
|
@@ -635,7 +624,8 @@ bool ValidateVop1Sdwa(Instruction& inst, uint32_t opcode, uint32_t modifier) {
|
|
|
|
|
SetUnsupported(inst, Family::VOP1, opcode, "VOP1 SDWA selector is invalid");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ((clamp != 0u || omod != 0u) && !IsVop1FloatResultOpcode(inst.opcode)) {
|
|
|
|
|
if ((clamp != 0u && !SupportsVop1Clamp(inst.opcode)) ||
|
|
|
|
|
(omod != 0u && !IsVop1FloatResultOpcode(inst.opcode))) {
|
|
|
|
|
SetUnsupported(inst, Family::VOP1, opcode, "VOP1 SDWA output modifiers are not supported");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@@ -644,10 +634,6 @@ bool ValidateVop1Sdwa(Instruction& inst, uint32_t opcode, uint32_t modifier) {
|
|
|
|
|
"VOP1 SDWA destination selector is not supported");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (HasUnsupportedVop1SdwaSourceModifiers(inst.opcode, src0_neg != 0u, src0_abs != 0u)) {
|
|
|
|
|
SetUnsupported(inst, Family::VOP1, opcode, "VOP1 SDWA source modifiers are not supported");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!IsVop1SdwaSourceSupported(inst.opcode, src0_sel, src0_neg != 0u, src0_abs != 0u)) {
|
|
|
|
|
SetUnsupported(inst, Family::VOP1, opcode, "VOP1 SDWA source selector is not supported");
|
|
|
|
|
return false;
|
|
|
|
@@ -685,10 +671,11 @@ bool DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
|
|
|
|
|
if (!DecodeScalarSource(src0 + (s0 == 0u ? 256u : 0u), pc, inst.src0, error)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
inst.dst.sdwa_sel = dst_sel;
|
|
|
|
|
inst.dst.sdwa_dst_unused = dst_u;
|
|
|
|
|
inst.dst.clamp = clamp != 0u;
|
|
|
|
|
inst.dst.omod = omod;
|
|
|
|
|
inst.dst.sdwa_sel = dst_sel;
|
|
|
|
|
inst.dst.sdwa_dst_unused = dst_u;
|
|
|
|
|
inst.dst.explicit_sdwa_dst = true;
|
|
|
|
|
inst.dst.clamp = clamp != 0u;
|
|
|
|
|
inst.dst.omod = omod;
|
|
|
|
|
inst.src0.sdwa_sel = src0_sel;
|
|
|
|
|
inst.src0.sdwa_sext = src0_sext != 0u;
|
|
|
|
|
inst.src0.negate = src0_neg != 0u;
|
|
|
|
@@ -780,6 +767,7 @@ bool IsVop2FloatSourceOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_MAC_F32:
|
|
|
|
|
case Opcode::V_MADMK_F32:
|
|
|
|
|
case Opcode::V_MADAK_F32:
|
|
|
|
|
case Opcode::V_CVT_PKRTZ_F16_F32:
|
|
|
|
|
case Opcode::V_ADD_F16:
|
|
|
|
|
case Opcode::V_SUB_F16:
|
|
|
|
|
case Opcode::V_SUBREV_F16:
|
|
|
|
@@ -804,6 +792,7 @@ bool IsVop2FloatResultOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_MAC_F32:
|
|
|
|
|
case Opcode::V_MADMK_F32:
|
|
|
|
|
case Opcode::V_MADAK_F32:
|
|
|
|
|
case Opcode::V_CVT_PKRTZ_F16_F32:
|
|
|
|
|
case Opcode::V_ADD_F16:
|
|
|
|
|
case Opcode::V_SUB_F16:
|
|
|
|
|
case Opcode::V_SUBREV_F16:
|
|
|
|
@@ -822,6 +811,9 @@ bool IsVop1FloatResultOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_CVT_F32_I32:
|
|
|
|
|
case Opcode::V_CVT_F32_U32:
|
|
|
|
|
case Opcode::V_CVT_F32_F16:
|
|
|
|
|
case Opcode::V_CVT_F16_F32:
|
|
|
|
|
case Opcode::V_CVT_F16_U16:
|
|
|
|
|
case Opcode::V_CVT_F16_I16:
|
|
|
|
|
case Opcode::V_CVT_OFF_F32_I4:
|
|
|
|
|
case Opcode::V_CVT_F32_UBYTE0:
|
|
|
|
|
case Opcode::V_CVT_F32_UBYTE1:
|
|
|
|
@@ -840,9 +832,14 @@ bool IsVop1FloatResultOpcode(Opcode opcode) {
|
|
|
|
|
case Opcode::V_RSQ_F32:
|
|
|
|
|
case Opcode::V_SQRT_F32:
|
|
|
|
|
case Opcode::V_RCP_F16:
|
|
|
|
|
case Opcode::V_SQRT_F16:
|
|
|
|
|
case Opcode::V_RSQ_F16:
|
|
|
|
|
case Opcode::V_LOG_F16:
|
|
|
|
|
case Opcode::V_EXP_F16:
|
|
|
|
|
case Opcode::V_FLOOR_F16:
|
|
|
|
|
case Opcode::V_CEIL_F16:
|
|
|
|
|
case Opcode::V_TRUNC_F16:
|
|
|
|
|
case Opcode::V_RNDNE_F16:
|
|
|
|
|
case Opcode::V_SIN_F16:
|
|
|
|
|
case Opcode::V_COS_F16:
|
|
|
|
|
case Opcode::V_SIN_F32:
|
|
|
|
@@ -957,6 +954,7 @@ constexpr Vop2SdwaRule VOP2_SDWA_RULES[] = {
|
|
|
|
|
{SdwaSelFull(), SdwaSelFull(), SdwaSelFull(), false, true},
|
|
|
|
|
{SdwaSelWords() | SdwaSelFull(), SdwaSelWords() | SdwaSelFull(), SdwaSelWords() | SdwaSelFull(),
|
|
|
|
|
true, true},
|
|
|
|
|
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, true},
|
|
|
|
|
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
|
|
|
|
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
|
|
|
|
{SdwaSelFull(), SdwaSelAll(), SdwaSelWords() | SdwaSelFull(), false, false},
|
|
|
|
@@ -981,7 +979,7 @@ bool IsVop2SdwaDestinationSupported(const Vop2SdwaRule& rule, const Vop2SdwaFiel
|
|
|
|
|
if (fields.dst_sel == 6u) {
|
|
|
|
|
return IsValidFullSdwaDestinationUnused(fields.dst_u);
|
|
|
|
|
}
|
|
|
|
|
return fields.dst_u == 2u && rule.partial_dst;
|
|
|
|
|
return fields.dst_u != 3u && rule.partial_dst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsFullWidthVop2Sdwa(const Vop2SdwaFields& fields) {
|
|
|
|
@@ -1087,10 +1085,11 @@ bool DecodeVop2Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
|
|
|
|
|
!DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, inst.src1, error)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
inst.dst.sdwa_sel = fields.dst_sel;
|
|
|
|
|
inst.dst.sdwa_dst_unused = fields.dst_u;
|
|
|
|
|
inst.dst.clamp = fields.clamp != 0u;
|
|
|
|
|
inst.dst.omod = fields.omod;
|
|
|
|
|
inst.dst.sdwa_sel = fields.dst_sel;
|
|
|
|
|
inst.dst.sdwa_dst_unused = fields.dst_u;
|
|
|
|
|
inst.dst.explicit_sdwa_dst = true;
|
|
|
|
|
inst.dst.clamp = fields.clamp != 0u;
|
|
|
|
|
inst.dst.omod = fields.omod;
|
|
|
|
|
inst.src0.sdwa_sel = fields.src0_sel;
|
|
|
|
|
inst.src0.sdwa_sext = fields.src0_sext != 0u;
|
|
|
|
|
inst.src0.negate = fields.src0_neg != 0u;
|
|
|
|
@@ -1117,7 +1116,6 @@ bool DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
|
|
|
|
ApplyDppModifier(inst.src0, modifier);
|
|
|
|
|
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
|
|
|
|
|
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
|
|
|
|
|
ApplyDefaultVop2F16Destination(inst);
|
|
|
|
|
const bool packed_fmac = inst.opcode == Opcode::V_PK_FMAC_F16;
|
|
|
|
|
if (packed_fmac) {
|
|
|
|
|
inst.src0.negate_hi = inst.src0.negate;
|
|
|
|
@@ -1451,6 +1449,7 @@ bool SupportsNativeVop3ResultModifiers(Opcode opcode) {
|
|
|
|
|
case Opcode::V_MAD_F32:
|
|
|
|
|
case Opcode::V_FMA_F32:
|
|
|
|
|
case Opcode::V_FMA_F16:
|
|
|
|
|
case Opcode::V_CVT_PKRTZ_F16_F32:
|
|
|
|
|
case Opcode::V_LDEXP_F32:
|
|
|
|
|
case Opcode::V_MIN3_F32:
|
|
|
|
|
case Opcode::V_MAX3_F32:
|
|
|
|
@@ -1459,12 +1458,17 @@ bool SupportsNativeVop3ResultModifiers(Opcode opcode) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SupportsNativeVop3Clamp(Opcode opcode) {
|
|
|
|
|
return SupportsNativeVop3ResultModifiers(opcode) || UsesInexactClampControl(opcode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool HasUnsupportedNativeVop3Modifiers(Opcode opcode, bool permlane, bool mad_mix,
|
|
|
|
|
bool carry_in_out, bool scalar_dst, uint32_t abs,
|
|
|
|
|
uint32_t op_sel, uint32_t clamp, uint32_t omod,
|
|
|
|
|
uint32_t neg) {
|
|
|
|
|
const bool source_modifiers = SupportsNativeVop3SourceModifiers(opcode);
|
|
|
|
|
const bool result_modifiers = SupportsNativeVop3ResultModifiers(opcode);
|
|
|
|
|
const bool clamp_modifier = SupportsNativeVop3Clamp(opcode);
|
|
|
|
|
|
|
|
|
|
if (permlane) {
|
|
|
|
|
return abs != 0u || (op_sel & ~0x3u) != 0u || clamp != 0u || omod != 0u || neg != 0u;
|
|
|
|
@@ -1496,7 +1500,7 @@ bool HasUnsupportedNativeVop3Modifiers(Opcode opcode, bool permlane, bool mad_mi
|
|
|
|
|
}
|
|
|
|
|
if (source_modifiers) {
|
|
|
|
|
return op_sel != 0u || (omod != 0u && !result_modifiers) ||
|
|
|
|
|
(clamp != 0u && !result_modifiers);
|
|
|
|
|
(clamp != 0u && !clamp_modifier);
|
|
|
|
|
}
|
|
|
|
|
if (result_modifiers) {
|
|
|
|
|
return abs != 0u || op_sel != 0u || neg != 0u;
|
|
|
|
@@ -1589,7 +1593,6 @@ bool DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|
|
|
|
if (!DecodeScalarSource(src0, pc, inst.src0, error)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ApplyDefaultVop2F16Destination(inst);
|
|
|
|
|
return FinalizeVop2Instruction(pc, code, word_index, inst, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1713,6 +1716,7 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|
|
|
|
const bool scalar_modifier_limits = UsesScalarDestination(inst.opcode);
|
|
|
|
|
const bool native_source_modifiers = SupportsNativeVop3SourceModifiers(inst.opcode);
|
|
|
|
|
const bool native_result_modifiers = SupportsNativeVop3ResultModifiers(inst.opcode);
|
|
|
|
|
const bool native_clamp_modifier = SupportsNativeVop3Clamp(inst.opcode);
|
|
|
|
|
const bool modifiers =
|
|
|
|
|
HasUnsupportedNativeVop3Modifiers(inst.opcode, permlane, mad_mix, vop3b_uses_sdst,
|
|
|
|
|
scalar_modifier_limits, abs, op_sel, clamp, omod, neg);
|
|
|
|
@@ -1747,7 +1751,7 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|
|
|
|
if (!dst_ok || !DecodeScalarSource(src0, pc, inst.src0, error)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
inst.dst.clamp = native_result_modifiers && clamp != 0u;
|
|
|
|
|
inst.dst.clamp = native_clamp_modifier && clamp != 0u;
|
|
|
|
|
inst.dst.omod = native_result_modifiers ? omod : 0u;
|
|
|
|
|
if (permlane) {
|
|
|
|
|
inst.dst.op_sel = (op_sel & 0x1u) != 0u;
|
|
|
|
|