[Hexagon] Update MCTargetDesc

Changes include:
- Updates to the instruction descriptor flags.
- Improvements to the packet shuffler and checker.
- Updates to the handling of certain relocations.
- Better handling of duplex instructions.

llvm-svn: 294226
This commit is contained in:
Krzysztof Parzyszek 2017-02-06 19:35:46 +00:00
parent 11d0b8df5f
commit 8cdfe8ecf3
35 changed files with 1240 additions and 718 deletions

View File

@ -27,9 +27,9 @@ def ArchV5: SubtargetFeature<"v5", "HexagonArchVersion", "V5", "Hexagon V5">;
def ArchV55: SubtargetFeature<"v55", "HexagonArchVersion", "V55", "Hexagon V55">;
def ArchV60: SubtargetFeature<"v60", "HexagonArchVersion", "V60", "Hexagon V60">;
def FeatureHVX: SubtargetFeature<"hvx", "UseHVXOps", "true",
def ExtensionHVX: SubtargetFeature<"hvx", "UseHVXOps", "true",
"Hexagon HVX instructions">;
def FeatureHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps", "true",
def ExtensionHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps", "true",
"Hexagon HVX Double instructions">;
def FeatureLongCalls: SubtargetFeature<"long-calls", "UseLongCalls", "true",
"Use constant-extended calls">;
@ -46,10 +46,10 @@ def HasV60T : Predicate<"HST->hasV60TOps()">,
def UseMEMOP : Predicate<"HST->useMemOps()">;
def IEEERndNearV5T : Predicate<"HST->modeIEEERndNear()">;
def UseHVXDbl : Predicate<"HST->useHVXDblOps()">,
AssemblerPredicate<"FeatureHVXDbl">;
AssemblerPredicate<"ExtensionHVXDbl">;
def UseHVXSgl : Predicate<"HST->useHVXSglOps()">;
def UseHVX : Predicate<"HST->useHVXSglOps() ||HST->useHVXDblOps()">,
AssemblerPredicate<"FeatureHVX">;
AssemblerPredicate<"ExtensionHVX">;
//===----------------------------------------------------------------------===//
// Classes used for relation maps.
@ -271,7 +271,7 @@ def : Proc<"hexagonv5", HexagonModelV4,
def : Proc<"hexagonv55", HexagonModelV55,
[ArchV4, ArchV5, ArchV55]>;
def : Proc<"hexagonv60", HexagonModelV60,
[ArchV4, ArchV5, ArchV55, ArchV60, FeatureHVX]>;
[ArchV4, ArchV5, ArchV55, ArchV60, ExtensionHVX]>;
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing

View File

@ -13,8 +13,8 @@
// *** Must match HexagonBaseInfo.h ***
//===----------------------------------------------------------------------===//
class IType<bits<5> t> {
bits<5> Value = t;
class IType<bits<6> t> {
bits<6> Value = t;
}
def TypePSEUDO : IType<0>;
def TypeALU32 : IType<1>;
@ -99,85 +99,85 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
// Instruction type according to the ISA.
IType Type = type;
let TSFlags{4-0} = Type.Value;
let TSFlags{5-0} = Type.Value;
// Solo instructions, i.e., those that cannot be in a packet with others.
bits<1> isSolo = 0;
let TSFlags{5} = isSolo;
let TSFlags{6} = isSolo;
// Packed only with A or X-type instructions.
bits<1> isSoloAX = 0;
let TSFlags{6} = isSoloAX;
let TSFlags{7} = isSoloAX;
// Only A-type instruction in first slot or nothing.
bits<1> isSoloAin1 = 0;
let TSFlags{7} = isSoloAin1;
let TSFlags{8} = isSoloAin1;
// Predicated instructions.
bits<1> isPredicated = 0;
let TSFlags{8} = isPredicated;
let TSFlags{9} = isPredicated;
bits<1> isPredicatedFalse = 0;
let TSFlags{9} = isPredicatedFalse;
let TSFlags{10} = isPredicatedFalse;
bits<1> isPredicatedNew = 0;
let TSFlags{10} = isPredicatedNew;
let TSFlags{11} = isPredicatedNew;
bits<1> isPredicateLate = 0;
let TSFlags{11} = isPredicateLate; // Late predicate producer insn.
let TSFlags{12} = isPredicateLate; // Late predicate producer insn.
// New-value insn helper fields.
bits<1> isNewValue = 0;
let TSFlags{12} = isNewValue; // New-value consumer insn.
let TSFlags{13} = isNewValue; // New-value consumer insn.
bits<1> hasNewValue = 0;
let TSFlags{13} = hasNewValue; // New-value producer insn.
let TSFlags{14} = hasNewValue; // New-value producer insn.
bits<3> opNewValue = 0;
let TSFlags{16-14} = opNewValue; // New-value produced operand.
let TSFlags{17-15} = opNewValue; // New-value produced operand.
bits<1> isNVStorable = 0;
let TSFlags{17} = isNVStorable; // Store that can become new-value store.
let TSFlags{18} = isNVStorable; // Store that can become new-value store.
bits<1> isNVStore = 0;
let TSFlags{18} = isNVStore; // New-value store insn.
let TSFlags{19} = isNVStore; // New-value store insn.
bits<1> isCVLoadable = 0;
let TSFlags{19} = isCVLoadable; // Load that can become cur-value load.
let TSFlags{20} = isCVLoadable; // Load that can become cur-value load.
bits<1> isCVLoad = 0;
let TSFlags{20} = isCVLoad; // Cur-value load insn.
let TSFlags{21} = isCVLoad; // Cur-value load insn.
// Immediate extender helper fields.
bits<1> isExtendable = 0;
let TSFlags{21} = isExtendable; // Insn may be extended.
let TSFlags{22} = isExtendable; // Insn may be extended.
bits<1> isExtended = 0;
let TSFlags{22} = isExtended; // Insn must be extended.
let TSFlags{23} = isExtended; // Insn must be extended.
bits<3> opExtendable = 0;
let TSFlags{25-23} = opExtendable; // Which operand may be extended.
let TSFlags{26-24} = opExtendable; // Which operand may be extended.
bits<1> isExtentSigned = 0;
let TSFlags{26} = isExtentSigned; // Signed or unsigned range.
let TSFlags{27} = isExtentSigned; // Signed or unsigned range.
bits<5> opExtentBits = 0;
let TSFlags{31-27} = opExtentBits; //Number of bits of range before extending.
let TSFlags{32-28} = opExtentBits; //Number of bits of range before extending.
bits<2> opExtentAlign = 0;
let TSFlags{33-32} = opExtentAlign; // Alignment exponent before extending.
let TSFlags{34-33} = opExtentAlign; // Alignment exponent before extending.
// If an instruction is valid on a subtarget, set the corresponding
// bit from validSubTargets.
// By default, instruction is valid on all subtargets.
SubTarget validSubTargets = HasAnySubT;
let TSFlags{39-34} = validSubTargets.Value;
let TSFlags{40-35} = validSubTargets.Value;
// Addressing mode for load/store instructions.
AddrModeType addrMode = NoAddrMode;
let TSFlags{42-40} = addrMode.Value;
let TSFlags{43-41} = addrMode.Value;
// Memory access size for mem access instructions (load/store)
MemAccessSize accessSize = NoMemAccess;
let TSFlags{46-43} = accessSize.Value;
let TSFlags{47-44} = accessSize.Value;
bits<1> isTaken = 0;
let TSFlags {47} = isTaken; // Branch prediction.
let TSFlags {48} = isTaken; // Branch prediction.
bits<1> isFP = 0;
let TSFlags {48} = isFP; // Floating-point.
let TSFlags {49} = isFP; // Floating-point.
bits<1> hasNewValue2 = 0;
let TSFlags{50} = hasNewValue2; // Second New-value producer insn.
let TSFlags{51} = hasNewValue2; // Second New-value producer insn.
bits<3> opNewValue2 = 0;
let TSFlags{53-51} = opNewValue2; // Second New-value produced operand.
let TSFlags{54-52} = opNewValue2; // Second New-value produced operand.
bits<1> isAccumulator = 0;
let TSFlags{54} = isAccumulator;
let TSFlags{55} = isAccumulator;
bit cofMax1 = 0;
let TSFlags{60} = cofMax1;
@ -200,6 +200,7 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
let NValueST = !if(isNVStore, "true", "false");
let isNT = !if(isNonTemporal, "true", "false");
let hasSideEffects = 0;
// *** Must match MCTargetDesc/HexagonBaseInfo.h ***
}

View File

@ -18,7 +18,7 @@
//----------------------------------------------------------------------------//
def TypeV4LDST : IType<9>;
def TypeNV : IType<10>;
def TypeNCJ : IType<10>;
def TypeDUPLEX : IType<11>;
def TypeCJ : IType<12>;
def TypeEXTENDER : IType<30>;
@ -61,7 +61,7 @@ class InstDuplex<bits<4> iClass, list<dag> pattern = [],
// *** Must match MCTargetDesc/HexagonBaseInfo.h ***
let TSFlags{4-0} = Type.Value;
let TSFlags{5-0} = Type.Value;
// Predicated instructions.
bits<1> isPredicated = 0;
@ -107,7 +107,7 @@ class InstDuplex<bits<4> iClass, list<dag> pattern = [],
//
class NVInst<dag outs, dag ins, string asmstr, list<dag> pattern = [],
string cstr = "", InstrItinClass itin = NCJ_tc_3or4stall_SLOT0>
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeNV>, OpcodeHexagon;
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeNCJ>, OpcodeHexagon;
class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [],
string cstr = "", InstrItinClass itin = NCJ_tc_3or4stall_SLOT0>

View File

