mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
shader: remove recompiler error-string propagation
This commit is contained in:
@@ -357,8 +357,8 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1, nullptr);
|
||||
DecodeScalarSource(ssamp * 4u, pc, inst.src2, nullptr);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1);
|
||||
DecodeScalarSource(ssamp * 4u, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,11 +241,11 @@ void DecodeSmem(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
MarkMemoryUnsupported(inst, Family::SMEM, opcode, "SMEM opcode is not implemented");
|
||||
}
|
||||
|
||||
DecodeScalarDestination(sdst, pc, inst.dst, nullptr);
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
// SMEM encodes SBASE in SGPR pairs. Scalar-buffer loads still use the same
|
||||
// pair index; their descriptor operand consumes four SGPRs from that base.
|
||||
DecodeScalarSource(sbase * 2u, pc, inst.src0, nullptr);
|
||||
DecodeScalarSource(soffset, pc, inst.src1, nullptr);
|
||||
DecodeScalarSource(sbase * 2u, pc, inst.src0);
|
||||
DecodeScalarSource(soffset, pc, inst.src1);
|
||||
inst.src_count = 2;
|
||||
}
|
||||
|
||||
@@ -278,8 +278,8 @@ void DecodeMubuf(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1, nullptr);
|
||||
DecodeScalarSource(soffset, pc, inst.src2, nullptr);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1);
|
||||
DecodeScalarSource(soffset, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
}
|
||||
|
||||
@@ -316,8 +316,8 @@ void DecodeMtbuf(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1, nullptr);
|
||||
DecodeScalarSource(soffset, pc, inst.src2, nullptr);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1);
|
||||
DecodeScalarSource(soffset, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ void DecodeFlat(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
DecodeVectorGpr(addr + 1u, inst.src1);
|
||||
inst.src_count = 2;
|
||||
} else {
|
||||
DecodeScalarSource(saddr, pc, inst.src1, nullptr);
|
||||
DecodeScalarSource(saddr, pc, inst.src1);
|
||||
inst.src_count = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,21 +105,18 @@ constexpr auto SOPK_OPS = Detail::MakeOpcodeTable<0x20>(SOPK_OPCODE_LIST);
|
||||
constexpr auto SOPC_OPS = Detail::MakeOpcodeTable<0x80>(SOPC_OPCODE_LIST);
|
||||
constexpr auto SOPP_OPS = Detail::MakeOpcodeTable<0x80>(SOPP_OPCODE_LIST);
|
||||
|
||||
bool DecodeBinarySources(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst, uint32_t ssrc0, uint32_t ssrc1, std::string* error) {
|
||||
if (!DecodeScalarSource(ssrc0, pc, inst.src0, error) ||
|
||||
!DecodeScalarSource(ssrc1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
void DecodeBinarySources(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst, uint32_t ssrc0, uint32_t ssrc1) {
|
||||
DecodeScalarSource(ssrc0, pc, inst.src0);
|
||||
DecodeScalarSource(ssrc1, pc, inst.src1);
|
||||
inst.src_count = 2;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 8u) & 0xffu;
|
||||
const uint32_t ssrc0 = word & 0xffu;
|
||||
@@ -134,35 +131,31 @@ bool DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::SOP1, opcode, "SOP1 opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (inst.opcode) {
|
||||
case Opcode::S_GETPC_B64:
|
||||
inst.src_count = 0;
|
||||
return DecodeScalarDestination(sdst, pc, inst.dst, error);
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
return;
|
||||
case Opcode::S_SETPC_B64:
|
||||
inst.src_count = 1;
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
if (!DecodeScalarSource(ssrc0, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(ssrc0, pc, inst.src0);
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (!DecodeScalarSource(ssrc0, pc, inst.src0, error) ||
|
||||
!DecodeScalarDestination(sdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(ssrc0, pc, inst.src0);
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
inst.src_count = 1;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeSop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeSop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 23u) & 0x7fu;
|
||||
const uint32_t ssrc1 = (word >> 8u) & 0xffu;
|
||||
@@ -178,17 +171,15 @@ bool DecodeSop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::SOP2, opcode, "SOP2 opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DecodeScalarDestination(sdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
}
|
||||
return DecodeBinarySources(pc, code, word_index, inst, ssrc0, ssrc1, error);
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
DecodeBinarySources(pc, code, word_index, inst, ssrc0, ssrc1);
|
||||
}
|
||||
|
||||
bool DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 23u) & 0x1fu;
|
||||
const uint32_t sdst = (word >> 16u) & 0x7fu;
|
||||
@@ -207,18 +198,18 @@ bool DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::SOPK, opcode, "SOPK opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (inst.opcode) {
|
||||
case Opcode::S_MOVK_I32: return DecodeScalarDestination(sdst, pc, inst.dst, error);
|
||||
case Opcode::S_MOVK_I32: DecodeScalarDestination(sdst, pc, inst.dst); return;
|
||||
case Opcode::S_WAITCNT: {
|
||||
const uint32_t waitcnt = word & 0xffffu;
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
inst.src0.signed_val = static_cast<int32_t>(waitcnt);
|
||||
inst.src0.value = waitcnt;
|
||||
inst.src_count = 1;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case Opcode::S_SETREG_B32:
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
@@ -226,26 +217,25 @@ bool DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
inst.src1.value = word & 0xffffu;
|
||||
inst.src1.signed_val = static_cast<int32_t>(imm);
|
||||
inst.src_count = 2;
|
||||
return DecodeScalarSource(sdst, pc, inst.src0, error);
|
||||
DecodeScalarSource(sdst, pc, inst.src0);
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
|
||||
inst.src1 = inst.src0;
|
||||
if (!DecodeScalarSource(sdst, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(sdst, pc, inst.src0);
|
||||
if (inst.opcode == Opcode::S_ADD_I32 || inst.opcode == Opcode::S_MULK_I32) {
|
||||
inst.src_count = 2;
|
||||
return DecodeScalarDestination(sdst, pc, inst.dst, error);
|
||||
DecodeScalarDestination(sdst, pc, inst.dst);
|
||||
return;
|
||||
}
|
||||
|
||||
inst.dst.kind = OperandKind::Scc;
|
||||
inst.src_count = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeSopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeSopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t ssrc1 = (word >> 8u) & 0xffu;
|
||||
const uint32_t ssrc0 = word & 0xffu;
|
||||
@@ -261,10 +251,10 @@ bool DecodeSopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::SOPC, opcode, "SOPC opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return DecodeBinarySources(pc, code, word_index, inst, ssrc0, ssrc1, error);
|
||||
DecodeBinarySources(pc, code, word_index, inst, ssrc0, ssrc1);
|
||||
}
|
||||
|
||||
void DecodeSopp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Decoder {
|
||||
|
||||
bool DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeSop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeSopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
void DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeSop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeSopk(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeSopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeSopp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ExportOps.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ImageOps.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/MemoryOps.h"
|
||||
@@ -17,12 +18,6 @@ uint32_t FloatBits(float value) {
|
||||
return std::bit_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
void SetError(std::string* error, const char* message) {
|
||||
if (error != nullptr) {
|
||||
*error = message;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasLiteral(const Instruction& inst) {
|
||||
return inst.src0.kind == OperandKind::LiteralConstant ||
|
||||
inst.src1.kind == OperandKind::LiteralConstant ||
|
||||
@@ -216,86 +211,76 @@ const char* ImageDimensionToString(ImageDimension dimension) {
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand, std::string* error) {
|
||||
void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand) {
|
||||
operand = {};
|
||||
|
||||
if (code <= 105u) {
|
||||
operand.kind = OperandKind::Sgpr;
|
||||
operand.reg = code;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (code >= 128u && code <= 192u) {
|
||||
operand.kind = OperandKind::IntegerInlineConstant;
|
||||
operand.signed_val = static_cast<int32_t>(code - 128u);
|
||||
operand.value = static_cast<uint32_t>(operand.signed_val);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (code >= 193u && code <= 208u) {
|
||||
operand.kind = OperandKind::IntegerInlineConstant;
|
||||
operand.signed_val = 192 - static_cast<int32_t>(code);
|
||||
operand.value = static_cast<uint32_t>(operand.signed_val);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (code >= 240u && code <= 247u) {
|
||||
constexpr float values[] = {0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f, 4.0f, -4.0f};
|
||||
operand.kind = OperandKind::FloatInlineConstant;
|
||||
operand.float_val = values[code - 240u];
|
||||
operand.value = FloatBits(operand.float_val);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (code >= 256u && code <= 511u) {
|
||||
DecodeVectorGpr(code - 256u, operand);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 106u: operand.kind = OperandKind::VccLo; return true;
|
||||
case 107u: operand.kind = OperandKind::VccHi; return true;
|
||||
case 124u: operand.kind = OperandKind::M0; return true;
|
||||
case 125u: operand.kind = OperandKind::Null; return true;
|
||||
case 126u: operand.kind = OperandKind::ExecLo; return true;
|
||||
case 127u: operand.kind = OperandKind::ExecHi; return true;
|
||||
case 239u: operand.kind = OperandKind::PopsExitingWaveId; return true;
|
||||
case 106u: operand.kind = OperandKind::VccLo; return;
|
||||
case 107u: operand.kind = OperandKind::VccHi; return;
|
||||
case 124u: operand.kind = OperandKind::M0; return;
|
||||
case 125u: operand.kind = OperandKind::Null; return;
|
||||
case 126u: operand.kind = OperandKind::ExecLo; return;
|
||||
case 127u: operand.kind = OperandKind::ExecHi; return;
|
||||
case 239u: operand.kind = OperandKind::PopsExitingWaveId; return;
|
||||
case 248u:
|
||||
operand.kind = OperandKind::FloatInlineConstant;
|
||||
operand.float_val = 0.15915494309189535f;
|
||||
operand.value = FloatBits(operand.float_val);
|
||||
return true;
|
||||
case 251u: operand.kind = OperandKind::VccZ; return true;
|
||||
case 252u: operand.kind = OperandKind::ExecZ; return true;
|
||||
case 253u: operand.kind = OperandKind::Scc; return true;
|
||||
case 255u: operand.kind = OperandKind::LiteralConstant; return true;
|
||||
default:
|
||||
if (error != nullptr) {
|
||||
*error = fmt::format("unsupported scalar source operand 0x{:08x} at pc 0x{:08x}",
|
||||
code, pc);
|
||||
}
|
||||
return false;
|
||||
return;
|
||||
case 251u: operand.kind = OperandKind::VccZ; return;
|
||||
case 252u: operand.kind = OperandKind::ExecZ; return;
|
||||
case 253u: operand.kind = OperandKind::Scc; return;
|
||||
case 255u: operand.kind = OperandKind::LiteralConstant; return;
|
||||
default: EXIT("unsupported scalar source operand 0x%08x at pc 0x%08x", code, pc);
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand, std::string* error) {
|
||||
void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand) {
|
||||
operand = {};
|
||||
|
||||
if (code <= 105u) {
|
||||
operand.kind = OperandKind::Sgpr;
|
||||
operand.reg = code;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 106u: operand.kind = OperandKind::VccLo; return true;
|
||||
case 107u: operand.kind = OperandKind::VccHi; return true;
|
||||
case 124u: operand.kind = OperandKind::M0; return true;
|
||||
case 125u: operand.kind = OperandKind::Null; return true;
|
||||
case 126u: operand.kind = OperandKind::ExecLo; return true;
|
||||
case 127u: operand.kind = OperandKind::ExecHi; return true;
|
||||
default:
|
||||
if (error != nullptr) {
|
||||
*error = fmt::format(
|
||||
"unsupported scalar destination operand 0x{:08x} at pc 0x{:08x}", code, pc);
|
||||
}
|
||||
return false;
|
||||
case 106u: operand.kind = OperandKind::VccLo; return;
|
||||
case 107u: operand.kind = OperandKind::VccHi; return;
|
||||
case 124u: operand.kind = OperandKind::M0; return;
|
||||
case 125u: operand.kind = OperandKind::Null; return;
|
||||
case 126u: operand.kind = OperandKind::ExecLo; return;
|
||||
case 127u: operand.kind = OperandKind::ExecHi; return;
|
||||
default: EXIT("unsupported scalar destination operand 0x%08x at pc 0x%08x", code, pc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,39 +353,33 @@ Family GetInstructionFamily(uint32_t word) {
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeInstruction(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeInstruction(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst) {
|
||||
const uint32_t pc = word_index * sizeof(uint32_t);
|
||||
switch (GetInstructionFamily(code[word_index])) {
|
||||
case Family::SOP1: return DecodeSop1(pc, code, word_index, inst, error);
|
||||
case Family::SOP2: return DecodeSop2(pc, code, word_index, inst, error);
|
||||
case Family::SOPK: return DecodeSopk(pc, code, word_index, inst, error);
|
||||
case Family::SOPC: return DecodeSopc(pc, code, word_index, inst, error);
|
||||
case Family::SOPP: DecodeSopp(pc, code, word_index, inst); return true;
|
||||
case Family::VOP1: return DecodeVop1(pc, code, word_index, inst, error);
|
||||
case Family::VOP2: return DecodeVop2(pc, code, word_index, inst, error);
|
||||
case Family::VOP3: return DecodeVop3(pc, code, word_index, inst, error);
|
||||
case Family::VOP3P: return DecodeVop3p(pc, code, word_index, inst, error);
|
||||
case Family::VOPC: return DecodeVopc(pc, code, word_index, inst, error);
|
||||
case Family::VINTRP: DecodeVintrp(pc, code, word_index, inst); return true;
|
||||
case Family::SMEM: DecodeSmem(pc, code, word_index, inst); return true;
|
||||
case Family::MUBUF: DecodeMubuf(pc, code, word_index, inst); return true;
|
||||
case Family::MTBUF: DecodeMtbuf(pc, code, word_index, inst); return true;
|
||||
case Family::FLAT: DecodeFlat(pc, code, word_index, inst); return true;
|
||||
case Family::DS: DecodeDs(pc, code, word_index, inst); return true;
|
||||
case Family::MIMG: DecodeMimg(pc, code, word_index, inst); return true;
|
||||
case Family::EXP: DecodeExp(pc, code, word_index, inst); return true;
|
||||
case Family::SOP1: DecodeSop1(pc, code, word_index, inst); return;
|
||||
case Family::SOP2: DecodeSop2(pc, code, word_index, inst); return;
|
||||
case Family::SOPK: DecodeSopk(pc, code, word_index, inst); return;
|
||||
case Family::SOPC: DecodeSopc(pc, code, word_index, inst); return;
|
||||
case Family::SOPP: DecodeSopp(pc, code, word_index, inst); return;
|
||||
case Family::VOP1: DecodeVop1(pc, code, word_index, inst); return;
|
||||
case Family::VOP2: DecodeVop2(pc, code, word_index, inst); return;
|
||||
case Family::VOP3: DecodeVop3(pc, code, word_index, inst); return;
|
||||
case Family::VOP3P: DecodeVop3p(pc, code, word_index, inst); return;
|
||||
case Family::VOPC: DecodeVopc(pc, code, word_index, inst); return;
|
||||
case Family::VINTRP: DecodeVintrp(pc, code, word_index, inst); return;
|
||||
case Family::SMEM: DecodeSmem(pc, code, word_index, inst); return;
|
||||
case Family::MUBUF: DecodeMubuf(pc, code, word_index, inst); return;
|
||||
case Family::MTBUF: DecodeMtbuf(pc, code, word_index, inst); return;
|
||||
case Family::FLAT: DecodeFlat(pc, code, word_index, inst); return;
|
||||
case Family::DS: DecodeDs(pc, code, word_index, inst); return;
|
||||
case Family::MIMG: DecodeMimg(pc, code, word_index, inst); return;
|
||||
case Family::EXP: DecodeExp(pc, code, word_index, inst); return;
|
||||
default:
|
||||
if (error != nullptr) {
|
||||
*error =
|
||||
fmt::format("unknown RDNA2 instruction family at pc 0x{:08x}, raw=0x{:08x}", pc,
|
||||
code[word_index]);
|
||||
}
|
||||
return false;
|
||||
EXIT("unknown RDNA2 instruction family at pc 0x%08x, raw=0x%08x", pc, code[word_index]);
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeProgram(std::span<const uint32_t> code, Program& program, std::string* error) {
|
||||
void DecodeProgram(std::span<const uint32_t> code, Program& program) {
|
||||
program.instructions.clear();
|
||||
program.instructions.reserve(code.size());
|
||||
program.code = code;
|
||||
@@ -408,10 +387,7 @@ bool DecodeProgram(std::span<const uint32_t> code, Program& program, std::string
|
||||
std::vector<bool> branch_targets;
|
||||
for (uint32_t word_index = 0; word_index < code.size();) {
|
||||
program.instructions.emplace_back();
|
||||
if (!DecodeInstruction(code, word_index, program.instructions.back(), error)) {
|
||||
program.instructions.pop_back();
|
||||
return false;
|
||||
}
|
||||
DecodeInstruction(code, word_index, program.instructions.back());
|
||||
|
||||
const auto& inst = program.instructions.back();
|
||||
word_index += inst.word_count;
|
||||
@@ -425,12 +401,11 @@ bool DecodeProgram(std::span<const uint32_t> code, Program& program, std::string
|
||||
}
|
||||
if (inst.opcode == Opcode::S_ENDPGM &&
|
||||
(word_index >= code.size() || branch_targets.empty() || !branch_targets[word_index])) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetError(error, "shader decode reached the code boundary before S_ENDPGM");
|
||||
return false;
|
||||
EXIT("shader decode reached the code boundary before S_ENDPGM");
|
||||
}
|
||||
|
||||
std::string OperandToString(const Operand& operand) {
|
||||
|
||||
@@ -704,12 +704,11 @@ struct Program {
|
||||
// Code spans are trusted to contain complete instructions, valid branch targets, and 32-bit PCs.
|
||||
Family GetInstructionFamily(uint32_t word);
|
||||
// The output object must be freshly initialized.
|
||||
bool DecodeInstruction(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeProgram(std::span<const uint32_t> code, Program& program, std::string* error);
|
||||
void DecodeInstruction(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst);
|
||||
void DecodeProgram(std::span<const uint32_t> code, Program& program);
|
||||
|
||||
bool DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand, std::string* error);
|
||||
bool DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand, std::string* error);
|
||||
void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand);
|
||||
void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand);
|
||||
void DecodeVectorGpr(uint32_t reg, Operand& operand);
|
||||
void ReadLiteralOperands(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst);
|
||||
void SetRawWords(Instruction& inst, std::span<const uint32_t> code, uint32_t word_index,
|
||||
|
||||
@@ -204,55 +204,52 @@ struct VopcOpcodeInfo {
|
||||
};
|
||||
|
||||
constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
||||
{0x00u, Opcode::V_CMP_F_F32}, {0x01u, Opcode::V_CMP_LT_F32},
|
||||
{0x02u, Opcode::V_CMP_EQ_F32}, {0x03u, Opcode::V_CMP_LE_F32},
|
||||
{0x04u, Opcode::V_CMP_GT_F32}, {0x05u, Opcode::V_CMP_LG_F32},
|
||||
{0x06u, Opcode::V_CMP_GE_F32}, {0x07u, Opcode::V_CMP_O_F32},
|
||||
{0x08u, Opcode::V_CMP_U_F32}, {0x09u, Opcode::V_CMP_NGE_F32},
|
||||
{0x0au, Opcode::V_CMP_NLG_F32}, {0x0bu, Opcode::V_CMP_NGT_F32},
|
||||
{0x0cu, Opcode::V_CMP_NLE_F32}, {0x0du, Opcode::V_CMP_NEQ_F32},
|
||||
{0x0eu, Opcode::V_CMP_NLT_F32}, {0x0fu, Opcode::V_CMP_TRU_F32},
|
||||
{0x11u, Opcode::V_CMPX_LT_F32}, {0x12u, Opcode::V_CMPX_EQ_F32},
|
||||
{0x13u, Opcode::V_CMPX_LE_F32}, {0x14u, Opcode::V_CMPX_GT_F32},
|
||||
{0x15u, Opcode::V_CMPX_LG_F32}, {0x16u, Opcode::V_CMPX_GE_F32},
|
||||
{0x19u, Opcode::V_CMPX_NGE_F32}, {0x1au, Opcode::V_CMPX_NLG_F32},
|
||||
{0x1bu, Opcode::V_CMPX_NGT_F32}, {0x1cu, Opcode::V_CMPX_NLE_F32},
|
||||
{0x1du, Opcode::V_CMPX_NEQ_F32}, {0x1eu, Opcode::V_CMPX_NLT_F32},
|
||||
{0x80u, Opcode::V_CMP_F_I32}, {0x81u, Opcode::V_CMP_LT_I32},
|
||||
{0x82u, Opcode::V_CMP_EQ_I32}, {0x83u, Opcode::V_CMP_LE_I32},
|
||||
{0x84u, Opcode::V_CMP_GT_I32}, {0x85u, Opcode::V_CMP_NE_I32},
|
||||
{0x86u, Opcode::V_CMP_GE_I32}, {0x87u, Opcode::V_CMP_T_I32},
|
||||
{0x88u, Opcode::V_CMP_CLASS_F32}, {0x89u, Opcode::V_CMP_LT_I16},
|
||||
{0x8au, Opcode::V_CMP_EQ_I16}, {0x8bu, Opcode::V_CMP_LE_I16},
|
||||
{0x8cu, Opcode::V_CMP_GT_I16}, {0x8du, Opcode::V_CMP_NE_I16},
|
||||
{0x8eu, Opcode::V_CMP_GE_I16}, {0x91u, Opcode::V_CMPX_LT_I32},
|
||||
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
||||
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
||||
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
||||
{0xa9u, Opcode::V_CMP_LT_U16},
|
||||
{0xaau, Opcode::V_CMP_EQ_U16}, {0xabu, Opcode::V_CMP_LE_U16},
|
||||
{0xacu, Opcode::V_CMP_GT_U16}, {0xadu, Opcode::V_CMP_NE_U16},
|
||||
{0xaeu, Opcode::V_CMP_GE_U16}, {0xbcu, Opcode::V_CMPX_GT_U16},
|
||||
{0xc0u, Opcode::V_CMP_F_U32},
|
||||
{0xc1u, Opcode::V_CMP_LT_U32}, {0xc2u, Opcode::V_CMP_EQ_U32},
|
||||
{0xc3u, Opcode::V_CMP_LE_U32}, {0xc4u, Opcode::V_CMP_GT_U32},
|
||||
{0xc5u, Opcode::V_CMP_NE_U32}, {0xc6u, Opcode::V_CMP_GE_U32},
|
||||
{0xc7u, Opcode::V_CMP_T_U32}, {0xa2u, Opcode::V_CMP_EQ_I64, false},
|
||||
{0xb5u, Opcode::V_CMPX_NE_I64, false},
|
||||
{0xd1u, Opcode::V_CMPX_LT_U32}, {0xd2u, Opcode::V_CMPX_EQ_U32},
|
||||
{0xd3u, Opcode::V_CMPX_LE_U32}, {0xd4u, Opcode::V_CMPX_GT_U32},
|
||||
{0xd5u, Opcode::V_CMPX_NE_U32}, {0xd6u, Opcode::V_CMPX_GE_U32},
|
||||
{0xe2u, Opcode::V_CMP_EQ_U64, false}, {0xe4u, Opcode::V_CMP_GT_U64, false},
|
||||
{0xe5u, Opcode::V_CMP_NE_U64, false},
|
||||
{0xf5u, Opcode::V_CMPX_NE_U64, false},
|
||||
{0xc9u, Opcode::V_CMP_LT_F16}, {0xcau, Opcode::V_CMP_EQ_F16},
|
||||
{0xcbu, Opcode::V_CMP_LE_F16}, {0xccu, Opcode::V_CMP_GT_F16},
|
||||
{0xcdu, Opcode::V_CMP_LG_F16}, {0xceu, Opcode::V_CMP_GE_F16},
|
||||
{0xedu, Opcode::V_CMP_NEQ_F16}, {0xd9u, Opcode::V_CMPX_LT_F16},
|
||||
{0xdau, Opcode::V_CMPX_EQ_F16}, {0xdbu, Opcode::V_CMPX_LE_F16},
|
||||
{0xdcu, Opcode::V_CMPX_GT_F16}, {0xdeu, Opcode::V_CMPX_GE_F16},
|
||||
{0xfbu, Opcode::V_CMPX_NGT_F16}, {0xfdu, Opcode::V_CMPX_NEQ_F16},
|
||||
{0xfeu, Opcode::V_CMPX_NLT_F16},
|
||||
{0x00u, Opcode::V_CMP_F_F32}, {0x01u, Opcode::V_CMP_LT_F32},
|
||||
{0x02u, Opcode::V_CMP_EQ_F32}, {0x03u, Opcode::V_CMP_LE_F32},
|
||||
{0x04u, Opcode::V_CMP_GT_F32}, {0x05u, Opcode::V_CMP_LG_F32},
|
||||
{0x06u, Opcode::V_CMP_GE_F32}, {0x07u, Opcode::V_CMP_O_F32},
|
||||
{0x08u, Opcode::V_CMP_U_F32}, {0x09u, Opcode::V_CMP_NGE_F32},
|
||||
{0x0au, Opcode::V_CMP_NLG_F32}, {0x0bu, Opcode::V_CMP_NGT_F32},
|
||||
{0x0cu, Opcode::V_CMP_NLE_F32}, {0x0du, Opcode::V_CMP_NEQ_F32},
|
||||
{0x0eu, Opcode::V_CMP_NLT_F32}, {0x0fu, Opcode::V_CMP_TRU_F32},
|
||||
{0x11u, Opcode::V_CMPX_LT_F32}, {0x12u, Opcode::V_CMPX_EQ_F32},
|
||||
{0x13u, Opcode::V_CMPX_LE_F32}, {0x14u, Opcode::V_CMPX_GT_F32},
|
||||
{0x15u, Opcode::V_CMPX_LG_F32}, {0x16u, Opcode::V_CMPX_GE_F32},
|
||||
{0x19u, Opcode::V_CMPX_NGE_F32}, {0x1au, Opcode::V_CMPX_NLG_F32},
|
||||
{0x1bu, Opcode::V_CMPX_NGT_F32}, {0x1cu, Opcode::V_CMPX_NLE_F32},
|
||||
{0x1du, Opcode::V_CMPX_NEQ_F32}, {0x1eu, Opcode::V_CMPX_NLT_F32},
|
||||
{0x80u, Opcode::V_CMP_F_I32}, {0x81u, Opcode::V_CMP_LT_I32},
|
||||
{0x82u, Opcode::V_CMP_EQ_I32}, {0x83u, Opcode::V_CMP_LE_I32},
|
||||
{0x84u, Opcode::V_CMP_GT_I32}, {0x85u, Opcode::V_CMP_NE_I32},
|
||||
{0x86u, Opcode::V_CMP_GE_I32}, {0x87u, Opcode::V_CMP_T_I32},
|
||||
{0x88u, Opcode::V_CMP_CLASS_F32}, {0x89u, Opcode::V_CMP_LT_I16},
|
||||
{0x8au, Opcode::V_CMP_EQ_I16}, {0x8bu, Opcode::V_CMP_LE_I16},
|
||||
{0x8cu, Opcode::V_CMP_GT_I16}, {0x8du, Opcode::V_CMP_NE_I16},
|
||||
{0x8eu, Opcode::V_CMP_GE_I16}, {0x91u, Opcode::V_CMPX_LT_I32},
|
||||
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
||||
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
||||
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
||||
{0xa9u, Opcode::V_CMP_LT_U16}, {0xaau, Opcode::V_CMP_EQ_U16},
|
||||
{0xabu, Opcode::V_CMP_LE_U16}, {0xacu, Opcode::V_CMP_GT_U16},
|
||||
{0xadu, Opcode::V_CMP_NE_U16}, {0xaeu, Opcode::V_CMP_GE_U16},
|
||||
{0xbcu, Opcode::V_CMPX_GT_U16}, {0xc0u, Opcode::V_CMP_F_U32},
|
||||
{0xc1u, Opcode::V_CMP_LT_U32}, {0xc2u, Opcode::V_CMP_EQ_U32},
|
||||
{0xc3u, Opcode::V_CMP_LE_U32}, {0xc4u, Opcode::V_CMP_GT_U32},
|
||||
{0xc5u, Opcode::V_CMP_NE_U32}, {0xc6u, Opcode::V_CMP_GE_U32},
|
||||
{0xc7u, Opcode::V_CMP_T_U32}, {0xa2u, Opcode::V_CMP_EQ_I64, false},
|
||||
{0xb5u, Opcode::V_CMPX_NE_I64, false}, {0xd1u, Opcode::V_CMPX_LT_U32},
|
||||
{0xd2u, Opcode::V_CMPX_EQ_U32}, {0xd3u, Opcode::V_CMPX_LE_U32},
|
||||
{0xd4u, Opcode::V_CMPX_GT_U32}, {0xd5u, Opcode::V_CMPX_NE_U32},
|
||||
{0xd6u, Opcode::V_CMPX_GE_U32}, {0xe2u, Opcode::V_CMP_EQ_U64, false},
|
||||
{0xe4u, Opcode::V_CMP_GT_U64, false}, {0xe5u, Opcode::V_CMP_NE_U64, false},
|
||||
{0xf5u, Opcode::V_CMPX_NE_U64, false}, {0xc9u, Opcode::V_CMP_LT_F16},
|
||||
{0xcau, Opcode::V_CMP_EQ_F16}, {0xcbu, Opcode::V_CMP_LE_F16},
|
||||
{0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16},
|
||||
{0xceu, Opcode::V_CMP_GE_F16}, {0xedu, Opcode::V_CMP_NEQ_F16},
|
||||
{0xd9u, Opcode::V_CMPX_LT_F16}, {0xdau, Opcode::V_CMPX_EQ_F16},
|
||||
{0xdbu, Opcode::V_CMPX_LE_F16}, {0xdcu, Opcode::V_CMPX_GT_F16},
|
||||
{0xdeu, Opcode::V_CMPX_GE_F16}, {0xfbu, Opcode::V_CMPX_NGT_F16},
|
||||
{0xfdu, Opcode::V_CMPX_NEQ_F16}, {0xfeu, Opcode::V_CMPX_NLT_F16},
|
||||
};
|
||||
|
||||
constexpr auto VOPC_OPS = Detail::MakeOpcodeTable<0x100>(VOPC_OPCODE_LIST);
|
||||
@@ -641,8 +638,8 @@ bool ValidateVop1Sdwa(Instruction& inst, uint32_t opcode, uint32_t modifier) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, Instruction& inst, std::string* error) {
|
||||
void DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto src0 = modifier & 0xffu;
|
||||
const auto dst_sel = (modifier >> 8u) & 0x7u;
|
||||
@@ -657,32 +654,27 @@ bool DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
|
||||
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
if (!ValidateVop1Sdwa(inst, opcode, modifier)) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
const bool scalar_dst = UsesScalarDestination(inst.opcode);
|
||||
if (scalar_dst) {
|
||||
if (!DecodeScalarDestination(vdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(vdst, pc, inst.dst);
|
||||
} else {
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
}
|
||||
if (!DecodeScalarSource(src0 + (s0 == 0u ? 256u : 0u), pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0 + (s0 == 0u ? 256u : 0u), pc, inst.src0);
|
||||
inst.dst.sdwa_sel = dst_sel;
|
||||
inst.dst.sdwa_dst_unused = dst_u;
|
||||
inst.dst.explicit_sdwa_dst = true;
|
||||
inst.dst.clamp = clamp != 0u;
|
||||
inst.dst.omod = omod;
|
||||
inst.src0.sdwa_sel = src0_sel;
|
||||
inst.src0.sdwa_sext = src0_sext != 0u;
|
||||
inst.src0.negate = src0_neg != 0u;
|
||||
inst.src0.absolute = src0_abs != 0u;
|
||||
inst.src_count = 1;
|
||||
inst.src0.sdwa_sel = src0_sel;
|
||||
inst.src0.sdwa_sext = src0_sext != 0u;
|
||||
inst.src0.negate = src0_neg != 0u;
|
||||
inst.src0.absolute = src0_abs != 0u;
|
||||
inst.src_count = 1;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplyDppModifier(Operand& operand, uint32_t modifier) {
|
||||
@@ -696,38 +688,33 @@ void ApplyDppModifier(Operand& operand, uint32_t modifier) {
|
||||
operand.dpp_row_mask = (modifier >> 28u) & 0xfu;
|
||||
}
|
||||
|
||||
bool DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, Instruction& inst, std::string* error) {
|
||||
void DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto src0 = modifier & 0xffu;
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
|
||||
const bool scalar_dst = UsesScalarDestination(inst.opcode);
|
||||
if (scalar_dst) {
|
||||
if (!DecodeScalarDestination(vdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(vdst, pc, inst.dst);
|
||||
} else {
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
}
|
||||
if (!DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0 + 256u, pc, inst.src0);
|
||||
ApplyDppModifier(inst.src0, modifier);
|
||||
inst.src_count = 1;
|
||||
|
||||
if (!IsVop1FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute)) {
|
||||
SetUnsupported(inst, Family::VOP1, opcode,
|
||||
"VOP1 DPP integer source modifiers are not supported");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
using Vop1ModifierDecodeFn = bool (*)(uint32_t pc, std::span<const uint32_t> code,
|
||||
using Vop1ModifierDecodeFn = void (*)(uint32_t pc, std::span<const uint32_t> code,
|
||||
uint32_t word_index, uint32_t opcode, uint32_t vdst,
|
||||
Instruction& inst, std::string* error);
|
||||
Instruction& inst);
|
||||
|
||||
struct Vop1ModifierDecoder {
|
||||
uint32_t escape = 0;
|
||||
@@ -740,20 +727,14 @@ constexpr Vop1ModifierDecoder VOP1_MODIFIER_DECODERS[] = {
|
||||
};
|
||||
|
||||
bool TryDecodeVop1Modifier(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t src0, uint32_t opcode, uint32_t vdst, Instruction& inst,
|
||||
std::string* error, bool* handled) {
|
||||
if (handled != nullptr) {
|
||||
*handled = false;
|
||||
}
|
||||
uint32_t src0, uint32_t opcode, uint32_t vdst, Instruction& inst) {
|
||||
for (const auto& decoder: VOP1_MODIFIER_DECODERS) {
|
||||
if (decoder.escape == src0) {
|
||||
if (handled != nullptr) {
|
||||
*handled = true;
|
||||
}
|
||||
return decoder.decode(pc, code, word_index, opcode, vdst, inst, error);
|
||||
decoder.decode(pc, code, word_index, opcode, vdst, inst);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsVop2FloatSourceOpcode(Opcode opcode) {
|
||||
@@ -1034,9 +1015,8 @@ bool ValidateVop2Sdwa(Instruction& inst, uint32_t opcode, const Vop2SdwaFields&
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FinalizeVop2Instruction(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst, std::string* error) {
|
||||
(void)pc;
|
||||
void FinalizeVop2Instruction(std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
switch (inst.opcode) {
|
||||
case Opcode::V_MADMK_F32:
|
||||
case Opcode::V_FMAMK_F16:
|
||||
@@ -1067,55 +1047,48 @@ bool FinalizeVop2Instruction(uint32_t pc, std::span<const uint32_t> code, uint32
|
||||
default: inst.src_count = 2; break;
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVop2Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, uint32_t vsrc1, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVop2Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, uint32_t vsrc1, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto fields = DecodeVop2SdwaFields(modifier);
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
if (!ValidateVop2Sdwa(inst, opcode, fields)) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
if (!DecodeScalarSource(fields.src0 + (fields.s0 == 0u ? 256u : 0u), pc, inst.src0, error) ||
|
||||
!DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(fields.src0 + (fields.s0 == 0u ? 256u : 0u), pc, inst.src0);
|
||||
DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, inst.src1);
|
||||
inst.dst.sdwa_sel = fields.dst_sel;
|
||||
inst.dst.sdwa_dst_unused = fields.dst_u;
|
||||
inst.dst.explicit_sdwa_dst = true;
|
||||
inst.dst.clamp = fields.clamp != 0u;
|
||||
inst.dst.omod = fields.omod;
|
||||
inst.src0.sdwa_sel = fields.src0_sel;
|
||||
inst.src0.sdwa_sext = fields.src0_sext != 0u;
|
||||
inst.src0.negate = fields.src0_neg != 0u;
|
||||
inst.src0.absolute = fields.src0_abs != 0u;
|
||||
inst.src1.sdwa_sel = fields.src1_sel;
|
||||
inst.src1.sdwa_sext = fields.src1_sext != 0u;
|
||||
inst.src1.negate = fields.src1_neg != 0u;
|
||||
inst.src1.absolute = fields.src1_abs != 0u;
|
||||
return FinalizeVop2Instruction(pc, code, word_index, inst, error);
|
||||
inst.src0.sdwa_sel = fields.src0_sel;
|
||||
inst.src0.sdwa_sext = fields.src0_sext != 0u;
|
||||
inst.src0.negate = fields.src0_neg != 0u;
|
||||
inst.src0.absolute = fields.src0_abs != 0u;
|
||||
inst.src1.sdwa_sel = fields.src1_sel;
|
||||
inst.src1.sdwa_sext = fields.src1_sext != 0u;
|
||||
inst.src1.negate = fields.src1_neg != 0u;
|
||||
inst.src1.absolute = fields.src1_abs != 0u;
|
||||
FinalizeVop2Instruction(code, word_index, inst);
|
||||
}
|
||||
|
||||
bool DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, uint32_t vsrc1, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vdst, uint32_t vsrc1, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto src0 = modifier & 0xffu;
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
DecodeVectorGpr(vsrc1, inst.src1);
|
||||
if (!DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0 + 256u, pc, inst.src0);
|
||||
ApplyDppModifier(inst.src0, modifier);
|
||||
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
|
||||
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
|
||||
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
|
||||
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
|
||||
const bool packed_fmac = inst.opcode == Opcode::V_PK_FMAC_F16;
|
||||
if (packed_fmac) {
|
||||
inst.src0.negate_hi = inst.src0.negate;
|
||||
@@ -1126,14 +1099,14 @@ bool DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
||||
(inst.src0.negate || inst.src0.absolute || inst.src1.negate || inst.src1.absolute)) {
|
||||
SetUnsupported(inst, Family::VOP2, opcode,
|
||||
"VOP2 DPP integer source modifiers are not supported");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
return FinalizeVop2Instruction(pc, code, word_index, inst, error);
|
||||
FinalizeVop2Instruction(code, word_index, inst);
|
||||
}
|
||||
|
||||
using Vop2ModifierDecodeFn = bool (*)(uint32_t pc, std::span<const uint32_t> code,
|
||||
using Vop2ModifierDecodeFn = void (*)(uint32_t pc, std::span<const uint32_t> code,
|
||||
uint32_t word_index, uint32_t opcode, uint32_t vdst,
|
||||
uint32_t vsrc1, Instruction& inst, std::string* error);
|
||||
uint32_t vsrc1, Instruction& inst);
|
||||
|
||||
struct Vop2ModifierDecoder {
|
||||
uint32_t escape = 0;
|
||||
@@ -1147,19 +1120,14 @@ constexpr Vop2ModifierDecoder VOP2_MODIFIER_DECODERS[] = {
|
||||
|
||||
bool TryDecodeVop2Modifier(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t src0, uint32_t opcode, uint32_t vdst, uint32_t vsrc1,
|
||||
Instruction& inst, std::string* error, bool* handled) {
|
||||
if (handled != nullptr) {
|
||||
*handled = false;
|
||||
}
|
||||
Instruction& inst) {
|
||||
for (const auto& decoder: VOP2_MODIFIER_DECODERS) {
|
||||
if (decoder.escape == src0) {
|
||||
if (handled != nullptr) {
|
||||
*handled = true;
|
||||
}
|
||||
return decoder.decode(pc, code, word_index, opcode, vdst, vsrc1, inst, error);
|
||||
decoder.decode(pc, code, word_index, opcode, vdst, vsrc1, inst);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct VopcSdwaFields {
|
||||
@@ -1200,31 +1168,29 @@ bool SupportsVopcSdwa(Opcode opcode) {
|
||||
return opcode != Opcode::UNSUPPORTED;
|
||||
}
|
||||
|
||||
bool DecodeVopcSdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vsrc1, Instruction& inst, std::string* error) {
|
||||
void DecodeVopcSdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vsrc1, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto fields = DecodeVopcSdwaFields(modifier);
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
if (fields.src0_sel > 6u || fields.src1_sel > 6u) {
|
||||
SetUnsupported(inst, Family::VOPC, opcode, "VOPC SDWA selector is invalid");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (!SupportsVopcSdwa(inst.opcode)) {
|
||||
SetUnsupported(inst, Family::VOPC, opcode,
|
||||
"VOPC SDWA modifier is not supported for opcode");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DecodeScalarSource(fields.src0 + (fields.s0 == 0u ? 256u : 0u), pc, inst.src0, error) ||
|
||||
!DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(fields.src0 + (fields.s0 == 0u ? 256u : 0u), pc, inst.src0);
|
||||
DecodeScalarSource(vsrc1 + (fields.s1 == 0u ? 256u : 0u), pc, inst.src1);
|
||||
if (IsVopcCompareExec(inst.opcode)) {
|
||||
inst.dst.kind = OperandKind::ExecLo;
|
||||
} else if (fields.sd == 0u) {
|
||||
inst.dst.kind = OperandKind::VccLo;
|
||||
} else if (!DecodeScalarDestination(fields.sdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
} else {
|
||||
DecodeScalarDestination(fields.sdst, pc, inst.dst);
|
||||
}
|
||||
inst.src0.sdwa_sel = fields.src0_sel;
|
||||
inst.src0.sdwa_sext = fields.src0_sext != 0u;
|
||||
@@ -1236,34 +1202,30 @@ bool DecodeVopcSdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
|
||||
inst.src1.absolute = fields.src1_abs != 0u;
|
||||
inst.src_count = 2;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVopcDpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vsrc1, Instruction& inst, std::string* error) {
|
||||
void DecodeVopcDpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
uint32_t opcode, uint32_t vsrc1, Instruction& inst) {
|
||||
const auto modifier = code[word_index + 1u];
|
||||
const auto src0 = modifier & 0xffu;
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOPC, opcode, "VOPC opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
const auto* info = Detail::FindOpcode(VOPC_OPS, opcode);
|
||||
if (info == nullptr || !info->supports_dpp) {
|
||||
SetUnsupported(inst, Family::VOPC, opcode, "VOPC DPP modifier is not supported for opcode");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
DecodeVectorGpr(vsrc1, inst.src1);
|
||||
if (!DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0 + 256u, pc, inst.src0);
|
||||
inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo;
|
||||
ApplyDppModifier(inst.src0, modifier);
|
||||
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
|
||||
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
|
||||
inst.src_count = 2;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t NativeVop3SourceCount(Opcode opcode) {
|
||||
@@ -1560,8 +1522,8 @@ bool IsVopcCompareExec(Opcode opcode) {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 25u) & 0x3fu;
|
||||
const uint32_t vdst = (word >> 17u) & 0xffu;
|
||||
@@ -1577,27 +1539,20 @@ bool DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
bool modifier_handled = false;
|
||||
if (!TryDecodeVop2Modifier(pc, code, word_index, src0, opcode, vdst, vsrc1, inst, error,
|
||||
&modifier_handled)) {
|
||||
return false;
|
||||
}
|
||||
if (modifier_handled) {
|
||||
return true;
|
||||
if (TryDecodeVop2Modifier(pc, code, word_index, src0, opcode, vdst, vsrc1, inst)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
DecodeVectorGpr(vsrc1, inst.src1);
|
||||
if (!DecodeScalarSource(src0, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
return FinalizeVop2Instruction(pc, code, word_index, inst, error);
|
||||
DecodeScalarSource(src0, pc, inst.src0);
|
||||
FinalizeVop2Instruction(code, word_index, inst);
|
||||
}
|
||||
|
||||
bool DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 9u) & 0xffu;
|
||||
const uint32_t src0 = word & 0x1ffu;
|
||||
@@ -1612,39 +1567,29 @@ bool DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOP1, opcode, "VOP1 opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (inst.opcode == Opcode::V_NOP) {
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
inst.src_count = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
bool modifier_handled = false;
|
||||
if (!TryDecodeVop1Modifier(pc, code, word_index, src0, opcode, vdst, inst, error,
|
||||
&modifier_handled)) {
|
||||
return false;
|
||||
}
|
||||
if (modifier_handled) {
|
||||
return true;
|
||||
if (TryDecodeVop1Modifier(pc, code, word_index, src0, opcode, vdst, inst)) {
|
||||
return;
|
||||
}
|
||||
const bool scalar_dst = UsesScalarDestination(inst.opcode);
|
||||
if (scalar_dst) {
|
||||
if (!DecodeScalarDestination(vdst, pc, inst.dst, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(vdst, pc, inst.dst);
|
||||
} else {
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
}
|
||||
if (!DecodeScalarSource(src0, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0, pc, inst.src0);
|
||||
inst.src_count = 1;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word = code[word_index];
|
||||
const uint32_t opcode = (word >> 17u) & 0xffu;
|
||||
const uint32_t src0 = word & 0x1ffu;
|
||||
@@ -1659,25 +1604,22 @@ bool DecodeVopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
SetRawWords(inst, code, word_index, 1);
|
||||
|
||||
switch (src0) {
|
||||
case 249u: return DecodeVopcSdwa(pc, code, word_index, opcode, vsrc1, inst, error);
|
||||
case 250u: return DecodeVopcDpp(pc, code, word_index, opcode, vsrc1, inst, error);
|
||||
case 249u: DecodeVopcSdwa(pc, code, word_index, opcode, vsrc1, inst); return;
|
||||
case 250u: DecodeVopcDpp(pc, code, word_index, opcode, vsrc1, inst); return;
|
||||
default: break;
|
||||
}
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOPC, opcode, "VOPC opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
DecodeVectorGpr(vsrc1, inst.src1);
|
||||
if (!DecodeScalarSource(src0, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0, pc, inst.src0);
|
||||
inst.src_count = 2;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error) {
|
||||
void DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word0 = code[word_index];
|
||||
const uint32_t word1 = code[word_index + 1u];
|
||||
const uint32_t opcode = (word0 >> 16u) & 0x3ffu;
|
||||
@@ -1728,29 +1670,26 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
reason = "VOP3 mad-mix clamp/omod is not implemented";
|
||||
}
|
||||
SetUnsupported(inst, Family::VOP3, opcode, reason);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOP3, opcode, "VOP3 opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (inst.opcode == Opcode::V_NOP) {
|
||||
inst.dst.kind = OperandKind::Null;
|
||||
inst.src_count = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
bool dst_ok = true;
|
||||
if (compare_exec) {
|
||||
inst.dst.kind = OperandKind::ExecLo;
|
||||
} else if (scalar_dst) {
|
||||
// VOP3A uses VDST for VOPC and the scalar-destination lane-read opcodes.
|
||||
dst_ok = DecodeScalarDestination(vdst, pc, inst.dst, error);
|
||||
DecodeScalarDestination(vdst, pc, inst.dst);
|
||||
} else {
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
}
|
||||
if (!dst_ok || !DecodeScalarSource(src0, pc, inst.src0, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src0, pc, inst.src0);
|
||||
inst.dst.clamp = native_clamp_modifier && clamp != 0u;
|
||||
inst.dst.omod = native_result_modifiers ? omod : 0u;
|
||||
if (permlane) {
|
||||
@@ -1758,15 +1697,13 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
inst.dst.op_sel_hi = (op_sel & 0x2u) != 0u;
|
||||
}
|
||||
if (vop3_vopc) {
|
||||
if (!DecodeScalarSource(src1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
inst.src_count = 2;
|
||||
if (native_source_modifiers) {
|
||||
ApplyNativeVop3SourceModifiers(inst, abs, neg);
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (IsVop3EncodedVop1(opcode)) {
|
||||
inst.src_count = 1;
|
||||
@@ -1774,45 +1711,35 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
ApplyNativeVop3SourceModifiers(inst, abs, neg);
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (carry_in_out) {
|
||||
if (!DecodeScalarDestination(sdst, pc, inst.dst2, error) ||
|
||||
!DecodeScalarSource(src1, pc, inst.src1, error) ||
|
||||
!DecodeScalarSource(src2, pc, inst.src2, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(sdst, pc, inst.dst2);
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
DecodeScalarSource(src2, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (vop3b_carry_out) {
|
||||
if (!DecodeScalarDestination(sdst, pc, inst.dst2, error) ||
|
||||
!DecodeScalarSource(src1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(sdst, pc, inst.dst2);
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
inst.src_count = 2;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (vop3b_mad_u64) {
|
||||
if (!DecodeScalarDestination(sdst, pc, inst.dst2, error) ||
|
||||
!DecodeScalarSource(src1, pc, inst.src1, error) ||
|
||||
!DecodeScalarSource(src2, pc, inst.src2, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarDestination(sdst, pc, inst.dst2);
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
DecodeScalarSource(src2, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (IsVop3EncodedVop2(opcode)) {
|
||||
if (!DecodeScalarSource(src1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
if (inst.opcode == Opcode::V_CNDMASK_B32) {
|
||||
if (!DecodeScalarSource(src2, pc, inst.src2, error)) {
|
||||
return false;
|
||||
}
|
||||
DecodeScalarSource(src2, pc, inst.src2);
|
||||
inst.src_count = 3;
|
||||
} else {
|
||||
inst.src_count = 2;
|
||||
@@ -1821,14 +1748,12 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
ApplyNativeVop3SourceModifiers(inst, abs, neg);
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
if (!DecodeScalarSource(src1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
inst.src_count = NativeVop3SourceCount(inst.opcode);
|
||||
if (inst.src_count > 2u && !DecodeScalarSource(src2, pc, inst.src2, error)) {
|
||||
return false;
|
||||
if (inst.src_count > 2u) {
|
||||
DecodeScalarSource(src2, pc, inst.src2);
|
||||
}
|
||||
if (mad_mix) {
|
||||
ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg);
|
||||
@@ -1844,11 +1769,10 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
ApplyNativeVop3SourceModifiers(inst, abs, neg);
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst, std::string* error) {
|
||||
void DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word0 = code[word_index];
|
||||
const uint32_t word1 = code[word_index + 1u];
|
||||
const uint32_t opcode = (word0 >> 16u) & 0x7fu;
|
||||
@@ -1872,16 +1796,14 @@ bool DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
||||
|
||||
if (inst.opcode == Opcode::UNSUPPORTED) {
|
||||
SetUnsupported(inst, Family::VOP3P, opcode, "VOP3P opcode is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
inst.src_count = Vop3pSourceCount(inst.opcode);
|
||||
DecodeVectorGpr(vdst, inst.dst);
|
||||
if (!DecodeScalarSource(src0, pc, inst.src0, error) ||
|
||||
!DecodeScalarSource(src1, pc, inst.src1, error)) {
|
||||
return false;
|
||||
}
|
||||
if (inst.src_count > 2u && !DecodeScalarSource(src2, pc, inst.src2, error)) {
|
||||
return false;
|
||||
DecodeScalarSource(src0, pc, inst.src0);
|
||||
DecodeScalarSource(src1, pc, inst.src1);
|
||||
if (inst.src_count > 2u) {
|
||||
DecodeScalarSource(src2, pc, inst.src2);
|
||||
}
|
||||
if (inst.opcode == Opcode::V_FMA_F32) {
|
||||
inst.dst.clamp = clamp != 0u;
|
||||
@@ -1891,7 +1813,7 @@ bool DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
||||
inst.dst.clamp = clamp != 0u;
|
||||
} else if (clamp != 0u) {
|
||||
SetUnsupported(inst, Family::VOP3P, opcode, "VOP3P integer clamp is not implemented");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
ApplyVop3pSourceModifiers(inst, op_sel, op_sel_hi, neg, neg_hi);
|
||||
if (inst.opcode == Opcode::V_MAD_MIXLO_F16) {
|
||||
@@ -1904,7 +1826,6 @@ bool DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
||||
ApplyVop3pMixAbsModifiers(inst);
|
||||
}
|
||||
ReadLiteralOperands(code, word_index, inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DecodeVintrp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Decoder {
|
||||
|
||||
bool DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeVopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, Instruction& inst,
|
||||
std::string* error);
|
||||
bool DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst, std::string* error);
|
||||
void DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeVopc(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeVop3p(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
void DecodeVintrp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user