1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Revert r220427, "[Hexagon] Adding encoding bits for add opcode."

It brought cyclic dependecy between HexagonAsmPrinter and HexagonDesc.

llvm-svn: 220478
This commit is contained in:
NAKAMURA Takumi 2014-10-23 11:31:22 +00:00
parent 417b0378da
commit d8b493b106
14 changed files with 235 additions and 231 deletions

View File

@ -48,40 +48,6 @@ public:
}; };
} }
static const uint16_t IntRegDecoderTable[] = {
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
Hexagon::R5, Hexagon::R6, Hexagon::R7, Hexagon::R8, Hexagon::R9,
Hexagon::R10, Hexagon::R11, Hexagon::R12, Hexagon::R13, Hexagon::R14,
Hexagon::R15, Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, Hexagon::R24,
Hexagon::R25, Hexagon::R26, Hexagon::R27, Hexagon::R28, Hexagon::R29,
Hexagon::R30, Hexagon::R31};
static const uint16_t PredRegDecoderTable[] = {Hexagon::P0, Hexagon::P1,
Hexagon::P2, Hexagon::P3};
static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t /*Address*/,
void const *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Register = IntRegDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return MCDisassembler::Success;
}
static DecodeStatus DecodePredRegsRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t /*Address*/,
void const *Decoder) {
if (RegNo > 3)
return MCDisassembler::Fail;
unsigned Register = PredRegDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return MCDisassembler::Success;
}
#include "HexagonGenDisassemblerTables.inc" #include "HexagonGenDisassemblerTables.inc"
static MCDisassembler *createHexagonDisassembler(Target const &T, static MCDisassembler *createHexagonDisassembler(Target const &T,

View File

@ -195,8 +195,8 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
unsigned Size = BundleMIs.size(); unsigned Size = BundleMIs.size();
assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!");
for (unsigned Index = 0; Index < Size; Index++) { for (unsigned Index = 0; Index < Size; Index++) {
HexagonMCInst MCI (BundleMIs[Index]->getOpcode()); HexagonMCInst MCI;
MCI.setPacketBegin(Index == 0); MCI.setPacketStart(Index == 0);
MCI.setPacketEnd(Index == (Size-1)); MCI.setPacketEnd(Index == (Size-1));
HexagonLowerToMC(BundleMIs[Index], MCI, *this); HexagonLowerToMC(BundleMIs[Index], MCI, *this);
@ -204,9 +204,9 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
} }
} }
else { else {
HexagonMCInst MCI(MI->getOpcode()); HexagonMCInst MCI;
if (MI->getOpcode() == Hexagon::ENDLOOP0) { if (MI->getOpcode() == Hexagon::ENDLOOP0) {
MCI.setPacketBegin(true); MCI.setPacketStart(true);
MCI.setPacketEnd(true); MCI.setPacketEnd(true);
} }
HexagonLowerToMC(MI, MCI, *this); HexagonLowerToMC(MI, MCI, *this);

View File

@ -92,77 +92,6 @@ def HexagonWrapperCombineII :
def HexagonWrapperCombineRR : def HexagonWrapperCombineRR :
SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>;
let hasSideEffects = 0, hasNewValue = 1, InputType = "reg" in
class T_ALU32_3op<string mnemonic, bits<3> 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<string mnemonic, bits<3> 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<string mnemonic, bits<3> MajOp, bits<3> MinOp,
bit OpsRev> {
def t : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 0, 0>;
def f : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 1, 0>;
def tnew : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 0, 1>;
def fnew : T_ALU32_3op_pred<mnemonic, MajOp, MinOp, OpsRev, 1, 1>;
}
multiclass T_ALU32_3op_A2<string mnemonic, bits<3> MajOp, bits<3> MinOp,
bit OpsRev, bit IsComm> {
let isPredicable = 1 in
def A2_#NAME : T_ALU32_3op <mnemonic, MajOp, MinOp, OpsRev, IsComm>;
defm A2_p#NAME : T_ALU32_3op_p<mnemonic, MajOp, MinOp, OpsRev>;
}
let isCodeGenOnly = 0 in
defm add : T_ALU32_3op_A2<"add", 0b011, 0b000, 0, 1>;
multiclass ALU32_Pbase<string mnemonic, RegisterClass RC, bit isNot, multiclass ALU32_Pbase<string mnemonic, RegisterClass RC, bit isNot,
bit isPredNew> { bit isPredNew> {
let isPredicatedNew = isPredNew in let isPredicatedNew = isPredNew in

View File

@ -24,8 +24,8 @@
using namespace llvm; using namespace llvm;
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol,
HexagonAsmPrinter &Printer) { HexagonAsmPrinter& Printer) {
MCContext &MC = Printer.OutContext; MCContext &MC = Printer.OutContext;
const MCExpr *ME; const MCExpr *ME;
@ -39,10 +39,10 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
} }
// Create an MCInst from a MachineInstr // Create an MCInst from a MachineInstr
void llvm::HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI, void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI,
HexagonAsmPrinter &AP) { HexagonAsmPrinter& AP) {
assert(MCI.getOpcode() == static_cast<unsigned>(MI->getOpcode()) && MCI.setOpcode(MI->getOpcode());
"MCI opcode should have been set on construction"); MCI.setDesc(MI->getDesc());
for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) {
const MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
@ -54,8 +54,7 @@ void llvm::HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI,
llvm_unreachable("unknown operand type"); llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register: case MachineOperand::MO_Register:
// Ignore all implicit register operands. // Ignore all implicit register operands.
if (MO.isImplicit()) if (MO.isImplicit()) continue;
continue;
MCO = MCOperand::CreateReg(MO.getReg()); MCO = MCOperand::CreateReg(MO.getReg());
break; break;
case MachineOperand::MO_FPImmediate: { case MachineOperand::MO_FPImmediate: {
@ -69,15 +68,16 @@ void llvm::HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI,
MCO = MCOperand::CreateImm(MO.getImm()); MCO = MCOperand::CreateImm(MO.getImm());
break; break;
case MachineOperand::MO_MachineBasicBlock: case MachineOperand::MO_MachineBasicBlock:
MCO = MCOperand::CreateExpr( MCO = MCOperand::CreateExpr
MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), AP.OutContext)); (MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(),
AP.OutContext));
break; break;
case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_GlobalAddress:
MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP); MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP);
break; break;
case MachineOperand::MO_ExternalSymbol: case MachineOperand::MO_ExternalSymbol:
MCO = MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()),
GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); AP);
break; break;
case MachineOperand::MO_JumpTableIndex: case MachineOperand::MO_JumpTableIndex:
MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP);
@ -86,8 +86,7 @@ void llvm::HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI,
MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP);
break; break;
case MachineOperand::MO_BlockAddress: case MachineOperand::MO_BlockAddress:
MCO = MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP);
GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
break; break;
} }