@ -9,10 +9,10 @@
#include "Hexagon.h"
#include "HexagonFixupKinds.h"
#include "HexagonMCTargetDesc.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCChecker.h"
#include "MCTargetDesc/HexagonMCCodeEmitter.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "llvm/MC/MCAsmBackend.h"
@ -59,9 +59,10 @@ class HexagonAsmBackend : public MCAsmBackend {
RF.getFixups() = Fixups;
}
public:
HexagonAsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) :
OSABI(OSABI), MCII (T.createMCInstrInfo()), RelaxTarget(new MCInst *),
Extender(nullptr) {}
HexagonAsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
StringRef CPU) :
OSABI(OSABI), CPU(CPU), MCII(T.createMCInstrInfo()),
RelaxTarget(new MCInst *), Extender(nullptr) {}
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
return createHexagonELFObjectWriter(OS, OSABI, CPU);
@ -88,101 +89,101 @@ public:
// This table *must* be in same the order of fixup_* kinds in
// HexagonFixupKinds.h.
//
// namei offset bits flags
{ "fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_LO16", 0, 32, 0 },
{ "fixup_Hexagon_HI16", 0, 32, 0 },
{ "fixup_Hexagon_32", 0, 32, 0 },
{ "fixup_Hexagon_16", 0, 32, 0 },
{ "fixup_Hexagon_8", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_0", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_1", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_2", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_3", 0, 32, 0 },
{ "fixup_Hexagon_HL16", 0, 32, 0 },
{ "fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_16_X", 0, 32, 0 },
{ "fixup_Hexagon_12_X", 0, 32, 0 },
{ "fixup_Hexagon_11_X", 0, 32, 0 },
{ "fixup_Hexagon_10_X", 0, 32, 0 },
{ "fixup_Hexagon_9_X", 0, 32, 0 },
{ "fixup_Hexagon_8_X", 0, 32, 0 },
{ "fixup_Hexagon_7_X", 0, 32, 0 },
{ "fixup_Hexagon_6_X", 0, 32, 0 },
{ "fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_COPY", 0, 32, 0 },
{ "fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
{ "fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
{ "fixup_Hexagon_RELATIVE", 0, 32, 0 },
{ "fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_32", 0, 32, 0 },
{ "fixup_Hexagon_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_32", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_16", 0, 32, 0 },
{ "fixup_Hexagon_GD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_LD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_IE_LO16", 0, 32, 0 },
{ "fixup_Hexagon_IE_HI16", 0, 32, 0 },
{ "fixup_Hexagon_IE_32", 0, 32, 0 },
{ "fixup_Hexagon_IE_16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_32", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_16", 0, 32, 0 },
{ "fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_16_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
// namei offset bits flags
{ "fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_LO16", 0, 32, 0 },
{ "fixup_Hexagon_HI16", 0, 32, 0 },
{ "fixup_Hexagon_32", 0, 32, 0 },
{ "fixup_Hexagon_16", 0, 32, 0 },
{ "fixup_Hexagon_8", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_0", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_1", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_2", 0, 32, 0 },
{ "fixup_Hexagon_GPREL16_3", 0, 32, 0 },
{ "fixup_Hexagon_HL16", 0, 32, 0 },
{ "fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_16_X", 0, 32, 0 },
{ "fixup_Hexagon_12_X", 0, 32, 0 },
{ "fixup_Hexagon_11_X", 0, 32, 0 },
{ "fixup_Hexagon_10_X", 0, 32, 0 },
{ "fixup_Hexagon_9_X", 0, 32, 0 },
{ "fixup_Hexagon_8_X", 0, 32, 0 },
{ "fixup_Hexagon_7_X", 0, 32, 0 },
{ "fixup_Hexagon_6_X", 0, 32, 0 },
{ "fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_COPY", 0, 32, 0 },
{ "fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
{ "fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
{ "fixup_Hexagon_RELATIVE", 0, 32, 0 },
{ "fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_32", 0, 32, 0 },
{ "fixup_Hexagon_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_32", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_16", 0, 32, 0 },
{ "fixup_Hexagon_GD_PLT_B22_PCREL",0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_LD_PLT_B22_PCREL",0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_IE_LO16", 0, 32, 0 },
{ "fixup_Hexagon_IE_HI16", 0, 32, 0 },
{ "fixup_Hexagon_IE_32", 0, 32, 0 },
{ "fixup_Hexagon_IE_16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_32", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_16", 0, 32, 0 },
{ "fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_16_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
{ "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
{ "fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
};
if (Kind < FirstTargetFixupKind)
@ -526,7 +527,7 @@ public:
if (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ ||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCJ &&
MCID.isBranch()) ||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNV &&
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNCJ &&
MCID.isBranch()) ||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR &&
HMI.getOpcode() != Hexagon::C4_addipc))
@ -723,7 +724,8 @@ public:
Size = 0;
}
}
bool Error = HexagonMCShuffle(*MCII, RF.getSubtargetInfo(), Inst);
bool Error = HexagonMCShuffle(true, *MCII, RF.getSubtargetInfo(),
Inst);
//assert(!Error);
(void)Error;
ReplaceInstruction(Asm.getEmitter(), RF, Inst);
@ -738,15 +740,17 @@ public:
}
}
}
};
} // end anonymous namespace
}; // class HexagonAsmBackend
namespace llvm {
MCAsmBackend *createHexagonAsmBackend(Target const &T,
} // namespace
// MCAsmBackend
MCAsmBackend *llvm::createHexagonAsmBackend(Target const &T,
MCRegisterInfo const & /*MRI*/,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options) {
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
return new HexagonAsmBackend(T, OSABI, CPU);
}
StringRef CPUString = Hexagon_MC::selectHexagonCPU(TT, CPU);
return new HexagonAsmBackend(T, TT, OSABI, CPUString);
}

View File

@ -42,7 +42,7 @@ namespace HexagonII {
TypeSYSTEM = 7,
TypeXTYPE = 8,
TypeV4LDST = 9,
TypeNV = 10,
TypeNCJ = 10,
TypeDUPLEX = 11,
TypeCJ = 12,
TypeCVI_FIRST = 13,
@ -68,16 +68,10 @@ namespace HexagonII {
};
enum SubTarget {
HasV2SubT = 0xf,
HasV2SubTOnly = 0x1,
NoV2SubT = 0x0,
HasV3SubT = 0xe,
HasV3SubTOnly = 0x2,
NoV3SubT = 0x1,
HasV4SubT = 0xc,
NoV4SubT = 0x3,
HasV5SubT = 0x8,
NoV5SubT = 0x7
HasV4SubT = 0x3f,
HasV5SubT = 0x3e,
HasV55SubT = 0x3c,
HasV60SubT = 0x38,
};
enum AddrMode {
@ -107,102 +101,101 @@ namespace HexagonII {
enum {
// This 5-bit field describes the insn type.
TypePos = 0,
TypeMask = 0x1f,
TypeMask = 0x3f,
// Solo instructions.
SoloPos = 5,
SoloPos = 6,
SoloMask = 0x1,
// Packed only with A or X-type instructions.
SoloAXPos = 6,
SoloAXPos = 7,
SoloAXMask = 0x1,
// Only A-type instruction in first slot or nothing.
SoloAin1Pos = 7,
SoloAin1Pos = 8,
SoloAin1Mask = 0x1,
// Predicated instructions.
PredicatedPos = 8,
PredicatedPos = 9,
PredicatedMask = 0x1,
PredicatedFalsePos = 9,
PredicatedFalsePos = 10,
PredicatedFalseMask = 0x1,
PredicatedNewPos = 10,
PredicatedNewPos = 11,
PredicatedNewMask = 0x1,
PredicateLatePos = 11,
PredicateLatePos = 12,
PredicateLateMask = 0x1,
// New-Value consumer instructions.
NewValuePos = 12,
NewValuePos = 13,
NewValueMask = 0x1,
// New-Value producer instructions.
hasNewValuePos = 13,
hasNewValuePos = 14,
hasNewValueMask = 0x1,
// Which operand consumes or produces a new value.
NewValueOpPos = 14,
NewValueOpPos = 15,
NewValueOpMask = 0x7,
// Stores that can become new-value stores.
mayNVStorePos = 17,
mayNVStorePos = 18,
mayNVStoreMask = 0x1,
// New-value store instructions.
NVStorePos = 18,
NVStorePos = 19,
NVStoreMask = 0x1,
// Loads that can become current-value loads.
mayCVLoadPos = 19,
mayCVLoadPos = 20,
mayCVLoadMask = 0x1,
// Current-value load instructions.
CVLoadPos = 20,
CVLoadPos = 21,
CVLoadMask = 0x1,
// Extendable insns.
ExtendablePos = 21,
ExtendablePos = 22,
ExtendableMask = 0x1,
// Insns must be extended.
ExtendedPos = 22,
ExtendedPos = 23,
ExtendedMask = 0x1,
// Which operand may be extended.
ExtendableOpPos = 23,
ExtendableOpPos = 24,
ExtendableOpMask = 0x7,
// Signed or unsigned range.
ExtentSignedPos = 26,
ExtentSignedPos = 27,
ExtentSignedMask = 0x1,
// Number of bits of range before extending operand.
ExtentBitsPos = 27,
ExtentBitsPos = 28,
ExtentBitsMask = 0x1f,
// Alignment power-of-two before extending operand.
ExtentAlignPos = 32,
ExtentAlignPos = 33,
ExtentAlignMask = 0x3,
// Valid subtargets
validSubTargetPos = 34,
validSubTargetMask = 0xf,
validSubTargetPos = 35,
validSubTargetMask = 0x3f,
// Addressing mode for load/store instructions.
AddrModePos = 40,
AddrModePos = 41,
AddrModeMask = 0x7,
// Access size for load/store instructions.
MemAccessSizePos = 43,
MemAccessSizePos = 44,
MemAccesSizeMask = 0xf,
// Branch predicted taken.
TakenPos = 47,
TakenPos = 48,
TakenMask = 0x1,
// Floating-point instructions.
FPPos = 48,
FPPos = 49,
FPMask = 0x1,
// New-Value producer-2 instructions.
hasNewValuePos2 = 50,
hasNewValuePos2 = 51,
hasNewValueMask2 = 0x1,
// Which operand consumes or produces a new value.
NewValueOpPos2 = 51,
NewValueOpPos2 = 52,
NewValueOpMask2 = 0x7,
// Accumulator instructions.
AccumulatorPos = 54,
AccumulatorPos = 55,
AccumulatorMask = 0x1,
// Complex XU, prevent xu competition by preferring slot3
PrefersSlot3Pos = 55,
PrefersSlot3Pos = 56,
PrefersSlot3Mask = 0x1,
CofMax1Pos = 60,
@ -217,8 +210,6 @@ namespace HexagonII {
// Hexagon Specific MachineOperand flags.
MO_NO_FLAG,
HMOTF_ConstExtended = 1,
/// MO_PCREL - On a symbol operand, indicates a PC-relative relocation
/// Used for computing a global address for PIC compilations
MO_PCREL,
@ -250,7 +241,13 @@ namespace HexagonII {
// MO_TPREL - indicates relocation for TLS
// local Executable method
MO_TPREL
MO_TPREL,
// HMOTF_ConstExtended
// Addendum to abovem, indicates a const extended op
// Can be used as a mask.
HMOTF_ConstExtended = 0x80
};
// Hexagon Sub-instruction classes.

View File

@ -23,6 +23,7 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = nullptr; // .xword is only supported by V9.
CommentString = "//";
SupportsDebugInformation = true;
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
InlineAsmStart = "# InlineAsm Start";
@ -30,8 +31,8 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
ZeroDirective = "\t.space\t";
AscizDirective = "\t.string\t";
SupportsDebugInformation = true;
MinInstAlignment = 4;
UsesELFSectionDirectiveForBSS = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
UseLogicalShr = false;
}

View File

@ -47,12 +47,40 @@ void HexagonMCChecker::init() {
if (HexagonMCInstrInfo::isBundle(MCB))
// Unfurl a bundle.
for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
init(*I.getInst());
MCInst const &Inst = *I.getInst();
if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
init(*Inst.getOperand(0).getInst());
init(*Inst.getOperand(1).getInst());
}
else
init(Inst);
}
else
init(MCB);
}
void HexagonMCChecker::initReg(MCInst const &MCI, unsigned R, unsigned &PredReg,
bool &isTrue) {
if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && isPredicateRegister(R)) {
// Note an used predicate register.
PredReg = R;
isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
// Note use of new predicate register.
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
NewPreds.insert(PredReg);
}
else
// Note register use. Super-registers are not tracked directly,
// but their components.
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
SRI.isValid();
++SRI)
if (!MCSubRegIterator(*SRI, &RI).isValid())
// Skip super-registers used indirectly.
Uses.insert(*SRI);
}
void HexagonMCChecker::init(MCInst const& MCI) {
const MCInstrDesc& MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
unsigned PredReg = Hexagon::NoRegister;
@ -60,28 +88,10 @@ void HexagonMCChecker::init(MCInst const& MCI) {
// Get used registers.
for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
if (MCI.getOperand(i).isReg()) {
unsigned R = MCI.getOperand(i).getReg();
if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && isPredicateRegister(R)) {
// Note an used predicate register.
PredReg = R;
isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
// Note use of new predicate register.
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
NewPreds.insert(PredReg);
}
else
// Note register use. Super-registers are not tracked directly,
// but their components.
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
SRI.isValid();
++SRI)
if (!MCSubRegIterator(*SRI, &RI).isValid())
// Skip super-registers used indirectly.
Uses.insert(*SRI);
}
if (MCI.getOperand(i).isReg())
initReg(MCI, MCI.getOperand(i).getReg(), PredReg, isTrue);
for (unsigned i = 0; i < MCID.getNumImplicitUses(); ++i)
initReg(MCI, MCID.getImplicitUses()[i], PredReg, isTrue);
// Get implicit register definitions.
if (const MCPhysReg *ImpDef = MCID.getImplicitDefs())
@ -216,9 +226,11 @@ void HexagonMCChecker::init(MCInst const& MCI) {
if (!MCSubRegIterator(N, &RI).isValid()) {
// Super-registers cannot use new values.
if (MCID.isBranch())
NewUses[N] = NewSense::Jmp(llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNV);
NewUses[N] = NewSense::Jmp(
llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
else
NewUses[N] = NewSense::Use(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
NewUses[N] = NewSense::Use(
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
}
}
}
@ -230,14 +242,18 @@ HexagonMCChecker::HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo cons
init();
}
bool HexagonMCChecker::check() {
bool HexagonMCChecker::check(bool FullCheck) {
bool chkB = checkBranches();
bool chkP = checkPredicates();
bool chkNV = checkNewValues();
bool chkR = checkRegisters();
bool chkS = checkSolo();
bool chkSh = checkShuffle();
bool chkSl = checkSlots();
bool chkSh = true;
if (FullCheck)
chkSh = checkShuffle();
bool chkSl = true;
if (FullCheck)
chkSl = checkSlots();
bool chk = chkB && chkP && chkNV && chkR && chkS && chkSh && chkSl;
return chk;
@ -504,7 +520,7 @@ bool HexagonMCChecker::checkShuffle() {
HexagonMCErrInfo errInfo;
// Branch info is lost when duplexing. The unduplexed insns must be
// checked and only branch errors matter for this case.
HexagonMCShuffler MCS(MCII, STI, MCB);
HexagonMCShuffler MCS(true, MCII, STI, MCB);
if (!MCS.check()) {
if (MCS.getError() == HexagonShuffler::SHUFFLE_ERROR_BRANCHES) {
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
@ -513,7 +529,7 @@ bool HexagonMCChecker::checkShuffle() {
return false;
}
}
HexagonMCShuffler MCSDX(MCII, STI, MCBDX);
HexagonMCShuffler MCSDX(true, MCII, STI, MCBDX);
if (!MCSDX.check()) {
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
errInfo.setShuffleError(MCSDX.getError());

View File

@ -168,6 +168,7 @@ class HexagonMCChecker {
void init();
void init(MCInst const&);
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
// Checks performed.
bool checkBranches();
@ -177,6 +178,7 @@ class HexagonMCChecker {
bool checkSolo();
bool checkShuffle();
bool checkSlots();
bool checkSize();
static void compoundRegisterMap(unsigned&);
@ -196,7 +198,7 @@ class HexagonMCChecker {
explicit HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst& mcb, MCInst &mcbdx,
const MCRegisterInfo& ri);
bool check();
bool check(bool FullCheck = true);
/// add a new error/warning
void addErrInfo(HexagonMCErrInfo &err) { ErrInfoQ.push(err.s); };

View File

@ -65,9 +65,10 @@ uint32_t HexagonMCCodeEmitter::parseBits(size_t Last,
return HexagonII::INST_PARSE_NOT_END;
}
void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS,
/// EncodeInstruction - Emit the bundle
void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
MCSubtargetInfo const &STI) const {
const MCSubtargetInfo &STI) const {
MCInst &HMB = const_cast<MCInst &>(MI);
assert(HexagonMCInstrInfo::isBundle(HMB));
@ -137,60 +138,7 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
MI.getOpcode() <= Hexagon::DuplexIClassF) {
assert(Parse == HexagonII::INST_PARSE_DUPLEX &&
"Emitting duplex without duplex parse bits");
unsigned dupIClass;
switch (MI.getOpcode()) {
case Hexagon::DuplexIClass0:
dupIClass = 0;
break;
case Hexagon::DuplexIClass1:
dupIClass = 1;
break;
case Hexagon::DuplexIClass2:
dupIClass = 2;
break;
case Hexagon::DuplexIClass3:
dupIClass = 3;
break;
case Hexagon::DuplexIClass4:
dupIClass = 4;
break;
case Hexagon::DuplexIClass5:
dupIClass = 5;
break;
case Hexagon::DuplexIClass6:
dupIClass = 6;
break;
case Hexagon::DuplexIClass7:
dupIClass = 7;
break;
case Hexagon::DuplexIClass8:
dupIClass = 8;
break;
case Hexagon::DuplexIClass9:
dupIClass = 9;
break;
case Hexagon::DuplexIClassA:
dupIClass = 10;
break;
case Hexagon::DuplexIClassB:
dupIClass = 11;
break;
case Hexagon::DuplexIClassC:
dupIClass = 12;
break;
case Hexagon::DuplexIClassD:
dupIClass = 13;
break;
case Hexagon::DuplexIClassE:
dupIClass = 14;
break;
case Hexagon::DuplexIClassF:
dupIClass = 15;
break;
default:
llvm_unreachable("Unimplemented DuplexIClass");
break;
}
unsigned dupIClass = MI.getOpcode() - Hexagon::DuplexIClass0;
// 29 is the bit position.
// 0b1110 =0xE bits are masked off and down shifted by 1 bit.
// Last bit is moved to bit position 13
@ -390,7 +338,8 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
int64_t Value;
if (ME->evaluateAsAbsolute(Value))
return Value;
assert(ME->getKind() == MCExpr::SymbolRef || ME->getKind() == MCExpr::Binary);
assert(ME->getKind() == MCExpr::SymbolRef ||
ME->getKind() == MCExpr::Binary);
if (ME->getKind() == MCExpr::Binary) {
MCBinaryExpr const *Binary = cast<MCBinaryExpr>(ME);
getExprOpValue(MI, MO, Binary->getLHS(), Fixups, STI);
@ -523,7 +472,7 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
else
if (MCID.mayStore() || MCID.mayLoad()) {
for (const MCPhysReg *ImpUses = MCID.getImplicitUses(); *ImpUses;
++ImpUses) {
++ImpUses) {
if (*ImpUses != Hexagon::GP)
continue;
switch (HexagonMCInstrInfo::getAccessSize(MCII, MI)) {
@ -543,8 +492,7 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
raise_relocation_error(bits, kind);
}
}
}
else
} else
raise_relocation_error(bits, kind);
break;
}
@ -759,6 +707,13 @@ unsigned
HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO,
SmallVectorImpl<MCFixup> &Fixups,
MCSubtargetInfo const &STI) const {
size_t OperandNumber = ~0U;
for (unsigned i = 0, n = MI.getNumOperands(); i < n; ++i)
if (&MI.getOperand(i) == &MO) {
OperandNumber = i;
break;
}
assert((OperandNumber != ~0U) && "Operand not found");
if (HexagonMCInstrInfo::isNewValue(MCII, MI) &&
&MO == &MI.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, MI))) {

View File

@ -14,6 +14,7 @@
#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/Debug.h"
@ -396,7 +397,7 @@ static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context,
/// is found update the contents fo the bundle with the compound insn.
/// If a compound instruction is found then the bundle will have one
/// additional slot.
void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII,
void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCI) {
assert(HexagonMCInstrInfo::isBundle(MCI) &&
"Non-Bundle where Bundle expected");
@ -405,8 +406,23 @@ void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII,
if (MCI.size() < 2)
return;
bool StartedValid = llvm::HexagonMCShuffle(false, MCII, STI, MCI);
// Create a vector, needed to keep the order of jump instructions.
MCInst CheckList(MCI);
// Look for compounds until none are found, only update the bundle when
// a compound is found.
while (lookForCompound(MCII, Context, MCI))
;
while (lookForCompound(MCII, Context, CheckList)) {
// Keep the original bundle around in case the shuffle fails.
MCInst OriginalBundle(MCI);
// Need to update the bundle.
MCI = CheckList;
if (StartedValid && !llvm::HexagonMCShuffle(false, MCII, STI, MCI)) {
DEBUG(dbgs() << "Found ERROR\n");
MCI = OriginalBundle;
}
}
}

View File

@ -15,6 +15,7 @@
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@ -262,6 +263,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
case Hexagon::EH_RETURN_JMPR:
case Hexagon::J2_jumpr:
case Hexagon::PS_jmpret:
// jumpr r31
// Actual form JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,internal>.
DstReg = MCI.getOperand(0).getReg();
@ -275,6 +277,12 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
case Hexagon::J2_jumprfnew:
case Hexagon::J2_jumprtnewpt:
case Hexagon::J2_jumprfnewpt:
case Hexagon::PS_jmprett:
case Hexagon::PS_jmpretf:
case Hexagon::PS_jmprettnew:
case Hexagon::PS_jmpretfnew:
case Hexagon::PS_jmprettnewpt:
case Hexagon::PS_jmpretfnewpt:
DstReg = MCI.getOperand(1).getReg();
SrcReg = MCI.getOperand(0).getReg();
// [if ([!]p0[.new])] jumpr r31
@ -284,15 +292,10 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
}
break;
case Hexagon::L4_return_t:
case Hexagon::L4_return_f:
case Hexagon::L4_return_tnew_pnt:
case Hexagon::L4_return_fnew_pnt:
case Hexagon::L4_return_tnew_pt:
case Hexagon::L4_return_fnew_pt:
// [if ([!]p0[.new])] dealloc_return
SrcReg = MCI.getOperand(0).getReg();
@ -565,7 +568,8 @@ bool HexagonMCInstrInfo::subInstWouldBeExtended(MCInst const &potentialDuplex) {
bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
MCInst const &MIa, bool ExtendedA,
MCInst const &MIb, bool ExtendedB,
bool bisReversable) {
bool bisReversable,
MCSubtargetInfo const &STI) {
// Slot 1 cannot be extended in duplexes PRM 10.5
if (ExtendedA)
return false;
@ -625,11 +629,16 @@ bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
return false;
}
// If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
// therefore, not duplexable if slot 1 is a store, and slot 0 is not.
if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
return false;
if (STI.getCPU().equals_lower("hexagonv4") ||
STI.getCPU().equals_lower("hexagonv5") ||
STI.getCPU().equals_lower("hexagonv55") ||
STI.getCPU().equals_lower("hexagonv60")) {
// If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
// therefore, not duplexable if slot 1 is a store, and slot 0 is not.
if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
return false;
}
}
return (isDuplexPairMatch(MIaG, MIbG));
@ -703,6 +712,7 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
Result.setOpcode(Hexagon::SA1_dec);
addOps(Result, Inst, 0);
addOps(Result, Inst, 1);
addOps(Result, Inst, 2);
break;
} // 1,2 SUBInst $Rd = add($Rs,#-1)
else if (Inst.getOperand(1).getReg() == Hexagon::R29) {
@ -806,20 +816,27 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
break; // none SUBInst deallocframe
case Hexagon::EH_RETURN_JMPR:
case Hexagon::J2_jumpr:
case Hexagon::PS_jmpret:
Result.setOpcode(Hexagon::SL2_jumpr31);
break; // none SUBInst jumpr r31
case Hexagon::J2_jumprf:
case Hexagon::PS_jmpretf:
Result.setOpcode(Hexagon::SL2_jumpr31_f);
break; // none SUBInst if (!p0) jumpr r31
case Hexagon::J2_jumprfnew:
case Hexagon::J2_jumprfnewpt:
case Hexagon::PS_jmpretfnewpt:
case Hexagon::PS_jmpretfnew:
Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
break; // none SUBInst if (!p0.new) jumpr:nt r31
case Hexagon::J2_jumprt:
case Hexagon::PS_jmprett:
Result.setOpcode(Hexagon::SL2_jumpr31_t);
break; // none SUBInst if (p0) jumpr r31
case Hexagon::J2_jumprtnew:
case Hexagon::J2_jumprtnewpt:
case Hexagon::PS_jmprettnewpt:
case Hexagon::PS_jmprettnew:
Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
break; // none SUBInst if (p0.new) jumpr:nt r31
case Hexagon::L2_loadrb_io:
@ -966,6 +983,7 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
if (Absolute && Value == -1) {
Result.setOpcode(Hexagon::SA1_setin1);
addOps(Result, Inst, 0);
addOps(Result, Inst, 1);
break; // 2 1 SUBInst $Rd = #-1
} else {
Result.setOpcode(Hexagon::SA1_seti);
@ -1005,6 +1023,7 @@ static bool isStoreInst(unsigned opCode) {
SmallVector<DuplexCandidate, 8>
HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
MCInst const &MCB) {
assert(isBundle(MCB));
SmallVector<DuplexCandidate, 8> duplexToTry;
@ -1033,7 +1052,7 @@ HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
*MCB.getOperand(j).getInst(),
HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
bisReversable)) {
bisReversable, STI)) {
// Get iClass.
unsigned iClass = iClassOfDuplexPair(
getDuplexCandidateGroup(*MCB.getOperand(k).getInst()),
@ -1058,7 +1077,7 @@ HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
*MCB.getOperand(k).getInst(),
HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
bisReversable)) {
bisReversable, STI)) {
// Get iClass.
unsigned iClass = iClassOfDuplexPair(
getDuplexCandidateGroup(*MCB.getOperand(j).getInst()),

View File

@ -37,30 +37,19 @@
using namespace llvm;
static cl::opt<unsigned>
GPSize("gpsize", cl::NotHidden,
cl::desc("Global Pointer Addressing Size. The default size is 8."),
cl::Prefix, cl::init(8));
static cl::opt<unsigned> GPSize
("gpsize", cl::NotHidden,
cl::desc("Global Pointer Addressing Size. The default size is 8."),
cl::Prefix,
cl::init(8));
void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCK,
void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCB,
const MCSubtargetInfo &STI) {
MCInst HMI = HexagonMCInstrInfo::createBundle();
MCInst *MCB;
if (MCK.getOpcode() != Hexagon::BUNDLE) {
HMI.addOperand(MCOperand::createInst(&MCK));
MCB = &HMI;
} else
MCB = const_cast<MCInst *>(&MCK);
// Examines packet and pad the packet, if needed, when an
// end-loop is in the bundle.
HexagonMCInstrInfo::padEndloop(getContext(), *MCB);
HexagonMCShuffle(*MCII, STI, *MCB);
assert(HexagonMCInstrInfo::bundleSize(*MCB) <= HEXAGON_PACKET_SIZE);
assert(MCB.getOpcode() == Hexagon::BUNDLE);
assert(HexagonMCInstrInfo::bundleSize(MCB) <= HEXAGON_PACKET_SIZE);
assert(HexagonMCInstrInfo::bundleSize(MCB) > 0);
bool Extended = false;
for (auto &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) {
for (auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
MCInst *MCI = const_cast<MCInst *>(I.getInst());
if (Extended) {
if (HexagonMCInstrInfo::isDuplex(*MCII, *MCI)) {
@ -77,11 +66,12 @@ void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCK,
// At this point, MCB is a bundle
// Iterate through the bundle and assign addends for the instructions
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) {
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
MCInst *MCI = const_cast<MCInst *>(I.getInst());
EmitSymbol(*MCI);
}
MCObjectStreamer::EmitInstruction(*MCB, STI);
MCObjectStreamer::EmitInstruction(MCB, STI);
}
void HexagonMCELFStreamer::EmitSymbol(const MCInst &Inst) {
@ -119,9 +109,11 @@ void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
MCSectionSubPair P = getCurrentSection();
SwitchSection(&Section);
EmitValueToAlignment(ByteAlignment, 0, 1, 0);
EmitLabel(Symbol);
EmitZeros(Size);
if (ELFSymbol->isUndefined(false)) {
EmitValueToAlignment(ByteAlignment, 0, 1, 0);
EmitLabel(Symbol);
EmitZeros(Size);
}
// Update the maximum alignment of the section if necessary.
if (ByteAlignment > Section.getAlignment())
@ -144,9 +136,10 @@ void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
ELFSymbol->setSize(MCConstantExpr::create(Size, getContext()));
}
void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(
MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment,
unsigned AccessSize) {
void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol,
uint64_t Size,
unsigned ByteAlignment,
unsigned AccessSize) {
getAssembler().registerSymbol(*Symbol);
auto ELFSymbol = cast<MCSymbolELF>(Symbol);
ELFSymbol->setBinding(ELF::STB_LOCAL);
@ -154,11 +147,12 @@ void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(
HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize);
}
namespace llvm {
MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_pwrite_stream &OS, MCCodeEmitter *CE) {
return new HexagonMCELFStreamer(Context, MAB, OS, CE);
}
namespace llvm {
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
MCAsmBackend &MAB,
raw_pwrite_stream &OS, MCCodeEmitter *CE) {
return new HexagonMCELFStreamer(Context, MAB, OS, CE);
}
} // end namespace llvm

View File

@ -27,6 +27,13 @@ public:
: MCELFStreamer(Context, TAB, OS, Emitter),
MCII(createHexagonMCInstrInfo()) {}
HexagonMCELFStreamer(MCContext &Context,
MCAsmBackend &TAB,
raw_pwrite_stream &OS, MCCodeEmitter *Emitter,
MCAssembler *Assembler) :
MCELFStreamer(Context, TAB, OS, Emitter),
MCII (createHexagonMCInstrInfo()) {}
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
void EmitSymbol(const MCInst &Inst);
void HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@ -36,8 +43,9 @@ public:
unsigned ByteAlignment, unsigned AccessSize);
};
MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_pwrite_stream &OS, MCCodeEmitter *CE);
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
MCAsmBackend &MAB, raw_pwrite_stream &OS,
MCCodeEmitter *CE);
} // end namespace llvm

