Hexagon LLVM中关于 TSFlags 使用

C:\work\riscv-gnu-toolchain-v0\riscv-gnu-toolchain\llvm\llvm\lib\Target\Hexagon\HexagonInstrFormats.td :
这是关于指令描述的基类:

class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
                  string cstr, InstrItinClass itin, IType type>
  : Instruction {
  let Namespace = "Hexagon";

  dag OutOperandList = outs;
  dag InOperandList = ins;
  let AsmString = asmstr;
  let Pattern = pattern;
  let Constraints = cstr;
  let Itinerary = itin;
  let Size = 4;

  // SoftFail is a field the disassembler can use to provide a way for
  // instructions to not match without killing the whole decode process. It is
  // mainly used for ARM, but Tablegen expects this field to exist or it fails
  // to build the decode table.
  field bits<32> SoftFail = 0;

  // *** Must match MCTargetDesc/HexagonBaseInfo.h ***

  // Instruction type according to the ISA.
  IType Type = type;
  let TSFlags{6-0} = Type.Value;

  // Solo instructions, i.e., those that cannot be in a packet with others.
  bits<1> isSolo = 0;
  let TSFlags{7} = isSolo;
  // Packed only with A or X-type instructions.
  bits<1> isSoloAX = 0;
  let TSFlags{8} = isSoloAX;
  // Restricts slot 1 to ALU-only instructions.
  bits<1> isRestrictSlot1AOK = 0;
  let TSFlags{9} = isRestrictSlot1AOK;
...

在文件 C:\work\riscv-gnu-toolchain-v0\riscv-gnu-toolchain\llvm\llvm\lib\Target\Hexagon\MCTargetDesc\HexagonBaseInfo.h 中:
能看到这样的定义:

// MCInstrDesc TSFlags
// *** Must match HexagonInstrFormat*.td ***
enum {
  // This 7-bit field describes the insn type.
  TypePos = 0,
  TypeMask = 0x7f,

  // Solo instructions.
  SoloPos = 7,
  SoloMask = 0x1,
  // Packed only with A or X-type instructions.
  SoloAXPos = 8,
  SoloAXMask = 0x1,
  // Only A-type instruction in first slot or nothing.
  RestrictSlot1AOKPos = 9,
  RestrictSlot1AOKMask = 0x1,

  // Predicated instructions.
  PredicatedPos = 10,
  PredicatedMask = 0x1,
  PredicatedFalsePos = 11,
  PredicatedFalseMask = 0x1,
  PredicatedNewPos = 12,
  PredicatedNewMask = 0x1,
  PredicateLatePos = 13,
  PredicateLateMask = 0x1,

  // New-Value consumer instructions.
  NewValuePos = 14,
  NewValueMask = 0x1,
  // New-Value producer instructions.
  hasNewValuePos = 15,
  hasNewValueMask = 0x1,
  // Which operand consumes or produces a new value.
  NewValueOpPos = 16,
  NewValueOpMask = 0x7,
  // Stores that can become new-value stores.
  mayNVStorePos = 19,
  mayNVStoreMask = 0x1,
  // New-value store instructions.
  NVStorePos = 20,
  NVStoreMask = 0x1,
  // Loads that can become current-value loads.
  mayCVLoadPos = 21,
  mayCVLoadMask = 0x1,
  // Current-value load instructions.
  CVLoadPos = 22,
  CVLoadMask = 0x1,

这块的xxxPos和xxxMask与InstHexagon中的TSFlags的描述要相互对应起来,修改的话要一起修改。

TSFlags 包含了Hexagon 指令所具有的特性,在td文件中给这些TSFlags 赋不同的值,相当于给指令打上了不同的标签。
等处理指令的时候,根据TSFlags 的不同,而做特定的处理。

我们以if (!p1.new) jump:nt L1这条指令为例子:
td文件是这样描述的:

def J2_jumpf : HInst<
(outs),
(ins PredRegs:$Pu4, b30_2Imm:$Ii),
"if (!$Pu4) jump:nt $Ii",
tc_56a124a7, TypeJ>, Enc_daea09, PredNewRel {
let Inst{0-0} = 0b0;
let Inst{12-10} = 0b000;
let Inst{21-21} = 0b1;
let Inst{31-24} = 0b01011100;
let isPredicated = 1;
let isPredicatedFalse = 1;
let isTerminator = 1;
let isBranch = 1;
let cofRelax1 = 1;
let cofRelax2 = 1;
let cofMax1 = 1;
let Defs = [PC];
let BaseOpcode = "J2_jump";
let InputType = "imm";
let isTaken = Inst{12};
let isExtendable = 1;
let opExtendable = 1;
let isExtentSigned = 1;
let opExtentBits = 17;
let opExtentAlign = 2;
}

在inc文件中,如果直接找类似cofRelax1 是找不到的。
在inc中,所有指令的信息最后都会存在这个表中:

extern const HexagonInstrTable HexagonDescs = {
  {
    { 741,	0,	0,	4,	80,	0,	0,	HexagonImpOpBase + 0,	1,	0, 0x0ULL },  // Inst #741 = invalid_decode
    { 740,	3,	1,	4,	22,	0,	0,	HexagonImpOpBase + 0,	379,	0, 0x800000000008011ULL },  // Inst #740 = V6_vsubw_dv
    { 739,	3,	1,	4,	18,	0,	0,	HexagonImpOpBase + 0,	376,	0, 0x3800000000008010ULL },  // Inst #739 = V6_vgtw
    { 738,	3,	1,	4,	18,	0,	0,	HexagonImpOpBase + 0,	376,	0, 0x3800000000008010ULL },  // Inst #738 = V6_veqw
    { 737,	3,	1,	4,	22,	0,	0,	HexagonImpOpBase + 0,	373,	0|(1ULL<<MCID::RegSequence), 0x800000000008011ULL },  // Inst #737 = V6_vcombine
    { 736,	3,	1,	4,	25,	0,	0,	HexagonImpOpBase + 0,	370,	0, 0x1800000000008410ULL },  // Inst #736 = V6_vcmov
...

HexagonInstrTable 的定义是这样的:

struct HexagonInstrTable {
  MCInstrDesc Insts[742];
  static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), "Unwanted padding between Insts and OperandInfo");
  MCOperandInfo OperandInfo[382];
  static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), "Unwanted padding between OperandInfo and ImplicitOps");
  MCPhysReg ImplicitOps[125];
};

