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);
}

浙公网安备 33010602011771号