View File

@ -11,7 +11,9 @@
#include "HexagonMCExpr.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@ -36,7 +38,47 @@ MCFragment *llvm::HexagonMCExpr::findAssociatedFragment() const {
return Expr->findAssociatedFragment();
}
void HexagonMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {}
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
switch (Expr->getKind()) {
case MCExpr::Target:
llvm_unreachable("Cannot handle nested target MCExpr");
break;
case MCExpr::Constant:
break;
case MCExpr::Binary: {
const MCBinaryExpr *be = cast<MCBinaryExpr>(Expr);
fixELFSymbolsInTLSFixupsImpl(be->getLHS(), Asm);
fixELFSymbolsInTLSFixupsImpl(be->getRHS(), Asm);
break;
}
case MCExpr::SymbolRef: {
const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(Expr);
switch (symRef.getKind()) {
default:
return;
case MCSymbolRefExpr::VK_Hexagon_GD_GOT:
case MCSymbolRefExpr::VK_Hexagon_LD_GOT:
case MCSymbolRefExpr::VK_Hexagon_GD_PLT:
case MCSymbolRefExpr::VK_Hexagon_LD_PLT:
case MCSymbolRefExpr::VK_Hexagon_IE:
case MCSymbolRefExpr::VK_Hexagon_IE_GOT:
case MCSymbolRefExpr::VK_TPREL:
break;
}
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
break;
}
case MCExpr::Unary:
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
break;
}
}
void HexagonMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
auto expr = getExpr();
fixELFSymbolsInTLSFixupsImpl(expr, Asm);
}
MCExpr const *HexagonMCExpr::getExpr() const { return Expr; }
@ -75,4 +117,4 @@ void HexagonMCExpr::setSignMismatch(bool Val) {
bool HexagonMCExpr::signMismatch() const {
return SignMismatch;
}
}

