shader: simplify translator dispatch to void handlers

This commit is contained in:
nmzik
2026-09-25 14:16:58 +04:00
parent ff54608569
commit 3585cd8f03
8 changed files with 398 additions and 464 deletions
@@ -106,12 +106,12 @@ void Translator::EXP(const Decoder::Instruction& inst) {
ir.Emit(IR::ValueOpcode::SetAttribute, {data, ir.GetExec()}, AddExportInfo(inst)); ir.Emit(IR::ValueOpcode::SetAttribute, {data, ir.GetExec()}, AddExportInfo(inst));
} }
bool Translator::EmitInterpolation(const Decoder::Instruction& inst) { void Translator::EmitInterpolation(const Decoder::Instruction& inst) {
switch (inst.opcode) { switch (inst.opcode) {
case Decoder::Opcode::V_INTERP_P1_F32: V_INTERP_P1_F32(); return true; case Decoder::Opcode::V_INTERP_P1_F32: V_INTERP_P1_F32(); return;
case Decoder::Opcode::V_INTERP_P2_F32: V_INTERP_P2_F32(inst); return true; case Decoder::Opcode::V_INTERP_P2_F32: V_INTERP_P2_F32(inst); return;
case Decoder::Opcode::V_INTERP_MOV_F32: V_INTERP_MOV_F32(inst); return true; case Decoder::Opcode::V_INTERP_MOV_F32: V_INTERP_MOV_F32(inst); return;
default: return false; default: return FailMissingTranslation(inst);
} }
} }
@@ -3,6 +3,11 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend { namespace Libs::Graphics::ShaderRecompiler::Frontend {
void Translator::FailMissingTranslation(const Decoder::Instruction& inst) {
EXIT("opcode %s at pc 0x%08x has no IR translation",
Decoder::InstructionToString(inst).c_str(), inst.pc);
}
void Translator::TranslateInstruction(const Decoder::Instruction& inst) { void Translator::TranslateInstruction(const Decoder::Instruction& inst) {
current_opcode = inst.opcode; current_opcode = inst.opcode;
current_pc = inst.pc; current_pc = inst.pc;
@@ -16,35 +21,26 @@ void Translator::TranslateInstruction(const Decoder::Instruction& inst) {
default: break; default: break;
} }
bool translated = false;
switch (inst.family) { switch (inst.family) {
case Decoder::Family::SOP1: case Decoder::Family::SOP1:
case Decoder::Family::SOP2: case Decoder::Family::SOP2:
case Decoder::Family::SOPK: case Decoder::Family::SOPK:
case Decoder::Family::SOPC: case Decoder::Family::SOPC:
case Decoder::Family::SOPP: translated = EmitScalar(inst); break; case Decoder::Family::SOPP: return EmitScalar(inst);
case Decoder::Family::VOP1: case Decoder::Family::VOP1:
case Decoder::Family::VOP2: case Decoder::Family::VOP2:
case Decoder::Family::VOP3: case Decoder::Family::VOP3:
case Decoder::Family::VOP3P: case Decoder::Family::VOP3P:
case Decoder::Family::VOPC: translated = EmitVector(inst); break; case Decoder::Family::VOPC: return EmitVector(inst);
case Decoder::Family::SMEM: case Decoder::Family::SMEM:
case Decoder::Family::MUBUF: case Decoder::Family::MUBUF:
case Decoder::Family::MTBUF: case Decoder::Family::MTBUF:
case Decoder::Family::FLAT: case Decoder::Family::FLAT:
case Decoder::Family::DS: case Decoder::Family::DS:
case Decoder::Family::MIMG: translated = EmitMemory(inst); break; case Decoder::Family::MIMG: return EmitMemory(inst);
case Decoder::Family::VINTRP: translated = EmitInterpolation(inst); break; case Decoder::Family::VINTRP: return EmitInterpolation(inst);
case Decoder::Family::EXP: case Decoder::Family::EXP: return EXP(inst);
EXP(inst); default: return FailMissingTranslation(inst);
translated = true;
break;
default: break;
}
if (!translated) {
EXIT("opcode %s at pc 0x%08x has no IR translation",
Decoder::InstructionToString(inst).c_str(), inst.pc);
} }
} }
@@ -5,7 +5,7 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend { namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::PackedFloat16(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::PackedFloat16(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool accumulator, bool quiet_snan) { bool accumulator, bool quiet_snan) {
const auto translate_lane = [&](bool high) { const auto translate_lane = [&](bool high) {
const auto lhs = ReadF16LaneAsF32(inst.src0, high, true); const auto lhs = ReadF16LaneAsF32(inst.src0, high, true);
@@ -43,16 +43,15 @@ bool Translator::PackedFloat16(const Decoder::Instruction& inst, IR::ValueOpcode
result = PackU16Lanes(override_lane(false), override_lane(true)); result = PackU16Lanes(override_lane(false), override_lane(true));
} }
WriteOperand(raw, result); WriteOperand(raw, result);
return true;
} }
bool Translator::Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool invalid_negative) { bool invalid_negative) {
const auto argument = ReadF16AsF32(inst.src0); const auto argument = ReadF16AsF32(inst.src0);
auto result = IR::F32(ir.Emit(opcode, {argument})); auto result = IR::F32(ir.Emit(opcode, {argument}));
if (!invalid_negative) { if (!invalid_negative) {
WriteF16(DestinationOperand(inst), result); WriteF16(DestinationOperand(inst), result);
return true; return;
} }
const auto negative = const auto negative =
IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {argument, IR::Value::F32(0.0f)})); IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {argument, IR::Value::F32(0.0f)}));
@@ -60,10 +59,9 @@ bool Translator::Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f))); const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u)); const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
Write16Bits(DestinationOperand(inst), ir.Select(negative, invalid, bits)); Write16Bits(DestinationOperand(inst), ir.Select(negative, invalid, bits));
return true;
} }
bool Translator::Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto argument = ReadF16AsF32(inst.src0); const auto argument = ReadF16AsF32(inst.src0);
const auto magnitude = const auto magnitude =
ir.BitwiseAnd(ir.BitCastU32(argument), IR::U32(IR::Value(0x7fffffffu))); ir.BitwiseAnd(ir.BitCastU32(argument), IR::U32(IR::Value(0x7fffffffu)));
@@ -96,18 +94,16 @@ bool Translator::Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode o
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f))); const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u)); const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
Write16Bits(DestinationOperand(inst), ir.Select(infinite, invalid, bits)); Write16Bits(DestinationOperand(inst), ir.Select(infinite, invalid, bits));
return true;
} }
bool Translator::Float16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Float16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool reverse) { bool reverse) {
const auto lhs = ReadF16AsF32(reverse ? inst.src1 : inst.src0); const auto lhs = ReadF16AsF32(reverse ? inst.src1 : inst.src0);
const auto rhs = ReadF16AsF32(reverse ? inst.src0 : inst.src1); const auto rhs = ReadF16AsF32(reverse ? inst.src0 : inst.src1);
WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {lhs, rhs}))); WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {lhs, rhs})));
return true;
} }
bool Translator::Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool accumulator, bool mix) { bool accumulator, bool mix) {
std::array<IR::Value, 3> args; std::array<IR::Value, 3> args;
for (uint32_t index = 0; index < args.size(); index++) { for (uint32_t index = 0; index < args.size(); index++) {
@@ -115,16 +111,14 @@ bool Translator::Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcod
args[index] = mix ? IR::Value(ReadMixF32(operand)) : IR::Value(ReadF16AsF32(operand)); args[index] = mix ? IR::Value(ReadMixF32(operand)) : IR::Value(ReadF16AsF32(operand));
} }
WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {args[0], args[1], args[2]}))); WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {args[0], args[1], args[2]})));
return true;
} }
bool Translator::FloatUnary(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::FloatUnary(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto type = IR::ArgTypeOf(opcode, 0); const auto type = IR::ArgTypeOf(opcode, 0);
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {ReadOperand(inst.src0, type)})); WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {ReadOperand(inst.src0, type)}));
return true;
} }
bool Translator::FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool reverse) { bool reverse) {
std::array<IR::Value, 2> args; std::array<IR::Value, 2> args;
for (uint32_t index = 0; index < args.size(); index++) { for (uint32_t index = 0; index < args.size(); index++) {
@@ -132,10 +126,9 @@ bool Translator::FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode o
args[index] = ReadOperand(operand, IR::ArgTypeOf(opcode, index)); args[index] = ReadOperand(operand, IR::ArgTypeOf(opcode, index));
} }
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1]})); WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1]}));
return true;
} }
bool Translator::FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool accumulator, bool mix) { bool accumulator, bool mix) {
std::array<IR::Value, 3> args; std::array<IR::Value, 3> args;
for (uint32_t index = 0; index < args.size(); index++) { for (uint32_t index = 0; index < args.size(); index++) {
@@ -145,10 +138,9 @@ bool Translator::FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode
: ReadOperand(operand, type); : ReadOperand(operand, type);
} }
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1], args[2]})); WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1], args[2]}));
return true;
} }
bool Translator::V_FREXP_MANT_F32(const Decoder::Instruction& inst) { void Translator::V_FREXP_MANT_F32(const Decoder::Instruction& inst) {
const auto bits = ReadU32(inst.src0); const auto bits = ReadU32(inst.src0);
const auto exponent = const auto exponent =
IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {bits, IR::Value(23u), IR::Value(8u)})); IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {bits, IR::Value(23u), IR::Value(8u)}));
@@ -166,10 +158,9 @@ bool Translator::V_FREXP_MANT_F32(const Decoder::Instruction& inst) {
ir.Select(zero, bits, subnormal)); ir.Select(zero, bits, subnormal));
const auto result = ir.Select(ir.IEqual(exponent, IR::U32(IR::Value(0xffu))), bits, finite); const auto result = ir.Select(ir.IEqual(exponent, IR::U32(IR::Value(0xffu))), bits, finite);
WriteOperand(DestinationOperand(inst), ir.BitCastF32(result)); WriteOperand(DestinationOperand(inst), ir.BitCastF32(result));
return true;
} }
bool Translator::V_DOT2C_F32_F16(const Decoder::Instruction& inst) { void Translator::V_DOT2C_F32_F16(const Decoder::Instruction& inst) {
auto a = inst.src0; auto a = inst.src0;
a.op_sel = false; a.op_sel = false;
a.op_sel_hi = true; a.op_sel_hi = true;
@@ -183,26 +174,25 @@ bool Translator::V_DOT2C_F32_F16(const Decoder::Instruction& inst) {
const auto acc = ReadMixF32(inst.dst); const auto acc = ReadMixF32(inst.dst);
const auto lo = IR::F32(ir.Emit(IR::ValueOpcode::FPFma32, {a_lo, b_lo, acc})); const auto lo = IR::F32(ir.Emit(IR::ValueOpcode::FPFma32, {a_lo, b_lo, acc}));
WriteOperand(DestinationOperand(inst), ir.Emit(IR::ValueOpcode::FPFma32, {a_hi, b_hi, lo})); WriteOperand(DestinationOperand(inst), ir.Emit(IR::ValueOpcode::FPFma32, {a_hi, b_hi, lo}));
return true;
} }
bool Translator::V_CUBEID_F32(const Decoder::Instruction& inst) { void Translator::V_CUBEID_F32(const Decoder::Instruction& inst) {
return FloatCube(inst, 0u); return FloatCube(inst, 0u);
} }
bool Translator::V_CUBESC_F32(const Decoder::Instruction& inst) { void Translator::V_CUBESC_F32(const Decoder::Instruction& inst) {
return FloatCube(inst, 1u); return FloatCube(inst, 1u);
} }
bool Translator::V_CUBETC_F32(const Decoder::Instruction& inst) { void Translator::V_CUBETC_F32(const Decoder::Instruction& inst) {
return FloatCube(inst, 2u); return FloatCube(inst, 2u);
} }
bool Translator::V_CUBEMA_F32(const Decoder::Instruction& inst) { void Translator::V_CUBEMA_F32(const Decoder::Instruction& inst) {
return FloatCube(inst, 3u); return FloatCube(inst, 3u);
} }
bool Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kind) { void Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kind) {
const auto x = ReadMixF32(inst.src0); const auto x = ReadMixF32(inst.src0);
const auto y = ReadMixF32(inst.src1); const auto y = ReadMixF32(inst.src1);
const auto z = ReadMixF32(inst.src2); const auto z = ReadMixF32(inst.src2);
@@ -242,7 +232,6 @@ bool Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kin
default: EXIT("invalid cube result kind"); default: EXIT("invalid cube result kind");
} }
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
} // namespace Libs::Graphics::ShaderRecompiler::Frontend } // namespace Libs::Graphics::ShaderRecompiler::Frontend
@@ -4,25 +4,23 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend { namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool arithmetic) { bool arithmetic) {
const auto value = ReadU16AsU32(inst.src1, arithmetic); const auto value = ReadU16AsU32(inst.src1, arithmetic);
const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u))); const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u)));
const auto result = IR::U32(ir.Emit(opcode, {value, count})); const auto result = IR::U32(ir.Emit(opcode, {value, count}));
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
return true;
} }
bool Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool sign) { bool sign) {
const auto lhs = ReadU16AsU32(inst.src0, sign); const auto lhs = ReadU16AsU32(inst.src0, sign);
const auto rhs = ReadU16AsU32(inst.src1, sign); const auto rhs = ReadU16AsU32(inst.src1, sign);
const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs})); const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs}));
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
return true;
} }
bool Translator::V_MAD_I16(const Decoder::Instruction& inst) { void Translator::V_MAD_I16(const Decoder::Instruction& inst) {
const auto lhs = ReadU16AsU32(inst.src0, true); const auto lhs = ReadU16AsU32(inst.src0, true);
const auto rhs = ReadU16AsU32(inst.src1, true); const auto rhs = ReadU16AsU32(inst.src1, true);
auto result = ir.IAdd(ir.IMul(lhs, rhs), ReadU16AsU32(inst.src2, true)); auto result = ir.IAdd(ir.IMul(lhs, rhs), ReadU16AsU32(inst.src2, true));
@@ -31,18 +29,16 @@ bool Translator::V_MAD_I16(const Decoder::Instruction& inst) {
result = IR::U32(ir.Emit(IR::ValueOpcode::SMin32, {result, IR::Value(0x7fffu)})); 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), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
return true;
} }
bool Translator::V_MED3_I16(const Decoder::Instruction& inst) { void Translator::V_MED3_I16(const Decoder::Instruction& inst) {
const auto result = IR::U32(ir.Emit( const auto result = IR::U32(ir.Emit(
IR::ValueOpcode::SMedTri32, {ReadU16AsU32(inst.src0, true), ReadU16AsU32(inst.src1, true), IR::ValueOpcode::SMedTri32, {ReadU16AsU32(inst.src0, true), ReadU16AsU32(inst.src1, true),
ReadU16AsU32(inst.src2, true)})); ReadU16AsU32(inst.src2, true)}));
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
return true;
} }
bool Translator::PackedInteger16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::PackedInteger16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool arithmetic) { bool arithmetic) {
const auto translate_lane = [&](bool high) { const auto translate_lane = [&](bool high) {
const auto count = const auto count =
@@ -52,10 +48,9 @@ bool Translator::PackedInteger16Shift(const Decoder::Instruction& inst, IR::Valu
}; };
WriteOperand(DestinationOperand(inst), WriteOperand(DestinationOperand(inst),
PackU16Lanes(translate_lane(false), translate_lane(true))); PackU16Lanes(translate_lane(false), translate_lane(true)));
return true;
} }
bool Translator::PackedInteger16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::PackedInteger16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto translate_lane = [&](bool high) { const auto translate_lane = [&](bool high) {
const auto lhs = ReadU16LaneAsU32(inst.src0, high, false); const auto lhs = ReadU16LaneAsU32(inst.src0, high, false);
const auto rhs = ReadU16LaneAsU32(inst.src1, high, false); const auto rhs = ReadU16LaneAsU32(inst.src1, high, false);
@@ -63,10 +58,9 @@ bool Translator::PackedInteger16Binary(const Decoder::Instruction& inst, IR::Val
}; };
WriteOperand(DestinationOperand(inst), WriteOperand(DestinationOperand(inst),
PackU16Lanes(translate_lane(false), translate_lane(true))); PackU16Lanes(translate_lane(false), translate_lane(true)));
return true;
} }
bool Translator::PackedInteger16Mad(const Decoder::Instruction& inst, bool sign) { void Translator::PackedInteger16Mad(const Decoder::Instruction& inst, bool sign) {
const auto translate_lane = [&](bool high) { const auto translate_lane = [&](bool high) {
const auto lhs = ReadU16LaneAsU32(inst.src0, high, false); const auto lhs = ReadU16LaneAsU32(inst.src0, high, false);
const auto rhs = ReadU16LaneAsU32(inst.src1, high, false); const auto rhs = ReadU16LaneAsU32(inst.src1, high, false);
@@ -74,10 +68,9 @@ bool Translator::PackedInteger16Mad(const Decoder::Instruction& inst, bool sign)
}; };
WriteOperand(DestinationOperand(inst), WriteOperand(DestinationOperand(inst),
PackU16Lanes(translate_lane(false), translate_lane(true))); PackU16Lanes(translate_lane(false), translate_lane(true)));
return true;
} }
bool Translator::PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool sign) { bool sign) {
const auto translate_lane = [&](bool high) { const auto translate_lane = [&](bool high) {
const auto lhs = ReadU16LaneAsU32(inst.src0, high, sign); const auto lhs = ReadU16LaneAsU32(inst.src0, high, sign);
@@ -86,7 +79,6 @@ bool Translator::PackedInteger16MinMax(const Decoder::Instruction& inst, IR::Val
}; };
WriteOperand(DestinationOperand(inst), WriteOperand(DestinationOperand(inst),
PackU16Lanes(translate_lane(false), translate_lane(true))); PackU16Lanes(translate_lane(false), translate_lane(true)));
return true;
} }
IR::U1 Translator::U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::U1 Translator::U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
@@ -100,7 +92,7 @@ IR::U1 Translator::U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpco
return negate_result ? ir.LogicalNot(result) : result; return negate_result ? ir.LogicalNot(result) : result;
} }
bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode, void Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result,
bool unary) { bool unary) {
const auto invocation_result = const auto invocation_result =
@@ -119,7 +111,7 @@ bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode lo
(inst.src_count > 1u && is_exec_or_vcc(inst.src1))) { (inst.src_count > 1u && is_exec_or_vcc(inst.src1))) {
const auto mask = WriteMask(inst.dst, invocation_result, true); const auto mask = WriteMask(inst.dst, invocation_result, true);
ir.SetScc(ir.INotEqual(ir.BitwiseOr(mask[0], mask[1]), IR::U32(IR::Value(0u)))); ir.SetScc(ir.INotEqual(ir.BitwiseOr(mask[0], mask[1]), IR::U32(IR::Value(0u))));
return true; return;
} }
const auto lhs = ReadU32Pair(inst.src0); const auto lhs = ReadU32Pair(inst.src0);
@@ -146,10 +138,9 @@ bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode lo
ir.SetScalarMaskTag(dst, mask_valid); ir.SetScalarMaskTag(dst, mask_valid);
} }
ir.SetScc(ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u)))); ir.SetScc(ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u))));
return true;
} }
bool Translator::SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
IR::Type type, bool reverse, bool mask_shift_count, IR::Type type, bool reverse, bool mask_shift_count,
bool update_scc) { bool update_scc) {
std::array<IR::Value, 3> args; std::array<IR::Value, 3> args;
@@ -177,10 +168,9 @@ bool Translator::SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode
ir.SetScc(ir.INotEqual(IR::U32(result), IR::U32(IR::Value(0u)))); ir.SetScc(ir.INotEqual(IR::U32(result), IR::U32(IR::Value(0u))));
} }
} }
return true;
} }
bool Translator::S_ASHR_I64(const Decoder::Instruction& inst) { void Translator::S_ASHR_I64(const Decoder::Instruction& inst) {
// Signed 64-bit sources sign-extend literals; generic B64 operands zero-extend them. // Signed 64-bit sources sign-extend literals; generic B64 operands zero-extend them.
const auto source = const auto source =
inst.src0.kind == Decoder::OperandKind::LiteralConstant inst.src0.kind == Decoder::OperandKind::LiteralConstant
@@ -192,10 +182,9 @@ bool Translator::S_ASHR_I64(const Decoder::Instruction& inst) {
ir.Emit(IR::ValueOpcode::ShiftRightArithmetic64, {source, ReadU32(inst.src1)}); ir.Emit(IR::ValueOpcode::ShiftRightArithmetic64, {source, ReadU32(inst.src1)});
WriteOperand(inst.dst, result); WriteOperand(inst.dst, result);
ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}))); ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
return true;
} }
bool Translator::ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool negate_rhs, bool negate_result, bool update_scc) { bool negate_rhs, bool negate_result, bool update_scc) {
const auto lhs = ReadU32(inst.src0); const auto lhs = ReadU32(inst.src0);
auto rhs = ReadU32(inst.src1); auto rhs = ReadU32(inst.src1);
@@ -210,31 +199,27 @@ bool Translator::ComposedIntegerBinary(const Decoder::Instruction& inst, IR::Val
if (update_scc) { if (update_scc) {
ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u)))); ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u))));
} }
return true;
} }
bool Translator::V_AND_OR_B32(const Decoder::Instruction& inst) { void Translator::V_AND_OR_B32(const Decoder::Instruction& inst) {
const auto result = const auto result =
ir.BitwiseOr(ir.BitwiseAnd(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2)); ir.BitwiseOr(ir.BitwiseAnd(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_OR3_B32(const Decoder::Instruction& inst) { void Translator::V_OR3_B32(const Decoder::Instruction& inst) {
const auto result = const auto result =
ir.BitwiseOr(ir.BitwiseOr(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2)); ir.BitwiseOr(ir.BitwiseOr(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_XOR3_B32(const Decoder::Instruction& inst) { void Translator::V_XOR3_B32(const Decoder::Instruction& inst) {
const auto result = const auto result =
ir.BitwiseXor(ir.BitwiseXor(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2)); ir.BitwiseXor(ir.BitwiseXor(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_FF1_I32_B64(const Decoder::Instruction& inst) { void Translator::S_FF1_I32_B64(const Decoder::Instruction& inst) {
const auto source = ExtractU64(ReadU64(inst.src0)); const auto source = ExtractU64(ReadU64(inst.src0));
const auto low_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]})); const auto low_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]}));
const auto high_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]})); const auto high_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]}));
@@ -243,10 +228,9 @@ bool Translator::S_FF1_I32_B64(const Decoder::Instruction& inst) {
ir.Select(ir.INotEqual(source[1], IR::U32(IR::Value(0u))), ir.Select(ir.INotEqual(source[1], IR::U32(IR::Value(0u))),
high_position, IR::U32(IR::Value(0xffffffffu)))); high_position, IR::U32(IR::Value(0xffffffffu))));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) { void Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) {
const auto source = ReadU32(inst.src0); const auto source = ReadU32(inst.src0);
const auto value = sign ? ir.BitwiseXor( const auto value = sign ? ir.BitwiseXor(
source, ir.ShiftRightArithmetic(source, IR::U32(IR::Value(31u)))) source, ir.ShiftRightArithmetic(source, IR::U32(IR::Value(31u))))
@@ -256,10 +240,9 @@ bool Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) {
const auto result = ir.Select(ir.INotEqual(value, IR::U32(IR::Value(0u))), position, const auto result = ir.Select(ir.INotEqual(value, IR::U32(IR::Value(0u))), position,
IR::U32(IR::Value(0xffffffffu))); IR::U32(IR::Value(0xffffffffu)));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_FLBIT_I32_B64(const Decoder::Instruction& inst) { void Translator::S_FLBIT_I32_B64(const Decoder::Instruction& inst) {
const auto source = ReadU64(inst.src0); const auto source = ReadU64(inst.src0);
const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb64, {source})); const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb64, {source}));
const auto position = ir.ISub(IR::U32(IR::Value(63u)), msb); const auto position = ir.ISub(IR::U32(IR::Value(63u)), msb);
@@ -268,10 +251,9 @@ bool Translator::S_FLBIT_I32_B64(const Decoder::Instruction& inst) {
{source, ir.ConstructU64(IR::U32(IR::Value(0u)), IR::U32(IR::Value(0u)))})); {source, ir.ConstructU64(IR::U32(IR::Value(0u)), IR::U32(IR::Value(0u)))}));
const auto result = ir.Select(nonzero, position, IR::U32(IR::Value(0xffffffffu))); const auto result = ir.Select(nonzero, position, IR::U32(IR::Value(0xffffffffu)));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::Integer24(const Decoder::Instruction& inst, bool sign, bool addend) { void Translator::Integer24(const Decoder::Instruction& inst, bool sign, bool addend) {
const auto extract24 = [&](IR::U32 value) { const auto extract24 = [&](IR::U32 value) {
return IR::U32( return IR::U32(
ir.Emit(sign ? IR::ValueOpcode::BitFieldSExtract : IR::ValueOpcode::BitFieldUExtract, ir.Emit(sign ? IR::ValueOpcode::BitFieldSExtract : IR::ValueOpcode::BitFieldUExtract,
@@ -284,10 +266,9 @@ bool Translator::Integer24(const Decoder::Instruction& inst, bool sign, bool add
result = ir.IAdd(result, ReadU32(inst.src2)); result = ir.IAdd(result, ReadU32(inst.src2));
} }
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_MAD_U64_U32(const Decoder::Instruction& inst) { void Translator::V_MAD_U64_U32(const Decoder::Instruction& inst) {
const auto lhs = ReadU32(inst.src0); const auto lhs = ReadU32(inst.src0);
const auto rhs = ReadU32(inst.src1); const auto rhs = ReadU32(inst.src1);
const auto add = ExtractU64(ReadU64(inst.src2)); const auto add = ExtractU64(ReadU64(inst.src2));
@@ -305,36 +286,32 @@ bool Translator::V_MAD_U64_U32(const Decoder::Instruction& inst) {
inst.dst2.kind != Decoder::OperandKind::Unknown) { inst.dst2.kind != Decoder::OperandKind::Unknown) {
WriteMask(inst.dst2, ir.LogicalOr(carry0, carry1)); WriteMask(inst.dst2, ir.LogicalOr(carry0, carry1));
} }
return true;
} }
bool Translator::V_SAD_U32(const Decoder::Instruction& inst) { void Translator::V_SAD_U32(const Decoder::Instruction& inst) {
const auto lhs = ReadU32(inst.src0); const auto lhs = ReadU32(inst.src0);
const auto rhs = ReadU32(inst.src1); const auto rhs = ReadU32(inst.src1);
const auto lo = IR::U32(ir.Emit(IR::ValueOpcode::UMin32, {lhs, rhs})); const auto lo = IR::U32(ir.Emit(IR::ValueOpcode::UMin32, {lhs, rhs}));
const auto hi = IR::U32(ir.Emit(IR::ValueOpcode::UMax32, {lhs, rhs})); const auto hi = IR::U32(ir.Emit(IR::ValueOpcode::UMax32, {lhs, rhs}));
const auto result = ir.IAdd(ir.ISub(hi, lo), ReadU32(inst.src2)); const auto result = ir.IAdd(ir.ISub(hi, lo), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_ADD3_U32(const Decoder::Instruction& inst) { void Translator::V_ADD3_U32(const Decoder::Instruction& inst) {
const auto result = const auto result =
ir.IAdd(ir.IAdd(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2)); ir.IAdd(ir.IAdd(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_BITSET_B32(const Decoder::Instruction& inst, bool set) { void Translator::S_BITSET_B32(const Decoder::Instruction& inst, bool set) {
const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(31u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(31u)));
const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), offset); const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), offset);
const auto old = ReadU32(inst.dst); const auto old = ReadU32(inst.dst);
const auto result = set ? ir.BitwiseOr(old, bit) : ir.BitwiseAnd(old, ir.BitwiseNot(bit)); const auto result = set ? ir.BitwiseOr(old, bit) : ir.BitwiseAnd(old, ir.BitwiseNot(bit));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_BITSET_B64(const Decoder::Instruction& inst, bool set) { void Translator::S_BITSET_B64(const Decoder::Instruction& inst, bool set) {
const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u)));
const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u))); const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u)));
const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), word_bit); const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), word_bit);
@@ -347,16 +324,14 @@ bool Translator::S_BITSET_B64(const Decoder::Instruction& inst, bool set) {
{offset, IR::Value(32u)})); {offset, IR::Value(32u)}));
WriteU32Pair(inst.dst, WriteU32Pair(inst.dst,
{ir.Select(high, old[0], low_value), ir.Select(high, high_value, old[1])}); {ir.Select(high, old[0], low_value), ir.Select(high, high_value, old[1])});
return true;
} }
bool Translator::V_BCNT_U32_B32(const Decoder::Instruction& inst) { void Translator::V_BCNT_U32_B32(const Decoder::Instruction& inst) {
const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {ReadU32(inst.src0)})); const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {ReadU32(inst.src0)}));
WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1))); WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1)));
return true;
} }
bool Translator::V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low) { void Translator::V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low) {
const auto lane = IR::U32(ir.Emit(IR::ValueOpcode::LaneId)); const auto lane = IR::U32(ir.Emit(IR::ValueOpcode::LaneId));
const auto local = ir.BitwiseAnd(lane, IR::U32(IR::Value(31u))); const auto local = ir.BitwiseAnd(lane, IR::U32(IR::Value(31u)));
const auto below = const auto below =
@@ -368,10 +343,9 @@ bool Translator::V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low) {
const auto active = ir.BitwiseAnd(ReadU32(inst.src0), thread_mask); const auto active = ir.BitwiseAnd(ReadU32(inst.src0), thread_mask);
const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {active})); const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {active}));
WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1))); WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1)));
return true;
} }
bool Translator::S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst) { void Translator::S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst) {
const auto replicate = [&](IR::U32 value) { const auto replicate = [&](IR::U32 value) {
auto bits = ir.BitwiseOr(value, ir.ShiftLeftLogical(value, IR::U32(IR::Value(8u)))); auto bits = ir.BitwiseOr(value, ir.ShiftLeftLogical(value, IR::U32(IR::Value(8u))));
bits = ir.BitwiseAnd(bits, IR::U32(IR::Value(0x00ff00ffu))); bits = ir.BitwiseAnd(bits, IR::U32(IR::Value(0x00ff00ffu)));
@@ -387,10 +361,9 @@ bool Translator::S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst) {
const auto low = ir.BitwiseAnd(source, IR::U32(IR::Value(0xffffu))); const auto low = ir.BitwiseAnd(source, IR::U32(IR::Value(0xffffu)));
const auto high = ir.ShiftRightLogical(source, IR::U32(IR::Value(16u))); const auto high = ir.ShiftRightLogical(source, IR::U32(IR::Value(16u)));
WriteOperand(DestinationOperand(inst), ir.ConstructU64(replicate(low), replicate(high))); WriteOperand(DestinationOperand(inst), ir.ConstructU64(replicate(low), replicate(high)));
return true;
} }
bool Translator::S_QUADMASK_B64(const Decoder::Instruction& inst) { void Translator::S_QUADMASK_B64(const Decoder::Instruction& inst) {
const auto compact = [&](IR::U32 value) { const auto compact = [&](IR::U32 value) {
auto bits = ir.BitwiseOr(value, ir.ShiftRightLogical(value, IR::U32(IR::Value(1u)))); auto bits = ir.BitwiseOr(value, ir.ShiftRightLogical(value, IR::U32(IR::Value(1u))));
bits = ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(2u)))); bits = ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(2u))));
@@ -409,16 +382,14 @@ bool Translator::S_QUADMASK_B64(const Decoder::Instruction& inst) {
const auto result = ir.ConstructU64(quads, IR::U32(IR::Value(0u))); const auto result = ir.ConstructU64(quads, IR::U32(IR::Value(0u)));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}))); ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
return true;
} }
bool Translator::BFM_B32(const Decoder::Instruction& inst) { void Translator::BFM_B32(const Decoder::Instruction& inst) {
const auto count = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(31u))); const auto count = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(31u)));
const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u)));
const auto result = ir.Emit(IR::ValueOpcode::BitFieldInsert, const auto result = ir.Emit(IR::ValueOpcode::BitFieldInsert,
{IR::Value(0u), IR::Value(0xffffffffu), offset, count}); {IR::Value(0u), IR::Value(0xffffffffu), offset, count});
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
IR::U32 Translator::RightMask32(IR::U32 count) { IR::U32 Translator::RightMask32(IR::U32 count) {
@@ -435,15 +406,14 @@ IR::U64 Translator::RightMask64(IR::U32 count) {
return ir.ConstructU64(RightMask32(low_count), RightMask32(high_count)); return ir.ConstructU64(RightMask32(low_count), RightMask32(high_count));
} }
bool Translator::S_BFM_B64(const Decoder::Instruction& inst) { void Translator::S_BFM_B64(const Decoder::Instruction& inst) {
const auto count = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u))); const auto count = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u)));
const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(63u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(63u)));
const auto result = ir.Emit(IR::ValueOpcode::ShiftLeftLogical64, {RightMask64(count), offset}); const auto result = ir.Emit(IR::ValueOpcode::ShiftLeftLogical64, {RightMask64(count), offset});
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_BFE_U32(const Decoder::Instruction& inst, bool sign) { void Translator::S_BFE_U32(const Decoder::Instruction& inst, bool sign) {
const auto source = ReadU32(inst.src0); const auto source = ReadU32(inst.src0);
const auto field = ReadU32(inst.src1); const auto field = ReadU32(inst.src1);
const auto offset = const auto offset =
@@ -457,10 +427,9 @@ bool Translator::S_BFE_U32(const Decoder::Instruction& inst, bool sign) {
const auto result = IR::U32(ir.Emit(opcode, {source, offset, count})); const auto result = IR::U32(ir.Emit(opcode, {source, offset, count}));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u)))); ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u))));
return true;
} }
bool Translator::S_BFE_U64(const Decoder::Instruction& inst) { void Translator::S_BFE_U64(const Decoder::Instruction& inst) {
const auto source = ReadU64(inst.src0); const auto source = ReadU64(inst.src0);
const auto field = ReadU32(inst.src1); const auto field = ReadU32(inst.src1);
const auto offset = const auto offset =
@@ -473,10 +442,9 @@ bool Translator::S_BFE_U64(const Decoder::Instruction& inst) {
const auto result = ir.Emit(IR::ValueOpcode::BitwiseAnd64, {shifted, RightMask64(count)}); const auto result = ir.Emit(IR::ValueOpcode::BitwiseAnd64, {shifted, RightMask64(count)});
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}))); ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
return true;
} }
bool Translator::V_BFE_U32(const Decoder::Instruction& inst, bool sign) { void Translator::V_BFE_U32(const Decoder::Instruction& inst, bool sign) {
const auto source = ReadU32(inst.src0); const auto source = ReadU32(inst.src0);
const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u)));
const auto raw_count = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); const auto raw_count = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u)));
@@ -485,29 +453,26 @@ bool Translator::V_BFE_U32(const Decoder::Instruction& inst, bool sign) {
const auto opcode = const auto opcode =
sign ? IR::ValueOpcode::BitFieldSExtract : IR::ValueOpcode::BitFieldUExtract; sign ? IR::ValueOpcode::BitFieldSExtract : IR::ValueOpcode::BitFieldUExtract;
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {source, offset, count})); WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {source, offset, count}));
return true;
} }
bool Translator::V_BFI_B32(const Decoder::Instruction& inst) { void Translator::V_BFI_B32(const Decoder::Instruction& inst) {
const auto bits = ReadU32(inst.src0); const auto bits = ReadU32(inst.src0);
const auto insert = ReadU32(inst.src1); const auto insert = ReadU32(inst.src1);
const auto base = ReadU32(inst.src2); const auto base = ReadU32(inst.src2);
const auto result = const auto result =
ir.BitwiseOr(ir.BitwiseAnd(bits, insert), ir.BitwiseAnd(ir.BitwiseNot(bits), base)); ir.BitwiseOr(ir.BitwiseAnd(bits, insert), ir.BitwiseAnd(ir.BitwiseNot(bits), base));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::S_BITCMP_B32(const Decoder::Instruction& inst, bool expected) { void Translator::S_BITCMP_B32(const Decoder::Instruction& inst, bool expected) {
const auto value = ReadU32(inst.src0); const auto value = ReadU32(inst.src0);
const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u)));
const auto bit = const auto bit =
IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {value, offset, IR::Value(1u)})); IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {value, offset, IR::Value(1u)}));
WriteCompareResult(inst.dst, ir.IEqual(bit, IR::U32(IR::Value(expected ? 1u : 0u)))); WriteCompareResult(inst.dst, ir.IEqual(bit, IR::U32(IR::Value(expected ? 1u : 0u))));
return true;
} }
bool Translator::S_BITCMP_B64(const Decoder::Instruction& inst, bool expected) { void Translator::S_BITCMP_B64(const Decoder::Instruction& inst, bool expected) {
const auto value = ReadU32Pair(inst.src0); const auto value = ReadU32Pair(inst.src0);
const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(63u))); const auto offset = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(63u)));
const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u))); const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u)));
@@ -516,10 +481,9 @@ bool Translator::S_BITCMP_B64(const Decoder::Instruction& inst, bool expected) {
const auto bit = const auto bit =
IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {word, word_bit, IR::Value(1u)})); IR::U32(ir.Emit(IR::ValueOpcode::BitFieldUExtract, {word, word_bit, IR::Value(1u)}));
WriteCompareResult(inst.dst, ir.IEqual(bit, IR::U32(IR::Value(expected ? 1u : 0u)))); WriteCompareResult(inst.dst, ir.IEqual(bit, IR::U32(IR::Value(expected ? 1u : 0u))));
return true;
} }
bool Translator::V_ALIGNBIT_B32(const Decoder::Instruction& inst) { void Translator::V_ALIGNBIT_B32(const Decoder::Instruction& inst) {
const auto hi = ReadU32(inst.src0); const auto hi = ReadU32(inst.src0);
const auto lo = ReadU32(inst.src1); const auto lo = ReadU32(inst.src1);
const auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); const auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u)));
@@ -530,10 +494,9 @@ bool Translator::V_ALIGNBIT_B32(const Decoder::Instruction& inst) {
const auto hi_part = const auto hi_part =
ir.Select(ir.INotEqual(shift, IR::U32(IR::Value(0u))), hi_part_raw, IR::U32(IR::Value(0u))); ir.Select(ir.INotEqual(shift, IR::U32(IR::Value(0u))), hi_part_raw, IR::U32(IR::Value(0u)));
WriteOperand(DestinationOperand(inst), ir.BitwiseOr(lo_part, hi_part)); WriteOperand(DestinationOperand(inst), ir.BitwiseOr(lo_part, hi_part));
return true;
} }
bool Translator::V_ALIGNBYTE_B32(const Decoder::Instruction& inst) { void Translator::V_ALIGNBYTE_B32(const Decoder::Instruction& inst) {
const auto hi = ReadU32(inst.src0); const auto hi = ReadU32(inst.src0);
const auto lo = ReadU32(inst.src1); const auto lo = ReadU32(inst.src1);
const auto byte_offset = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); const auto byte_offset = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u)));
@@ -546,39 +509,34 @@ bool Translator::V_ALIGNBYTE_B32(const Decoder::Instruction& inst) {
IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {byte_offset, IR::Value(8u)})); IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {byte_offset, IR::Value(8u)}));
WriteOperand(DestinationOperand(inst), WriteOperand(DestinationOperand(inst),
ir.Select(in_range, ExtractU64(shifted)[0], IR::U32(IR::Value(0u)))); ir.Select(in_range, ExtractU64(shifted)[0], IR::U32(IR::Value(0u))));
return true;
} }
bool Translator::V_LSHL_ADD_U32(const Decoder::Instruction& inst) { void Translator::V_LSHL_ADD_U32(const Decoder::Instruction& inst) {
const auto shift = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto shift = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u)));
const auto result = ir.IAdd(ir.ShiftLeftLogical(ReadU32(inst.src0), shift), ReadU32(inst.src2)); const auto result = ir.IAdd(ir.ShiftLeftLogical(ReadU32(inst.src0), shift), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_ADD_LSHL_U32(const Decoder::Instruction& inst) { void Translator::V_ADD_LSHL_U32(const Decoder::Instruction& inst) {
const auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); const auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u)));
const auto result = ir.ShiftLeftLogical(ir.IAdd(ReadU32(inst.src0), ReadU32(inst.src1)), shift); const auto result = ir.ShiftLeftLogical(ir.IAdd(ReadU32(inst.src0), ReadU32(inst.src1)), shift);
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_XAD_U32(const Decoder::Instruction& inst) { void Translator::V_XAD_U32(const Decoder::Instruction& inst) {
const auto result = const auto result =
ir.IAdd(ir.BitwiseXor(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2)); ir.IAdd(ir.BitwiseXor(ReadU32(inst.src0), ReadU32(inst.src1)), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_LSHL_OR_B32(const Decoder::Instruction& inst) { void Translator::V_LSHL_OR_B32(const Decoder::Instruction& inst) {
const auto shift = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto shift = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u)));
const auto result = const auto result =
ir.BitwiseOr(ir.ShiftLeftLogical(ReadU32(inst.src0), shift), ReadU32(inst.src2)); ir.BitwiseOr(ir.ShiftLeftLogical(ReadU32(inst.src0), shift), ReadU32(inst.src2));
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::V_CNDMASK_B32(const Decoder::Instruction& inst) { void Translator::V_CNDMASK_B32(const Decoder::Instruction& inst) {
Decoder::Operand mask_operand; Decoder::Operand mask_operand;
mask_operand.kind = Decoder::OperandKind::VccLo; mask_operand.kind = Decoder::OperandKind::VccLo;
if (inst.src_count >= 3u) { if (inst.src_count >= 3u) {
@@ -594,17 +552,15 @@ bool Translator::V_CNDMASK_B32(const Decoder::Instruction& inst) {
result = ir.Select(condition, ReadU32(inst.src1), ReadU32(inst.src0)); result = ir.Select(condition, ReadU32(inst.src1), ReadU32(inst.src0));
} }
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
bool Translator::PackB16(const Decoder::Instruction& inst, bool high0, bool high1) { void Translator::PackB16(const Decoder::Instruction& inst, bool high0, bool high1) {
const auto lo = high0 ? ir.ShiftRightLogical(ReadU32(inst.src0), IR::U32(IR::Value(16u))) const auto lo = high0 ? ir.ShiftRightLogical(ReadU32(inst.src0), IR::U32(IR::Value(16u)))
: ReadU32(inst.src0); : ReadU32(inst.src0);
const auto hi = high1 ? ir.ShiftRightLogical(ReadU32(inst.src1), IR::U32(IR::Value(16u))) const auto hi = high1 ? ir.ShiftRightLogical(ReadU32(inst.src1), IR::U32(IR::Value(16u)))
: ReadU32(inst.src1); : ReadU32(inst.src1);
const auto result = PackU16Lanes(lo, hi); const auto result = PackU16Lanes(lo, hi);
WriteOperand(DestinationOperand(inst), result); WriteOperand(DestinationOperand(inst), result);
return true;
} }
} // namespace Libs::Graphics::ShaderRecompiler::Frontend } // namespace Libs::Graphics::ShaderRecompiler::Frontend
@@ -1,3 +1,4 @@
#include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h" #include "graphics/shader/recompiler/frontend/translate/Translator.h"
#include "graphics/shader/recompiler/frontend/decode/ImageOps.h" #include "graphics/shader/recompiler/frontend/decode/ImageOps.h"
@@ -404,7 +405,7 @@ IR::Value Translator::NarrowSubdword(IR::U32 value, uint32_t bits) {
: ir.Emit(IR::ValueOpcode::ConvertU16U32, {value}); : ir.Emit(IR::ValueOpcode::ConvertU16U32, {value});
} }
bool Translator::S_LOAD(const Decoder::Instruction& inst, bool raw) { void Translator::S_LOAD(const Decoder::Instruction& inst, bool raw) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = const auto resource =
raw ? GetScalarAddressResource(RawScalarLoadBase(inst.src0)) : GetBufferResource(memory); raw ? GetScalarAddressResource(RawScalarLoadBase(inst.src0)) : GetBufferResource(memory);
@@ -427,10 +428,9 @@ bool Translator::S_LOAD(const Decoder::Instruction& inst, bool raw) {
for (uint32_t component = 0; component < memory.data_dwords; component++) { for (uint32_t component = 0; component < memory.data_dwords; component++) {
WriteOperand(ScalarDestinationOperand(inst.dst, component), loaded[component]); WriteOperand(ScalarDestinationOperand(inst.dst, component), loaded[component]);
} }
return true;
} }
bool Translator::BUFFER_LOAD(const Decoder::Instruction& inst) { void Translator::BUFFER_LOAD(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
IR::ValueOpcode opcode; IR::ValueOpcode opcode;
const auto bits = memory.data_bits; const auto bits = memory.data_bits;
@@ -444,10 +444,15 @@ bool Translator::BUFFER_LOAD(const Decoder::Instruction& inst) {
case 2u: opcode = IR::ValueOpcode::LoadBufferU32x2; break; case 2u: opcode = IR::ValueOpcode::LoadBufferU32x2; break;
case 3u: opcode = IR::ValueOpcode::LoadBufferU32x3; break; case 3u: opcode = IR::ValueOpcode::LoadBufferU32x3; break;
case 4u: opcode = IR::ValueOpcode::LoadBufferU32x4; break; case 4u: opcode = IR::ValueOpcode::LoadBufferU32x4; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported buffer load dword count %u",
Decoder::InstructionToString(inst).c_str(), inst.pc,
memory.data_dwords);
} }
break; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported buffer load width %u",
Decoder::InstructionToString(inst).c_str(), inst.pc, bits);
} }
const auto resource = GetBufferResource(memory); const auto resource = GetBufferResource(memory);
const auto address = ReadBufferAddress(inst, 0); const auto address = ReadBufferAddress(inst, 0);
@@ -464,10 +469,9 @@ bool Translator::BUFFER_LOAD(const Decoder::Instruction& inst) {
ir.CompositeExtract(loaded, component)); ir.CompositeExtract(loaded, component));
} }
} }
return true;
} }
bool Translator::BUFFER_STORE(const Decoder::Instruction& inst) { void Translator::BUFFER_STORE(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetBufferResource(memory); const auto resource = GetBufferResource(memory);
const auto address = ReadBufferAddress(inst, 1); const auto address = ReadBufferAddress(inst, 1);
@@ -508,17 +512,21 @@ bool Translator::BUFFER_STORE(const Decoder::Instruction& inst) {
ReadU32(OffsetOperand(data_src, 2u)), ReadU32(OffsetOperand(data_src, 2u)),
ReadU32(OffsetOperand(data_src, 3u))}); ReadU32(OffsetOperand(data_src, 3u))});
break; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported buffer store dword count %u",
Decoder::InstructionToString(inst).c_str(), inst.pc,
memory.data_dwords);
} }
break; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported buffer store width %u",
Decoder::InstructionToString(inst).c_str(), inst.pc, memory.data_bits);
} }
ir.Emit(opcode, {resource, address.index, address.offset, address.soffset, value, ir.GetExec()}, ir.Emit(opcode, {resource, address.index, address.offset, address.soffset, value, ir.GetExec()},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
return true;
} }
bool Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetBufferResource(memory); const auto resource = GetBufferResource(memory);
const auto address = ReadBufferAddress(inst, 1); const auto address = ReadBufferAddress(inst, 1);
@@ -543,10 +551,9 @@ bool Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
if (inst.glc) { if (inst.glc) {
WriteOperand(inst.dst, result); WriteOperand(inst.dst, result);
} }
return true;
} }
bool Translator::IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 1)); const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 1));
@@ -556,10 +563,9 @@ bool Translator::IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
if (inst.glc) { if (inst.glc) {
WriteOperand(inst.dst, result); WriteOperand(inst.dst, result);
} }
return true;
} }
bool Translator::DS_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::DS_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool returns_value) { bool returns_value) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto address = ReadU32(MemorySourceAt(inst, 1)); const auto address = ReadU32(MemorySourceAt(inst, 1));
@@ -568,10 +574,9 @@ bool Translator::DS_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opc
if (returns_value) { if (returns_value) {
WriteOperand(inst.dst, result); WriteOperand(inst.dst, result);
} }
return true;
} }
bool Translator::FLAT_LOAD(const Decoder::Instruction& inst) { void Translator::FLAT_LOAD(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
IR::ValueOpcode opcode; IR::ValueOpcode opcode;
const auto bits = memory.data_bits; const auto bits = memory.data_bits;
@@ -580,7 +585,9 @@ bool Translator::FLAT_LOAD(const Decoder::Instruction& inst) {
case 8u: opcode = IR::ValueOpcode::LoadAddressU8; break; case 8u: opcode = IR::ValueOpcode::LoadAddressU8; break;
case 16u: opcode = IR::ValueOpcode::LoadAddressU16; break; case 16u: opcode = IR::ValueOpcode::LoadAddressU16; break;
case 32u: opcode = IR::ValueOpcode::LoadAddressU32; break; case 32u: opcode = IR::ValueOpcode::LoadAddressU32; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported flat load width %u",
Decoder::InstructionToString(inst).c_str(), inst.pc, bits);
} }
const auto address = ReadAddressOperands(inst, 0); const auto address = ReadAddressOperands(inst, 0);
const auto active = ir.GetExec(); const auto active = ir.GetExec();
@@ -595,10 +602,9 @@ bool Translator::FLAT_LOAD(const Decoder::Instruction& inst) {
WriteOperand(OffsetOperand(inst.dst, index), WriteOperand(OffsetOperand(inst.dst, index),
bits == 32u ? loaded : WidenSubdword(loaded, bits, sign)); bits == 32u ? loaded : WidenSubdword(loaded, bits, sign));
} }
return true;
} }
bool Translator::FLAT_STORE(const Decoder::Instruction& inst) { void Translator::FLAT_STORE(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto data_op = MemorySourceAt(inst, 0); const auto data_op = MemorySourceAt(inst, 0);
const auto address = ReadAddressOperands(inst, 1); const auto address = ReadAddressOperands(inst, 1);
@@ -607,7 +613,9 @@ bool Translator::FLAT_STORE(const Decoder::Instruction& inst) {
case 8u: opcode = IR::ValueOpcode::StoreAddressU8; break; case 8u: opcode = IR::ValueOpcode::StoreAddressU8; break;
case 16u: opcode = IR::ValueOpcode::StoreAddressU16; break; case 16u: opcode = IR::ValueOpcode::StoreAddressU16; break;
case 32u: opcode = IR::ValueOpcode::StoreAddressU32; break; case 32u: opcode = IR::ValueOpcode::StoreAddressU32; break;
default: return false; default:
EXIT("opcode %s at pc 0x%08x has unsupported flat store width %u",
Decoder::InstructionToString(inst).c_str(), inst.pc, memory.data_bits);
} }
const auto count = memory.data_bits == 32u ? memory.data_dwords : 1u; const auto count = memory.data_bits == 32u ? memory.data_dwords : 1u;
for (uint32_t index = 0; index < count; index++) { for (uint32_t index = 0; index < count; index++) {
@@ -622,20 +630,18 @@ bool Translator::FLAT_STORE(const Decoder::Instruction& inst) {
ir.Emit(opcode, {address.resource, address.low, address.high, value, ir.GetExec()}, ir.Emit(opcode, {address.resource, address.low, address.high, value, ir.GetExec()},
AddMemoryInfo(component, inst.pc)); AddMemoryInfo(component, inst.pc));
} }
return true;
} }
bool Translator::IMAGE_GET_RESINFO(const Decoder::Instruction& inst) { void Translator::IMAGE_GET_RESINFO(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 0)); const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 0));
const auto result = ir.Emit(IR::ValueOpcode::ImageQueryDimensions, {resource, address}, const auto result = ir.Emit(IR::ValueOpcode::ImageQueryDimensions, {resource, address},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
WriteImageComponents(inst.dst, result, memory, 4u); WriteImageComponents(inst.dst, result, memory, 4u);
return true;
} }
bool Translator::IMAGE_GET_LOD(const Decoder::Instruction& inst) { void Translator::IMAGE_GET_LOD(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto sampler = GetSamplerResource(memory); const auto sampler = GetSamplerResource(memory);
@@ -643,30 +649,27 @@ bool Translator::IMAGE_GET_LOD(const Decoder::Instruction& inst) {
const auto result = ir.Emit(IR::ValueOpcode::ImageQueryLod, {resource, sampler, address}, const auto result = ir.Emit(IR::ValueOpcode::ImageQueryLod, {resource, sampler, address},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
WriteImageComponents(inst.dst, result, memory, 2u); WriteImageComponents(inst.dst, result, memory, 2u);
return true;
} }
bool Translator::IMAGE_LOAD(const Decoder::Instruction& inst) { void Translator::IMAGE_LOAD(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 0)); const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 0));
const auto result = ir.Emit(IR::ValueOpcode::ImageRead, {resource, address, ir.GetExec()}, const auto result = ir.Emit(IR::ValueOpcode::ImageRead, {resource, address, ir.GetExec()},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
WriteImageComponents(inst.dst, result, memory, 4u); WriteImageComponents(inst.dst, result, memory, 4u);
return true;
} }
bool Translator::IMAGE_STORE(const Decoder::Instruction& inst) { void Translator::IMAGE_STORE(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 1)); const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 1));
const auto data = ConstructU32x4(MemorySourceAt(inst, 0), memory.data_dwords); const auto data = ConstructU32x4(MemorySourceAt(inst, 0), memory.data_dwords);
ir.Emit(IR::ValueOpcode::ImageWrite, {resource, address, data, ir.GetExec()}, ir.Emit(IR::ValueOpcode::ImageWrite, {resource, address, data, ir.GetExec()},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
return true;
} }
bool Translator::IMAGE_SAMPLE(const Decoder::Instruction& inst) { void Translator::IMAGE_SAMPLE(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto sampler = GetSamplerResource(memory); const auto sampler = GetSamplerResource(memory);
@@ -683,10 +686,9 @@ bool Translator::IMAGE_SAMPLE(const Decoder::Instruction& inst) {
} else { } else {
WriteImageComponents(inst.dst, result, memory, 4u); WriteImageComponents(inst.dst, result, memory, 4u);
} }
return true;
} }
bool Translator::IMAGE_GATHER(const Decoder::Instruction& inst) { void Translator::IMAGE_GATHER(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto resource = GetImageResource(memory); const auto resource = GetImageResource(memory);
const auto sampler = GetSamplerResource(memory); const auto sampler = GetSamplerResource(memory);
@@ -697,7 +699,6 @@ bool Translator::IMAGE_GATHER(const Decoder::Instruction& inst) {
WriteOperand(OffsetOperand(inst.dst, index), WriteOperand(OffsetOperand(inst.dst, index),
ir.Emit(IR::ValueOpcode::CompositeExtractU32x4, {result, IR::Value(index)})); ir.Emit(IR::ValueOpcode::CompositeExtractU32x4, {result, IR::Value(index)}));
} }
return true;
} }
IR::Value Translator::LoadSharedU32(uint32_t width, IR::U32 address, const IR::MemoryInfo& memory, IR::Value Translator::LoadSharedU32(uint32_t width, IR::U32 address, const IR::MemoryInfo& memory,
@@ -753,7 +754,7 @@ void Translator::WriteSharedU32(uint32_t width, IR::U32 address,
} }
} }
bool Translator::DS_READ(const Decoder::Instruction& inst) { void Translator::DS_READ(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto address = ReadU32(MemorySourceAt(inst, 0)); const auto address = ReadU32(MemorySourceAt(inst, 0));
if (memory.data_bits == 32u) { if (memory.data_bits == 32u) {
@@ -762,16 +763,15 @@ bool Translator::DS_READ(const Decoder::Instruction& inst) {
for (uint32_t index = 0; index < width; index++) { for (uint32_t index = 0; index < width; index++) {
WriteOperand(OffsetOperand(inst.dst, index), ExtractSharedU32(loaded, width, index)); WriteOperand(OffsetOperand(inst.dst, index), ExtractSharedU32(loaded, width, index));
} }
return true; return;
} }
const auto opcode = const auto opcode =
memory.data_bits == 8u ? IR::ValueOpcode::LoadSharedU8 : IR::ValueOpcode::LoadSharedU16; memory.data_bits == 8u ? IR::ValueOpcode::LoadSharedU8 : IR::ValueOpcode::LoadSharedU16;
const auto loaded = ir.Emit(opcode, {address, ir.GetExec()}, AddMemoryInfo(memory, inst.pc)); const auto loaded = ir.Emit(opcode, {address, ir.GetExec()}, AddMemoryInfo(memory, inst.pc));
WriteOperand(inst.dst, WidenSubdword(loaded, memory.data_bits, memory.data_signed)); WriteOperand(inst.dst, WidenSubdword(loaded, memory.data_bits, memory.data_signed));
return true;
} }
bool Translator::DS_READ2(const Decoder::Instruction& inst) { void Translator::DS_READ2(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto width = memory.data_dwords / 2u; const auto width = memory.data_dwords / 2u;
const auto address = ReadU32(MemorySourceAt(inst, 0)); const auto address = ReadU32(MemorySourceAt(inst, 0));
@@ -790,10 +790,9 @@ bool Translator::DS_READ2(const Decoder::Instruction& inst) {
WriteOperand(OffsetOperand(inst.dst, width + index), WriteOperand(OffsetOperand(inst.dst, width + index),
ExtractSharedU32(second_value, width, index)); ExtractSharedU32(second_value, width, index));
} }
return true;
} }
bool Translator::DS_WRITE(const Decoder::Instruction& inst) { void Translator::DS_WRITE(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto width = memory.data_dwords; const auto width = memory.data_dwords;
const auto data_operand = MemorySourceAt(inst, 0); const auto data_operand = MemorySourceAt(inst, 0);
@@ -804,16 +803,15 @@ bool Translator::DS_WRITE(const Decoder::Instruction& inst) {
const auto address = ReadU32(MemorySourceAt(inst, 1)); const auto address = ReadU32(MemorySourceAt(inst, 1));
if (memory.data_bits == 32u) { if (memory.data_bits == 32u) {
WriteSharedU32(width, address, values, memory, inst.pc); WriteSharedU32(width, address, values, memory, inst.pc);
return true; return;
} }
const auto opcode = const auto opcode =
memory.data_bits == 8u ? IR::ValueOpcode::WriteSharedU8 : IR::ValueOpcode::WriteSharedU16; memory.data_bits == 8u ? IR::ValueOpcode::WriteSharedU8 : IR::ValueOpcode::WriteSharedU16;
ir.Emit(opcode, {address, NarrowSubdword(IR::U32(values[0]), memory.data_bits), ir.GetExec()}, ir.Emit(opcode, {address, NarrowSubdword(IR::U32(values[0]), memory.data_bits), ir.GetExec()},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
return true;
} }
bool Translator::DS_WRITE2(const Decoder::Instruction& inst) { void Translator::DS_WRITE2(const Decoder::Instruction& inst) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto width = memory.data_dwords / 2u; const auto width = memory.data_dwords / 2u;
const auto address = ReadU32(MemorySourceAt(inst, 1)); const auto address = ReadU32(MemorySourceAt(inst, 1));
@@ -834,28 +832,25 @@ bool Translator::DS_WRITE2(const Decoder::Instruction& inst) {
second.offset = memory.secondary_offset; second.offset = memory.secondary_offset;
WriteSharedU32(width, address, second_values, second, inst.pc); WriteSharedU32(width, address, second_values, second, inst.pc);
} }
return true;
} }
bool Translator::DS_MINMAX_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::DS_MINMAX_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
ir.Emit(opcode, ir.Emit(opcode,
{ReadU32(MemorySourceAt(inst, 1)), ReadU32(MemorySourceAt(inst, 0)), {ReadU32(MemorySourceAt(inst, 1)), ReadU32(MemorySourceAt(inst, 0)),
ReadU32(MemorySourceAt(inst, 2)), ir.GetExec()}, ReadU32(MemorySourceAt(inst, 2)), ir.GetExec()},
AddMemoryInfo(memory, inst.pc)); AddMemoryInfo(memory, inst.pc));
return true;
} }
bool Translator::DS_APPEND_CONSUME(const Decoder::Instruction& inst, IR::ValueOpcode opcode) { void Translator::DS_APPEND_CONSUME(const Decoder::Instruction& inst, IR::ValueOpcode opcode) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
WriteOperand(inst.dst, ir.Emit(opcode, WriteOperand(inst.dst, ir.Emit(opcode,
{ReadU32(MemorySourceAt(inst, 0)), ir.GetExec(), ir.GetExecLo(), {ReadU32(MemorySourceAt(inst, 0)), ir.GetExec(), ir.GetExecLo(),
ir.GetExecHi()}, ir.GetExecHi()},
AddMemoryInfo(memory, inst.pc))); AddMemoryInfo(memory, inst.pc)));
return true;
} }
bool Translator::DS_ADDTID(const Decoder::Instruction& inst, bool write) { void Translator::DS_ADDTID(const Decoder::Instruction& inst, bool write) {
const auto memory = MemoryInfoFromDecoded(inst); const auto memory = MemoryInfoFromDecoded(inst);
const auto base = const auto base =
ir.BitwiseAnd(ReadU32(MemorySourceAt(inst, write ? 1u : 0u)), IR::U32(IR::Value(0xffffu))); ir.BitwiseAnd(ReadU32(MemorySourceAt(inst, write ? 1u : 0u)), IR::U32(IR::Value(0xffffu)));
@@ -869,24 +864,21 @@ bool Translator::DS_ADDTID(const Decoder::Instruction& inst, bool write) {
WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::LoadSharedU32, {address, ir.GetExec()}, WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::LoadSharedU32, {address, ir.GetExec()},
AddMemoryInfo(memory, inst.pc))); AddMemoryInfo(memory, inst.pc)));
} }
return true;
} }
bool Translator::DS_SWIZZLE_B32(const Decoder::Instruction& inst) { void Translator::DS_SWIZZLE_B32(const Decoder::Instruction& inst) {
WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::SwizzleU32, WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::SwizzleU32,
{ReadU32(MemorySourceAt(inst, 0)), {ReadU32(MemorySourceAt(inst, 0)),
ReadU32(MemorySourceAt(inst, 1)), ir.GetExec()})); ReadU32(MemorySourceAt(inst, 1)), ir.GetExec()}));
return true;
} }
bool Translator::DS_BPERMUTE_B32(const Decoder::Instruction& inst) { void Translator::DS_BPERMUTE_B32(const Decoder::Instruction& inst) {
const auto address = ir.IAdd(ReadU32(inst.src0), IR::U32(IR::Value(inst.offset))); const auto address = ir.IAdd(ReadU32(inst.src0), IR::U32(IR::Value(inst.offset)));
WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::BpermuteU32, WriteOperand(inst.dst, ir.Emit(IR::ValueOpcode::BpermuteU32,
{ReadU32(inst.src1), address, ir.GetExec()})); {ReadU32(inst.src1), address, ir.GetExec()}));
return true;
} }
bool Translator::EmitMemory(const Decoder::Instruction& inst) { void Translator::EmitMemory(const Decoder::Instruction& inst) {
switch (inst.opcode) { switch (inst.opcode) {
case Decoder::Opcode::S_LOAD_DWORD: case Decoder::Opcode::S_LOAD_DWORD:
case Decoder::Opcode::S_LOAD_DWORDX2: case Decoder::Opcode::S_LOAD_DWORDX2:
@@ -907,7 +899,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst) {
for (uint32_t component = 0; component < 2; component++) { for (uint32_t component = 0; component < 2; component++) {
WriteOperand(ScalarDestinationOperand(inst.dst, component), IR::Value(UINT32_MAX)); WriteOperand(ScalarDestinationOperand(inst.dst, component), IR::Value(UINT32_MAX));
} }
return true; return;
} }
case Decoder::Opcode::BUFFER_LOAD_UBYTE: case Decoder::Opcode::BUFFER_LOAD_UBYTE:
@@ -1105,7 +1097,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst) {
case Decoder::Opcode::DS_WRITE_B64: case Decoder::Opcode::DS_WRITE_B64:
case Decoder::Opcode::DS_WRITE_B96: case Decoder::Opcode::DS_WRITE_B96:
case Decoder::Opcode::DS_WRITE_B128: return DS_WRITE(inst); case Decoder::Opcode::DS_WRITE_B128: return DS_WRITE(inst);
default: return false; default: return FailMissingTranslation(inst);
} }
} }
@@ -2,106 +2,106 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend { namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::EmitScalar(const Decoder::Instruction& inst) { void Translator::EmitScalar(const Decoder::Instruction& inst) {
using O = Decoder::Opcode; using O = Decoder::Opcode;
switch (inst.opcode) { switch (inst.opcode) {
case O::S_MOV_B32: case O::S_MOV_B32:
case O::S_MOVK_I32: MOV_B32(inst, false); return true; case O::S_MOVK_I32: MOV_B32(inst, false); return;
case O::S_MOV_B64: S_MOV_B64(inst); return true; case O::S_MOV_B64: S_MOV_B64(inst); return;
case O::S_WQM_B32: S_WQM(inst, false); return true; case O::S_WQM_B32: S_WQM(inst, false); return;
case O::S_WQM_B64: S_WQM(inst, true); return true; case O::S_WQM_B64: S_WQM(inst, true); return;
case O::S_GETPC_B64: S_GETPC_B64(inst); return true; case O::S_GETPC_B64: S_GETPC_B64(inst); return;
case O::S_SETPC_B64: return true; case O::S_SETPC_B64: return;
case O::S_SUBVECTOR_LOOP_BEGIN: S_SUBVECTOR_LOOP(inst, true); return true; case O::S_SUBVECTOR_LOOP_BEGIN: S_SUBVECTOR_LOOP(inst, true); return;
case O::S_SUBVECTOR_LOOP_END: S_SUBVECTOR_LOOP(inst, false); return true; case O::S_SUBVECTOR_LOOP_END: S_SUBVECTOR_LOOP(inst, false); return;
case O::S_CSELECT_B32: S_CSELECT_B32(inst); return true; case O::S_CSELECT_B32: S_CSELECT_B32(inst); return;
case O::S_CSELECT_B64: ScalarSelect64(inst, inst.src1); return true; case O::S_CSELECT_B64: ScalarSelect64(inst, inst.src1); return;
case O::S_CMOV_B64: ScalarSelect64(inst, inst.dst); return true; case O::S_CMOV_B64: ScalarSelect64(inst, inst.dst); return;
case O::S_SETREG_B32: EmitControlNop(); return true; case O::S_SETREG_B32: EmitControlNop(); return;
case O::S_WAITCNT: EmitWaitcnt(); return true; case O::S_WAITCNT: EmitWaitcnt(); return;
case O::S_AND_SAVEEXEC_B32: case O::S_AND_SAVEEXEC_B32:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, false, false); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, false, false);
return true; return;
case O::S_ANDN1_SAVEEXEC_B32: case O::S_ANDN1_SAVEEXEC_B32:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, true, false); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, true, false);
return true; return;
case O::S_ORN2_SAVEEXEC_B32: case O::S_ORN2_SAVEEXEC_B32:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalOr, true, false, false); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalOr, true, false, false);
return true; return;
case O::S_AND_SAVEEXEC_B64: case O::S_AND_SAVEEXEC_B64:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, false, true); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, false, true);
return true; return;
case O::S_ANDN1_SAVEEXEC_B64: case O::S_ANDN1_SAVEEXEC_B64:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, true, true); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalAnd, false, true, true);
return true; return;
case O::S_ORN2_SAVEEXEC_B64: case O::S_ORN2_SAVEEXEC_B64:
S_SAVEEXEC(inst, IR::ValueOpcode::LogicalOr, true, false, true); S_SAVEEXEC(inst, IR::ValueOpcode::LogicalOr, true, false, true);
return true; return;
case O::S_ADD_U32: ADD_U32(inst, false, false); return true; case O::S_ADD_U32: ADD_U32(inst, false, false); return;
case O::S_ADDC_U32: ADD_U32(inst, false, true); return true; case O::S_ADDC_U32: ADD_U32(inst, false, true); return;
case O::S_SUB_U32: SUB_U32(inst, false, false); return true; case O::S_SUB_U32: SUB_U32(inst, false, false); return;
case O::S_SUBB_U32: SUBB_U32(inst, false, false); return true; case O::S_SUBB_U32: SUBB_U32(inst, false, false); return;
case O::S_ABSDIFF_I32: S_ABSDIFF_I32(inst); return true; case O::S_ABSDIFF_I32: S_ABSDIFF_I32(inst); return;
case O::S_ADD_I32: S_ADD_SUB_I32(inst, false); return true; case O::S_ADD_I32: S_ADD_SUB_I32(inst, false); return;
case O::S_SUB_I32: S_ADD_SUB_I32(inst, true); return true; case O::S_SUB_I32: S_ADD_SUB_I32(inst, true); return;
case O::S_LSHL1_ADD_U32: S_LSHL_ADD_U32(inst, 1u); return true; case O::S_LSHL1_ADD_U32: S_LSHL_ADD_U32(inst, 1u); return;
case O::S_LSHL2_ADD_U32: S_LSHL_ADD_U32(inst, 2u); return true; case O::S_LSHL2_ADD_U32: S_LSHL_ADD_U32(inst, 2u); return;
case O::S_LSHL3_ADD_U32: S_LSHL_ADD_U32(inst, 3u); return true; case O::S_LSHL3_ADD_U32: S_LSHL_ADD_U32(inst, 3u); return;
case O::S_LSHL4_ADD_U32: S_LSHL_ADD_U32(inst, 4u); return true; case O::S_LSHL4_ADD_U32: S_LSHL_ADD_U32(inst, 4u); return;
case O::S_MIN_I32: case O::S_MIN_I32:
ScalarMinMax32(inst, IR::ValueOpcode::SMin32, IR::ValueOpcode::SLessThan32); ScalarMinMax32(inst, IR::ValueOpcode::SMin32, IR::ValueOpcode::SLessThan32);
return true; return;
case O::S_MAX_I32: case O::S_MAX_I32:
ScalarMinMax32(inst, IR::ValueOpcode::SMax32, IR::ValueOpcode::SGreaterThan32); ScalarMinMax32(inst, IR::ValueOpcode::SMax32, IR::ValueOpcode::SGreaterThan32);
return true; return;
case O::S_MIN_U32: case O::S_MIN_U32:
ScalarMinMax32(inst, IR::ValueOpcode::UMin32, IR::ValueOpcode::ULessThan32); ScalarMinMax32(inst, IR::ValueOpcode::UMin32, IR::ValueOpcode::ULessThan32);
return true; return;
case O::S_MAX_U32: case O::S_MAX_U32:
ScalarMinMax32(inst, IR::ValueOpcode::UMax32, IR::ValueOpcode::UGreaterThan32); ScalarMinMax32(inst, IR::ValueOpcode::UMax32, IR::ValueOpcode::UGreaterThan32);
return true; return;
case O::S_CMP_EQ_U32: case O::S_CMP_EQ_U32:
case O::S_CMP_EQ_I32: case O::S_CMP_EQ_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_LG_U32: case O::S_CMP_LG_U32:
case O::S_CMP_LG_I32: case O::S_CMP_LG_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_GT_U32: case O::S_CMP_GT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_GE_U32: case O::S_CMP_GE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, true, EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, true,
false); false);
return true; return;
case O::S_CMP_LT_U32: case O::S_CMP_LT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_LE_U32: case O::S_CMP_LE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_GT_I32: case O::S_CMP_GT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_GE_I32: case O::S_CMP_GE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, true, EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, true,
false); false);
return true; return;
case O::S_CMP_LT_I32: case O::S_CMP_LT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_LE_I32: case O::S_CMP_LE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, true, false);
return true; return;
case O::S_CMP_EQ_U64: case O::S_CMP_EQ_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, true, false);
return true; return;
case O::S_CMP_LG_U64: case O::S_CMP_LG_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, true, false); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, true, false);
return true; return;
case O::S_AND_B64: case O::S_AND_B64:
return S_U64_MASK(inst, IR::ValueOpcode::LogicalAnd, IR::ValueOpcode::BitwiseAnd32, return S_U64_MASK(inst, IR::ValueOpcode::LogicalAnd, IR::ValueOpcode::BitwiseAnd32,
@@ -217,12 +217,12 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
case O::S_NOP: case O::S_NOP:
case O::S_SLEEP: case O::S_SLEEP:
case O::S_SETPRIO: case O::S_SETPRIO:
case O::S_TRAP: EmitControlNop(); return true; case O::S_TRAP: EmitControlNop(); return;
case O::S_WAITCNT_DEPCTR: EmitWaitcnt(); return true; case O::S_WAITCNT_DEPCTR: EmitWaitcnt(); return;
case O::S_BARRIER: S_BARRIER(); return true; case O::S_BARRIER: S_BARRIER(); return;
case O::S_SENDMSG: S_SENDMSG(inst); return true; case O::S_SENDMSG: S_SENDMSG(inst); return;
case O::S_TTRACEDATA: S_TTRACEDATA(); return true; case O::S_TTRACEDATA: S_TTRACEDATA(); return;
case O::S_INST_PREFETCH: S_INST_PREFETCH(); return true; case O::S_INST_PREFETCH: S_INST_PREFETCH(); return;
case O::S_BRANCH: case O::S_BRANCH:
case O::S_CBRANCH_SCC0: case O::S_CBRANCH_SCC0:
case O::S_CBRANCH_SCC1: case O::S_CBRANCH_SCC1:
@@ -231,8 +231,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
case O::S_CBRANCH_EXECZ: case O::S_CBRANCH_EXECZ:
case O::S_CBRANCH_EXECNZ: case O::S_CBRANCH_EXECNZ:
case O::S_CBRANCH_CDBGSYS: case O::S_CBRANCH_CDBGSYS:
case O::S_ENDPGM: return true; case O::S_ENDPGM: return;
default: return false; default: return FailMissingTranslation(inst);
} }
} }
@@ -80,34 +80,34 @@ private:
BufferAddress ReadBufferAddress(const Decoder::Instruction& inst, uint32_t source_offset); BufferAddress ReadBufferAddress(const Decoder::Instruction& inst, uint32_t source_offset);
IR::U32 WidenSubdword(IR::Value value, uint32_t bits, bool sign); IR::U32 WidenSubdword(IR::Value value, uint32_t bits, bool sign);
IR::Value NarrowSubdword(IR::U32 value, uint32_t bits); IR::Value NarrowSubdword(IR::U32 value, uint32_t bits);
bool S_LOAD(const Decoder::Instruction& inst, bool raw); void S_LOAD(const Decoder::Instruction& inst, bool raw);
bool BUFFER_LOAD(const Decoder::Instruction& inst); void BUFFER_LOAD(const Decoder::Instruction& inst);
bool BUFFER_STORE(const Decoder::Instruction& inst); void BUFFER_STORE(const Decoder::Instruction& inst);
bool BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool DS_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool returns_value); void DS_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool returns_value);
bool FLAT_LOAD(const Decoder::Instruction& inst); void FLAT_LOAD(const Decoder::Instruction& inst);
bool FLAT_STORE(const Decoder::Instruction& inst); void FLAT_STORE(const Decoder::Instruction& inst);
bool IMAGE_GET_RESINFO(const Decoder::Instruction& inst); void IMAGE_GET_RESINFO(const Decoder::Instruction& inst);
bool IMAGE_GET_LOD(const Decoder::Instruction& inst); void IMAGE_GET_LOD(const Decoder::Instruction& inst);
bool IMAGE_LOAD(const Decoder::Instruction& inst); void IMAGE_LOAD(const Decoder::Instruction& inst);
bool IMAGE_STORE(const Decoder::Instruction& inst); void IMAGE_STORE(const Decoder::Instruction& inst);
bool IMAGE_SAMPLE(const Decoder::Instruction& inst); void IMAGE_SAMPLE(const Decoder::Instruction& inst);
bool IMAGE_GATHER(const Decoder::Instruction& inst); void IMAGE_GATHER(const Decoder::Instruction& inst);
IR::Value LoadSharedU32(uint32_t width, IR::U32 address, const IR::MemoryInfo& memory, IR::Value LoadSharedU32(uint32_t width, IR::U32 address, const IR::MemoryInfo& memory,
uint32_t pc); uint32_t pc);
IR::Value ExtractSharedU32(IR::Value value, uint32_t width, uint32_t index); IR::Value ExtractSharedU32(IR::Value value, uint32_t width, uint32_t index);
void WriteSharedU32(uint32_t width, IR::U32 address, const std::array<IR::Value, 4>& values, void WriteSharedU32(uint32_t width, IR::U32 address, const std::array<IR::Value, 4>& values,
const IR::MemoryInfo& memory, uint32_t pc); const IR::MemoryInfo& memory, uint32_t pc);
bool DS_READ(const Decoder::Instruction& inst); void DS_READ(const Decoder::Instruction& inst);
bool DS_READ2(const Decoder::Instruction& inst); void DS_READ2(const Decoder::Instruction& inst);
bool DS_WRITE(const Decoder::Instruction& inst); void DS_WRITE(const Decoder::Instruction& inst);
bool DS_WRITE2(const Decoder::Instruction& inst); void DS_WRITE2(const Decoder::Instruction& inst);
bool DS_MINMAX_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void DS_MINMAX_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool DS_APPEND_CONSUME(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void DS_APPEND_CONSUME(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool DS_ADDTID(const Decoder::Instruction& inst, bool write); void DS_ADDTID(const Decoder::Instruction& inst, bool write);
bool DS_SWIZZLE_B32(const Decoder::Instruction& inst); void DS_SWIZZLE_B32(const Decoder::Instruction& inst);
bool DS_BPERMUTE_B32(const Decoder::Instruction& inst); void DS_BPERMUTE_B32(const Decoder::Instruction& inst);
IR::F32 SelectF32(IR::U1 condition, IR::F32 true_value, IR::F32 false_value); IR::F32 SelectF32(IR::U1 condition, IR::F32 true_value, IR::F32 false_value);
IR::U32 ConvertF32ToU32Saturated(IR::F32 value, float upper_bound, float safe_upper, IR::U32 ConvertF32ToU32Saturated(IR::F32 value, float upper_bound, float safe_upper,
@@ -143,77 +143,77 @@ private:
void V_CVT_PKNORM_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void V_CVT_PKNORM_F32(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
void V_CVT_PK_U8_F32(const Decoder::Instruction& inst); void V_CVT_PK_U8_F32(const Decoder::Instruction& inst);
void V_PACK_B32_F16(const Decoder::Instruction& inst); void V_PACK_B32_F16(const Decoder::Instruction& inst);
bool PackedFloat16(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator, void PackedFloat16(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator,
bool quiet_snan); bool quiet_snan);
bool Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool invalid_negative); bool invalid_negative);
bool Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool Float16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool reverse); void Float16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool reverse);
bool Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator, void Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator,
bool mix); bool mix);
bool FloatUnary(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void FloatUnary(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool reverse); void FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool reverse);
bool FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator, void FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool accumulator,
bool mix); bool mix);
bool V_FREXP_MANT_F32(const Decoder::Instruction& inst); void V_FREXP_MANT_F32(const Decoder::Instruction& inst);
bool V_DOT2C_F32_F16(const Decoder::Instruction& inst); void V_DOT2C_F32_F16(const Decoder::Instruction& inst);
bool V_CUBEID_F32(const Decoder::Instruction& inst); void V_CUBEID_F32(const Decoder::Instruction& inst);
bool V_CUBESC_F32(const Decoder::Instruction& inst); void V_CUBESC_F32(const Decoder::Instruction& inst);
bool V_CUBETC_F32(const Decoder::Instruction& inst); void V_CUBETC_F32(const Decoder::Instruction& inst);
bool V_CUBEMA_F32(const Decoder::Instruction& inst); void V_CUBEMA_F32(const Decoder::Instruction& inst);
bool FloatCube(const Decoder::Instruction& inst, uint32_t result_kind); void FloatCube(const Decoder::Instruction& inst, uint32_t result_kind);
bool Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool arithmetic); void Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool arithmetic);
bool Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign); void Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
bool V_MAD_I16(const Decoder::Instruction& inst); void V_MAD_I16(const Decoder::Instruction& inst);
bool V_MED3_I16(const Decoder::Instruction& inst); void V_MED3_I16(const Decoder::Instruction& inst);
bool PackedInteger16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void PackedInteger16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool arithmetic); bool arithmetic);
bool PackedInteger16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode); void PackedInteger16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode);
bool PackedInteger16Mad(const Decoder::Instruction& inst, bool sign); void PackedInteger16Mad(const Decoder::Instruction& inst, bool sign);
bool PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign); void PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
bool S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode, void S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary); IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary);
IR::U1 U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool negate_rhs, IR::U1 U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool negate_rhs,
bool negate_result); bool negate_result);
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type, void SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
bool reverse, bool mask_shift_count, bool update_scc); bool reverse, bool mask_shift_count, bool update_scc);
bool S_ASHR_I64(const Decoder::Instruction& inst); void S_ASHR_I64(const Decoder::Instruction& inst);
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool negate_rhs, bool negate_result, bool update_scc); bool negate_rhs, bool negate_result, bool update_scc);
bool V_AND_OR_B32(const Decoder::Instruction& inst); void V_AND_OR_B32(const Decoder::Instruction& inst);
bool V_OR3_B32(const Decoder::Instruction& inst); void V_OR3_B32(const Decoder::Instruction& inst);
bool V_XOR3_B32(const Decoder::Instruction& inst); void V_XOR3_B32(const Decoder::Instruction& inst);
bool S_FF1_I32_B64(const Decoder::Instruction& inst); void S_FF1_I32_B64(const Decoder::Instruction& inst);
bool V_FFBH_32(const Decoder::Instruction& inst, bool sign); void V_FFBH_32(const Decoder::Instruction& inst, bool sign);
bool S_FLBIT_I32_B64(const Decoder::Instruction& inst); void S_FLBIT_I32_B64(const Decoder::Instruction& inst);
bool Integer24(const Decoder::Instruction& inst, bool sign, bool addend); void Integer24(const Decoder::Instruction& inst, bool sign, bool addend);
bool V_MAD_U64_U32(const Decoder::Instruction& inst); void V_MAD_U64_U32(const Decoder::Instruction& inst);
bool V_SAD_U32(const Decoder::Instruction& inst); void V_SAD_U32(const Decoder::Instruction& inst);
bool V_ADD3_U32(const Decoder::Instruction& inst); void V_ADD3_U32(const Decoder::Instruction& inst);
bool S_BITSET_B32(const Decoder::Instruction& inst, bool set); void S_BITSET_B32(const Decoder::Instruction& inst, bool set);
bool S_BITSET_B64(const Decoder::Instruction& inst, bool set); void S_BITSET_B64(const Decoder::Instruction& inst, bool set);
bool V_BCNT_U32_B32(const Decoder::Instruction& inst); void V_BCNT_U32_B32(const Decoder::Instruction& inst);
bool V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low); void V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
bool S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst); void S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
bool S_QUADMASK_B64(const Decoder::Instruction& inst); void S_QUADMASK_B64(const Decoder::Instruction& inst);
bool BFM_B32(const Decoder::Instruction& inst); void BFM_B32(const Decoder::Instruction& inst);
IR::U32 RightMask32(IR::U32 count); IR::U32 RightMask32(IR::U32 count);
IR::U64 RightMask64(IR::U32 count); IR::U64 RightMask64(IR::U32 count);
bool S_BFM_B64(const Decoder::Instruction& inst); void S_BFM_B64(const Decoder::Instruction& inst);
bool S_BFE_U32(const Decoder::Instruction& inst, bool sign); void S_BFE_U32(const Decoder::Instruction& inst, bool sign);
bool S_BFE_U64(const Decoder::Instruction& inst); void S_BFE_U64(const Decoder::Instruction& inst);
bool V_BFE_U32(const Decoder::Instruction& inst, bool sign); void V_BFE_U32(const Decoder::Instruction& inst, bool sign);
bool V_BFI_B32(const Decoder::Instruction& inst); void V_BFI_B32(const Decoder::Instruction& inst);
bool S_BITCMP_B32(const Decoder::Instruction& inst, bool expected); void S_BITCMP_B32(const Decoder::Instruction& inst, bool expected);
bool S_BITCMP_B64(const Decoder::Instruction& inst, bool expected); void S_BITCMP_B64(const Decoder::Instruction& inst, bool expected);
bool V_ALIGNBIT_B32(const Decoder::Instruction& inst); void V_ALIGNBIT_B32(const Decoder::Instruction& inst);
bool V_ALIGNBYTE_B32(const Decoder::Instruction& inst); void V_ALIGNBYTE_B32(const Decoder::Instruction& inst);
bool V_LSHL_ADD_U32(const Decoder::Instruction& inst); void V_LSHL_ADD_U32(const Decoder::Instruction& inst);
bool V_ADD_LSHL_U32(const Decoder::Instruction& inst); void V_ADD_LSHL_U32(const Decoder::Instruction& inst);
bool V_XAD_U32(const Decoder::Instruction& inst); void V_XAD_U32(const Decoder::Instruction& inst);
bool V_LSHL_OR_B32(const Decoder::Instruction& inst); void V_LSHL_OR_B32(const Decoder::Instruction& inst);
bool V_CNDMASK_B32(const Decoder::Instruction& inst); void V_CNDMASK_B32(const Decoder::Instruction& inst);
bool PackB16(const Decoder::Instruction& inst, bool high0, bool high1); void PackB16(const Decoder::Instruction& inst, bool high0, bool high1);
void S_SUBVECTOR_LOOP(const Decoder::Instruction& inst, bool begin); void S_SUBVECTOR_LOOP(const Decoder::Instruction& inst, bool begin);
void S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation, bool negate_exec, void S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation, bool negate_exec,
@@ -249,10 +249,11 @@ private:
void V_INTERP_MOV_F32(const Decoder::Instruction& inst); void V_INTERP_MOV_F32(const Decoder::Instruction& inst);
void EXP(const Decoder::Instruction& inst); void EXP(const Decoder::Instruction& inst);
bool EmitScalar(const Decoder::Instruction& inst); void EmitScalar(const Decoder::Instruction& inst);
bool EmitVector(const Decoder::Instruction& inst); void EmitVector(const Decoder::Instruction& inst);
bool EmitInterpolation(const Decoder::Instruction& inst); void EmitInterpolation(const Decoder::Instruction& inst);
bool EmitMemory(const Decoder::Instruction& inst); void EmitMemory(const Decoder::Instruction& inst);
static void FailMissingTranslation(const Decoder::Instruction& inst);
IR::Program& program; IR::Program& program;
IR::IREmitter ir; IR::IREmitter ir;
@@ -2,322 +2,322 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend { namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::EmitVector(const Decoder::Instruction& inst) { void Translator::EmitVector(const Decoder::Instruction& inst) {
using O = Decoder::Opcode; using O = Decoder::Opcode;
switch (inst.opcode) { switch (inst.opcode) {
case O::V_NOP: return true; case O::V_NOP: return;
case O::V_ADD_I32: ADD_U32(inst, true, false); return true; case O::V_ADD_I32: ADD_U32(inst, true, false); return;
case O::V_ADDC_U32: ADD_U32(inst, true, true); return true; case O::V_ADDC_U32: ADD_U32(inst, true, true); return;
case O::V_SUB_I32: SUB_U32(inst, true, false); return true; case O::V_SUB_I32: SUB_U32(inst, true, false); return;
case O::V_SUBREV_I32: SUB_U32(inst, true, true); return true; case O::V_SUBREV_I32: SUB_U32(inst, true, true); return;
case O::V_SUB_CO_CI_U32: SUBB_U32(inst, true, false); return true; case O::V_SUB_CO_CI_U32: SUBB_U32(inst, true, false); return;
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true, true); return true; case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true, true); return;
case O::V_MOV_B32: MOV_B32(inst, true); return true; case O::V_MOV_B32: MOV_B32(inst, true); return;
case O::V_MOVRELS_B32: V_MOVRELS_B32(inst); return true; case O::V_MOVRELS_B32: V_MOVRELS_B32(inst); return;
case O::V_MOVRELD_B32: V_MOVRELD_B32(inst); return true; case O::V_MOVRELD_B32: V_MOVRELD_B32(inst); return;
case O::V_READFIRSTLANE_B32: V_READFIRSTLANE_B32(inst); return true; case O::V_READFIRSTLANE_B32: V_READFIRSTLANE_B32(inst); return;
case O::V_READLANE_B32: V_READLANE_B32(inst); return true; case O::V_READLANE_B32: V_READLANE_B32(inst); return;
case O::V_WRITELANE_B32: V_WRITELANE_B32(inst); return true; case O::V_WRITELANE_B32: V_WRITELANE_B32(inst); return;
case O::V_PERMLANE16_B32: V_PERMLANE16_B32(inst, false); return true; case O::V_PERMLANE16_B32: V_PERMLANE16_B32(inst, false); return;
case O::V_PERMLANEX16_B32: V_PERMLANE16_B32(inst, true); return true; case O::V_PERMLANEX16_B32: V_PERMLANE16_B32(inst, true); return;
case O::V_CMP_F_I32: case O::V_CMP_F_I32:
case O::V_CMP_F_U32: EmitCompareConstant(inst, false, false, false); return true; case O::V_CMP_F_U32: EmitCompareConstant(inst, false, false, false); return;
case O::V_CMP_T_I32: case O::V_CMP_T_I32:
case O::V_CMP_T_U32: EmitCompareConstant(inst, true, false, false); return true; case O::V_CMP_T_U32: EmitCompareConstant(inst, true, false, false); return;
case O::V_CMP_EQ_U32: case O::V_CMP_EQ_U32:
case O::V_CMP_EQ_I32: case O::V_CMP_EQ_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_EQ_U32: case O::V_CMPX_EQ_U32:
case O::V_CMPX_EQ_I32: case O::V_CMPX_EQ_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::IEqual32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_NE_U32: case O::V_CMP_NE_U32:
case O::V_CMP_NE_I32: case O::V_CMP_NE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_NE_U32: case O::V_CMPX_NE_U32:
case O::V_CMPX_NE_I32: case O::V_CMPX_NE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_GT_U32: case O::V_CMP_GT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_GT_U32: case O::V_CMPX_GT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_GE_U32: case O::V_CMP_GE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, false,
false); false);
return true; return;
case O::V_CMPX_GE_U32: case O::V_CMPX_GE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual32, IR::Type::U32, false,
true); true);
return true; return;
case O::V_CMP_LT_U32: case O::V_CMP_LT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_LT_U32: case O::V_CMPX_LT_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_LE_U32: case O::V_CMP_LE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, false,
false); false);
return true; return;
case O::V_CMPX_LE_U32: case O::V_CMPX_LE_U32:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_GT_I32: case O::V_CMP_GT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_GT_I32: case O::V_CMPX_GT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThan32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_GE_I32: case O::V_CMP_GE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, false,
false); false);
return true; return;
case O::V_CMPX_GE_I32: case O::V_CMPX_GE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::SGreaterThanEqual32, IR::Type::U32, false,
true); true);
return true; return;
case O::V_CMP_LT_I32: case O::V_CMP_LT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, false, false);
return true; return;
case O::V_CMPX_LT_I32: case O::V_CMPX_LT_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_LE_I32: case O::V_CMP_LE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, false, EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, false,
false); false);
return true; return;
case O::V_CMPX_LE_I32: case O::V_CMPX_LE_I32:
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual32, IR::Type::U32, false, true);
return true; return;
case O::V_CMP_EQ_I64: case O::V_CMP_EQ_I64:
case O::V_CMP_EQ_U64: case O::V_CMP_EQ_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, false, false);
return true; return;
case O::V_CMP_LT_U64: case O::V_CMP_LT_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan64, IR::Type::U64, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan64, IR::Type::U64, false, false);
return true; return;
case O::V_CMP_GT_U64: case O::V_CMP_GT_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan64, IR::Type::U64, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan64, IR::Type::U64, false, false);
return true; return;
case O::V_CMP_NE_U64: case O::V_CMP_NE_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, false, false); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, false, false);
return true; return;
case O::V_CMPX_NE_I64: case O::V_CMPX_NE_I64:
case O::V_CMPX_NE_U64: case O::V_CMPX_NE_U64:
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, false, true); EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, false, true);
return true; return;
case O::V_CMP_EQ_U16: case O::V_CMP_EQ_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, false, false);
return true; return;
case O::V_CMP_EQ_I16: case O::V_CMP_EQ_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, true, false);
return true; return;
case O::V_CMP_NE_U16: case O::V_CMP_NE_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, false, false);
return true; return;
case O::V_CMP_NE_I16: case O::V_CMP_NE_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, true, false);
return true; return;
case O::V_CMP_GT_U16: case O::V_CMP_GT_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThan32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThan32, false, false);
return true; return;
case O::V_CMPX_GT_U16: case O::V_CMPX_GT_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThan32, false, true); EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThan32, false, true);
return true; return;
case O::V_CMP_GE_U16: case O::V_CMP_GE_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThanEqual32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThanEqual32, false, false);
return true; return;
case O::V_CMP_LT_U16: case O::V_CMP_LT_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::ULessThan32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::ULessThan32, false, false);
return true; return;
case O::V_CMPX_LT_U16: case O::V_CMPX_LT_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::ULessThan32, false, true); EmitInteger16Compare(inst, IR::ValueOpcode::ULessThan32, false, true);
return true; return;
case O::V_CMPX_EQ_U16: case O::V_CMPX_EQ_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, false, true); EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, false, true);
return true; return;
case O::V_CMP_LE_U16: case O::V_CMP_LE_U16:
EmitInteger16Compare(inst, IR::ValueOpcode::ULessThanEqual32, false, false); EmitInteger16Compare(inst, IR::ValueOpcode::ULessThanEqual32, false, false);
return true; return;
case O::V_CMP_GT_I16: case O::V_CMP_GT_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThan32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThan32, true, false);
return true; return;
case O::V_CMP_GE_I16: case O::V_CMP_GE_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThanEqual32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThanEqual32, true, false);
return true; return;
case O::V_CMP_LT_I16: case O::V_CMP_LT_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::SLessThan32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::SLessThan32, true, false);
return true; return;
case O::V_CMP_LE_I16: case O::V_CMP_LE_I16:
EmitInteger16Compare(inst, IR::ValueOpcode::SLessThanEqual32, true, false); EmitInteger16Compare(inst, IR::ValueOpcode::SLessThanEqual32, true, false);
return true; return;
case O::V_CMP_F_F32: EmitCompareConstant(inst, false, false, false); return true; case O::V_CMP_F_F32: EmitCompareConstant(inst, false, false, false); return;
case O::V_CMP_TRU_F32: EmitCompareConstant(inst, true, false, false); return true; case O::V_CMP_TRU_F32: EmitCompareConstant(inst, true, false, false); return;
case O::V_CMP_EQ_F32: case O::V_CMP_EQ_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, false, false);
return true; return;
case O::V_CMPX_EQ_F32: case O::V_CMPX_EQ_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, false, true);
return true; return;
case O::V_CMP_LG_F32: case O::V_CMP_LG_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, false, false);
return true; return;
case O::V_CMPX_LG_F32: case O::V_CMPX_LG_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, false, true);
return true; return;
case O::V_CMP_GT_F32: case O::V_CMP_GT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, false, false);
return true; return;
case O::V_CMPX_GT_F32: case O::V_CMPX_GT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, false, true);
return true; return;
case O::V_CMP_GE_F32: case O::V_CMP_GE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, false, false);
return true; return;
case O::V_CMPX_GE_F32: case O::V_CMPX_GE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, false, true);
return true; return;
case O::V_CMP_LT_F32: case O::V_CMP_LT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, false, false);
return true; return;
case O::V_CMPX_LT_F32: case O::V_CMPX_LT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, false, true);
return true; return;
case O::V_CMP_LE_F32: case O::V_CMP_LE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, false, false);
return true; return;
case O::V_CMPX_LE_F32: case O::V_CMPX_LE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, false, true);
return true; return;
case O::V_CMP_NLG_F32: case O::V_CMP_NLG_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordEqual32, false, false);
return true; return;
case O::V_CMPX_NLG_F32: case O::V_CMPX_NLG_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordEqual32, false, true);
return true; return;
case O::V_CMP_NEQ_F32: case O::V_CMP_NEQ_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, false, false);
return true; return;
case O::V_CMPX_NEQ_F32: case O::V_CMPX_NEQ_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, false, true);
return true; return;
case O::V_CMP_NLE_F32: case O::V_CMP_NLE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThan32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThan32, false, false);
return true; return;
case O::V_CMPX_NLE_F32: case O::V_CMPX_NLE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThan32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThan32, false, true);
return true; return;
case O::V_CMP_NLT_F32: case O::V_CMP_NLT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, false, false);
return true; return;
case O::V_CMPX_NLT_F32: case O::V_CMPX_NLT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, false, true);
return true; return;
case O::V_CMP_NGE_F32: case O::V_CMP_NGE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThan32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThan32, false, false);
return true; return;
case O::V_CMPX_NGE_F32: case O::V_CMPX_NGE_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThan32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThan32, false, true);
return true; return;
case O::V_CMP_NGT_F32: case O::V_CMP_NGT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, false, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, false, false);
return true; return;
case O::V_CMPX_NGT_F32: case O::V_CMPX_NGT_F32:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, false, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, false, true);
return true; return;
case O::V_CMP_EQ_F16: case O::V_CMP_EQ_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, true, false);
return true; return;
case O::V_CMPX_EQ_F16: case O::V_CMPX_EQ_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, true, true);
return true; return;
case O::V_CMP_LG_F16: case O::V_CMP_LG_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdNotEqual32, true, false);
return true; return;
case O::V_CMP_GT_F16: case O::V_CMP_GT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, true, false);
return true; return;
case O::V_CMPX_GT_F16: case O::V_CMPX_GT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThan32, true, true);
return true; return;
case O::V_CMP_GE_F16: case O::V_CMP_GE_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, true, false);
return true; return;
case O::V_CMPX_GE_F16: case O::V_CMPX_GE_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual32, true, true);
return true; return;
case O::V_CMP_LT_F16: case O::V_CMP_LT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, true, false);
return true; return;
case O::V_CMPX_LT_F16: case O::V_CMPX_LT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThan32, true, true);
return true; return;
case O::V_CMP_LE_F16: case O::V_CMP_LE_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, false);
return true; return;
case O::V_CMPX_LE_F16: case O::V_CMPX_LE_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, true);
return true; return;
case O::V_CMP_NGT_F16: case O::V_CMP_NGT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, false);
return true; return;
case O::V_CMPX_NGT_F16: case O::V_CMPX_NGT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, true);
return true; return;
case O::V_CMP_NEQ_F16: case O::V_CMP_NEQ_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, true, false);
return true; return;
case O::V_CMPX_NEQ_F16: case O::V_CMPX_NEQ_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, true, true);
return true; return;
case O::V_CMP_NLT_F16: case O::V_CMP_NLT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, false); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, false);
return true; return;
case O::V_CMPX_NLT_F16: case O::V_CMPX_NLT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, true); EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, true);
return true; return;
case O::V_CMP_O_F32: EmitFloatOrderedCompare(inst, true, false); return true; case O::V_CMP_O_F32: EmitFloatOrderedCompare(inst, true, false); return;
case O::V_CMP_U_F32: EmitFloatOrderedCompare(inst, false, false); return true; case O::V_CMP_U_F32: EmitFloatOrderedCompare(inst, false, false); return;
case O::V_CMPX_O_F32: EmitFloatOrderedCompare(inst, true, true); return true; case O::V_CMPX_O_F32: EmitFloatOrderedCompare(inst, true, true); return;
case O::V_CMP_CLASS_F32: EmitFloatClassCompare(inst, false); return true; case O::V_CMP_CLASS_F32: EmitFloatClassCompare(inst, false); return;
case O::V_CMPX_CLASS_F32: EmitFloatClassCompare(inst, true); return true; case O::V_CMPX_CLASS_F32: EmitFloatClassCompare(inst, true); return;
case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return true; case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return;
case O::V_CVT_F32_UBYTE1: V_CVT_F32_UBYTE(inst, 1); return true; case O::V_CVT_F32_UBYTE1: V_CVT_F32_UBYTE(inst, 1); return;
case O::V_CVT_F32_UBYTE2: V_CVT_F32_UBYTE(inst, 2); return true; case O::V_CVT_F32_UBYTE2: V_CVT_F32_UBYTE(inst, 2); return;
case O::V_CVT_F32_UBYTE3: V_CVT_F32_UBYTE(inst, 3); return true; case O::V_CVT_F32_UBYTE3: V_CVT_F32_UBYTE(inst, 3); return;
case O::V_CVT_F32_U32: V_CVT_F32_U32(inst); return true; case O::V_CVT_F32_U32: V_CVT_F32_U32(inst); return;
case O::V_CVT_F32_I32: V_CVT_F32_I32(inst); return true; case O::V_CVT_F32_I32: V_CVT_F32_I32(inst); return;
case O::V_CVT_U32_F32: V_CVT_U32_F32(inst); return true; case O::V_CVT_U32_F32: V_CVT_U32_F32(inst); return;
case O::V_CVT_I32_F32: V_CVT_I32_F32(inst); return true; case O::V_CVT_I32_F32: V_CVT_I32_F32(inst); return;
case O::V_CVT_F16_F32: V_CVT_F16_F32(inst); return true; case O::V_CVT_F16_F32: V_CVT_F16_F32(inst); return;
case O::V_CVT_F32_F16: V_CVT_F32_F16(inst); return true; case O::V_CVT_F32_F16: V_CVT_F32_F16(inst); return;
case O::V_CVT_F16_U16: V_CVT_F16_16(inst, false); return true; case O::V_CVT_F16_U16: V_CVT_F16_16(inst, false); return;
case O::V_CVT_F16_I16: V_CVT_F16_16(inst, true); return true; case O::V_CVT_F16_I16: V_CVT_F16_16(inst, true); return;
case O::V_CVT_U16_F16: V_CVT_16_F16(inst, false); return true; case O::V_CVT_U16_F16: V_CVT_16_F16(inst, false); return;
case O::V_CVT_I16_F16: V_CVT_16_F16(inst, true); return true; case O::V_CVT_I16_F16: V_CVT_16_F16(inst, true); return;
case O::V_CVT_RPI_I32_F32: V_CVT_RPI_I32_F32(inst); return true; case O::V_CVT_RPI_I32_F32: V_CVT_RPI_I32_F32(inst); return;
case O::V_CVT_FLR_I32_F32: V_CVT_FLR_I32_F32(inst); return true; case O::V_CVT_FLR_I32_F32: V_CVT_FLR_I32_F32(inst); return;
case O::V_FREXP_EXP_I32_F32: V_FREXP_EXP_I32_F32(inst); return true; case O::V_FREXP_EXP_I32_F32: V_FREXP_EXP_I32_F32(inst); return;
case O::V_CVT_OFF_F32_I4: V_CVT_OFF_F32_I4(inst); return true; case O::V_CVT_OFF_F32_I4: V_CVT_OFF_F32_I4(inst); return;
case O::V_CVT_PKRTZ_F16_F32: V_CVT_PKRTZ_F16_F32(inst); return true; case O::V_CVT_PKRTZ_F16_F32: V_CVT_PKRTZ_F16_F32(inst); return;
case O::V_CVT_PKNORM_I16_F32: case O::V_CVT_PKNORM_I16_F32:
V_CVT_PKNORM_F32(inst, IR::ValueOpcode::PackSnorm2x16); V_CVT_PKNORM_F32(inst, IR::ValueOpcode::PackSnorm2x16);
return true; return;
case O::V_CVT_PKNORM_U16_F32: case O::V_CVT_PKNORM_U16_F32:
V_CVT_PKNORM_F32(inst, IR::ValueOpcode::PackUnorm2x16); V_CVT_PKNORM_F32(inst, IR::ValueOpcode::PackUnorm2x16);
return true; return;
case O::V_CVT_PK_U8_F32: V_CVT_PK_U8_F32(inst); return true; case O::V_CVT_PK_U8_F32: V_CVT_PK_U8_F32(inst); return;
case O::V_PACK_B32_F16: V_PACK_B32_F16(inst); return true; case O::V_PACK_B32_F16: V_PACK_B32_F16(inst); return;
case O::V_CVT_PK_U16_U32: case O::V_CVT_PK_U16_U32:
case O::V_CVT_PK_I16_I32: return PackB16(inst, false, false); case O::V_CVT_PK_I16_I32: return PackB16(inst, false, false);
@@ -538,7 +538,7 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
case O::V_XAD_U32: return V_XAD_U32(inst); case O::V_XAD_U32: return V_XAD_U32(inst);
case O::V_LSHL_OR_B32: return V_LSHL_OR_B32(inst); case O::V_LSHL_OR_B32: return V_LSHL_OR_B32(inst);
case O::V_CNDMASK_B32: return V_CNDMASK_B32(inst); case O::V_CNDMASK_B32: return V_CNDMASK_B32(inst);
default: return false; default: return FailMissingTranslation(inst);
} }
} }