This commit is contained in:
ivan999 2025-07-10 16:09:34 +05:30 committed by GitHub
commit 99f72c8760
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 157 additions and 279 deletions

View file

@ -16,76 +16,6 @@ T extract(T value, u32 lst, u32 fst) {
} }
} // namespace bit } // namespace bit
InstEncoding GetInstructionEncoding(u32 token) {
auto encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_9bit);
switch (encoding) {
case InstEncoding::SOP1:
case InstEncoding::SOPP:
case InstEncoding::SOPC:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_7bit);
switch (encoding) {
case InstEncoding::VOP1:
case InstEncoding::VOPC:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_6bit);
switch (encoding) {
case InstEncoding::VOP3:
case InstEncoding::EXP:
case InstEncoding::VINTRP:
case InstEncoding::DS:
case InstEncoding::MUBUF:
case InstEncoding::MTBUF:
case InstEncoding::MIMG:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_5bit);
switch (encoding) {
case InstEncoding::SMRD:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_4bit);
switch (encoding) {
case InstEncoding::SOPK:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_2bit);
switch (encoding) {
case InstEncoding::SOP2:
return encoding;
default:
break;
}
encoding = static_cast<InstEncoding>(token & (u32)EncodingMask::MASK_1bit);
switch (encoding) {
case InstEncoding::VOP2:
return encoding;
default:
break;
}
UNREACHABLE();
return InstEncoding::ILLEGAL;
}
bool HasAdditionalLiteral(InstEncoding encoding, Opcode opcode) { bool HasAdditionalLiteral(InstEncoding encoding, Opcode opcode) {
switch (encoding) { switch (encoding) {
case InstEncoding::SOPK: { case InstEncoding::SOPK: {
@ -107,128 +37,153 @@ bool IsVop3BEncoding(Opcode opcode) {
opcode == Opcode::V_MAD_U64_U32 || opcode == Opcode::V_MAD_I64_I32; opcode == Opcode::V_MAD_U64_U32 || opcode == Opcode::V_MAD_I64_I32;
} }
GcnInst GcnDecodeContext::decodeInstruction(GcnCodeSlice& code) { inline static InstEncoding castToken(u32 token, EncodingMask mask) {
const uint32_t token = code.at(0); return static_cast<InstEncoding>(token & static_cast<u32>(mask));
}
InstEncoding encoding = GetInstructionEncoding(token); GcnInst GcnDecodeContext::decodeInstruction(GcnCodeSlice& code) {
ASSERT_MSG(encoding != InstEncoding::ILLEGAL, "illegal encoding"); const u32 token = code.at(0);
uint32_t encodingLen = getEncodingLength(encoding);
// Clear the instruction // Clear the instruction
m_instruction = GcnInst(); m_instruction = GcnInst();
// Decode OpcodeMap opcodeMap;
if (encodingLen == sizeof(uint32_t)) { bool is64bit = false;
decodeInstruction32(encoding, code);
m_instruction.encoding = castToken(token, EncodingMask::MASK_7bit);
switch (m_instruction.encoding) {
case InstEncoding::VOP1:
opcodeMap = OpcodeMap::OP_MAP_VOP1;
decodeInstructionVOP1(code.readu32());
break;
case InstEncoding::VOPC:
opcodeMap = OpcodeMap::OP_MAP_VOPC;
decodeInstructionVOPC(code.readu32());
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_1bit);
switch (m_instruction.encoding) {
case InstEncoding::VOP2:
opcodeMap = OpcodeMap::OP_MAP_VOP2;
decodeInstructionVOP2(code.readu32());
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_9bit);
switch (m_instruction.encoding) {
case InstEncoding::SOP1:
opcodeMap = OpcodeMap::OP_MAP_SOP1;
decodeInstructionSOP1(code.readu32());
break;
case InstEncoding::SOPP:
opcodeMap = OpcodeMap::OP_MAP_SOPP;
decodeInstructionSOPP(code.readu32());
break;
case InstEncoding::SOPC:
opcodeMap = OpcodeMap::OP_MAP_SOPC;
decodeInstructionSOPC(code.readu32());
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_6bit);
switch (m_instruction.encoding) {
case InstEncoding::VINTRP:
opcodeMap = OpcodeMap::OP_MAP_VINTRP;
decodeInstructionVINTRP(code.readu32());
break;
case InstEncoding::VOP3:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_VOP3;
decodeInstructionVOP3(code.readu64()); // VOP3 is 64 bits instruction
break;
case InstEncoding::EXP:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_EXP;
decodeInstructionEXP(code.readu64()); // EXP is 64 bits instruction
break;
case InstEncoding::DS:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_DS;
decodeInstructionDS(code.readu64()); // DS is 64 bits instruction
break;
case InstEncoding::MUBUF:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_MUBUF;
decodeInstructionMUBUF(code.readu64()); // MUBUF is 64 bits instruction
break;
case InstEncoding::MTBUF:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_MTBUF;
decodeInstructionMTBUF(code.readu64()); // MTBUF is 64 bits instruction
break;
case InstEncoding::MIMG:
is64bit = true;
opcodeMap = OpcodeMap::OP_MAP_MIMG;
decodeInstructionMIMG(code.readu64()); // MIMG is 64 bits instruction
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_5bit);
switch (m_instruction.encoding) {
case InstEncoding::SMRD:
opcodeMap = OpcodeMap::OP_MAP_SMRD;
decodeInstructionSMRD(code.readu32());
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_4bit);
switch (m_instruction.encoding) {
case InstEncoding::SOPK:
opcodeMap = OpcodeMap::OP_MAP_SOPK;
decodeInstructionSOPK(code.readu32());
break;
default:
m_instruction.encoding = castToken(token, EncodingMask::MASK_2bit);
switch (m_instruction.encoding) {
case InstEncoding::SOP2:
opcodeMap = OpcodeMap::OP_MAP_SOP2;
decodeInstructionSOP2(code.readu32());
break;
default:
UNREACHABLE();
ASSERT_MSG("illegal encoding");
} // switch mask_2bit
} // switch mask_4bit
} // switch mask_5bit
} // switch mask_6bit
} // switch mask_9bit
} // switch mask_1bit
} // switch mask_7bit
if (is64bit) {
// Update instruction meta info.
updateInstructionMeta(opcodeMap, sizeof(uint64_t));
} else { } else {
decodeInstruction64(encoding, code); // Update instruction meta info.
} updateInstructionMeta(opcodeMap, sizeof(uint32_t));
// Detect literal constant. Only 32 bits instructions may have literal constant.
// Update instruction meta info. // Note: Literal constant decode must be performed after meta info updated.
updateInstructionMeta(encoding); decodeLiteralConstant(opcodeMap, code);
// Detect literal constant. Only 32 bits instructions may have literal constant.
// Note: Literal constant decode must be performed after meta info updated.
if (encodingLen == sizeof(u32)) {
decodeLiteralConstant(encoding, code);
} }
repairOperandType(); repairOperandType();
return m_instruction; return m_instruction;
} }
uint32_t GcnDecodeContext::getEncodingLength(InstEncoding encoding) { uint32_t GcnDecodeContext::mapEncodingOp(OpcodeMap opcodeMap, Opcode opcode) {
uint32_t instLength = 0;
switch (encoding) {
case InstEncoding::SOP1:
case InstEncoding::SOPP:
case InstEncoding::SOPC:
case InstEncoding::SOPK:
case InstEncoding::SOP2:
case InstEncoding::VOP1:
case InstEncoding::VOPC:
case InstEncoding::VOP2:
case InstEncoding::SMRD:
case InstEncoding::VINTRP:
instLength = sizeof(uint32_t);
break;
case InstEncoding::VOP3:
case InstEncoding::MUBUF:
case InstEncoding::MTBUF:
case InstEncoding::MIMG:
case InstEncoding::DS:
case InstEncoding::EXP:
instLength = sizeof(uint64_t);
break;
default:
break;
}
return instLength;
}
uint32_t GcnDecodeContext::getOpMapOffset(InstEncoding encoding) {
uint32_t offset = 0;
switch (encoding) {
case InstEncoding::SOP1:
offset = (uint32_t)OpcodeMap::OP_MAP_SOP1;
break;
case InstEncoding::SOPP:
offset = (uint32_t)OpcodeMap::OP_MAP_SOPP;
break;
case InstEncoding::SOPC:
offset = (uint32_t)OpcodeMap::OP_MAP_SOPC;
break;
case InstEncoding::VOP1:
offset = (uint32_t)OpcodeMap::OP_MAP_VOP1;
break;
case InstEncoding::VOPC:
offset = (uint32_t)OpcodeMap::OP_MAP_VOPC;
break;
case InstEncoding::VOP3:
offset = (uint32_t)OpcodeMap::OP_MAP_VOP3;
break;
case InstEncoding::EXP:
offset = (uint32_t)OpcodeMap::OP_MAP_EXP;
break;
case InstEncoding::VINTRP:
offset = (uint32_t)OpcodeMap::OP_MAP_VINTRP;
break;
case InstEncoding::DS:
offset = (uint32_t)OpcodeMap::OP_MAP_DS;
break;
case InstEncoding::MUBUF:
offset = (uint32_t)OpcodeMap::OP_MAP_MUBUF;
break;
case InstEncoding::MTBUF:
offset = (uint32_t)OpcodeMap::OP_MAP_MTBUF;
break;
case InstEncoding::MIMG:
offset = (uint32_t)OpcodeMap::OP_MAP_MIMG;
break;
case InstEncoding::SMRD:
offset = (uint32_t)OpcodeMap::OP_MAP_SMRD;
break;
case InstEncoding::SOPK:
offset = (uint32_t)OpcodeMap::OP_MAP_SOPK;
break;
case InstEncoding::SOP2:
offset = (uint32_t)OpcodeMap::OP_MAP_SOP2;
break;
case InstEncoding::VOP2:
offset = (uint32_t)OpcodeMap::OP_MAP_VOP2;
break;
default:
break;
}
return offset;
}
uint32_t GcnDecodeContext::mapEncodingOp(InstEncoding encoding, Opcode opcode) {
// Map from uniform opcode to encoding specific opcode. // Map from uniform opcode to encoding specific opcode.
uint32_t encodingOp = 0; uint32_t encodingOp = 0;
if (encoding == InstEncoding::VOP3) { if (m_instruction.encoding == InstEncoding::VOP3) {
if (opcode >= Opcode::V_CMP_F_F32 && opcode <= Opcode::V_CMPX_T_U64) { if (opcode >= Opcode::V_CMP_F_F32 && opcode <= Opcode::V_CMPX_T_U64) {
uint32_t op = uint32_t op =
static_cast<uint32_t>(opcode) - static_cast<uint32_t>(OpcodeMap::OP_MAP_VOPC); static_cast<uint32_t>(opcode) - static_cast<uint32_t>(OpcodeMap::OP_MAP_VOPC);
@ -246,28 +201,27 @@ uint32_t GcnDecodeContext::mapEncodingOp(InstEncoding encoding, Opcode opcode) {
static_cast<uint32_t>(opcode) - static_cast<uint32_t>(OpcodeMap::OP_MAP_VOP3); static_cast<uint32_t>(opcode) - static_cast<uint32_t>(OpcodeMap::OP_MAP_VOP3);
} }
} else { } else {
uint32_t mapOffset = getOpMapOffset(encoding); uint32_t mapOffset = static_cast<uint32_t>(opcodeMap);
encodingOp = static_cast<uint32_t>(opcode) - mapOffset; encodingOp = static_cast<uint32_t>(opcode) - mapOffset;
} }
return encodingOp; return encodingOp;
} }
void GcnDecodeContext::updateInstructionMeta(InstEncoding encoding) { void GcnDecodeContext::updateInstructionMeta(OpcodeMap opcodeMap, uint32_t encodingLength) {
uint32_t encodingOp = mapEncodingOp(encoding, m_instruction.opcode); uint32_t encodingOp = mapEncodingOp(opcodeMap, m_instruction.opcode);
InstFormat instFormat = InstructionFormat(encoding, encodingOp); InstFormat instFormat = InstructionFormat(m_instruction.encoding, encodingOp);
ASSERT_MSG(instFormat.src_type != ScalarType::Undefined && ASSERT_MSG(instFormat.src_type != ScalarType::Undefined &&
instFormat.dst_type != ScalarType::Undefined, instFormat.dst_type != ScalarType::Undefined,
"Instruction format table incomplete for opcode {} ({}, encoding = 0x{:x})", "Instruction format table incomplete for opcode {} ({}, encoding = 0x{:x})",
magic_enum::enum_name(m_instruction.opcode), u32(m_instruction.opcode), magic_enum::enum_name(m_instruction.opcode), u32(m_instruction.opcode),
u32(encoding)); u32(m_instruction.encoding));
m_instruction.inst_class = instFormat.inst_class; m_instruction.inst_class = instFormat.inst_class;
m_instruction.category = instFormat.inst_category; m_instruction.category = instFormat.inst_category;
m_instruction.encoding = encoding;
m_instruction.src_count = instFormat.src_count; m_instruction.src_count = instFormat.src_count;
m_instruction.length = getEncodingLength(encoding); m_instruction.length = encodingLength;
// Update src operand scalar type. // Update src operand scalar type.
auto setOperandType = [&instFormat](InstOperand& src) { auto setOperandType = [&instFormat](InstOperand& src) {
@ -337,74 +291,10 @@ OperandField GcnDecodeContext::getOperandField(uint32_t code) {
return field; return field;
} }
void GcnDecodeContext::decodeInstruction32(InstEncoding encoding, GcnCodeSlice& code) { void GcnDecodeContext::decodeLiteralConstant(OpcodeMap opcodeMap, GcnCodeSlice& code) {
u32 hexInstruction = code.readu32(); if (HasAdditionalLiteral(m_instruction.encoding, m_instruction.opcode)) {
switch (encoding) { u32 encoding_op = mapEncodingOp(opcodeMap, m_instruction.opcode);
case InstEncoding::SOP1: InstFormat instFormat = InstructionFormat(m_instruction.encoding, encoding_op);
decodeInstructionSOP1(hexInstruction);
break;
case InstEncoding::SOPP:
decodeInstructionSOPP(hexInstruction);
break;
case InstEncoding::SOPC:
decodeInstructionSOPC(hexInstruction);
break;
case InstEncoding::SOPK:
decodeInstructionSOPK(hexInstruction);
break;
case InstEncoding::SOP2:
decodeInstructionSOP2(hexInstruction);
break;
case InstEncoding::VOP1:
decodeInstructionVOP1(hexInstruction);
break;
case InstEncoding::VOPC:
decodeInstructionVOPC(hexInstruction);
break;
case InstEncoding::VOP2:
decodeInstructionVOP2(hexInstruction);
break;
case InstEncoding::SMRD:
decodeInstructionSMRD(hexInstruction);
break;
case InstEncoding::VINTRP:
decodeInstructionVINTRP(hexInstruction);
break;
default:
break;
}
}
void GcnDecodeContext::decodeInstruction64(InstEncoding encoding, GcnCodeSlice& code) {
uint64_t hexInstruction = code.readu64();
switch (encoding) {
case InstEncoding::VOP3:
decodeInstructionVOP3(hexInstruction);
break;
case InstEncoding::MUBUF:
decodeInstructionMUBUF(hexInstruction);
break;
case InstEncoding::MTBUF:
decodeInstructionMTBUF(hexInstruction);
break;
case InstEncoding::MIMG:
decodeInstructionMIMG(hexInstruction);
break;
case InstEncoding::DS:
decodeInstructionDS(hexInstruction);
break;
case InstEncoding::EXP:
decodeInstructionEXP(hexInstruction);
break;
default:
break;
}
}
void GcnDecodeContext::decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice& code) {
if (HasAdditionalLiteral(encoding, m_instruction.opcode)) {
u32 encoding_op = mapEncodingOp(encoding, m_instruction.opcode);
InstFormat instFormat = InstructionFormat(encoding, encoding_op);
m_instruction.src[m_instruction.src_count].field = OperandField::LiteralConst; m_instruction.src[m_instruction.src_count].field = OperandField::LiteralConst;
m_instruction.src[m_instruction.src_count].type = instFormat.src_type; m_instruction.src[m_instruction.src_count].type = instFormat.src_type;
m_instruction.src[m_instruction.src_count].code = code.readu32(); m_instruction.src[m_instruction.src_count].code = code.readu32();

View file

@ -16,13 +16,7 @@ struct InstFormat {
ScalarType dst_type = ScalarType::Undefined; ScalarType dst_type = ScalarType::Undefined;
}; };
InstEncoding GetInstructionEncoding(u32 token); InstFormat InstructionFormat(InstEncoding encoding, uint32_t opcode);
u32 GetEncodingLength(InstEncoding encoding);
InstFormat InstructionFormat(InstEncoding encoding, u32 opcode);
Opcode DecodeOpcode(u32 token);
class GcnCodeSlice { class GcnCodeSlice {
public: public:
@ -58,30 +52,26 @@ public:
GcnInst decodeInstruction(GcnCodeSlice& code); GcnInst decodeInstruction(GcnCodeSlice& code);
private: private:
uint32_t getEncodingLength(InstEncoding encoding); uint32_t mapEncodingOp(OpcodeMap opcodeMap, Opcode opcode);
uint32_t getOpMapOffset(InstEncoding encoding); void updateInstructionMeta(OpcodeMap opcodeMap, uint32_t encodingLength);
uint32_t mapEncodingOp(InstEncoding encoding, Opcode opcode);
void updateInstructionMeta(InstEncoding encoding);
uint32_t getMimgModifier(Opcode opcode); uint32_t getMimgModifier(Opcode opcode);
void repairOperandType(); void repairOperandType();
OperandField getOperandField(uint32_t code); OperandField getOperandField(uint32_t code);
void decodeInstruction32(InstEncoding encoding, GcnCodeSlice& code); void decodeLiteralConstant(OpcodeMap opcodeMap, GcnCodeSlice& code);
void decodeInstruction64(InstEncoding encoding, GcnCodeSlice& code);
void decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice& code);
// 32 bits encodings // 32 bits encodings
void decodeInstructionSOP1(uint32_t hexInstruction); void decodeInstructionSOP1(u32 hexInstruction);
void decodeInstructionSOPP(uint32_t hexInstruction); void decodeInstructionSOPP(u32 hexInstruction);
void decodeInstructionSOPC(uint32_t hexInstruction); void decodeInstructionSOPC(u32 hexInstruction);
void decodeInstructionSOPK(uint32_t hexInstruction); void decodeInstructionSOPK(u32 hexInstruction);
void decodeInstructionSOP2(uint32_t hexInstruction); void decodeInstructionSOP2(u32 hexInstruction);
void decodeInstructionVOP1(uint32_t hexInstruction); void decodeInstructionVOP1(u32 hexInstruction);
void decodeInstructionVOPC(uint32_t hexInstruction); void decodeInstructionVOPC(u32 hexInstruction);
void decodeInstructionVOP2(uint32_t hexInstruction); void decodeInstructionVOP2(u32 hexInstruction);
void decodeInstructionSMRD(uint32_t hexInstruction); void decodeInstructionSMRD(u32 hexInstruction);
void decodeInstructionVINTRP(uint32_t hexInstruction); void decodeInstructionVINTRP(u32 hexInstruction);
// 64 bits encodings // 64 bits encodings
void decodeInstructionVOP3(uint64_t hexInstruction); void decodeInstructionVOP3(uint64_t hexInstruction);
void decodeInstructionMUBUF(uint64_t hexInstruction); void decodeInstructionMUBUF(uint64_t hexInstruction);

View file

@ -2244,8 +2244,6 @@ enum class InstEncoding : u32 {
/// InstructionEncodingMask_1bit /// InstructionEncodingMask_1bit
/// bits [31:31] - (0) /// bits [31:31] - (0)
VOP2 = 0x00000000u << 31, VOP2 = 0x00000000u << 31,
ILLEGAL
}; };
enum class InstClass : u32 { enum class InstClass : u32 {