View File

@ -16,10 +16,9 @@
#include "Hexagon.h"
#include "HexagonBaseInfo.h"
#include "HexagonMCChecker.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSubtargetInfo.h"
namespace llvm {
@ -59,31 +58,36 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCB,
HexagonMCChecker *Check) {
// Check the bundle for errors.
bool CheckOk = Check ? Check->check(false) : true;
if (!CheckOk)
return false;
// Examine the packet and convert pairs of instructions to compound
// instructions when possible.
if (!HexagonDisableCompound)
HexagonMCInstrInfo::tryCompound(MCII, Context, MCB);
// Check the bundle for errors.
bool CheckOk = Check ? Check->check() : true;
if (!CheckOk)
return false;
HexagonMCShuffle(MCII, STI, MCB);
HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB);
HexagonMCShuffle(false, MCII, STI, MCB);
// Examine the packet and convert pairs of instructions to duplex
// instructions when possible.
MCInst InstBundlePreDuplex = MCInst(MCB);
if (!HexagonDisableDuplex) {
SmallVector<DuplexCandidate, 8> possibleDuplexes;
possibleDuplexes = HexagonMCInstrInfo::getDuplexPossibilties(MCII, MCB);
possibleDuplexes =
HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB);
HexagonMCShuffle(MCII, STI, Context, MCB, possibleDuplexes);
}
// Examines packet and pad the packet, if needed, when an
// end-loop is in the bundle.
HexagonMCInstrInfo::padEndloop(Context, MCB);
HexagonMCInstrInfo::padEndloop(MCB);
// If compounding and duplexing didn't reduce the size below
// 4 or less we have a packet that is too big.
if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE)
return false;
HexagonMCShuffle(MCII, STI, MCB);
// Check the bundle for errors.
CheckOk = Check ? Check->check(true) : true;
if (!CheckOk)
return false;
HexagonMCShuffle(true, MCII, STI, MCB);
return true;
}
@ -111,20 +115,6 @@ MCInst HexagonMCInstrInfo::createBundle() {
return Result;
}
MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass,
MCInst const &inst0,
MCInst const &inst1) {
assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf");
MCInst *duplexInst = new (Context) MCInst;
duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass);
MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0));
MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1));
duplexInst->addOperand(MCOperand::createInst(SubInst0));
duplexInst->addOperand(MCOperand::createInst(SubInst1));
return duplexInst;
}
MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
MCInst const &Inst,
MCOperand const &MO) {
@ -142,6 +132,20 @@ MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
return XMI;
}
MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass,
MCInst const &inst0,
MCInst const &inst1) {
assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf");
MCInst *duplexInst = new (Context) MCInst;
duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass);
MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0));
MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1));
duplexInst->addOperand(MCOperand::createInst(SubInst0));
duplexInst->addOperand(MCOperand::createInst(SubInst1));
return duplexInst;
}
MCInst const *HexagonMCInstrInfo::extenderForIndex(MCInst const &MCB,
size_t Index) {
assert(Index <= bundleSize(MCB));
@ -169,22 +173,9 @@ HexagonMCInstrInfo::getAccessSize(MCInstrInfo const &MCII, MCInst const &MCI) {
HexagonII::MemAccesSizeMask));
}
unsigned HexagonMCInstrInfo::getBitCount(MCInstrInfo const &MCII,
MCInst const &MCI) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
}
// Return constant extended operand number.
unsigned short HexagonMCInstrInfo::getCExtOpNum(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
}
MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII,
MCInst const &MCI) {
return (MCII.get(MCI.getOpcode()));
return MCII.get(MCI.getOpcode());
}
unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) {
@ -272,32 +263,32 @@ unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII,
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
}
// Return the max value that a constant extendable operand can have
// without being extended.
/// Return the maximum value of an extendable operand.
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
MCInst const &MCI) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
unsigned isSigned =
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
bool S = (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
if (isSigned) // if value is signed
return ~(-1U << (bits - 1));
assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
HexagonMCInstrInfo::isExtended(MCII, MCI));
if (S) // if value is signed
return ~(-1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1));
else
return ~(-1U << bits);
return ~(-1 << HexagonMCInstrInfo::getExtentBits(MCII, MCI));
}
// Return the min value that a constant extendable operand can have
// without being extended.
/// Return the minimum value of an extendable operand.
int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII,
MCInst const &MCI) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
unsigned isSigned =
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
bool S = (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
if (isSigned) // if value is signed
return -1U << (bits - 1);
assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
HexagonMCInstrInfo::isExtended(MCII, MCI));
if (S) // if value is signed
return -1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1);
else
return 0;
}
@ -315,9 +306,7 @@ unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII,
MCInst const &MCI) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
unsigned const O =
(F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask;
unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI);
MCOperand const &MCO = MCI.getOperand(O);
assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
@ -345,6 +334,13 @@ HexagonMCInstrInfo::getNewValueOperand2(MCInstrInfo const &MCII,
return (MCO);
}
/// Return the Hexagon ISA class for the insn.
unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
}
int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
@ -357,17 +353,14 @@ int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
return Hexagon::ArchV4;
case HexagonII::HasV5SubT:
return Hexagon::ArchV5;
case HexagonII::HasV55SubT:
return Hexagon::ArchV55;
case HexagonII::HasV60SubT:
return Hexagon::ArchV60;
}
}
// Return the Hexagon ISA class for the insn.
unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
}
/// Return the slots this instruction can execute out of
unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
MCInst const &MCI) {
@ -377,6 +370,49 @@ unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
return ((II[SchedClass].FirstStage + HexagonStages)->getUnits());
}
/// Return the slots this instruction consumes in addition to
/// the slot(s) it can execute out of
unsigned HexagonMCInstrInfo::getOtherReservedSlots(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
MCInst const &MCI) {
const InstrItinerary *II = STI.getSchedModel().InstrItineraries;
int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();
unsigned Slots = 0;
// FirstStage are slots that this instruction can execute in.
// FirstStage+1 are slots that are also consumed by this instruction.
// For example: vmemu can only execute in slot 0 but also consumes slot 1.
for (unsigned Stage = II[SchedClass].FirstStage + 1;
Stage < II[SchedClass].LastStage; ++Stage) {
unsigned Units = (Stage + HexagonStages)->getUnits();
if (Units > HexagonGetLastSlot())
break;
// fyi: getUnits() will return 0x1, 0x2, 0x4 or 0x8
Slots |= Units;
}
// if 0 is returned, then no additional slots are consumed by this inst.
return Slots;
}
bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
auto MI = I.getInst();
if (HexagonMCInstrInfo::isDuplex(MCII, *MI))
return true;
}
return false;
}
bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
return extenderForIndex(MCB, Index) != nullptr;
}
bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
@ -390,11 +426,7 @@ bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
return false;
}
bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
return extenderForIndex(MCB, Index) != nullptr;
}
// Return whether the instruction is a legal new-value producer.
/// Return whether the insn produces a value.
bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
@ -414,46 +446,19 @@ MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) {
return *MCB.getOperand(bundleInstructionsOffset + Index).getInst();
}
/// Return where the instruction is an accumulator.
bool HexagonMCInstrInfo::isAccumulator(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask);
}
bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) {
auto Result = Hexagon::BUNDLE == MCI.getOpcode();
assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm()));
return Result;
}
// Return whether the insn is an actual insn.
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
return (!HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
!HexagonMCInstrInfo::isPrefix(MCII, MCI) &&
HexagonMCInstrInfo::getType(MCII, MCI) != HexagonII::TypeENDLOOP);
}
bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
}
bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
MCInst const &MCI) {
return getType(MCII, MCI) == HexagonII::TypeCJ;
}
bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) {
return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) ||
(Reg >= Hexagon::D8 && Reg <= Hexagon::D11));
}
bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI);
}
// Return whether the instruction needs to be constant extended.
// 1) Always return true if the instruction has 'isExtended' flag set.
//
// isExtendable:
// 2) For immediate extended operands, return true only if the value is
// out-of-range.
// 3) For global address, always return true.
bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
MCInst const &MCI) {
if (HexagonMCInstrInfo::isExtended(MCII, MCI))
@ -468,7 +473,7 @@ bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeJ) ||
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCJ &&
HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()) ||
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNV &&
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ &&
HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()))
return false;
// Otherwise loop instructions and other CR insts are handled by relaxation
@ -488,6 +493,30 @@ bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
return (MinValue > Value || Value > MaxValue);
}
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
return !HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
!HexagonMCInstrInfo::isPrefix(MCII, MCI);
}
bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
}
bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
MCInst const &MCI) {
return (getType(MCII, MCI) == HexagonII::TypeCJ);
}
bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) {
return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) ||
(Reg >= Hexagon::D8 && Reg <= Hexagon::D11));
}
bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI);
}
bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII,
MCInst const &MCI) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
@ -524,20 +553,17 @@ bool HexagonMCInstrInfo::isIntRegForSubInst(unsigned Reg) {
(Reg >= Hexagon::R16 && Reg <= Hexagon::R23));
}
// Return whether the insn is a new-value consumer.
/// Return whether the insn expects newly produced value.
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask);
}
// Return whether the operand can be constant extended.
bool HexagonMCInstrInfo::isOperandExtended(MCInstrInfo const &MCII,
MCInst const &MCI,
unsigned short OperandNum) {
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) ==
OperandNum;
/// Return whether the operand is extendable.
bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII,
MCInst const &MCI, unsigned short O) {
return (O == HexagonMCInstrInfo::getExtendableOp(MCII, MCI));
}
bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) {
@ -580,8 +606,22 @@ bool HexagonMCInstrInfo::isPredReg(unsigned Reg) {
return (Reg >= Hexagon::P0 && Reg <= Hexagon::P3_0);
}
bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
/// Return whether the insn can be packaged only with A and X-type insns.
bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
}
/// Return whether the insn can be packaged only with an A-type insn in slot #1.
bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
}
/// Return whether the insn is solo, i.e., cannot be in a packet.
bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
}
@ -657,17 +697,6 @@ bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) {
}
}
bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
}
bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
}
bool HexagonMCInstrInfo::isVector(MCInstrInfo const &MCII, MCInst const &MCI) {
if ((getType(MCII, MCI) <= HexagonII::TypeCVI_LAST) &&
(getType(MCII, MCI) >= HexagonII::TypeCVI_FIRST))
@ -699,8 +728,7 @@ bool HexagonMCInstrInfo::mustExtend(MCExpr const &Expr) {
return HExpr.mustExtend();
}
void HexagonMCInstrInfo::setMustNotExtend(MCExpr const &Expr, bool Val) {
HexagonMCExpr &HExpr =
const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
HExpr.setMustNotExtend(Val);
}
bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) {
@ -719,7 +747,7 @@ bool HexagonMCInstrInfo::s23_2_reloc(MCExpr const &Expr) {
return HExpr->s23_2_reloc();
}
void HexagonMCInstrInfo::padEndloop(MCContext &Context, MCInst &MCB) {
void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {
MCInst Nop;
Nop.setOpcode(Hexagon::A2_nop);
assert(isBundle(MCB));
@ -727,7 +755,7 @@ void HexagonMCInstrInfo::padEndloop(MCContext &Context, MCInst &MCB) {
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) ||
((HexagonMCInstrInfo::isOuterLoop(MCB) &&
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE))))
MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop)));
MCB.addOperand(MCOperand::createInst(new MCInst(Nop)));
}
bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,

