mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[Hexagon] Disassembling, printing, and emitting instructions a whole-bundle at a time which is the semantic unit for Hexagon. Fixing tests to use the new format. Disabling tests in the direct object emission path for a followup patch.
llvm-svn: 238556
This commit is contained in:
parent
2ea0919069
commit
084c4d499d
@ -7,9 +7,11 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "Hexagon.h"
|
||||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||||
|
|
||||||
#include "llvm/MC/MCContext.h"
|
#include "llvm/MC/MCContext.h"
|
||||||
#include "llvm/MC/MCDisassembler.h"
|
#include "llvm/MC/MCDisassembler.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
@ -27,6 +29,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace Hexagon;
|
||||||
|
|
||||||
#define DEBUG_TYPE "hexagon-disassembler"
|
#define DEBUG_TYPE "hexagon-disassembler"
|
||||||
|
|
||||||
@ -37,9 +40,14 @@ namespace {
|
|||||||
/// \brief Hexagon disassembler for all Hexagon platforms.
|
/// \brief Hexagon disassembler for all Hexagon platforms.
|
||||||
class HexagonDisassembler : public MCDisassembler {
|
class HexagonDisassembler : public MCDisassembler {
|
||||||
public:
|
public:
|
||||||
|
std::unique_ptr<MCInst *> CurrentBundle;
|
||||||
HexagonDisassembler(MCSubtargetInfo const &STI, MCContext &Ctx)
|
HexagonDisassembler(MCSubtargetInfo const &STI, MCContext &Ctx)
|
||||||
: MCDisassembler(STI, Ctx) {}
|
: MCDisassembler(STI, Ctx), CurrentBundle(new MCInst *) {}
|
||||||
|
|
||||||
|
DecodeStatus getSingleInstruction(MCInst &Instr, MCInst &MCB,
|
||||||
|
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
|
raw_ostream &VStream, raw_ostream &CStream,
|
||||||
|
bool &Complete) const;
|
||||||
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
|
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
|
||||||
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
raw_ostream &VStream,
|
raw_ostream &VStream,
|
||||||
@ -191,17 +199,53 @@ DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
|||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
raw_ostream &os,
|
raw_ostream &os,
|
||||||
raw_ostream &cs) const {
|
raw_ostream &cs) const {
|
||||||
Size = 4;
|
DecodeStatus Result = DecodeStatus::Success;
|
||||||
if (Bytes.size() < 4)
|
bool Complete = false;
|
||||||
return MCDisassembler::Fail;
|
Size = 0;
|
||||||
|
|
||||||
uint32_t insn =
|
*CurrentBundle = &MI;
|
||||||
|
MI.setOpcode(Hexagon::BUNDLE);
|
||||||
|
MI.addOperand(MCOperand::createImm(0));
|
||||||
|
while (Result == Success && Complete == false)
|
||||||
|
{
|
||||||
|
if (Bytes.size() < HEXAGON_INSTR_SIZE)
|
||||||
|
return MCDisassembler::Fail;
|
||||||
|
MCInst * Inst = new (getContext()) MCInst;
|
||||||
|
Result = getSingleInstruction(*Inst, MI, Bytes, Address, os, cs, Complete);
|
||||||
|
MI.addOperand(MCOperand::createInst(Inst));
|
||||||
|
Size += HEXAGON_INSTR_SIZE;
|
||||||
|
Bytes = Bytes.slice(HEXAGON_INSTR_SIZE);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeStatus HexagonDisassembler::getSingleInstruction(
|
||||||
|
MCInst &MI, MCInst &MCB, ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
|
raw_ostream &os, raw_ostream &cs, bool &Complete) const {
|
||||||
|
assert(Bytes.size() >= HEXAGON_INSTR_SIZE);
|
||||||
|
|
||||||
|
uint32_t Instruction =
|
||||||
llvm::support::endian::read<uint32_t, llvm::support::little,
|
llvm::support::endian::read<uint32_t, llvm::support::little,
|
||||||
llvm::support::unaligned>(Bytes.data());
|
llvm::support::unaligned>(Bytes.data());
|
||||||
|
|
||||||
// Remove parse bits.
|
auto BundleSize = HexagonMCInstrInfo::bundleSize(MCB);
|
||||||
insn &= ~static_cast<uint32_t>(HexagonII::InstParseBits::INST_PARSE_MASK);
|
if ((Instruction & HexagonII::INST_PARSE_MASK) ==
|
||||||
DecodeStatus Result = decodeInstruction(DecoderTable32, MI, insn, Address, this, STI);
|
HexagonII::INST_PARSE_LOOP_END) {
|
||||||
HexagonMCInstrInfo::AppendImplicitOperands(MI);
|
if (BundleSize == 0)
|
||||||
|
HexagonMCInstrInfo::setInnerLoop(MCB);
|
||||||
|
else if (BundleSize == 1)
|
||||||
|
HexagonMCInstrInfo::setOuterLoop(MCB);
|
||||||
|
else
|
||||||
|
return DecodeStatus::Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeStatus Result = DecodeStatus::Success;
|
||||||
|
if ((Instruction & HexagonII::INST_PARSE_MASK) ==
|
||||||
|
HexagonII::INST_PARSE_PACKET_END)
|
||||||
|
Complete = true;
|
||||||
|
// Calling the auto-generated decoder function.
|
||||||
|
Result =
|
||||||
|
decodeInstruction(DecoderTable32, MI, Instruction, Address, this, STI);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -76,4 +76,8 @@ namespace llvm {
|
|||||||
// Maximum number of words and instructions in a packet.
|
// Maximum number of words and instructions in a packet.
|
||||||
#define HEXAGON_PACKET_SIZE 4
|
#define HEXAGON_PACKET_SIZE 4
|
||||||
|
|
||||||
|
// Minimum number of instructions in an end-loop packet.
|
||||||
|
#define HEXAGON_PACKET_INNER_SIZE 2
|
||||||
|
#define HEXAGON_PACKET_OUTER_SIZE 3
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -177,47 +177,29 @@ bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
|||||||
/// the current output stream.
|
/// the current output stream.
|
||||||
///
|
///
|
||||||
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
|
MCInst MCB;
|
||||||
|
MCB.setOpcode(Hexagon::BUNDLE);
|
||||||
|
MCB.addOperand(MCOperand::createImm(0));
|
||||||
|
|
||||||
if (MI->isBundle()) {
|
if (MI->isBundle()) {
|
||||||
std::vector<MachineInstr const *> BundleMIs;
|
const MachineBasicBlock* MBB = MI->getParent();
|
||||||
|
|
||||||
const MachineBasicBlock *MBB = MI->getParent();
|
|
||||||
MachineBasicBlock::const_instr_iterator MII = MI;
|
MachineBasicBlock::const_instr_iterator MII = MI;
|
||||||
++MII;
|
unsigned IgnoreCount = 0;
|
||||||
unsigned int IgnoreCount = 0;
|
|
||||||
while (MII != MBB->end() && MII->isInsideBundle()) {
|
|
||||||
const MachineInstr *MInst = MII;
|
|
||||||
if (MInst->getOpcode() == TargetOpcode::DBG_VALUE ||
|
|
||||||
MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) {
|
|
||||||
IgnoreCount++;
|
|
||||||
++MII;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// BundleMIs.push_back(&*MII);
|
|
||||||
BundleMIs.push_back(MInst);
|
|
||||||
++MII;
|
|
||||||
}
|
|
||||||
unsigned Size = BundleMIs.size();
|
|
||||||
assert((Size + IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!");
|
|
||||||
for (unsigned Index = 0; Index < Size; Index++) {
|
|
||||||
MCInst MCI;
|
|
||||||
|
|
||||||
HexagonLowerToMC(BundleMIs[Index], MCI, *this);
|
for (++MII; MII != MBB->end() && MII->isInsideBundle(); ++MII) {
|
||||||
HexagonMCInstrInfo::AppendImplicitOperands(MCI);
|
if (MII->getOpcode() == TargetOpcode::DBG_VALUE ||
|
||||||
HexagonMCInstrInfo::setPacketBegin(MCI, Index == 0);
|
MII->getOpcode() == TargetOpcode::IMPLICIT_DEF)
|
||||||
HexagonMCInstrInfo::setPacketEnd(MCI, Index == (Size - 1));
|
++IgnoreCount;
|
||||||
EmitToStreamer(*OutStreamer, MCI);
|
else {
|
||||||
|
HexagonLowerToMC(MII, MCB, *this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MCInst MCI;
|
HexagonLowerToMC(MI, MCB, *this);
|
||||||
HexagonLowerToMC(MI, MCI, *this);
|
HexagonMCInstrInfo::padEndloop(MCB);
|
||||||
HexagonMCInstrInfo::AppendImplicitOperands(MCI);
|
|
||||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
|
||||||
HexagonMCInstrInfo::setPacketBegin(MCI, true);
|
|
||||||
HexagonMCInstrInfo::setPacketEnd(MCI, true);
|
|
||||||
}
|
|
||||||
EmitToStreamer(*OutStreamer, MCI);
|
|
||||||
}
|
}
|
||||||
|
EmitToStreamer(*OutStreamer, MCB);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,8 @@ def DoubleWordAccess : MemAccessSize<4>;// Double word access instruction (memd)
|
|||||||
class OpcodeHexagon {
|
class OpcodeHexagon {
|
||||||
field bits<32> Inst = ?; // Default to an invalid insn.
|
field bits<32> Inst = ?; // Default to an invalid insn.
|
||||||
bits<4> IClass = 0; // ICLASS
|
bits<4> IClass = 0; // ICLASS
|
||||||
bits<2> IParse = 0; // Parse bits.
|
|
||||||
|
|
||||||
let Inst{31-28} = IClass;
|
let Inst{31-28} = IClass;
|
||||||
let Inst{15-14} = IParse;
|
|
||||||
|
|
||||||
bits<1> zero = 0;
|
bits<1> zero = 0;
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,12 @@
|
|||||||
#include "Hexagon.h"
|
#include "Hexagon.h"
|
||||||
#include "HexagonAsmPrinter.h"
|
#include "HexagonAsmPrinter.h"
|
||||||
#include "HexagonMachineFunctionInfo.h"
|
#include "HexagonMachineFunctionInfo.h"
|
||||||
|
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||||
|
|
||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Mangler.h"
|
#include "llvm/IR/Mangler.h"
|
||||||
|
#include "llvm/MC/MCContext.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
#include "llvm/MC/MCInst.h"
|
#include "llvm/MC/MCInst.h"
|
||||||
|
|
||||||
@ -38,9 +41,20 @@ static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create an MCInst from a MachineInstr
|
// Create an MCInst from a MachineInstr
|
||||||
void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCI,
|
void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCB,
|
||||||
HexagonAsmPrinter& AP) {
|
HexagonAsmPrinter& AP) {
|
||||||
MCI.setOpcode(MI->getOpcode());
|
if(MI->getOpcode() == Hexagon::ENDLOOP0){
|
||||||
|
HexagonMCInstrInfo::setInnerLoop(MCB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(MI->getOpcode() == Hexagon::ENDLOOP1){
|
||||||
|
HexagonMCInstrInfo::setOuterLoop(MCB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MCInst* MCI = new (AP.OutContext) MCInst;
|
||||||
|
MCI->setOpcode(MI->getOpcode());
|
||||||
|
assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) &&
|
||||||
|
"MCI opcode should have been set on construction");
|
||||||
|
|
||||||
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);
|
||||||
@ -88,6 +102,7 @@ void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCI,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCI.addOperand(MCO);
|
MCI->addOperand(MCO);
|
||||||
}
|
}
|
||||||
|
MCB.addOperand(MCOperand::createInst(MCI));
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ namespace HexagonII {
|
|||||||
MO_GPREL
|
MO_GPREL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InstParseBits : uint32_t {
|
enum InstParseBits {
|
||||||
INST_PARSE_MASK = 0x0000c000,
|
INST_PARSE_MASK = 0x0000c000,
|
||||||
INST_PARSE_PACKET_END = 0x0000c000,
|
INST_PARSE_PACKET_END = 0x0000c000,
|
||||||
INST_PARSE_LOOP_END = 0x00008000,
|
INST_PARSE_LOOP_END = 0x00008000,
|
||||||
|
@ -28,7 +28,47 @@ using namespace llvm;
|
|||||||
#define GET_INSTRUCTION_NAME
|
#define GET_INSTRUCTION_NAME
|
||||||
#include "HexagonGenAsmWriter.inc"
|
#include "HexagonGenAsmWriter.inc"
|
||||||
|
|
||||||
const char HexagonInstPrinter::PacketPadding = '\t';
|
HexagonAsmInstPrinter::HexagonAsmInstPrinter(MCInstPrinter *RawPrinter)
|
||||||
|
: MCInstPrinter(*RawPrinter), RawPrinter(RawPrinter) {}
|
||||||
|
|
||||||
|
void HexagonAsmInstPrinter::printInst(MCInst const *MI, raw_ostream &O,
|
||||||
|
StringRef Annot,
|
||||||
|
MCSubtargetInfo const &STI) {
|
||||||
|
assert(HexagonMCInstrInfo::isBundle(*MI));
|
||||||
|
assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
|
||||||
|
std::string Buffer;
|
||||||
|
{
|
||||||
|
raw_string_ostream TempStream(Buffer);
|
||||||
|
RawPrinter->printInst(MI, TempStream, "", STI);
|
||||||
|
}
|
||||||
|
StringRef Contents(Buffer);
|
||||||
|
auto PacketBundle = Contents.rsplit('\n');
|
||||||
|
auto HeadTail = PacketBundle.first.split('\n');
|
||||||
|
auto Preamble = "\t{\n\t\t";
|
||||||
|
auto Separator = "";
|
||||||
|
while(!HeadTail.first.empty()) {
|
||||||
|
O << Separator;
|
||||||
|
StringRef Inst;
|
||||||
|
auto Duplex = HeadTail.first.split('\v');
|
||||||
|
if(!Duplex.second.empty()){
|
||||||
|
O << Duplex.first << "\n";
|
||||||
|
Inst = Duplex.second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Inst = Duplex.first;
|
||||||
|
O << Preamble;
|
||||||
|
O << Inst;
|
||||||
|
HeadTail = HeadTail.second.split('\n');
|
||||||
|
Preamble = "";
|
||||||
|
Separator = "\n\t\t";
|
||||||
|
}
|
||||||
|
O << "\n\t}" << PacketBundle.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexagonAsmInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
|
||||||
|
RawPrinter->printRegName(O, RegNo);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the minimum value that a constant extendable operand can have
|
// Return the minimum value that a constant extendable operand can have
|
||||||
// without being extended.
|
// without being extended.
|
||||||
static int getMinValue(uint64_t TSFlags) {
|
static int getMinValue(uint64_t TSFlags) {
|
||||||
@ -77,48 +117,38 @@ void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
|
|||||||
OS << getRegisterName(RegNo);
|
OS << getRegisterName(RegNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &O,
|
void HexagonInstPrinter::setExtender(MCInst const &MCI) {
|
||||||
|
HasExtender = HexagonMCInstrInfo::isImmext(MCI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &OS,
|
||||||
StringRef Annot,
|
StringRef Annot,
|
||||||
const MCSubtargetInfo &STI) {
|
MCSubtargetInfo const &STI) {
|
||||||
const char startPacket = '{',
|
assert(HexagonMCInstrInfo::isBundle(*MI));
|
||||||
endPacket = '}';
|
assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
|
||||||
// TODO: add outer HW loop when it's supported too.
|
HasExtender = false;
|
||||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
|
||||||
// Ending a harware loop is different from ending an regular packet.
|
MCInst const &MCI = *I.getInst();
|
||||||
assert(HexagonMCInstrInfo::isPacketEnd(*MI) && "Loop-end must also end the packet");
|
printInstruction(&MCI, OS);
|
||||||
|
setExtender(MCI);
|
||||||
if (HexagonMCInstrInfo::isPacketBegin(*MI)) {
|
OS << "\n";
|
||||||
// There must be a packet to end a loop.
|
|
||||||
// FIXME: when shuffling is always run, this shouldn't be needed.
|
|
||||||
MCInst Nop;
|
|
||||||
StringRef NoAnnot;
|
|
||||||
|
|
||||||
Nop.setOpcode (Hexagon::A2_nop);
|
|
||||||
HexagonMCInstrInfo::setPacketBegin (Nop, HexagonMCInstrInfo::isPacketBegin(*MI));
|
|
||||||
printInst (&Nop, O, NoAnnot, STI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the packet.
|
|
||||||
if (HexagonMCInstrInfo::isPacketEnd(*MI))
|
|
||||||
O << PacketPadding << endPacket;
|
|
||||||
|
|
||||||
printInstruction(MI, O);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Prefix the insn opening the packet.
|
|
||||||
if (HexagonMCInstrInfo::isPacketBegin(*MI))
|
|
||||||
O << PacketPadding << startPacket << '\n';
|
|
||||||
|
|
||||||
printInstruction(MI, O);
|
|
||||||
|
|
||||||
// Suffix the insn closing the packet.
|
|
||||||
if (HexagonMCInstrInfo::isPacketEnd(*MI))
|
|
||||||
// Suffix the packet in a new line always, since the GNU assembler has
|
|
||||||
// issues with a closing brace on the same line as CONST{32,64}.
|
|
||||||
O << '\n' << PacketPadding << endPacket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printAnnotation(O, Annot);
|
auto Separator = "";
|
||||||
|
if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
|
||||||
|
OS << Separator;
|
||||||
|
Separator = " ";
|
||||||
|
MCInst ME;
|
||||||
|
ME.setOpcode(Hexagon::ENDLOOP0);
|
||||||
|
printInstruction(&ME, OS);
|
||||||
|
}
|
||||||
|
if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
|
||||||
|
OS << Separator;
|
||||||
|
Separator = " ";
|
||||||
|
MCInst ME;
|
||||||
|
ME.setOpcode(Hexagon::ENDLOOP1);
|
||||||
|
printInstruction(&ME, OS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||||
|
@ -18,6 +18,21 @@
|
|||||||
#include "llvm/MC/MCInstrInfo.h"
|
#include "llvm/MC/MCInstrInfo.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class HexagonAsmInstPrinter : public MCInstPrinter {
|
||||||
|
public:
|
||||||
|
HexagonAsmInstPrinter(MCInstPrinter *RawPrinter);
|
||||||
|
void printInst(MCInst const *MI, raw_ostream &O, StringRef Annot,
|
||||||
|
MCSubtargetInfo const &STI) override;
|
||||||
|
void printRegName(raw_ostream &O, unsigned RegNo) const override;
|
||||||
|
std::unique_ptr<MCInstPrinter> RawPrinter;
|
||||||
|
};
|
||||||
|
/// Prints bundles as a newline separated list of individual instructions
|
||||||
|
/// Duplexes are separated by a vertical tab \v character
|
||||||
|
/// A trailing line includes bundle properties such as endloop0/1
|
||||||
|
///
|
||||||
|
/// r0 = add(r1, r2)
|
||||||
|
/// r0 = #0 \v jump 0x0
|
||||||
|
/// :endloop0 :endloop1
|
||||||
class HexagonInstPrinter : public MCInstPrinter {
|
class HexagonInstPrinter : public MCInstPrinter {
|
||||||
public:
|
public:
|
||||||
explicit HexagonInstPrinter(MCAsmInfo const &MAI,
|
explicit HexagonInstPrinter(MCAsmInfo const &MAI,
|
||||||
@ -74,11 +89,11 @@ namespace llvm {
|
|||||||
void printSymbol(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool hi)
|
void printSymbol(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool hi)
|
||||||
const;
|
const;
|
||||||
|
|
||||||
static const char PacketPadding;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const MCInstrInfo &MII;
|
const MCInstrInfo &MII;
|
||||||
|
|
||||||
|
bool HasExtender;
|
||||||
|
void setExtender(MCInst const &MCI);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -32,16 +32,6 @@ using namespace Hexagon;
|
|||||||
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// \brief 10.6 Instruction Packets
|
|
||||||
/// 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(MCInst const &HMI) {
|
|
||||||
unsigned const ParseFieldOffset = 14;
|
|
||||||
ParseField Field = HexagonMCInstrInfo::isPacketEnd(HMI) ? ParseField::end
|
|
||||||
: ParseField::last0;
|
|
||||||
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);
|
||||||
OS << static_cast<uint8_t>((Binary >> 0x08) & 0xff);
|
OS << static_cast<uint8_t>((Binary >> 0x08) & 0xff);
|
||||||
@ -53,15 +43,120 @@ void emitLittleEndian(uint64_t Binary, raw_ostream &OS) {
|
|||||||
HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII,
|
HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII,
|
||||||
MCContext &aMCT)
|
MCContext &aMCT)
|
||||||
: MCT(aMCT), MCII(aMII), Addend(new unsigned(0)),
|
: MCT(aMCT), MCII(aMII), Addend(new unsigned(0)),
|
||||||
Extended(new bool(false)) {}
|
Extended(new bool(false)), CurrentBundle(new MCInst const *) {}
|
||||||
|
|
||||||
|
uint32_t HexagonMCCodeEmitter::parseBits(size_t Instruction, size_t Last,
|
||||||
|
MCInst const &MCB,
|
||||||
|
MCInst const &MCI) const {
|
||||||
|
if (Instruction == 0) {
|
||||||
|
if (HexagonMCInstrInfo::isInnerLoop(MCB)) {
|
||||||
|
assert(Instruction != Last);
|
||||||
|
return HexagonII::INST_PARSE_LOOP_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Instruction == 1) {
|
||||||
|
if (HexagonMCInstrInfo::isOuterLoop(MCB)) {
|
||||||
|
assert(Instruction != Last);
|
||||||
|
return HexagonII::INST_PARSE_LOOP_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Instruction == Last)
|
||||||
|
return HexagonII::INST_PARSE_PACKET_END;
|
||||||
|
return HexagonII::INST_PARSE_NOT_END;
|
||||||
|
}
|
||||||
|
|
||||||
void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
MCSubtargetInfo const &STI) const {
|
MCSubtargetInfo const &STI) const {
|
||||||
uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI) | getPacketBits(MI);
|
MCInst &HMB = const_cast<MCInst &>(MI);
|
||||||
assert(HexagonMCInstrInfo::getDesc(MCII, MI).getSize() == 4 &&
|
|
||||||
"All instructions should be 32bit");
|
assert(HexagonMCInstrInfo::isBundle(HMB));
|
||||||
(void)&MCII;
|
DEBUG(dbgs() << "Encoding bundle\n";);
|
||||||
|
*Addend = 0;
|
||||||
|
*Extended = false;
|
||||||
|
*CurrentBundle = &MI;
|
||||||
|
size_t Instruction = 0;
|
||||||
|
size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1;
|
||||||
|
for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) {
|
||||||
|
MCInst &HMI = const_cast<MCInst &>(*I.getInst());
|
||||||
|
EncodeSingleInstruction(HMI, OS, Fixups, STI,
|
||||||
|
parseBits(Instruction, Last, HMB, HMI),
|
||||||
|
Instruction);
|
||||||
|
*Extended = HexagonMCInstrInfo::isImmext(HMI);
|
||||||
|
*Addend += HEXAGON_INSTR_SIZE;
|
||||||
|
++Instruction;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// EncodeSingleInstruction - Emit a single
|
||||||
|
void HexagonMCCodeEmitter::EncodeSingleInstruction(
|
||||||
|
const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI, uint32_t Parse, size_t Index) const {
|
||||||
|
MCInst HMB = MI;
|
||||||
|
assert(!HexagonMCInstrInfo::isBundle(HMB));
|
||||||
|
uint64_t Binary;
|
||||||
|
|
||||||
|
// Pseudo instructions don't get encoded and shouldn't be here
|
||||||
|
// in the first place!
|
||||||
|
assert(!HexagonMCInstrInfo::getDesc(MCII, HMB).isPseudo() &&
|
||||||
|
"pseudo-instruction found");
|
||||||
|
DEBUG(dbgs() << "Encoding insn"
|
||||||
|
" `" << HexagonMCInstrInfo::getName(MCII, HMB) << "'"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
if (HexagonMCInstrInfo::isNewValue(MCII, HMB)) {
|
||||||
|
// Calculate the new value distance to the associated producer
|
||||||
|
MCOperand &MCO =
|
||||||
|
HMB.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, HMB));
|
||||||
|
unsigned SOffset = 0;
|
||||||
|
unsigned Register = MCO.getReg();
|
||||||
|
unsigned Register1;
|
||||||
|
auto Instructions = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle);
|
||||||
|
auto i = Instructions.begin() + Index - 1;
|
||||||
|
for (;; --i) {
|
||||||
|
assert(i != Instructions.begin() - 1 && "Couldn't find producer");
|
||||||
|
MCInst const &Inst = *i->getInst();
|
||||||
|
if (HexagonMCInstrInfo::isImmext(Inst))
|
||||||
|
continue;
|
||||||
|
++SOffset;
|
||||||
|
Register1 =
|
||||||
|
HexagonMCInstrInfo::hasNewValue(MCII, Inst)
|
||||||
|
? HexagonMCInstrInfo::getNewValueOperand(MCII, Inst).getReg()
|
||||||
|
: static_cast<unsigned>(Hexagon::NoRegister);
|
||||||
|
if (Register != Register1)
|
||||||
|
// This isn't the register we're looking for
|
||||||
|
continue;
|
||||||
|
if (!HexagonMCInstrInfo::isPredicated(MCII, Inst))
|
||||||
|
// Producer is unpredicated
|
||||||
|
break;
|
||||||
|
assert(HexagonMCInstrInfo::isPredicated(MCII, HMB) &&
|
||||||
|
"Unpredicated consumer depending on predicated producer");
|
||||||
|
if (HexagonMCInstrInfo::isPredicatedTrue(MCII, Inst) ==
|
||||||
|
HexagonMCInstrInfo::isPredicatedTrue(MCII, HMB))
|
||||||
|
// Producer predicate sense matched ours
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Hexagon PRM 10.11 Construct Nt from distance
|
||||||
|
unsigned Offset = SOffset;
|
||||||
|
Offset <<= 1;
|
||||||
|
MCO.setReg(Offset + Hexagon::R0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary = getBinaryCodeForInstr(HMB, Fixups, STI);
|
||||||
|
// Check for unimplemented instructions. Immediate extenders
|
||||||
|
// are encoded as zero, so they need to be accounted for.
|
||||||
|
if ((!Binary) &&
|
||||||
|
((HMB.getOpcode() != DuplexIClass0) && (HMB.getOpcode() != A4_ext) &&
|
||||||
|
(HMB.getOpcode() != A4_ext_b) && (HMB.getOpcode() != A4_ext_c) &&
|
||||||
|
(HMB.getOpcode() != A4_ext_g))) {
|
||||||
|
// Use a A2_nop for unimplemented instructions.
|
||||||
|
DEBUG(dbgs() << "Unimplemented inst: "
|
||||||
|
" `" << HexagonMCInstrInfo::getName(MCII, HMB) << "'"
|
||||||
|
"\n");
|
||||||
|
llvm_unreachable("Unimplemented Instruction");
|
||||||
|
}
|
||||||
|
Binary |= Parse;
|
||||||
emitLittleEndian(Binary, OS);
|
emitLittleEndian(Binary, OS);
|
||||||
++MCNumEmitted;
|
++MCNumEmitted;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ class HexagonMCCodeEmitter : public MCCodeEmitter {
|
|||||||
MCInstrInfo const &MCII;
|
MCInstrInfo const &MCII;
|
||||||
std::unique_ptr<unsigned> Addend;
|
std::unique_ptr<unsigned> Addend;
|
||||||
std::unique_ptr<bool> Extended;
|
std::unique_ptr<bool> Extended;
|
||||||
|
std::unique_ptr<MCInst const *> CurrentBundle;
|
||||||
|
|
||||||
// helper routine for getMachineOpValue()
|
// helper routine for getMachineOpValue()
|
||||||
unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,
|
unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,
|
||||||
@ -39,12 +40,21 @@ class HexagonMCCodeEmitter : public MCCodeEmitter {
|
|||||||
public:
|
public:
|
||||||
HexagonMCCodeEmitter(MCInstrInfo const &aMII, MCContext &aMCT);
|
HexagonMCCodeEmitter(MCInstrInfo const &aMII, MCContext &aMCT);
|
||||||
|
|
||||||
|
// Return parse bits for instruction `MCI' inside bundle `MCB'
|
||||||
|
uint32_t parseBits(size_t Instruction, size_t Last, MCInst const &MCB,
|
||||||
|
MCInst const &MCI) const;
|
||||||
|
|
||||||
MCSubtargetInfo const &getSubtargetInfo() const;
|
MCSubtargetInfo const &getSubtargetInfo() const;
|
||||||
|
|
||||||
void encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
void encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
MCSubtargetInfo const &STI) const override;
|
MCSubtargetInfo const &STI) const override;
|
||||||
|
|
||||||
|
void EncodeSingleInstruction(const MCInst &MI, raw_ostream &OS,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI,
|
||||||
|
uint32_t Parse, size_t Index) const;
|
||||||
|
|
||||||
// \brief TableGen'erated function for getting the
|
// \brief TableGen'erated function for getting the
|
||||||
// binary encoding for an instruction.
|
// binary encoding for an instruction.
|
||||||
uint64_t getBinaryCodeForInstr(MCInst const &MI,
|
uint64_t getBinaryCodeForInstr(MCInst const &MI,
|
||||||
|
@ -11,13 +11,23 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "HexagonMCInstrInfo.h"
|
#include "Hexagon.h"
|
||||||
#include "HexagonBaseInfo.h"
|
#include "HexagonBaseInfo.h"
|
||||||
|
#include "HexagonMCInstrInfo.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
void HexagonMCInstrInfo::AppendImplicitOperands(MCInst &MCI) {
|
iterator_range<MCInst::const_iterator>
|
||||||
MCI.addOperand(MCOperand::createImm(0));
|
HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) {
|
||||||
MCI.addOperand(MCOperand::createInst(nullptr));
|
assert(isBundle(MCI));
|
||||||
|
return iterator_range<MCInst::const_iterator>(
|
||||||
|
MCI.begin() + bundleInstructionsOffset, MCI.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) {
|
||||||
|
if (HexagonMCInstrInfo::isBundle(MCI))
|
||||||
|
return (MCI.size() - bundleInstructionsOffset);
|
||||||
|
else
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
HexagonII::MemAccessSize
|
HexagonII::MemAccessSize
|
||||||
@ -58,12 +68,6 @@ unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII,
|
|||||||
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
|
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<16> HexagonMCInstrInfo::GetImplicitBits(MCInst const &MCI) {
|
|
||||||
SanityCheckImplicitOperands(MCI);
|
|
||||||
std::bitset<16> Bits(MCI.getOperand(MCI.getNumOperands() - 2).getImm());
|
|
||||||
return Bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the max value that a constant extendable operand can have
|
// Return the max value that a constant extendable operand can have
|
||||||
// without being extended.
|
// without being extended.
|
||||||
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
|
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
|
||||||
@ -99,9 +103,14 @@ char const *HexagonMCInstrInfo::getName(MCInstrInfo const &MCII,
|
|||||||
return MCII.getName(MCI.getOpcode());
|
return MCII.getName(MCI.getOpcode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the operand that consumes or produces a new value.
|
unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
|
||||||
MCOperand const &HexagonMCInstrInfo::getNewValue(MCInstrInfo const &MCII,
|
|
||||||
MCInst const &MCI) {
|
MCInst const &MCI) {
|
||||||
|
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||||
|
return ((F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII,
|
||||||
|
MCInst const &MCI) {
|
||||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||||
unsigned const O =
|
unsigned const O =
|
||||||
(F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask;
|
(F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask;
|
||||||
@ -128,6 +137,12 @@ bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
|
|||||||
return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask);
|
return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
// Return whether the insn is an actual insn.
|
||||||
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
|
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||||
return (!HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
|
return (!HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
|
||||||
@ -187,6 +202,18 @@ bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII,
|
|||||||
return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
|
return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) {
|
||||||
|
auto Op = MCI.getOpcode();
|
||||||
|
return (Op == Hexagon::A4_ext_b || Op == Hexagon::A4_ext_c ||
|
||||||
|
Op == Hexagon::A4_ext_g || Op == Hexagon::A4_ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HexagonMCInstrInfo::isInnerLoop(MCInst const &MCI) {
|
||||||
|
assert(isBundle(MCI));
|
||||||
|
int64_t Flags = MCI.getOperand(0).getImm();
|
||||||
|
return (Flags & innerLoopMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether the insn is a new-value consumer.
|
// Return whether the insn is a new-value consumer.
|
||||||
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
|
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
|
||||||
MCInst const &MCI) {
|
MCInst const &MCI) {
|
||||||
@ -203,14 +230,23 @@ bool HexagonMCInstrInfo::isOperandExtended(MCInstrInfo const &MCII,
|
|||||||
OperandNum;
|
OperandNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HexagonMCInstrInfo::isPacketBegin(MCInst const &MCI) {
|
bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) {
|
||||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
assert(isBundle(MCI));
|
||||||
return Bits.test(packetBeginIndex);
|
int64_t Flags = MCI.getOperand(0).getImm();
|
||||||
|
return (Flags & outerLoopMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HexagonMCInstrInfo::isPacketEnd(MCInst const &MCI) {
|
bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII,
|
||||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
MCInst const &MCI) {
|
||||||
return Bits.test(packetEndIndex);
|
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||||
|
return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HexagonMCInstrInfo::isPredicatedTrue(MCInstrInfo const &MCII,
|
||||||
|
MCInst const &MCI) {
|
||||||
|
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||||
|
return (
|
||||||
|
!((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether the insn is a prefix.
|
// Return whether the insn is a prefix.
|
||||||
@ -224,25 +260,26 @@ bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
|
|||||||
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
|
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonMCInstrInfo::resetPacket(MCInst &MCI) {
|
void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {
|
||||||
setPacketBegin(MCI, false);
|
MCInst Nop;
|
||||||
setPacketEnd(MCI, false);
|
Nop.setOpcode(Hexagon::A2_nop);
|
||||||
|
assert(isBundle(MCB));
|
||||||
|
while ((HexagonMCInstrInfo::isInnerLoop(MCB) &&
|
||||||
|
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) ||
|
||||||
|
((HexagonMCInstrInfo::isOuterLoop(MCB) &&
|
||||||
|
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE))))
|
||||||
|
MCB.addOperand(MCOperand::createInst(new MCInst(Nop)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonMCInstrInfo::SetImplicitBits(MCInst &MCI, std::bitset<16> Bits) {
|
void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) {
|
||||||
SanityCheckImplicitOperands(MCI);
|
assert(isBundle(MCI));
|
||||||
MCI.getOperand(MCI.getNumOperands() - 2).setImm(Bits.to_ulong());
|
MCOperand &Operand = MCI.getOperand(0);
|
||||||
|
Operand.setImm(Operand.getImm() | innerLoopMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonMCInstrInfo::setPacketBegin(MCInst &MCI, bool f) {
|
void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
|
||||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
assert(isBundle(MCI));
|
||||||
Bits.set(packetBeginIndex, f);
|
MCOperand &Operand = MCI.getOperand(0);
|
||||||
SetImplicitBits(MCI, Bits);
|
Operand.setImm(Operand.getImm() | outerLoopMask);
|
||||||
}
|
|
||||||
|
|
||||||
void HexagonMCInstrInfo::setPacketEnd(MCInst &MCI, bool f) {
|
|
||||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
|
||||||
Bits.set(packetEndIndex, f);
|
|
||||||
SetImplicitBits(MCI, Bits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,19 @@ namespace HexagonII {
|
|||||||
enum class MemAccessSize;
|
enum class MemAccessSize;
|
||||||
}
|
}
|
||||||
namespace HexagonMCInstrInfo {
|
namespace HexagonMCInstrInfo {
|
||||||
void AppendImplicitOperands(MCInst &MCI);
|
size_t const innerLoopOffset = 0;
|
||||||
|
int64_t const innerLoopMask = 1 << innerLoopOffset;
|
||||||
|
|
||||||
|
size_t const outerLoopOffset = 1;
|
||||||
|
int64_t const outerLoopMask = 1 << outerLoopOffset;
|
||||||
|
|
||||||
|
size_t const bundleInstructionsOffset = 1;
|
||||||
|
|
||||||
|
// Returns the number of instructions in the bundle
|
||||||
|
size_t bundleSize(MCInst const &MCI);
|
||||||
|
|
||||||
|
// Returns a iterator range of instructions in this bundle
|
||||||
|
iterator_range<MCInst::const_iterator> bundleInstructions(MCInst const &MCI);
|
||||||
|
|
||||||
// Return memory access size
|
// Return memory access size
|
||||||
HexagonII::MemAccessSize getAccessSize(MCInstrInfo const &MCII,
|
HexagonII::MemAccessSize getAccessSize(MCInstrInfo const &MCII,
|
||||||
@ -48,8 +60,6 @@ unsigned getExtentAlignment(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
// Return the number of logical bits of the extendable operand
|
// Return the number of logical bits of the extendable operand
|
||||||
unsigned getExtentBits(MCInstrInfo const &MCII, MCInst const &MCI);
|
unsigned getExtentBits(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
std::bitset<16> GetImplicitBits(MCInst const &MCI);
|
|
||||||
|
|
||||||
// Return the max value that a constant extendable operand can have
|
// Return the max value that a constant extendable operand can have
|
||||||
// without being extended.
|
// without being extended.
|
||||||
int getMaxValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
int getMaxValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
@ -61,8 +71,11 @@ int getMinValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
// Return instruction name
|
// Return instruction name
|
||||||
char const *getName(MCInstrInfo const &MCII, MCInst const &MCI);
|
char const *getName(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
|
// Return the operand index for the new value.
|
||||||
|
unsigned short getNewValueOp(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
// Return the operand that consumes or produces a new value.
|
// Return the operand that consumes or produces a new value.
|
||||||
MCOperand const &getNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
// Return the Hexagon ISA class for the insn.
|
// Return the Hexagon ISA class for the insn.
|
||||||
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
|
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
@ -70,6 +83,9 @@ unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
// Return whether the instruction is a legal new-value producer.
|
// Return whether the instruction is a legal new-value producer.
|
||||||
bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool hasNewValue(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.
|
// Return whether the insn is an actual insn.
|
||||||
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
@ -82,6 +98,12 @@ bool isExtendable(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
// Return whether the instruction must be always extended.
|
// Return whether the instruction must be always extended.
|
||||||
bool isExtended(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool isExtended(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
|
// Returns whether this instruction is an immediate extender
|
||||||
|
bool isImmext(MCInst const &MCI);
|
||||||
|
|
||||||
|
// Returns whether this bundle is an endloop0
|
||||||
|
bool isInnerLoop(MCInst const &MCI);
|
||||||
|
|
||||||
// Return whether the insn is a new-value consumer.
|
// Return whether the insn is a new-value consumer.
|
||||||
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
@ -89,9 +111,14 @@ bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
bool isOperandExtended(MCInstrInfo const &MCII, MCInst const &MCI,
|
bool isOperandExtended(MCInstrInfo const &MCII, MCInst const &MCI,
|
||||||
unsigned short OperandNum);
|
unsigned short OperandNum);
|
||||||
|
|
||||||
bool isPacketBegin(MCInst const &MCI);
|
// Returns whether this bundle is an endloop1
|
||||||
|
bool isOuterLoop(MCInst const &MCI);
|
||||||
|
|
||||||
bool isPacketEnd(MCInst const &MCI);
|
// Return whether this instruction is predicated
|
||||||
|
bool isPredicated(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
|
// Return whether the predicate sense is true
|
||||||
|
bool isPredicatedTrue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
// Return whether the insn is a prefix.
|
// Return whether the insn is a prefix.
|
||||||
bool isPrefix(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool isPrefix(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
@ -99,23 +126,14 @@ bool isPrefix(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||||||
// Return whether the insn is solo, i.e., cannot be in a packet.
|
// Return whether the insn is solo, i.e., cannot be in a packet.
|
||||||
bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);
|
bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||||
|
|
||||||
static const size_t packetBeginIndex = 0;
|
// Pad the bundle with nops to satisfy endloop requirements
|
||||||
static const size_t packetEndIndex = 1;
|
void padEndloop(MCInst &MCI);
|
||||||
|
|
||||||
void resetPacket(MCInst &MCI);
|
// Marks a bundle as endloop0
|
||||||
|
void setInnerLoop(MCInst &MCI);
|
||||||
|
|
||||||
inline void SanityCheckImplicitOperands(MCInst const &MCI) {
|
// Marks a bundle as endloop1
|
||||||
assert(MCI.getNumOperands() >= 2 && "At least the two implicit operands");
|
void setOuterLoop(MCInst &MCI);
|
||||||
assert(MCI.getOperand(MCI.getNumOperands() - 1).isInst() &&
|
|
||||||
"Implicit bits and flags");
|
|
||||||
assert(MCI.getOperand(MCI.getNumOperands() - 2).isImm() && "Parent pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetImplicitBits(MCInst &MCI, std::bitset<16> Bits);
|
|
||||||
|
|
||||||
void setPacketBegin(MCInst &MCI, bool Y);
|
|
||||||
|
|
||||||
void setPacketEnd(MCInst &MCI, bool Y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||||
|
; XFAIL:
|
||||||
|
|
||||||
; Check that the packetizer generates valid packets with constant
|
; Check that the packetizer generates valid packets with constant
|
||||||
; extended instructions.
|
; extended instructions.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||||
|
; XFAIL:
|
||||||
; Check that the packetizer generates valid packets with constant
|
; Check that the packetizer generates valid packets with constant
|
||||||
; extended add and base+offset store instructions.
|
; extended add and base+offset store instructions.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a, i32 %b)
|
define i1 @foo (i32 %a, i32 %b)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 004100f2 00404089 00c09f52
|
; CHECK: p0 = cmp.eq(r0, r1)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a)
|
define i1 @foo (i32 %a)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 40450075 00404089 00c09f52
|
; CHECK: p0 = cmp.eq(r0, #42)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a, i32 %b)
|
define i1 @foo (i32 %a, i32 %b)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 004140f2 00404089 00c09f52
|
; CHECK: p0 = cmp.gt(r0, r1)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31 }
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a)
|
define i1 @foo (i32 %a)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 40454075 00404089 00c09f52
|
; CHECK: p0 = cmp.gt(r0, #42)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a, i32 %b)
|
define i1 @foo (i32 %a, i32 %b)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 004041f2 00404089 00c09f52
|
; CHECK: p0 = cmp.gt(r1, r0)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a, i32 %b)
|
define i1 @foo (i32 %a, i32 %b)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 004160f2 00404089 00c09f52
|
; CHECK: p0 = cmp.gtu(r0, r1)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a)
|
define i1 @foo (i32 %a)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 40458075 00404089 00c09f52
|
; CHECK: p0 = cmp.gtu(r0, #42)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
;; RUN: llc -mtriple=hexagon-unknown-elf -filetype=obj %s -o - \
|
||||||
;; RUN: | llvm-objdump -s - | FileCheck %s
|
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
define i1 @foo (i32 %a, i32 %b)
|
define i1 @foo (i32 %a, i32 %b)
|
||||||
{
|
{
|
||||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
|||||||
ret i1 %1
|
ret i1 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK: 0000 004061f2 00404089 00c09f52
|
; CHECK: p0 = cmp.gtu(r1, r0)
|
||||||
|
; CHECK: r0 = p0
|
||||||
|
; CHECK: jumpr r31
|
@ -205,7 +205,7 @@ namespace {
|
|||||||
class PrettyPrinter {
|
class PrettyPrinter {
|
||||||
public:
|
public:
|
||||||
virtual ~PrettyPrinter(){}
|
virtual ~PrettyPrinter(){}
|
||||||
virtual void printInst(MCInstPrinter &IP, const MCInst *MI, bool ShowRawInsn,
|
virtual void printInst(MCInstPrinter &IP, const MCInst *MI,
|
||||||
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
raw_ostream &OS, StringRef Annot,
|
raw_ostream &OS, StringRef Annot,
|
||||||
MCSubtargetInfo const &STI) {
|
MCSubtargetInfo const &STI) {
|
||||||
@ -218,8 +218,66 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
PrettyPrinter PrettyPrinterInst;
|
PrettyPrinter PrettyPrinterInst;
|
||||||
|
class HexagonPrettyPrinter : public PrettyPrinter {
|
||||||
|
public:
|
||||||
|
void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
|
raw_ostream &OS) {
|
||||||
|
uint32_t opcode =
|
||||||
|
(Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
|
||||||
|
OS << format("%8" PRIx64 ":", Address);
|
||||||
|
if (!NoShowRawInsn) {
|
||||||
|
OS << "\t";
|
||||||
|
dumpBytes(Bytes.slice(0, 4), OS);
|
||||||
|
OS << format("%08" PRIx32, opcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void printInst(MCInstPrinter &IP, const MCInst *MI,
|
||||||
|
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||||
|
raw_ostream &OS, StringRef Annot,
|
||||||
|
MCSubtargetInfo const &STI) override {
|
||||||
|
std::string Buffer;
|
||||||
|
{
|
||||||
|
raw_string_ostream TempStream(Buffer);
|
||||||
|
IP.printInst(MI, TempStream, "", STI);
|
||||||
|
}
|
||||||
|
StringRef Contents(Buffer);
|
||||||
|
// Split off bundle attributes
|
||||||
|
auto PacketBundle = Contents.rsplit('\n');
|
||||||
|
// Split off first instruction from the rest
|
||||||
|
auto HeadTail = PacketBundle.first.split('\n');
|
||||||
|
auto Preamble = " { ";
|
||||||
|
auto Separator = "";
|
||||||
|
while(!HeadTail.first.empty()) {
|
||||||
|
OS << Separator;
|
||||||
|
Separator = "\n";
|
||||||
|
printLead(Bytes, Address, OS);
|
||||||
|
OS << Preamble;
|
||||||
|
Preamble = " ";
|
||||||
|
StringRef Inst;
|
||||||
|
auto Duplex = HeadTail.first.split('\v');
|
||||||
|
if(!Duplex.second.empty()){
|
||||||
|
OS << Duplex.first;
|
||||||
|
OS << "; ";
|
||||||
|
Inst = Duplex.second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Inst = HeadTail.first;
|
||||||
|
OS << Inst;
|
||||||
|
Bytes = Bytes.slice(4);
|
||||||
|
Address += 4;
|
||||||
|
HeadTail = HeadTail.second.split('\n');
|
||||||
|
}
|
||||||
|
OS << " } " << PacketBundle.second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
HexagonPrettyPrinter HexagonPrettyPrinterInst;
|
||||||
PrettyPrinter &selectPrettyPrinter(Triple const &Triple, MCInstPrinter &IP) {
|
PrettyPrinter &selectPrettyPrinter(Triple const &Triple, MCInstPrinter &IP) {
|
||||||
return PrettyPrinterInst;
|
switch(Triple.getArch()) {
|
||||||
|
default:
|
||||||
|
return PrettyPrinterInst;
|
||||||
|
case Triple::hexagon:
|
||||||
|
return HexagonPrettyPrinterInst;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +464,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
|
|||||||
if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
|
if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
|
||||||
SectionAddr + Index, DebugOut,
|
SectionAddr + Index, DebugOut,
|
||||||
CommentStream)) {
|
CommentStream)) {
|
||||||
PIP.printInst(*IP, &Inst, !NoShowRawInsn,
|
PIP.printInst(*IP, &Inst,
|
||||||
Bytes.slice(Index, Size),
|
Bytes.slice(Index, Size),
|
||||||
SectionAddr + Index, outs(), "", *STI);
|
SectionAddr + Index, outs(), "", *STI);
|
||||||
outs() << CommentStream.str();
|
outs() << CommentStream.str();
|
||||||
|
Loading…
Reference in New Issue
Block a user