其实HexagonDescs 就包含了MCInstrDesc Insts[742];MCOperandInfo OperandInfo[382];MCPhysReg ImplicitOps[125];这三组数据。
第一个{}中的就是Insts[742],我们找到 J2_jumpf
{ 648, 2, 0, 4, 11, 0, 1, HexagonImpOpBase + 55, 174, 0|(1ULL<<MCID::Branch)|(1ULL<<MCID::Terminator), 0x7a32800c23ULL }, // Inst #648 = J2_jumpf
每个数据的意义对应到 MCInstrDesc 每个成员:


class MCInstrDesc {
public:
  // FIXME: Disable copies and moves.
  // Do not allow MCInstrDescs to be copied or moved. They should only exist in
  // the <Target>Insts table because they rely on knowing their own address to
  // find other information elsewhere in the same table.

  unsigned short Opcode;         // The opcode number
  unsigned short NumOperands;    // Num of args (may be more if variable_ops)
  unsigned char NumDefs;         // Num of args that are definitions
  unsigned char Size;            // Number of bytes in encoding.
  unsigned short SchedClass;     // enum identifying instr sched class
  unsigned char NumImplicitUses; // Num of regs implicitly used
  unsigned char NumImplicitDefs; // Num of regs implicitly defined
  unsigned short ImplicitOffset; // Offset to start of implicit op list
  unsigned short OpInfoOffset;   // Offset to info about operands
  uint64_t Flags;                // Flags identifying machine instr class
  uint64_t TSFlags;              // Target Specific Flag values

TSFlags正好就对应到最后一个: 也就是说 0x7a32800c23ULL 包含了 J2_jumpf 的所有TSFlags信息。
随便找一个为例:

  bit cofRelax1 = 0;
  let TSFlags{37} = cofRelax1;

TSFlags的37bit就表示了cofRelax1,在0x7a32800c23ULL 中找到37bit的值,就知道cofRelax1的属性了。

bool HexagonMCInstrInfo::isCofRelax1(MCInstrInfo const &MCII,
                                     MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::CofRelax1Pos) & HexagonII::CofRelax1Mask);
}
posted @ 2025-08-27 17:50  pch126  阅读(12)  评论(0)    收藏  举报