View File

@ -19,11 +19,8 @@
namespace llvm {
class HexagonMCChecker;
class MCContext;
class MCInstrDesc;
class MCInstrInfo;
class MCInst;
class MCOperand;
class MCSubtargetInfo;
namespace HexagonII {
enum class MemAccessSize;
@ -67,6 +64,15 @@ bool canonicalizePacket(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCB,
HexagonMCChecker *Checker);
// Create a duplex instruction given the two subinsts
MCInst *deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0,
MCInst const &inst1);
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst,
MCOperand const &MO);
// Convert this instruction in to a duplex subinst
MCInst deriveSubInst(MCInst const &Inst);
// Clamp off upper 26 bits of extendable operand for emission
void clampExtended(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);
@ -77,36 +83,18 @@ MCInst const *extenderForIndex(MCInst const &MCB, size_t Index);
void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB,
MCInst const &MCI);
// Create a duplex instruction given the two subinsts
MCInst *deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0,
MCInst const &inst1);
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst,
MCOperand const &MO);
// Convert this instruction in to a duplex subinst
MCInst deriveSubInst(MCInst const &Inst);
// Return the extender for instruction at Index or nullptr if none
MCInst const *extenderForIndex(MCInst const &MCB, size_t Index);
// Return memory access size
HexagonII::MemAccessSize getAccessSize(MCInstrInfo const &MCII,
MCInst const &MCI);
// Return number of bits in the constant extended operand.
unsigned getBitCount(MCInstrInfo const &MCII, MCInst const &MCI);
// Return constant extended operand number.
unsigned short getCExtOpNum(MCInstrInfo const &MCII, MCInst const &MCI);
MCInstrDesc const &getDesc(MCInstrInfo const &MCII, MCInst const &MCI);
// Return which duplex group this instruction belongs to
unsigned getDuplexCandidateGroup(MCInst const &MI);
// Return a list of all possible instruction duplex combinations
SmallVector<DuplexCandidate, 8> getDuplexPossibilties(MCInstrInfo const &MCII,
MCInst const &MCB);
SmallVector<DuplexCandidate, 8>
getDuplexPossibilties(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst const &MCB);
unsigned getDuplexRegisterNumbering(unsigned Reg);
MCExpr const &getExpr(MCExpr const &Expr);
@ -143,7 +131,6 @@ MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI);
unsigned short getNewValueOp2(MCInstrInfo const &MCII, MCInst const &MCI);
MCOperand const &getNewValueOperand2(MCInstrInfo const &MCII,
MCInst const &MCI);
int getSubTarget(MCInstrInfo const &MCII, MCInst const &MCI);
// Return the Hexagon ISA class for the insn.
@ -152,6 +139,9 @@ unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
/// Return the slots used by the insn.
unsigned getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst const &MCI);
unsigned getOtherReservedSlots(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst const &MCI);
bool hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI);
// Does the packet have an extender for the instruction at Index
bool hasExtenderForIndex(MCInst const &MCB, size_t Index);
@ -161,19 +151,6 @@ bool hasImmExt(MCInst const &MCI);
// Return whether the instruction is a legal new-value producer.
bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
bool hasNewValue2(MCInstrInfo const &MCII, MCInst const &MCI);
// Return the instruction at Index
MCInst const &instruction(MCInst const &MCB, size_t Index);
// Returns whether this MCInst is a wellformed bundle
bool isBundle(MCInst const &MCI);
// Return whether the insn is an actual insn.
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCompound(MCInstrInfo const &MCII, MCInst const &MCI);
// Return the duplex iclass given the two duplex classes
unsigned iClassOfDuplexPair(unsigned Ga, unsigned Gb);
int64_t minConstant(MCInst const &MCI, size_t Index);
@ -189,6 +166,18 @@ template <unsigned N> bool inRange(MCInst const &MCI, size_t Index) {
return isUInt<N>(minConstant(MCI, Index));
}
// Return the instruction at Index
MCInst const &instruction(MCInst const &MCB, size_t Index);
bool isAccumulator(MCInstrInfo const &MCII, MCInst const &MCI);
// Returns whether this MCInst is a wellformed bundle
bool isBundle(MCInst const &MCI);
// Return whether the insn is an actual insn.
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCompound(MCInstrInfo const &MCII, MCInst const &MCI);
// Return whether the instruction needs to be constant extended.
bool isConstExtended(MCInstrInfo const &MCII, MCInst const &MCI);
@ -229,15 +218,12 @@ bool isMemStoreReorderEnabled(MCInst const &MCI);
// Return whether the insn is a new-value consumer.
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
// Return true if the operand can be constant extended.
bool isOperandExtended(MCInstrInfo const &MCII, MCInst const &MCI,
unsigned short OperandNum);
bool isOpExtendable(MCInstrInfo const &MCII, MCInst const &MCI, unsigned short);
// Can these two instructions be duplexed
bool isOrderedDuplexPair(MCInstrInfo const &MCII, MCInst const &MIa,
bool ExtendedA, MCInst const &MIb, bool ExtendedB,
bool bisReversable);
bool bisReversable, MCSubtargetInfo const &STI);
// Returns whether this bundle is an endloop1
bool isOuterLoop(MCInst const &MCI);
@ -270,12 +256,11 @@ bool mustExtend(MCExpr const &Expr);
bool mustNotExtend(MCExpr const &Expr);
// Pad the bundle with nops to satisfy endloop requirements
void padEndloop(MCContext &Context, MCInst &MCI);
void padEndloop(MCInst &MCI);
bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
// Replace the instructions inside MCB, represented by Candidate
void replaceDuplex(MCContext &Context, MCInst &MCB, DuplexCandidate Candidate);
void replaceDuplex(MCContext &Context, MCInst &MCI, DuplexCandidate Candidate);
bool s23_2_reloc(MCExpr const &Expr);
// Marks a bundle as endloop0
@ -295,7 +280,8 @@ unsigned SubregisterBit(unsigned Consumer, unsigned Producer,
unsigned Producer2);
// Attempt to find and replace compound pairs
void tryCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);
void tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCI);
}
}

View File