View File

@ -91,13 +91,14 @@ void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O,
// Ending a harware loop is different from ending an regular packet. // Ending a harware loop is different from ending an regular packet.
assert(MI->isPacketEnd() && "Loop-end must also end the packet"); assert(MI->isPacketEnd() && "Loop-end must also end the packet");
if (MI->isPacketBegin()) { if (MI->isPacketStart()) {
// There must be a packet to end a loop. // There must be a packet to end a loop.
// FIXME: when shuffling is always run, this shouldn't be needed. // FIXME: when shuffling is always run, this shouldn't be needed.
HexagonMCInst Nop (Hexagon::NOP); HexagonMCInst Nop;
StringRef NoAnnot; StringRef NoAnnot;
Nop.setPacketBegin (MI->isPacketBegin()); Nop.setOpcode (Hexagon::NOP);
Nop.setPacketStart (MI->isPacketStart());
printInst (&Nop, O, NoAnnot); printInst (&Nop, O, NoAnnot);
} }
@ -109,7 +110,7 @@ void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O,
} }
else { else {
// Prefix the insn opening the packet. // Prefix the insn opening the packet.
if (MI->isPacketBegin()) if (MI->isPacketStart())
O << PacketPadding << startPacket << '\n'; O << PacketPadding << startPacket << '\n';
printInstruction(MI, O); printInstruction(MI, O);

View File

@ -38,7 +38,7 @@ enum class ParseField { duplex = 0x0, last0 = 0x1, last1 = 0x2, end = 0x3 };
uint32_t getPacketBits(HexagonMCInst const &HMI) { uint32_t getPacketBits(HexagonMCInst const &HMI) {
unsigned const ParseFieldOffset = 14; unsigned const ParseFieldOffset = 14;
ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0; ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0;
return static_cast<uint32_t>(Field) << ParseFieldOffset; return static_cast <uint32_t> (Field) << ParseFieldOffset;
} }
void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { void emitLittleEndian(uint64_t Binary, raw_ostream &OS) {
OS << static_cast<uint8_t>((Binary >> 0x00) & 0xff); OS << static_cast<uint8_t>((Binary >> 0x00) & 0xff);
@ -57,9 +57,8 @@ void HexagonMCCodeEmitter::EncodeInstruction(MCInst const &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups, SmallVectorImpl<MCFixup> &Fixups,
MCSubtargetInfo const &STI) const { MCSubtargetInfo const &STI) const {
HexagonMCInst const &HMB = static_cast<HexagonMCInst const &>(MI); HexagonMCInst const &HMB = static_cast<HexagonMCInst const &>(MI);
uint64_t Binary = uint64_t Binary = getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB);
getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB); assert(HMB.getDesc().getSize() == 4 && "All instructions should be 32bit");
Binary |= getPacketBits(HMB);
emitLittleEndian(Binary, OS); emitLittleEndian(Binary, OS);
++MCNumEmitted; ++MCNumEmitted;
} }

View File

@ -12,52 +12,68 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "HexagonInstrInfo.h" #include "HexagonInstrInfo.h"
#include "HexagonTargetMachine.h"
#include "MCTargetDesc/HexagonBaseInfo.h" #include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInst.h" #include "MCTargetDesc/HexagonMCInst.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h" #include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm; using namespace llvm;
HexagonMCInst::HexagonMCInst(unsigned op) // Return the slots used by the insn.
: packetBegin(false), packetEnd(false), unsigned HexagonMCInst::getUnits(const HexagonTargetMachine* TM) const {
MCID(llvm::TheHexagonTarget.createMCInstrInfo()->get(op)) { const HexagonInstrInfo *QII = TM->getSubtargetImpl()->getInstrInfo();
assert(MCID.getSize() == 4 && "All instructions should be 32bit"); const InstrItineraryData *II =
setOpcode(op); TM->getSubtargetImpl()->getInstrItineraryData();
} const InstrStage*
IS = II->beginStage(QII->get(this->getOpcode()).getSchedClass());
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()); 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 { bool HexagonMCInst::isNewValue() const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask);
} }
// Return whether the instruction is a legal new-value producer.
bool HexagonMCInst::hasNewValue() const { bool HexagonMCInst::hasNewValue() const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask);
} }
MCOperand const &HexagonMCInst::getNewValue() const { // Return the operand that consumes or produces a new value.
const uint64_t F = MCID.TSFlags; const MCOperand& HexagonMCInst::getNewValue() const {
const unsigned O = const uint64_t F = MCID->TSFlags;
(F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask; const unsigned O = (F >> HexagonII::NewValueOpPos) &
const MCOperand &MCO = getOperand(O); HexagonII::NewValueOpMask;
const MCOperand& MCO = getOperand(O);
assert((isNewValue() || hasNewValue()) && MCO.isReg()); assert ((isNewValue() || hasNewValue()) && MCO.isReg());
return (MCO); return (MCO);
} }
@ -68,6 +84,7 @@ MCOperand const &HexagonMCInst::getNewValue() const {
// 2) For immediate extended operands, return true only if the value is // 2) For immediate extended operands, return true only if the value is
// out-of-range. // out-of-range.
// 3) For global address, always return true. // 3) For global address, always return true.
bool HexagonMCInst::isConstExtended(void) const { bool HexagonMCInst::isConstExtended(void) const {
if (isExtended()) if (isExtended())
return true; return true;
@ -76,9 +93,9 @@ bool HexagonMCInst::isConstExtended(void) const {
return false; return false;
short ExtOpNum = getCExtOpNum(); short ExtOpNum = getCExtOpNum();
int MinValue = getMinValue(); int MinValue = getMinValue();
int MaxValue = getMaxValue(); int MaxValue = getMaxValue();
const MCOperand &MO = getOperand(ExtOpNum); const MCOperand& MO = getOperand(ExtOpNum);
// We could be using an instruction with an extendable immediate and shoehorn // 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 // a global address into it. If it is a global address it will be constant
@ -97,51 +114,62 @@ bool HexagonMCInst::isConstExtended(void) const {
return (ImmValue < MinValue || ImmValue > MaxValue); return (ImmValue < MinValue || ImmValue > MaxValue);
} }
// Return whether the instruction must be always extended.
bool HexagonMCInst::isExtended(void) const { bool HexagonMCInst::isExtended(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
} }
// Return true if the instruction may be extended based on the operand value.
bool HexagonMCInst::isExtendable(void) const { bool HexagonMCInst::isExtendable(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
} }
// Return number of bits in the constant extended operand.
unsigned HexagonMCInst::getBitCount(void) const { unsigned HexagonMCInst::getBitCount(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
} }
// Return constant extended operand number.
unsigned short HexagonMCInst::getCExtOpNum(void) const { unsigned short HexagonMCInst::getCExtOpNum(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
} }
// Return whether the operand can be constant extended.
bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const { bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) == return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask)
OperandNum; == OperandNum;
} }
// Return the min value that a constant extendable operand can have
// without being extended.
int HexagonMCInst::getMinValue(void) const { int HexagonMCInst::getMinValue(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
unsigned isSigned = unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; & HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; unsigned bits = (F >> HexagonII::ExtentBitsPos)
& HexagonII::ExtentBitsMask;
if (isSigned) if (isSigned) // if value is signed
return -1U << (bits - 1); return -1U << (bits - 1);
else else
return 0; return 0;
} }
// Return the max value that a constant extendable operand can have
// without being extended.
int HexagonMCInst::getMaxValue(void) const { int HexagonMCInst::getMaxValue(void) const {
const uint64_t F = MCID.TSFlags; const uint64_t F = MCID->TSFlags;
unsigned isSigned = unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; & HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask; unsigned bits = (F >> HexagonII::ExtentBitsPos)
& HexagonII::ExtentBitsMask;
if (isSigned) if (isSigned) // if value is signed
return ~(-1U << (bits - 1)); return ~(-1U << (bits - 1));
else else
return ~(-1U << bits); return ~(-1U << bits);

View File

@ -14,55 +14,87 @@
#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H #ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINST_H
#include "HexagonTargetMachine.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
namespace llvm { namespace llvm {
class MCInstrDesc; class MCOperand;
class MCOperand;
class HexagonTargetMachine;
class HexagonMCInst : public MCInst { class HexagonMCInst: public MCInst {
public: // MCID is set during instruction lowering.
explicit HexagonMCInst(unsigned op); // It is needed in order to access TSFlags for
// use in checking MC instruction properties.
const MCInstrDesc *MCID;
/// 10.6 Instruction Packets // Packet start and end markers
bool isPacketBegin() const; unsigned packetStart: 1, packetEnd: 1;
/// \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: public:
/// \brief Return whether this must be always extended. explicit HexagonMCInst():
bool isExtended() const; MCInst(), MCID(nullptr), packetStart(0), packetEnd(0) {};
/// \brief Return true if this may be extended based on the operand value. HexagonMCInst(const MCInstrDesc& mcid):
bool isExtendable() const; MCInst(), MCID(&mcid), packetStart(0), packetEnd(0) {};
/// \brief Return if the operand can be constant extended.
bool isOperandExtended(unsigned short const OperandNum) const; bool isPacketStart() const { return (packetStart); };
/// \brief Return the min value that a constant extendable operand can have bool isPacketEnd() const { return (packetEnd); };
/// without being extended. void setPacketStart(bool Y) { packetStart = Y; };
int getMinValue() const; void setPacketEnd(bool Y) { packetEnd = Y; };
/// \brief Return the max value that a constant extendable operand can have void resetPacket() { setPacketStart(false); setPacketEnd(false); };
/// without being extended.
int getMaxValue() const; // Return the slots used by the insn.
bool packetBegin; unsigned getUnits(const HexagonTargetMachine* TM) const;
bool packetEnd;
MCInstrDesc const &MCID; // 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 #endif

View File

@ -34,7 +34,7 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC #define GET_REGINFO_MC_DESC
#include "HexagonGenRegisterInfo.inc" #include "HexagonGenRegisterInfo.inc"
static llvm::MCInstrInfo *createHexagonMCInstrInfo() { static MCInstrInfo *createHexagonMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo(); MCInstrInfo *X = new MCInstrInfo();
InitHexagonMCInstrInfo(X); InitHexagonMCInstrInfo(X);
return X; return X;

View File

@ -15,8 +15,6 @@
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCTARGETDESC_H
namespace llvm { namespace llvm {
struct InstrItinerary;
struct InstrStage;
class MCCodeEmitter; class MCCodeEmitter;
class MCContext; class MCContext;
class MCInstrInfo; class MCInstrInfo;

View File

@ -1,4 +0,0 @@
# RUN: llvm-mc --triple hexagon -disassemble < %s | FileCheck %s
0x11 0xdf 0x15 0xf3
# CHECK: r17 = add(r21, r31)

View File

@ -1,3 +0,0 @@
if 'Hexagon' not in config.root.targets:
config.unsupported = True

View File

@ -7,3 +7,9 @@ add_llvm_unittest(MCTests
StringTableBuilderTest.cpp StringTableBuilderTest.cpp
YAMLTest.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()

View File

@ -0,0 +1,53 @@
#include "gtest/gtest.h"
#include <memory>
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "MCTargetDesc/HexagonMCInst.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
namespace {
class TestEmitter {
public:
TestEmitter() : Triple("hexagon-unknown-elf") {
LLVMInitializeHexagonTargetInfo();
LLVMInitializeHexagonTarget();
LLVMInitializeHexagonTargetMC();
std::string error;
Target = llvm::TargetRegistry::lookupTarget("hexagon", error);
assert(Target != nullptr && "Expected to find target");
assert(error.empty() && "Error should be empty if we have a target");
RegisterInfo = Target->createMCRegInfo(Triple);
assert(RegisterInfo != nullptr && "Expecting to find register info");
AsmInfo = Target->createMCAsmInfo(*RegisterInfo, Triple);
assert(AsmInfo != nullptr && "Expecting to find asm info");
Context = new llvm::MCContext(AsmInfo, RegisterInfo, nullptr);
assert(Context != nullptr && "Expecting to create a context");
Subtarget = Target->createMCSubtargetInfo(Triple, "hexagonv4", "");
assert(Subtarget != nullptr && "Expecting to find a subtarget");
InstrInfo = Target->createMCInstrInfo();
assert(InstrInfo != nullptr && "Expecting to find instr info");
Emitter = Target->createMCCodeEmitter(*InstrInfo, *RegisterInfo, *Subtarget,
*Context);
assert(Emitter != nullptr);
}
std::string Triple;
llvm::Target const *Target;
llvm::MCRegisterInfo *RegisterInfo;
llvm::MCAsmInfo *AsmInfo;
llvm::MCContext *Context;
llvm::MCSubtargetInfo *Subtarget;
llvm::MCInstrInfo *InstrInfo;
llvm::MCCodeEmitter *Emitter;
};
TestEmitter Emitter;
}
TEST(HexagonMCCodeEmitter, emitter_creation) {
ASSERT_NE(nullptr, Emitter.Emitter);
}