Index: lib/Target/Hexagon/HexagonAsmPrinter.cpp =================================================================== --- lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -192,24 +192,24 @@ BundleMIs.push_back(MInst); ++MII; } - unsigned Size = BundleMIs.size(); - assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); - for (unsigned Index = 0; Index < Size; Index++) { - HexagonMCInst MCI; - MCI.setPacketStart(Index == 0); - MCI.setPacketEnd(Index == (Size-1)); - - HexagonLowerToMC(BundleMIs[Index], MCI, *this); + unsigned Size = BundleMIs.size(); + assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); + for (unsigned Index = 0; Index < Size; Index++) { + HexagonMCInst MCI (BundleMIs[Index]->getOpcode()); + MCI.setPacketBegin(Index == 0); + MCI.setPacketEnd(Index == (Size-1)); + + HexagonLowerToMC(BundleMIs[Index], MCI, *this); EmitToStreamer(OutStreamer, MCI); - } - } - else { - HexagonMCInst MCI; - if (MI->getOpcode() == Hexagon::ENDLOOP0) { - MCI.setPacketStart(true); - MCI.setPacketEnd(true); - } - HexagonLowerToMC(MI, MCI, *this); + } + } + else { + HexagonMCInst MCI(MI->getOpcode()); + if (MI->getOpcode() == Hexagon::ENDLOOP0) { + MCI.setPacketBegin(true); + MCI.setPacketEnd(true); + } + HexagonLowerToMC(MI, MCI, *this); EmitToStreamer(OutStreamer, MCI); } Index: lib/Target/Hexagon/HexagonInstrInfo.td =================================================================== --- lib/Target/Hexagon/HexagonInstrInfo.td +++ lib/Target/Hexagon/HexagonInstrInfo.td @@ -89,12 +89,82 @@ def HexagonWrapperCombineII : SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>; -def HexagonWrapperCombineRR : - SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; - -multiclass ALU32_Pbase { - let isPredicatedNew = isPredNew in +def HexagonWrapperCombineRR : + SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; + +let hasSideEffects = 0, hasNewValue = 1, InputType = "reg" in +class T_ALU32_3op MajOp, bits<3> MinOp, bit OpsRev, + bit IsComm> + : ALU32_rr<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = "#mnemonic#"($Rs, $Rt)", + [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel, PredRel { + let isCommutable = IsComm; + let BaseOpcode = mnemonic#_rr; + let CextOpcode = mnemonic; + + bits<5> Rs; + bits<5> Rt; + bits<5> Rd; + + let IClass = 0b1111; + let Inst{27} = 0b0; + let Inst{26-24} = MajOp; + let Inst{23-21} = MinOp; + let Inst{20-16} = !if(OpsRev,Rt,Rs); + let Inst{12-8} = !if(OpsRev,Rs,Rt); + let Inst{4-0} = Rd; +} + +let hasSideEffects = 0, hasNewValue = 1 in +class T_ALU32_3op_pred MajOp, bits<3> MinOp, + bit OpsRev, bit PredNot, bit PredNew> + : ALU32_rr<(outs IntRegs:$Rd), (ins PredRegs:$Pu, IntRegs:$Rs, IntRegs:$Rt), + "if ("#!if(PredNot,"!","")#"$Pu"#!if(PredNew,".new","")#") "# + "$Rd = "#mnemonic#"($Rs, $Rt)", + [], "", ALU32_3op_tc_1_SLOT0123>, ImmRegRel, PredNewRel { + let isPredicated = 1; + let isPredicatedFalse = PredNot; + let isPredicatedNew = PredNew; + let BaseOpcode = mnemonic#_rr; + let CextOpcode = mnemonic; + + bits<2> Pu; + bits<5> Rs; + bits<5> Rt; + bits<5> Rd; + + let IClass = 0b1111; + let Inst{27} = 0b1; + let Inst{26-24} = MajOp; + let Inst{23-21} = MinOp; + let Inst{20-16} = !if(OpsRev,Rt,Rs); + let Inst{13} = PredNew; + let Inst{12-8} = !if(OpsRev,Rs,Rt); + let Inst{7} = PredNot; + let Inst{6-5} = Pu; + let Inst{4-0} = Rd; +} + +multiclass T_ALU32_3op_p MajOp, bits<3> MinOp, + bit OpsRev> { + def t : T_ALU32_3op_pred; + def f : T_ALU32_3op_pred; + def tnew : T_ALU32_3op_pred; + def fnew : T_ALU32_3op_pred; +} + +multiclass T_ALU32_3op_A2 MajOp, bits<3> MinOp, + bit OpsRev, bit IsComm> { + let isPredicable = 1 in + def A2_#NAME : T_ALU32_3op ; + defm A2_p#NAME : T_ALU32_3op_p; +} + +defm add : T_ALU32_3op_A2<"add", 0b011, 0b000, 0, 1>; + +multiclass ALU32_Pbase { + let isPredicatedNew = isPredNew in def NAME : ALU32_rr<(outs RC:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs: $src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", Index: lib/Target/Hexagon/HexagonMCInstLower.cpp =================================================================== --- lib/Target/Hexagon/HexagonMCInstLower.cpp +++ lib/Target/Hexagon/HexagonMCInstLower.cpp @@ -21,14 +21,14 @@ #include "llvm/IR/Mangler.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" - -using namespace llvm; - -static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol, - HexagonAsmPrinter& Printer) { - MCContext &MC = Printer.OutContext; - const MCExpr *ME; - + +using namespace llvm; + +static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, + HexagonAsmPrinter &Printer) { + MCContext &MC = Printer.OutContext; + const MCExpr *ME; + ME = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, MC); if (!MO.isJTI() && MO.getOffset()) @@ -36,28 +36,29 @@ MC); return (MCOperand::CreateExpr(ME)); -} - -// Create an MCInst from a MachineInstr -void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI, - HexagonAsmPrinter& AP) { - MCI.setOpcode(MI->getOpcode()); - MCI.setDesc(MI->getDesc()); - - for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { - const MachineOperand &MO = MI->getOperand(i); +} + +// Create an MCInst from a MachineInstr +void llvm::HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI, + HexagonAsmPrinter &AP) { + assert(MCI.getOpcode() == static_cast(MI->getOpcode()) && + "MCI opcode should have been set on construction"); + + for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { + const MachineOperand &MO = MI->getOperand(i); MCOperand MCO; switch (MO.getType()) { default: MI->dump(); - llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) continue; - MCO = MCOperand::CreateReg(MO.getReg()); - break; - case MachineOperand::MO_FPImmediate: { + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + continue; + MCO = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_FPImmediate: { APFloat Val = MO.getFPImm()->getValueAPF(); // FP immediates are used only when setting GPRs, so they may be dealt // with like regular immediates from this point on. @@ -65,31 +66,31 @@ break; } case MachineOperand::MO_Immediate: - MCO = MCOperand::CreateImm(MO.getImm()); + MCO = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCO = MCOperand::CreateExpr( + MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), AP.OutContext)); + break; + case MachineOperand::MO_GlobalAddress: + MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP); + break; + case MachineOperand::MO_ExternalSymbol: + MCO = + GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); + break; + case MachineOperand::MO_JumpTableIndex: + MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); break; - case MachineOperand::MO_MachineBasicBlock: - MCO = MCOperand::CreateExpr - (MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), - AP.OutContext)); - break; - case MachineOperand::MO_GlobalAddress: - MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP); - break; - case MachineOperand::MO_ExternalSymbol: - MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), - AP); - break; - case MachineOperand::MO_JumpTableIndex: - MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); - break; case MachineOperand::MO_ConstantPoolIndex: - MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); - break; - case MachineOperand::MO_BlockAddress: - MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP); - break; - } - + MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); + break; + case MachineOperand::MO_BlockAddress: + MCO = + GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); + break; + } + MCI.addOperand(MCO); } } Index: lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp =================================================================== --- lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp +++ lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp @@ -49,33 +49,32 @@ endPacket = '}'; // TODO: add outer HW loop when it's supported too. if (MI->getOpcode() == Hexagon::ENDLOOP0) { - // Ending a harware loop is different from ending an regular packet. - assert(MI->isPacketEnd() && "Loop-end must also end the packet"); - - if (MI->isPacketStart()) { - // There must be a packet to end a loop. - // FIXME: when shuffling is always run, this shouldn't be needed. - HexagonMCInst Nop; - StringRef NoAnnot; - - Nop.setOpcode (Hexagon::NOP); - Nop.setPacketStart (MI->isPacketStart()); - printInst (&Nop, O, NoAnnot); - } - + // Ending a harware loop is different from ending an regular packet. + assert(MI->isPacketEnd() && "Loop-end must also end the packet"); + + if (MI->isPacketBegin()) { + // There must be a packet to end a loop. + // FIXME: when shuffling is always run, this shouldn't be needed. + HexagonMCInst Nop (Hexagon::NOP); + StringRef NoAnnot; + + Nop.setPacketBegin (MI->isPacketBegin()); + printInst (&Nop, O, NoAnnot); + } + // Close the packet. if (MI->isPacketEnd()) O << PacketPadding << endPacket; printInstruction(MI, O); - } - else { - // Prefix the insn opening the packet. - if (MI->isPacketStart()) - O << PacketPadding << startPacket << '\n'; + } + else { + // Prefix the insn opening the packet. + if (MI->isPacketBegin()) + O << PacketPadding << startPacket << '\n'; + + printInstruction(MI, O); - printInstruction(MI, O); - // Suffix the insn closing the packet. if (MI->isPacketEnd()) // Suffix the packet in a new line always, since the GNU assembler has Index: lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -35,13 +35,13 @@ /// Possible values for instruction packet parse field. enum class ParseField { duplex = 0x0, last0 = 0x1, last1 = 0x2, end = 0x3 }; /// \brief Returns the packet bits based on instruction position. -uint32_t getPacketBits(HexagonMCInst const &HMI) { - unsigned const ParseFieldOffset = 14; - ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0; - return static_cast (Field) << ParseFieldOffset; -} -void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { - OS << static_cast((Binary >> 0x00) & 0xff); +uint32_t getPacketBits(HexagonMCInst const &HMI) { + unsigned const ParseFieldOffset = 14; + ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0; + return static_cast(Field) << ParseFieldOffset; +} +void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { + OS << static_cast((Binary >> 0x00) & 0xff); OS << static_cast((Binary >> 0x08) & 0xff); OS << static_cast((Binary >> 0x10) & 0xff); OS << static_cast((Binary >> 0x18) & 0xff); @@ -54,14 +54,15 @@ : MST(aMST), MCT(aMCT) {} void HexagonMCCodeEmitter::EncodeInstruction(MCInst const &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - MCSubtargetInfo const &STI) const { - HexagonMCInst const &HMB = static_cast(MI); - uint64_t Binary = getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB); - assert(HMB.getDesc().getSize() == 4 && "All instructions should be 32bit"); - emitLittleEndian(Binary, OS); - ++MCNumEmitted; -} + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const { + HexagonMCInst const &HMB = static_cast(MI); + uint64_t Binary = + getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB); + Binary |= getPacketBits(HMB); + emitLittleEndian(Binary, OS); + ++MCNumEmitted; +} unsigned HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, Index: lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h +++ lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h @@ -11,90 +11,58 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H -#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H - -#include "HexagonTargetMachine.h" -#include "llvm/MC/MCInst.h" - -namespace llvm { - class MCOperand; - - class HexagonMCInst: public MCInst { - // MCID is set during instruction lowering. - // It is needed in order to access TSFlags for - // use in checking MC instruction properties. - const MCInstrDesc *MCID; - - // Packet start and end markers - unsigned packetStart: 1, packetEnd: 1; - - public: - explicit HexagonMCInst(): - MCInst(), MCID(nullptr), packetStart(0), packetEnd(0) {}; - HexagonMCInst(const MCInstrDesc& mcid): - MCInst(), MCID(&mcid), packetStart(0), packetEnd(0) {}; - - bool isPacketStart() const { return (packetStart); }; - bool isPacketEnd() const { return (packetEnd); }; - void setPacketStart(bool Y) { packetStart = Y; }; - void setPacketEnd(bool Y) { packetEnd = Y; }; - void resetPacket() { setPacketStart(false); setPacketEnd(false); }; - - // Return the slots used by the insn. - unsigned getUnits(const HexagonTargetMachine* TM) const; - - // Return the Hexagon ISA class for the insn. - unsigned getType() const; - - void setDesc(const MCInstrDesc& mcid) { MCID = &mcid; }; - const MCInstrDesc& getDesc(void) const { return *MCID; }; - - // Return whether the insn is an actual insn. - bool isCanon() const; - - // Return whether the insn is a prefix. - bool isPrefix() const; - - // Return whether the insn is solo, i.e., cannot be in a packet. - bool isSolo() const; - - // Return whether the instruction needs to be constant extended. - bool isConstExtended() const; - - // Return constant extended operand number. - unsigned short getCExtOpNum(void) const; - - // Return whether the insn is a new-value consumer. - bool isNewValue() const; - - // Return whether the instruction is a legal new-value producer. - bool hasNewValue() const; - - // Return the operand that consumes or produces a new value. - const MCOperand& getNewValue() const; - - // Return number of bits in the constant extended operand. - unsigned getBitCount(void) const; - - private: - // Return whether the instruction must be always extended. - bool isExtended() const; - - // Return true if the insn may be extended based on the operand value. - bool isExtendable() const; - - // Return true if the operand can be constant extended. - bool isOperandExtended(const unsigned short OperandNum) const; - - // Return the min value that a constant extendable operand can have - // without being extended. - int getMinValue() const; - - // Return the max value that a constant extendable operand can have - // without being extended. - int getMaxValue() const; - }; -} - -#endif +#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H + +#include "llvm/MC/MCInst.h" + +namespace llvm { +class MCInstrDesc; +class MCOperand; +class HexagonTargetMachine; + +class HexagonMCInst : public MCInst { +public: + explicit HexagonMCInst(unsigned op); + + /// 10.6 Instruction Packets + bool isPacketBegin() const; + /// \brief Is this marked as last in packet. + bool isPacketEnd() const; + void setPacketBegin(bool Y); + /// \brief Mark this as last in packet. + void setPacketEnd(bool Y); + /// \brief Return the slots used. + unsigned getUnits(HexagonTargetMachine const &TM) const; + bool isConstExtended() const; + /// \brief Return constant extended operand number. + unsigned short getCExtOpNum(void) const; + /// \brief Return whether this is a new-value consumer. + bool isNewValue() const; + /// \brief Return whether this is a legal new-value producer. + bool hasNewValue() const; + /// \brief Return the operand that consumes or produces a new value. + MCOperand const &getNewValue() const; + /// \brief Return number of bits in the constant extended operand. + unsigned getBitCount(void) const; + +private: + /// \brief Return whether this must be always extended. + bool isExtended() const; + /// \brief Return true if this may be extended based on the operand value. + bool isExtendable() const; + /// \brief Return if the operand can be constant extended. + bool isOperandExtended(unsigned short const OperandNum) const; + /// \brief Return the min value that a constant extendable operand can have + /// without being extended. + int getMinValue() const; + /// \brief Return the max value that a constant extendable operand can have + /// without being extended. + int getMaxValue() const; + bool packetBegin; + bool packetEnd; + MCInstrDesc const &MCID; +}; +} + +#endif Index: lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp +++ lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp @@ -9,96 +9,79 @@ // // This class extends MCInst to allow some Hexagon VLIW annotations. // -//===----------------------------------------------------------------------===// - -#include "HexagonInstrInfo.h" -#include "MCTargetDesc/HexagonBaseInfo.h" -#include "MCTargetDesc/HexagonMCInst.h" -#include "MCTargetDesc/HexagonMCTargetDesc.h" - -using namespace llvm; - -// Return the slots used by the insn. -unsigned HexagonMCInst::getUnits(const HexagonTargetMachine* TM) const { - const HexagonInstrInfo *QII = TM->getSubtargetImpl()->getInstrInfo(); - const InstrItineraryData *II = - TM->getSubtargetImpl()->getInstrItineraryData(); - const InstrStage* - IS = II->beginStage(QII->get(this->getOpcode()).getSchedClass()); - - return (IS->getUnits()); -} - -// Return the Hexagon ISA class for the insn. -unsigned HexagonMCInst::getType() const { - const uint64_t F = MCID->TSFlags; - - return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); -} - -// Return whether the insn is an actual insn. -bool HexagonMCInst::isCanon() const { - return (!MCID->isPseudo() && - !isPrefix() && - getType() != HexagonII::TypeENDLOOP); -} - -// Return whether the insn is a prefix. -bool HexagonMCInst::isPrefix() const { - return (getType() == HexagonII::TypePREFIX); -} - -// Return whether the insn is solo, i.e., cannot be in a packet. -bool HexagonMCInst::isSolo() const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask); -} - -// Return whether the insn is a new-value consumer. -bool HexagonMCInst::isNewValue() const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); -} - -// Return whether the instruction is a legal new-value producer. -bool HexagonMCInst::hasNewValue() const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); -} - -// Return the operand that consumes or produces a new value. -const MCOperand& HexagonMCInst::getNewValue() const { - const uint64_t F = MCID->TSFlags; - const unsigned O = (F >> HexagonII::NewValueOpPos) & - HexagonII::NewValueOpMask; - const MCOperand& MCO = getOperand(O); - - assert ((isNewValue() || hasNewValue()) && MCO.isReg()); - return (MCO); -} - +//===----------------------------------------------------------------------===// + +#include "HexagonInstrInfo.h" +#include "HexagonTargetMachine.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +HexagonMCInst::HexagonMCInst(unsigned op) + : packetBegin(true), packetEnd(true), + MCID(llvm::TheHexagonTarget.createMCInstrInfo()->get(op)) { + assert(MCID.getSize() == 4 && "All instructions should be 32bit"); + setOpcode(op); +} + +bool HexagonMCInst::isPacketBegin() const { return packetBegin; } +bool HexagonMCInst::isPacketEnd() const { return packetEnd; } +void HexagonMCInst::setPacketEnd(bool Y) { packetEnd = Y; } +void HexagonMCInst::setPacketBegin(bool Y) { packetBegin = Y; } + +unsigned HexagonMCInst::getUnits(HexagonTargetMachine const &TM) const { + const HexagonInstrInfo *QII = TM.getSubtargetImpl()->getInstrInfo(); + const InstrItineraryData *II = TM.getSubtargetImpl()->getInstrItineraryData(); + const InstrStage *IS = + II->beginStage(QII->get(this->getOpcode()).getSchedClass()); + + return (IS->getUnits()); +} + +bool HexagonMCInst::isNewValue() const { + const uint64_t F = MCID.TSFlags; + return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); +} + +bool HexagonMCInst::hasNewValue() const { + const uint64_t F = MCID.TSFlags; + return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); +} + +MCOperand const &HexagonMCInst::getNewValue() const { + const uint64_t F = MCID.TSFlags; + const unsigned O = + (F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask; + const MCOperand &MCO = getOperand(O); + + assert((isNewValue() || hasNewValue()) && MCO.isReg()); + return (MCO); +} + // 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. +// 2) For immediate extended operands, return true only if the value is +// out-of-range. +// 3) For global address, always return true. +bool HexagonMCInst::isConstExtended(void) const { + if (isExtended()) + return true; -bool HexagonMCInst::isConstExtended(void) const { - if (isExtended()) - return true; - if (!isExtendable()) - return false; - - short ExtOpNum = getCExtOpNum(); - int MinValue = getMinValue(); - int MaxValue = getMaxValue(); - const MCOperand& MO = getOperand(ExtOpNum); - - // We could be using an instruction with an extendable immediate and shoehorn - // a global address into it. If it is a global address it will be constant + return false; + + short ExtOpNum = getCExtOpNum(); + int MinValue = getMinValue(); + int MaxValue = getMaxValue(); + const MCOperand &MO = getOperand(ExtOpNum); + + // We could be using an instruction with an extendable immediate and shoehorn + // a global address into it. If it is a global address it will be constant // extended. We do this for COMBINE. // We currently only handle isGlobal() because it is the only kind of // object we are going to end up with here for now. @@ -111,66 +94,55 @@ assert(MO.isImm() && "Extendable operand must be Immediate type"); int ImmValue = MO.getImm(); - return (ImmValue < MinValue || ImmValue > MaxValue); + return (ImmValue < MinValue || ImmValue > MaxValue); +} + +bool HexagonMCInst::isExtended(void) const { + const uint64_t F = MCID.TSFlags; + return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; +} + +bool HexagonMCInst::isExtendable(void) const { + const uint64_t F = MCID.TSFlags; + return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; +} + +unsigned HexagonMCInst::getBitCount(void) const { + const uint64_t F = MCID.TSFlags; + return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); +} + +unsigned short HexagonMCInst::getCExtOpNum(void) const { + const uint64_t F = MCID.TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); +} + +bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const { + const uint64_t F = MCID.TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) == + OperandNum; +} + +int HexagonMCInst::getMinValue(void) const { + const uint64_t F = MCID.TSFlags; + unsigned isSigned = + (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; + + if (isSigned) + return -1U << (bits - 1); + else + return 0; +} + +int HexagonMCInst::getMaxValue(void) const { + const uint64_t F = MCID.TSFlags; + unsigned isSigned = + (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; + + if (isSigned) + return ~(-1U << (bits - 1)); + else + return ~(-1U << bits); } - -// Return whether the instruction must be always extended. -bool HexagonMCInst::isExtended(void) const { - const uint64_t F = MCID->TSFlags; - return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; -} - -// Return true if the instruction may be extended based on the operand value. -bool HexagonMCInst::isExtendable(void) const { - const uint64_t F = MCID->TSFlags; - return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; -} - -// Return number of bits in the constant extended operand. -unsigned HexagonMCInst::getBitCount(void) const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); -} - -// Return constant extended operand number. -unsigned short HexagonMCInst::getCExtOpNum(void) const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); -} - -// Return whether the operand can be constant extended. -bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const { - const uint64_t F = MCID->TSFlags; - return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) - == OperandNum; -} - -// Return the min value that a constant extendable operand can have -// without being extended. -int HexagonMCInst::getMinValue(void) const { - const uint64_t F = MCID->TSFlags; - unsigned isSigned = (F >> HexagonII::ExtentSignedPos) - & HexagonII::ExtentSignedMask; - unsigned bits = (F >> HexagonII::ExtentBitsPos) - & HexagonII::ExtentBitsMask; - - if (isSigned) // if value is signed - return -1U << (bits - 1); - else - return 0; -} - -// Return the max value that a constant extendable operand can have -// without being extended. -int HexagonMCInst::getMaxValue(void) const { - const uint64_t F = MCID->TSFlags; - unsigned isSigned = (F >> HexagonII::ExtentSignedPos) - & HexagonII::ExtentSignedMask; - unsigned bits = (F >> HexagonII::ExtentBitsPos) - & HexagonII::ExtentBitsMask; - - if (isSigned) // if value is signed - return ~(-1U << (bits - 1)); - else - return ~(-1U << bits); -} Index: lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h +++ lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h @@ -12,12 +12,14 @@ //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H -#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H - -namespace llvm { -class MCCodeEmitter; -class MCContext; -class MCInstrInfo; +#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H + +namespace llvm { +struct InstrItinerary; +struct InstrStage; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; class MCRegisterInfo; class MCSubtargetInfo; class Target; Index: lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -31,13 +31,13 @@ #define GET_SUBTARGETINFO_MC_DESC #include "HexagonGenSubtargetInfo.inc" -#define GET_REGINFO_MC_DESC -#include "HexagonGenRegisterInfo.inc" - -static MCInstrInfo *createHexagonMCInstrInfo() { - MCInstrInfo *X = new MCInstrInfo(); - InitHexagonMCInstrInfo(X); - return X; +#define GET_REGINFO_MC_DESC +#include "HexagonGenRegisterInfo.inc" + +static llvm::MCInstrInfo *createHexagonMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitHexagonMCInstrInfo(X); + return X; } static MCRegisterInfo *createHexagonMCRegisterInfo(StringRef TT) { Index: unittests/MC/CMakeLists.txt =================================================================== --- unittests/MC/CMakeLists.txt +++ unittests/MC/CMakeLists.txt @@ -4,12 +4,12 @@ ) add_llvm_unittest(MCTests - StringTableBuilderTest.cpp - YAMLTest.cpp - ) - -foreach(t ${LLVM_TARGETS_TO_BUILD}) - if (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") - add_subdirectory(${t}) + StringTableBuilderTest.cpp + YAMLTest.cpp + ) + +foreach(t ${LLVM_TARGETS_TO_BUILD}) + if (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") + add_subdirectory(${t}) endif (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") endforeach() Index: unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp =================================================================== --- unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp +++ unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp @@ -43,11 +43,41 @@ llvm::MCContext *Context; llvm::MCSubtargetInfo *Subtarget; llvm::MCInstrInfo *InstrInfo; - llvm::MCCodeEmitter *Emitter; -}; -TestEmitter Emitter; -} - -TEST(HexagonMCCodeEmitter, emitter_creation) { - ASSERT_NE(nullptr, Emitter.Emitter); -} + llvm::MCCodeEmitter *Emitter; +}; +TestEmitter Emitter; +llvm::SmallVector EmptyFixups; +uint32_t Encode(unsigned opcode, std::vector const &operands, + llvm::SmallVectorImpl const & = EmptyFixups) { + llvm::HexagonMCInst inst(opcode); + for (auto &i : operands) { + inst.addOperand(i); + } + std::string str; + { + llvm::raw_string_ostream stream(str); + Emitter.Emitter->EncodeInstruction(inst, stream, EmptyFixups, + *Emitter.Subtarget); + } + assert(str.size() == 4 && "All instructions are 32 bits"); + uint32_t result = (static_cast(str[3]) << 0x18) | + (static_cast(str[2]) << 0x10) | + (static_cast(str[1]) << 0x08) | + (static_cast(str[0]) << 0x00); + return result; +} +llvm::MCOperand Reg(unsigned reg) { return llvm::MCOperand::CreateReg(reg); } +llvm::MCOperand Imm(int64_t imm) { return llvm::MCOperand::CreateImm(imm); } +} + +using namespace llvm; +using namespace Hexagon; + +TEST(HexagonMCCodeEmitter, emitter_creation) { + ASSERT_NE(nullptr, Emitter.Emitter); +} + +/// \brief Instruction encoding with different register numbers +TEST(HexagonMCCodeEmitter, add_Rd_Rs_Rt) { + EXPECT_EQ(0xf315df11, Encode(A2_add, {Reg(R17), Reg(R21), Reg(R31)})); +}