@ -33,42 +33,39 @@ void HexagonMCShuffler::init(MCInst &MCB) {
MCInst const *Extender = nullptr;
// Copy the bundle for the shuffling.
for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
MCInst *MI = const_cast<MCInst *>(I.getInst());
MCInst &MI = *const_cast<MCInst *>(I.getInst());
DEBUG(dbgs() << "Shuffling: " << MCII.getName(MI.getOpcode()));
assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo());
if (!HexagonMCInstrInfo::isImmext(*MI)) {
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
false);
if (!HexagonMCInstrInfo::isImmext(MI)) {
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
Extender = nullptr;
} else
Extender = MI;
Extender = &MI;
}
}
BundleFlags = MCB.getOperand(0).getImm();
}
void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,
void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
bool bInsertAtFront) {
if (HexagonMCInstrInfo::isBundle(MCB)) {
if (bInsertAtFront && AddMI)
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
false);
if (bInsertAtFront)
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
MCInst const *Extender = nullptr;
// Copy the bundle for the shuffling.
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
MCInst *MI = const_cast<MCInst *>(I.getInst());
if (!HexagonMCInstrInfo::isImmext(*MI)) {
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
false);
MCInst &MI = *const_cast<MCInst *>(I.getInst());
if (!HexagonMCInstrInfo::isImmext(MI)) {
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
Extender = nullptr;
} else
Extender = MI;
Extender = &MI;
}
if (!bInsertAtFront && AddMI)
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
false);
if (!bInsertAtFront)
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
}
BundleFlags = MCB.getOperand(0).getImm();
@ -80,11 +77,11 @@ void HexagonMCShuffler::copyTo(MCInst &MCB) {
// Copy the results into the bundle.
for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
MCInst const *MI = I->getDesc();
MCInst const &MI = I->getDesc();
MCInst const *Extender = I->getExtender();
if (Extender)
MCB.addOperand(MCOperand::createInst(Extender));
MCB.addOperand(MCOperand::createInst(MI));
MCB.addOperand(MCOperand::createInst(&MI));
}
}
@ -98,9 +95,9 @@ bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
return (!getError());
}
bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &MCB) {
HexagonMCShuffler MCS(MCII, STI, MCB);
bool llvm::HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &MCB) {
HexagonMCShuffler MCS(true, MCII, STI, MCB);
if (DisableShuffle)
// Ignore if user chose so.
@ -124,6 +121,18 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
if (!MCS.reshuffleTo(MCB)) {
// Unless there is any error, which should not happen at this point.
unsigned shuffleError = MCS.getError();
if (!Fatal && (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS))
return false;
if (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS) {
errs() << "\nFailing packet:\n";
for (const auto& I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
MCInst *MI = const_cast<MCInst *>(I.getInst());
errs() << HexagonMCInstrInfo::getName(MCII, *MI) << ' ' << HexagonMCInstrInfo::getDesc(MCII, *MI).getOpcode() << '\n';
}
errs() << '\n';
}
switch (shuffleError) {
default:
llvm_unreachable("unknown error");
@ -176,7 +185,7 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
MCInst Attempt(MCB);
HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
HexagonMCShuffler MCS(MCII, STI, Attempt); // copy packet to the shuffler
HexagonMCShuffler MCS(true, MCII, STI, Attempt); // copy packet to the shuffler
if (MCS.size() == 1) { // case of one duplex
// copy the created duplex in the shuffler to the bundle
MCS.copyTo(MCB);
@ -191,7 +200,7 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
}
if (doneShuffling == false) {
HexagonMCShuffler MCS(MCII, STI, MCB);
HexagonMCShuffler MCS(true, MCII, STI, MCB);
doneShuffling = MCS.reshuffleTo(MCB); // shuffle
shuffleError = MCS.getError();
}
@ -202,8 +211,8 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
}
bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &MCB, MCInst const *AddMI, int fixupCount) {
if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
MCInst &MCB, MCInst const &AddMI, int fixupCount) {
if (!HexagonMCInstrInfo::isBundle(MCB))
return false;
// if fixups present, make sure we don't insert too many nops that would
@ -211,8 +220,15 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
if (bundleSize >= HEXAGON_PACKET_SIZE)
return false;
bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB);
if (fixupCount >= 2) {
return false;
if (bhasDuplex) {
if (bundleSize >= HEXAGON_PACKET_SIZE - 1) {
return false;
}
} else {
return false;
}
} else {
if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
return false;
@ -221,7 +237,16 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
if (DisableShuffle)
return false;
HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
// mgl: temporary code (shuffler doesn't take into account the fact that
// a duplex takes up two slots. for example, 3 nops can be put into a packet
// containing a duplex oversubscribing slots by 1).
unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCB))
? HEXAGON_PACKET_SIZE
: HEXAGON_PACKET_SIZE - 1;
if (bhasDuplex && bundleSize >= maxBundleSize)
return false;
HexagonMCShuffler MCS(MCII, STI, MCB, AddMI, false);
if (!MCS.reshuffleTo(MCB)) {
unsigned shuffleError = MCS.getError();
switch (shuffleError) {

View File

@ -27,16 +27,16 @@ class HexagonMCShuffler : public HexagonShuffler {
bool duplex_present;
public:
HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &MCB)
HexagonMCShuffler(bool Fatal, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &MCB)
: HexagonShuffler(MCII, STI) {
init(MCB);
};
HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &MCB, const MCInst *AddMI,
bool bInsertAtFront = false)
MCInst &MCB, MCInst const &AddMI,
bool InsertAtFront)
: HexagonShuffler(MCII, STI) {
init(MCB, AddMI, bInsertAtFront);
init(MCB, AddMI, InsertAtFront);
};
// Copy reordered bundle to another.
@ -49,14 +49,14 @@ public:
private:
void init(MCInst &MCB);
void init(MCInst &MCB, const MCInst *AddMI, bool bInsertAtFront = false);
void init(MCInst &MCB, MCInst const &AddMI, bool InsertAtFront);
};
// Invocation of the shuffler.
bool HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &);
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &);
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCInst &, const MCInst *, int);
MCInst &, MCInst const &, int);
unsigned HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &,
SmallVector<DuplexCandidate, 8>);

View File

@ -22,6 +22,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
@ -95,31 +96,19 @@ StringRef Hexagon_MC::selectHexagonCPU(const Triple &TT, StringRef CPU) {
return ArchV;
}
MCInstrInfo *llvm::createHexagonMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitHexagonMCInstrInfo(X);
return X;
unsigned HexagonGetLastSlot() {
return HexagonItinerariesV4FU::SLOT3;
}
static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
InitHexagonMCRegisterInfo(X, Hexagon::R31);
return X;
}
static MCSubtargetInfo *
createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
CPU = Hexagon_MC::selectHexagonCPU(TT, CPU);
return createHexagonMCSubtargetInfoImpl(TT, CPU, FS);
}
namespace {
class HexagonTargetAsmStreamer : public HexagonTargetStreamer {
public:
HexagonTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &, bool,
MCInstPrinter &)
formatted_raw_ostream &OS,
bool isVerboseAsm,
MCInstPrinter &IP)
: HexagonTargetStreamer(S) {}
void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS,
@ -156,24 +145,15 @@ public:
class HexagonTargetELFStreamer : public HexagonTargetStreamer {
public:
HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)
: HexagonTargetStreamer(S) {
auto Bits = STI.getFeatureBits();
unsigned Flags = 0;
if (Bits[Hexagon::ArchV60])
Flags = ELF::EF_HEXAGON_MACH_V60;
else if (Bits[Hexagon::ArchV55])
Flags = ELF::EF_HEXAGON_MACH_V55;
else if (Bits[Hexagon::ArchV5])
Flags = ELF::EF_HEXAGON_MACH_V5;
else if (Bits[Hexagon::ArchV4])
Flags = ELF::EF_HEXAGON_MACH_V4;
getStreamer().getAssembler().setELFHeaderEFlags(Flags);
}
MCELFStreamer &getStreamer() {
return static_cast<MCELFStreamer &>(Streamer);
}
HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)
: HexagonTargetStreamer(S) {
MCAssembler &MCA = getStreamer().getAssembler();
MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI));
}
void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment,
@ -196,13 +176,26 @@ public:
} // end anonymous namespace
llvm::MCInstrInfo *llvm::createHexagonMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitHexagonMCInstrInfo(X);
return X;
}
static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
InitHexagonMCRegisterInfo(X, Hexagon::R31);
return X;
}
static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT) {
MCAsmInfo *MAI = new HexagonMCAsmInfo(TT);
// VirtualFP = (R30 + #0).
MCCFIInstruction Inst =
MCCFIInstruction::createDefCfa(nullptr, Hexagon::R30, 0);
MCCFIInstruction::createDefCfa(nullptr,
MRI.getDwarfRegNum(Hexagon::R30, true), 0);
MAI->addInitialFrameState(Inst);
return MAI;
@ -212,31 +205,133 @@ static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI) {
const MCRegisterInfo &MRI)
{
if (SyntaxVariant == 0)
return (new HexagonInstPrinter(MAI, MII, MRI));
return new HexagonInstPrinter(MAI, MII, MRI);
else
return nullptr;
}
static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S,
formatted_raw_ostream &OS,
MCInstPrinter *InstPrint,
bool IsVerboseAsm) {
return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *InstPrint);
static MCTargetStreamer *
createMCAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
MCInstPrinter *IP, bool IsVerboseAsm) {
return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *IP);
}
static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context,
MCAsmBackend &MAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll) {
return createHexagonELFStreamer(Context, MAB, OS, Emitter);
static MCStreamer *createMCStreamer(Triple const &T,
MCContext &Context,
MCAsmBackend &MAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter,
bool RelaxAll) {
return createHexagonELFStreamer(T, Context, MAB, OS, Emitter);
}
static MCTargetStreamer *
createHexagonObjectTargetStreamer(MCStreamer &S, MCSubtargetInfo const &STI) {
createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
return new HexagonTargetELFStreamer(S, STI);
}
static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
uint64_t FB = STI->getFeatureBits().to_ullong();
if (FB & (1ULL << F))
STI->ToggleFeature(F);
}
static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
uint64_t FB = STI->getFeatureBits().to_ullong();
return (FB & (1ULL << F)) != 0;
}
StringRef Hexagon_MC::ParseHexagonTriple(const Triple &TT, StringRef CPU) {
StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
StringRef FS = "";
if (CPUName.equals_lower("hexagonv60"))
FS = "+hvx";
return FS;
}
static bool isCPUValid(std::string CPU)
{
std::vector<std::string> table
{
"hexagonv4",
"hexagonv5",
"hexagonv55",
"hexagonv60",
};
return std::find(table.begin(), table.end(), CPU) != table.end();
}
MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
StringRef CPU,
StringRef FS) {
StringRef ArchFS = (FS.size()) ? FS : Hexagon_MC::ParseHexagonTriple(TT, CPU);
StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
if (!isCPUValid(CPUName.str()))
{
errs() << "error: invalid CPU \"" << CPUName.str().c_str() << "\" specified\n";
return nullptr;
}
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
if (X->getFeatureBits()[Hexagon::ExtensionHVXDbl]) {
llvm::FeatureBitset Features = X->getFeatureBits();
X->setFeatureBits(Features.set(Hexagon::ExtensionHVX));
}
return X;
}
unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) {
static std::map<StringRef,unsigned> ElfFlags = {
{"hexagonv4", ELF::EF_HEXAGON_MACH_V4},
{"hexagonv5", ELF::EF_HEXAGON_MACH_V5},
{"hexagonv55", ELF::EF_HEXAGON_MACH_V55},
{"hexagonv60", ELF::EF_HEXAGON_MACH_V60},
};
auto F = ElfFlags.find(STI.getCPU());
assert(F != ElfFlags.end() && "Unrecognized Architecture");
return F->second;
}
namespace {
class HexagonMCInstrAnalysis : public MCInstrAnalysis {
public:
HexagonMCInstrAnalysis(MCInstrInfo const *Info) : MCInstrAnalysis(Info) {}
bool isUnconditionalBranch(MCInst const &Inst) const override {
//assert(!HexagonMCInstrInfo::isBundle(Inst));
return MCInstrAnalysis::isUnconditionalBranch(Inst);
}
bool isConditionalBranch(MCInst const &Inst) const override {
//assert(!HexagonMCInstrInfo::isBundle(Inst));
return MCInstrAnalysis::isConditionalBranch(Inst);
}
bool evaluateBranch(MCInst const &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const override {
//assert(!HexagonMCInstrInfo::isBundle(Inst));
if(!HexagonMCInstrInfo::isExtendable(*Info, Inst))
return false;
auto const &Extended(HexagonMCInstrInfo::getExtendableOperand(*Info, Inst));
assert(Extended.isExpr());
int64_t Value;
if(!Extended.getExpr()->evaluateAsAbsolute(Value))
return false;
Target = Value;
return true;
}
};
}
static MCInstrAnalysis *createHexagonMCInstrAnalysis(const MCInstrInfo *Info) {
return new HexagonMCInstrAnalysis(Info);
}
// Force static initialization.
extern "C" void LLVMInitializeHexagonTargetMC() {
// Register the MC asm info.
@ -252,7 +347,7 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(getTheHexagonTarget(),
createHexagonMCSubtargetInfo);
Hexagon_MC::createHexagonMCSubtargetInfo);
// Register the MC Code Emitter
TargetRegistry::RegisterMCCodeEmitter(getTheHexagonTarget(),
@ -262,8 +357,18 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
TargetRegistry::RegisterMCAsmBackend(getTheHexagonTarget(),
createHexagonAsmBackend);
// Register the MC instruction analyzer.
TargetRegistry::RegisterMCInstrAnalysis(getTheHexagonTarget(),
createHexagonMCInstrAnalysis);
// Register the obj streamer
TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(), createMCStreamer);
TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(),
createMCStreamer);
// Register the obj target streamer
TargetRegistry::RegisterObjectTargetStreamer(getTheHexagonTarget(),
createHexagonObjectTargetStreamer);
// Register the asm streamer
TargetRegistry::RegisterAsmTargetStreamer(getTheHexagonTarget(),
@ -272,7 +377,4 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
// Register the MC Inst Printer
TargetRegistry::RegisterMCInstPrinter(getTheHexagonTarget(),
createHexagonMCInstPrinter);
TargetRegistry::RegisterObjectTargetStreamer(
getTheHexagonTarget(), createHexagonObjectTargetStreamer);
}

View File

@ -41,6 +41,18 @@ extern cl::opt<bool> HexagonDisableDuplex;
extern const InstrStage HexagonStages[];
MCInstrInfo *createHexagonMCInstrInfo();
MCRegisterInfo *createHexagonMCRegisterInfo(StringRef TT);
namespace Hexagon_MC {
StringRef ParseHexagonTriple(const Triple &TT, StringRef CPU);
StringRef selectHexagonCPU(const Triple &TT, StringRef CPU);
/// Create a Hexagon MCSubtargetInfo instance. This is exposed so Asm parser,
/// etc. do not need to go through TargetRegistry.
MCSubtargetInfo *createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU,
StringRef FS);
unsigned GetELFFlags(const MCSubtargetInfo &STI);
}
MCCodeEmitter *createHexagonMCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
@ -53,14 +65,9 @@ MCAsmBackend *createHexagonAsmBackend(const Target &T,
MCObjectWriter *createHexagonELFObjectWriter(raw_pwrite_stream &OS,
uint8_t OSABI, StringRef CPU);
} // End llvm namespace
namespace Hexagon_MC {
StringRef selectHexagonCPU(const Triple &TT, StringRef CPU);
} // end namespace Hexagon_MC
} // end namespace llvm
unsigned HexagonGetLastSlot();
// Define symbolic names for Hexagon registers. This defines a mapping from
// register name to register number.

View File

@ -37,16 +37,16 @@ class HexagonBid {
unsigned Bid;
public:
HexagonBid() : Bid(0){};
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
HexagonBid() : Bid(0){}
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
// Check if the insn priority is overflowed.
bool isSold() const { return (Bid >= MAX); };
bool isSold() const { return (Bid >= MAX); }
HexagonBid &operator+=(const HexagonBid &B) {
Bid += B.Bid;
return *this;
};
}
};
// Slot shuffling allocation.
@ -56,7 +56,7 @@ class HexagonUnitAuction {
unsigned isSold : HEXAGON_PACKET_SIZE;
public:
HexagonUnitAuction() : isSold(0){};
HexagonUnitAuction(unsigned cs = 0) : isSold(cs){};
// Allocate slots.
bool bid(unsigned B) {
@ -70,11 +70,10 @@ public:
isSold |= Scores[i].isSold() << i;
}
return true;
;
} else
// Error if the desired slots are already full.
return false;
};
}
};
} // end anonymous namespace
@ -83,9 +82,6 @@ unsigned HexagonResource::setWeight(unsigned s) {
const unsigned MaskWeight = SlotWeight - 1;
bool Key = (1 << s) & getUnits();
// TODO: Improve this API so that we can prevent misuse statically.
assert(SlotWeight * s < 32 && "Argument to setWeight too large.");
// Calculate relative weight of the insn for the given slot, weighing it the
// heavier the more restrictive the insn is and the lowest the slots that the
// insn may be executed in.
@ -141,6 +137,40 @@ HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL,
}
}
struct CVIUnits {
unsigned Units;
unsigned Lanes;
};
typedef SmallVector<struct CVIUnits, 8> HVXInstsT;
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
{
for (unsigned i = 1 ; i < Lanes ; ++i)
startBit = (startBit << 1) | startBit;
return startBit;
}
static bool checkHVXPipes(const HVXInstsT& hvxInsts, unsigned startIdx, unsigned usedUnits)
{
if (startIdx < hvxInsts.size()) {
if (!hvxInsts[startIdx].Units)
return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
for (unsigned b = 0x1 ; b <= 0x8 ; b <<= 1) {
if ((hvxInsts[startIdx].Units & b) == 0)
continue;
unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes);
if ((allBits & usedUnits) == 0) {
if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
return true;
}
}
return false;
}
return true;
}
HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI)
: MCII(MCII), STI(STI) {
@ -154,21 +184,76 @@ void HexagonShuffler::reset() {
Error = SHUFFLE_SUCCESS;
}
void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
unsigned S, bool X) {
HexagonInstr PI(&TUL, MCII, ID, Extender, S, X);
void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
unsigned S) {
HexagonInstr PI(&TUL, MCII, &ID, Extender, S);
Packet.push_back(PI);
}
static struct {
unsigned first;
unsigned second;
} jumpSlots[] = { {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1} };
#define MAX_JUMP_SLOTS (sizeof(jumpSlots)/sizeof(jumpSlots[0]))
namespace {
bool isDuplexAGroup(unsigned Opcode) {
switch (Opcode) {
case Hexagon::SA1_addi:
case Hexagon::SA1_addrx:
case Hexagon::SA1_addsp:
case Hexagon::SA1_and1:
case Hexagon::SA1_clrf:
case Hexagon::SA1_clrfnew:
case Hexagon::SA1_clrt:
case Hexagon::SA1_clrtnew:
case Hexagon::SA1_cmpeqi:
case Hexagon::SA1_combine0i:
case Hexagon::SA1_combine1i:
case Hexagon::SA1_combine2i:
case Hexagon::SA1_combine3i:
case Hexagon::SA1_combinerz:
case Hexagon::SA1_combinezr:
case Hexagon::SA1_dec:
case Hexagon::SA1_inc:
case Hexagon::SA1_seti:
case Hexagon::SA1_setin1:
case Hexagon::SA1_sxtb:
case Hexagon::SA1_sxth:
case Hexagon::SA1_tfr:
case Hexagon::SA1_zxtb:
case Hexagon::SA1_zxth:
return true;
break;
default:
return false;
}
}
unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
unsigned Result = 0;
unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
if (Type == HexagonII::TypeDUPLEX) {
unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode();
unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode();
Result += !isDuplexAGroup(subInst0Opcode);
Result += !isDuplexAGroup(subInst1Opcode);
} else
Result += Type != HexagonII::TypeALU32 &&
Type != HexagonII::TypeXTYPE;
return Result;
}
}
/// Check that the packet is legal and enforce relative insn order.
bool HexagonShuffler::check() {
// Descriptive slot masks.
const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
slotThree = 0x8, //slotFirstJump = 0x8,
slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
// Highest slots for branches and stores used to keep their original order.
unsigned slotJump = slotFirstJump;
//unsigned slotJump = slotFirstJump;
unsigned slotLoadStore = slotFirstLoadStore;
// Number of branches, solo branches, indirect branches.
unsigned jumps = 0, jump1 = 0;
@ -188,36 +273,39 @@ bool HexagonShuffler::check() {
unsigned onlyNo1 = 0;
unsigned xtypeFloat = 0;
unsigned pSlot3Cnt = 0;
unsigned memops = 0;
unsigned deallocs = 0;
iterator slot3ISJ = end();
std::vector<iterator> foundBranches;
unsigned reservedSlots = 0;
// Collect information from the insns in the packet.
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const *ID = ISJ->getDesc();
MCInst const &ID = ISJ->getDesc();
if (HexagonMCInstrInfo::isSolo(MCII, *ID))
solo += !ISJ->isSoloException();
else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
onlyAX += !ISJ->isSoloException();
else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
onlyAin1 += !ISJ->isSoloException();
if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&
HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
++neitherAnorX;
if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
if (HexagonMCInstrInfo::isSolo(MCII, ID))
solo++;
else if (HexagonMCInstrInfo::isSoloAX(MCII, ID))
onlyAX++;
else if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
onlyAin1++;
neitherAnorX += countNeitherAnorX(MCII, ID);
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
++pSlot3Cnt;
slot3ISJ = ISJ;
}
if (HexagonMCInstrInfo::isCofMax1(MCII, *ID))
reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID);
if (HexagonMCInstrInfo::isCofMax1(MCII, ID))
++jump1;
switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
switch (HexagonMCInstrInfo::getType(MCII, ID)) {
case HexagonII::TypeXTYPE:
if (HexagonMCInstrInfo::isFloat(MCII, *ID))
if (HexagonMCInstrInfo::isFloat(MCII, ID))
++xtypeFloat;
break;
case HexagonII::TypeJR:
case HexagonII::TypeJ:
++jumps;
foundBranches.push_back(ISJ);
break;
case HexagonII::TypeCVI_VM_VP_LDU:
++onlyNo1;
@ -228,10 +316,14 @@ bool HexagonShuffler::check() {
case HexagonII::TypeLD:
++loads;
++memory;
if (ISJ->Core.getUnits() == slotSingleLoad)
if (ISJ->Core.getUnits() == slotSingleLoad ||
HexagonMCInstrInfo::getType(MCII, ID) ==
HexagonII::TypeCVI_VM_VP_LDU)
++load0;
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) {
++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
foundBranches.push_back(ISJ);
}
break;
case HexagonII::TypeCVI_VM_STU:
++onlyNo1;
@ -241,26 +333,50 @@ bool HexagonShuffler::check() {
case HexagonII::TypeST:
++stores;
++memory;
if (ISJ->Core.getUnits() == slotSingleStore)
if (ISJ->Core.getUnits() == slotSingleStore ||
HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU)
++store0;
break;
case HexagonII::TypeV4LDST:
++loads;
++stores;
++store1;
++memops;
++memory;
break;
case HexagonII::TypeNV:
case HexagonII::TypeNCJ:
++memory; // NV insns are memory-like.
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
++jumps, ++jump1;
foundBranches.push_back(ISJ);
}
break;
case HexagonII::TypeCR:
// Legacy conditional branch predicated on a register.
case HexagonII::TypeSYSTEM:
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
++loads;
case HexagonII::TypeCJ:
if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
++jumps;
foundBranches.push_back(ISJ);
}
break;
case HexagonII::TypeDUPLEX: {
++duplex;
MCInst const &Inst0 = *ID.getOperand(0).getInst();
MCInst const &Inst1 = *ID.getOperand(1).getInst();
if (HexagonMCInstrInfo::isCofMax1(MCII, Inst0))
++jump1;
if (HexagonMCInstrInfo::isCofMax1(MCII, Inst1))
++jump1;
if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) {
++jumps;
foundBranches.push_back(ISJ);
}
if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) {
++jumps;
foundBranches.push_back(ISJ);
}
break;
}
}
}
@ -277,12 +393,20 @@ bool HexagonShuffler::check() {
Error = SHUFFLE_ERROR_BRANCHES;
return false;
}
if (memops && stores > 1) {
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
return false;
}
if (deallocs && stores) {
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
return false;
}
// Modify packet accordingly.
// TODO: need to reserve slots #0 and #1 for duplex insns.
bool bOnlySlot3 = false;
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const *ID = ISJ->getDesc();
MCInst const &ID = ISJ->getDesc();
if (!ISJ->Core.getUnits()) {
// Error if insn may not be executed in any slot.
@ -291,40 +415,24 @@ bool HexagonShuffler::check() {
}
// Exclude from slot #1 any insn but A2_nop.
if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
if (HexagonMCInstrInfo::getDesc(MCII, ID).getOpcode() != Hexagon::A2_nop)
if (onlyNo1)
ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
// Exclude from slot #1 any insn but A-type.
if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)
if (HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32)
if (onlyAin1)
ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
// Branches must keep the original order.
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
if (jumps > 1) {
if (slotJump < slotLastJump) {
// Error if indirect branch with another branch or
// no more slots available for branches.
Error = SHUFFLE_ERROR_BRANCHES;
return false;
}
// Pin the branch to the highest slot available to it.
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
// Update next highest slot available to branches.
slotJump >>= 1;
}
// A single load must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
if (loads == 1 && loads == memory)
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
if (loads == 1 && loads == memory && memops == 0)
// Pin the load to slot #0.
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
}
// A single store must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
if (!store0) {
if (stores == 1)
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
@ -347,7 +455,7 @@ bool HexagonShuffler::check() {
}
}
// flag if an instruction can only be executed in slot 3
// flag if an instruction requires to be in slot 3
if (ISJ->Core.getUnits() == slotThree)
bOnlySlot3 = true;
@ -358,14 +466,61 @@ bool HexagonShuffler::check() {
}
}
// preserve branch order
bool validateSlots = true;
if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
if (jumps > 1) {
if (foundBranches.size() > 2) {
Error = SHUFFLE_ERROR_BRANCHES;
return false;
}
// try all possible choices
for (unsigned int i = 0 ; i < MAX_JUMP_SLOTS ; ++i) {
// validate first jump with this slot rule
if (!(jumpSlots[i].first & foundBranches[0]->Core.getUnits()))
continue;
// validate second jump with this slot rule
if (!(jumpSlots[i].second & foundBranches[1]->Core.getUnits()))
continue;
// both valid for this configuration, set new slot rules
PacketSave = Packet;
foundBranches[0]->Core.setUnits(jumpSlots[i].first);
foundBranches[1]->Core.setUnits(jumpSlots[i].second);
HexagonUnitAuction AuctionCore(reservedSlots);
std::sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot "slotJump"
bool bFail = false;
for (iterator I = begin(); I != end() && bFail != true; ++I)
if (!AuctionCore.bid(I->Core.getUnits()))
bFail = true;
// if yes, great, if not then restore original slot mask
if (!bFail) {
validateSlots = false; // all good, no need to re-do auction
break;
}
else
// restore original values
Packet = PacketSave;
}
if (validateSlots == true) {
Error = SHUFFLE_ERROR_NOSLOTS;
return false;
}
}
if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
validateSlots = true;
// save off slot mask of instruction marked with A_PREFER_SLOT3
// and then pin it to slot #3
unsigned saveUnits = slot3ISJ->Core.getUnits();
slot3ISJ->Core.setUnits(saveUnits & slotThree);
HexagonUnitAuction AuctionCore;
HexagonUnitAuction AuctionCore(reservedSlots);
std::sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot #3
@ -379,16 +534,16 @@ bool HexagonShuffler::check() {
validateSlots = false; // all good, no need to re-do auction
else
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const *ID = ISJ->getDesc();
if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
MCInst const &ID = ISJ->getDesc();
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID))
ISJ->Core.setUnits(saveUnits);
}
}
// Check if any slot, core, is over-subscribed.
// Check if any slot, core or CVI, is over-subscribed.
// Verify the core slot subscriptions.
if (validateSlots) {
HexagonUnitAuction AuctionCore;
HexagonUnitAuction AuctionCore(reservedSlots);
std::sort(begin(), end(), HexagonInstr::lessCore);
@ -399,17 +554,27 @@ bool HexagonShuffler::check() {
}
}
// Verify the CVI slot subscriptions.
{
HexagonUnitAuction AuctionCVI;
std::sort(begin(), end(), HexagonInstr::lessCVI);
for (iterator I = begin(); I != end(); ++I)
for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid?
if (!AuctionCVI.bid(I->CVI.getUnits() << i)) {
Error = SHUFFLE_ERROR_SLOTS;
return false;
}
std::sort(begin(), end(), HexagonInstr::lessCVI);
// create vector of hvx instructions to check
HVXInstsT hvxInsts;
hvxInsts.clear();
for (iterator I = begin(); I != end(); ++I) {
struct CVIUnits inst;
inst.Units = I->CVI.getUnits();
inst.Lanes = I->CVI.getLanes();
if (inst.Units == 0)
continue; // not an hvx inst or an hvx inst that doesn't uses any pipes
hvxInsts.push_back(inst);
}
// if there are any hvx instructions in this packet, check pipe usage
if (hvxInsts.size() > 0) {
unsigned startIdx, usedUnits;
startIdx = usedUnits = 0x0;
if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) {
// too many pipes used to be valid
Error = SHUFFLE_ERROR_SLOTS;
return false;
}
}
Error = SHUFFLE_SUCCESS;
@ -452,10 +617,12 @@ bool HexagonShuffler::shuffle() {
}
for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
dbgs() << ':'
<< HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
.getOpcode();
DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); if (ISJ->CVI.isValid()) {
dbgs() << '/';
dbgs().write_hex(ISJ->CVI.getUnits()) << '|';
dbgs() << ISJ->CVI.getLanes();
} dbgs() << ':'
<< HexagonMCInstrInfo::getDesc(MCII, ISJ->getDesc()).getOpcode();
dbgs() << '\n');
DEBUG(dbgs() << '\n');

View File

@ -36,6 +36,7 @@ public:
void setUnits(unsigned s) {
Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
setWeight(s);
};
unsigned setWeight(unsigned s);
@ -44,7 +45,8 @@ public:
// Check if the resources are in ascending slot order.
static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
return (countPopulation(A.getUnits()) <
countPopulation(B.getUnits()));
};
// Check if the resources are in ascending weight order.
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
@ -86,10 +88,10 @@ public:
unsigned s, MCInst const *id);
static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
bool isValid() const { return (Valid); };
unsigned getLanes() const { return (Lanes); };
bool mayLoad() const { return (Load); };
bool mayStore() const { return (Store); };
bool isValid() const { return Valid; };
unsigned getLanes() const { return Lanes; };
bool mayLoad() const { return Load; };
bool mayStore() const { return Store; };
};
// Handle to an insn used by the shuffling algorithm.
@ -100,21 +102,17 @@ class HexagonInstr {
MCInst const *Extender;
HexagonResource Core;
HexagonCVIResource CVI;
bool SoloException;
public:
HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
MCInstrInfo const &MCII, MCInst const *id,
MCInst const *Extender, unsigned s, bool x = false)
: ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id),
SoloException(x) {};
MCInst const *Extender, unsigned s)
: ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
MCInst const *getDesc() const { return (ID); };
MCInst const &getDesc() const { return *ID; };
MCInst const *getExtender() const { return Extender; }
unsigned isSoloException() const { return (SoloException); };
// Check if the handles are in ascending order for shuffling purposes.
bool operator<(const HexagonInstr &B) const {
return (HexagonResource::lessWeight(B.Core, Core));
@ -136,6 +134,7 @@ class HexagonShuffler {
// Insn handles in a bundle.
HexagonPacket Packet;
HexagonPacket PacketSave;
// Shuffling error code.
unsigned Error;
@ -178,8 +177,7 @@ public:
iterator end() { return (Packet.end()); };
// Add insn handle to the bundle .
void append(MCInst const *ID, MCInst const *Extender, unsigned S,
bool X = false);
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
// Return the error code for the last check or shuffling of the bundle.
void setError(unsigned Err) { Error = Err; };

View File

@ -0,0 +1,6 @@
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -t - | FileCheck %s
# CHECK: 00000062 g *COM* 00000008 quartet_table_isqrt
.common quartet_table_isqrt, 98, 8
.common quartet_table_isqrt, 98, 8

View File

@ -0,0 +1,8 @@
# RUN: not llvm-mc -arch=hexagon -filetype=obj %s
#CHECK: 9400c000 { dcfetch(r0 + #0) }
junk:
{
dcfetch(r0 + #junk)
}

View File

@ -1,7 +1,10 @@
// RUN: llvm-mc -arch=hexagon -filetype=obj -o - %s | llvm-objdump -d - | FileCheck %s
// REQUIRES: asserts
.text
// CHECK: { r7 = #-1; r7 = #-1 }
.long 0x3a373a27
// CHECK: { if (!p0.new) r7 = #0; if (p0.new) r7 = #0 }
.long 0x3a573a47
{ r7 = #-1
r6 = #-1 }
// CHECK: { r7 = #-1; r6 = #-1 }
{ p0 = r0
if (p0.new) r7 = #0
if (!p0.new) r7 = #0 }
// CHECK: if (p0.new) r7 = #0; if (!p0.new) r7 = #0

View File

@ -0,0 +1,9 @@
# RUN: not llvm-mc -arch=hexagon %s 2> %t
# RUN: FileCheck < %t %s
.equ a, 0
.set a, 1
.equ a, 2
.equiv a, 3
# CHECK: {{[Ee]}}rror: redefinition of 'a'

View File

@ -0,0 +1,23 @@
; RUN: llc -filetype=obj -march=hexagon %s -o - | llvm-objdump -r - | FileCheck %s
; CHECK: RELOCATION RECORDS FOR [.rela.text]:
; CHECK: 00000000 R_HEX_B22_PCREL printf
; CHECK: 00000004 R_HEX_32_6_X .rodata.str1.1
; CHECK: 00000008 R_HEX_6_X .rodata.str1.1
target triple = "hexagon-unknown--elf"
@.str = private unnamed_addr constant [10 x i8] c"cxfir.log\00", align 1
declare i32 @printf(i8*, ...) #1
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0))
ret i32 0
}
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

View File

@ -0,0 +1,8 @@
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s
#
.I1:
nop
# CHECK: .I1:
# CHECK: nop

View File

@ -0,0 +1,10 @@
# RUN: not llvm-mc -arch=hexagon -filetype=obj %s 2>%t; FileCheck %s <%t
# Don't allow a symbolic operand for an insn that cannot take a
# relocation.
r7:6 = rol(r5:4,#r2)
# This should produce an error
#CHECK: error:

View File

@ -0,0 +1,55 @@
# RUN: llvm-mc -arch=hexagon -filetype=asm %s 2>%t; FileCheck %s <%t
#
# Check that proper packets are not wrongly flagged as invalid.
1-3-4-f:
{
r3 = memub(r2++#1)
if (cmp.eq(r3.new,#0)) jump:nt .
jumpr lr
r4 = #4
}
# CHECK-NOT: rror: invalid instruction packet
1-3-f-f:
{
r3 = memub(r2++#1)
if (cmp.eq(r3.new,#0)) jump:nt .
r5 = #5
r4 = #4
}
# CHECK-NOT: rror: invalid instruction packet
# Special case of a fat packet that will slim when a compound is formed.
3-3-8-c:
{ LOOP0(3-3-8-c, R7)
P0 = CMP.GT(R7, #0)
IF (!P0.NEW) JUMP:NT .
R21:20 = MEMD(R0+#16)
R23:22 = MEMD(R0+#24)
}
# CHECK-NOT: rror: invalid instruction packet
1-f-f-f:
{
r3 = #3
if (cmp.eq(r3.new,#0)) jump:nt .
r5 = #5
r4 = #4
}
# CHECK-NOT: rror: invalid instruction packet
4:
jumpr lr
# CHECK-NOT: rror: invalid instruction packet
f-f-f-f:
{
r3 = #3
r2 = #2
r5 = #5
r4 = #4
}
# CHECK-NOT: rror: invalid instruction packet

View File

@ -0,0 +1,4 @@
# RUN: not llvm-mc -arch=hexagon -filetype=asm junk123.s 2>%t ; FileCheck %s < %t
#
# CHECK: junk123.s: {{[N|n]}}o such file or directory

View File

@ -0,0 +1,7 @@
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -t - | FileCheck %s
#
sym_a:
.set sym_d, sym_a + 8
# CHECK: 00000000 .text 00000000 sym_a
# CHECK: 00000008 .text 00000000 sym_d

View File

@ -0,0 +1,7 @@
# RUN: not llvm-mc -arch=hexagon -filetype=asm %s 2>&1 | FileCheck %s
# Expect errors here, insn needs to be extended
R1 = mpyi(R2, #-256)
# CHECK: error:
R3 = mpyi(R4, #256)
# CHECK: error:

View File

@ -0,0 +1,10 @@
# RUN: llvm-mc -triple hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s
# CHECK: 11 df 75 f1
r17 = xor(r21, lr)
# CHECK: 1d df 35 f3
sp = sub(lr, r21)
# CHECK: 15 c0 3e 71
fp.l = #21

View File

@ -12,6 +12,14 @@ r_hex_b15_pcrel:
r_hex_b7_pcrel:
{ loop1 (#undefined, #0) }
# CHECK: R_HEX_LO16
r_hex_lo16:
{ r0.l = #lo(undefined) }
# CHECK: R_HEX_HI16
r_hex_hi16:
{ r0.h = #hi(undefined) }
# CHECK: R_HEX_32
r_hex_32:
.word undefined
@ -68,10 +76,6 @@ r_hex_b22_pcrel_x:
r_hex_b15_pcrel_x:
{ if (p0) jump ##undefined }
# CHECK: R_HEX_B9_PCREL_X
r_hex_b9_pcrel_x:
{ r0 = #0 ; jump ##undefined }
# CHECK: R_HEX_B7_PCREL_X
r_hex_b7_pcrel_x:
{ loop1 (##undefined, #0) }