mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +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/HexagonMCInstrInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
@ -27,6 +29,7 @@
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Hexagon;
|
||||
|
||||
#define DEBUG_TYPE "hexagon-disassembler"
|
||||
|
||||
@ -37,9 +40,14 @@ namespace {
|
||||
/// \brief Hexagon disassembler for all Hexagon platforms.
|
||||
class HexagonDisassembler : public MCDisassembler {
|
||||
public:
|
||||
std::unique_ptr<MCInst *> CurrentBundle;
|
||||
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,
|
||||
ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
raw_ostream &VStream,
|
||||
@ -191,17 +199,53 @@ DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
uint64_t Address,
|
||||
raw_ostream &os,
|
||||
raw_ostream &cs) const {
|
||||
Size = 4;
|
||||
if (Bytes.size() < 4)
|
||||
return MCDisassembler::Fail;
|
||||
DecodeStatus Result = DecodeStatus::Success;
|
||||
bool Complete = false;
|
||||
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::unaligned>(Bytes.data());
|
||||
|
||||
// Remove parse bits.
|
||||
insn &= ~static_cast<uint32_t>(HexagonII::InstParseBits::INST_PARSE_MASK);
|
||||
DecodeStatus Result = decodeInstruction(DecoderTable32, MI, insn, Address, this, STI);
|
||||
HexagonMCInstrInfo::AppendImplicitOperands(MI);
|
||||
auto BundleSize = HexagonMCInstrInfo::bundleSize(MCB);
|
||||
if ((Instruction & HexagonII::INST_PARSE_MASK) ==
|
||||
HexagonII::INST_PARSE_LOOP_END) {
|
||||
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;
|
||||
}
|
||||
|
@ -76,4 +76,8 @@ namespace llvm {
|
||||
// Maximum number of words and instructions in a packet.
|
||||
#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
|
||||
|
@ -177,47 +177,29 @@ bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
||||
/// the current output stream.
|
||||
///
|
||||
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
if (MI->isBundle()) {
|
||||
std::vector<MachineInstr const *> BundleMIs;
|
||||
MCInst MCB;
|
||||
MCB.setOpcode(Hexagon::BUNDLE);
|
||||
MCB.addOperand(MCOperand::createImm(0));
|
||||
|
||||
if (MI->isBundle()) {
|
||||
const MachineBasicBlock* MBB = MI->getParent();
|
||||
MachineBasicBlock::const_instr_iterator MII = MI;
|
||||
++MII;
|
||||
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;
|
||||
unsigned IgnoreCount = 0;
|
||||
|
||||
HexagonLowerToMC(BundleMIs[Index], MCI, *this);
|
||||
HexagonMCInstrInfo::AppendImplicitOperands(MCI);
|
||||
HexagonMCInstrInfo::setPacketBegin(MCI, Index == 0);
|
||||
HexagonMCInstrInfo::setPacketEnd(MCI, Index == (Size - 1));
|
||||
EmitToStreamer(*OutStreamer, MCI);
|
||||
for (++MII; MII != MBB->end() && MII->isInsideBundle(); ++MII) {
|
||||
if (MII->getOpcode() == TargetOpcode::DBG_VALUE ||
|
||||
MII->getOpcode() == TargetOpcode::IMPLICIT_DEF)
|
||||
++IgnoreCount;
|
||||
else {
|
||||
HexagonLowerToMC(MII, MCB, *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
MCInst MCI;
|
||||
HexagonLowerToMC(MI, MCI, *this);
|
||||
HexagonMCInstrInfo::AppendImplicitOperands(MCI);
|
||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
||||
HexagonMCInstrInfo::setPacketBegin(MCI, true);
|
||||
HexagonMCInstrInfo::setPacketEnd(MCI, true);
|
||||
}
|
||||
EmitToStreamer(*OutStreamer, MCI);
|
||||
HexagonLowerToMC(MI, MCB, *this);
|
||||
HexagonMCInstrInfo::padEndloop(MCB);
|
||||
}
|
||||
EmitToStreamer(*OutStreamer, MCB);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -66,10 +66,8 @@ def DoubleWordAccess : MemAccessSize<4>;// Double word access instruction (memd)
|
||||
class OpcodeHexagon {
|
||||
field bits<32> Inst = ?; // Default to an invalid insn.
|
||||
bits<4> IClass = 0; // ICLASS
|
||||
bits<2> IParse = 0; // Parse bits.
|
||||
|
||||
let Inst{31-28} = IClass;
|
||||
let Inst{15-14} = IParse;
|
||||
|
||||
bits<1> zero = 0;
|
||||
}
|
||||
|
@ -15,9 +15,12 @@
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonAsmPrinter.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.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
|
||||
void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCI,
|
||||
void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCB,
|
||||
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++) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
@ -88,6 +102,7 @@ void llvm::HexagonLowerToMC(MachineInstr const* MI, MCInst& MCI,
|
||||
break;
|
||||
}
|
||||
|
||||
MCI.addOperand(MCO);
|
||||
MCI->addOperand(MCO);
|
||||
}
|
||||
MCB.addOperand(MCOperand::createInst(MCI));
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ namespace HexagonII {
|
||||
MO_GPREL
|
||||
};
|
||||
|
||||
enum class InstParseBits : uint32_t {
|
||||
enum InstParseBits {
|
||||
INST_PARSE_MASK = 0x0000c000,
|
||||
INST_PARSE_PACKET_END = 0x0000c000,
|
||||
INST_PARSE_LOOP_END = 0x00008000,
|
||||
|
@ -28,7 +28,47 @@ using namespace llvm;
|
||||
#define GET_INSTRUCTION_NAME
|
||||
#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
|
||||
// without being extended.
|
||||
static int getMinValue(uint64_t TSFlags) {
|
||||
@ -77,48 +117,38 @@ void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
|
||||
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,
|
||||
const MCSubtargetInfo &STI) {
|
||||
const char startPacket = '{',
|
||||
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(HexagonMCInstrInfo::isPacketEnd(*MI) && "Loop-end must also end the packet");
|
||||
|
||||
if (HexagonMCInstrInfo::isPacketBegin(*MI)) {
|
||||
// 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);
|
||||
MCSubtargetInfo const &STI) {
|
||||
assert(HexagonMCInstrInfo::isBundle(*MI));
|
||||
assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
|
||||
HasExtender = false;
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
|
||||
MCInst const &MCI = *I.getInst();
|
||||
printInstruction(&MCI, OS);
|
||||
setExtender(MCI);
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
// Close the packet.
|
||||
if (HexagonMCInstrInfo::isPacketEnd(*MI))
|
||||
O << PacketPadding << endPacket;
|
||||
|
||||
printInstruction(MI, O);
|
||||
auto Separator = "";
|
||||
if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
|
||||
OS << Separator;
|
||||
Separator = " ";
|
||||
MCInst ME;
|
||||
ME.setOpcode(Hexagon::ENDLOOP0);
|
||||
printInstruction(&ME, OS);
|
||||
}
|
||||
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;
|
||||
if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
|
||||
OS << Separator;
|
||||
Separator = " ";
|
||||
MCInst ME;
|
||||
ME.setOpcode(Hexagon::ENDLOOP1);
|
||||
printInstruction(&ME, OS);
|
||||
}
|
||||
|
||||
printAnnotation(O, Annot);
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
|
@ -18,6 +18,21 @@
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
|
||||
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 {
|
||||
public:
|
||||
explicit HexagonInstPrinter(MCAsmInfo const &MAI,
|
||||
@ -74,11 +89,11 @@ namespace llvm {
|
||||
void printSymbol(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool hi)
|
||||
const;
|
||||
|
||||
static const char PacketPadding;
|
||||
|
||||
private:
|
||||
const MCInstrInfo &MII;
|
||||
|
||||
bool HasExtender;
|
||||
void setExtender(MCInst const &MCI);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -32,16 +32,6 @@ using namespace Hexagon;
|
||||
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
||||
|
||||
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) {
|
||||
OS << static_cast<uint8_t>((Binary >> 0x00) & 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,
|
||||
MCContext &aMCT)
|
||||
: 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,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
MCSubtargetInfo const &STI) const {
|
||||
uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI) | getPacketBits(MI);
|
||||
assert(HexagonMCInstrInfo::getDesc(MCII, MI).getSize() == 4 &&
|
||||
"All instructions should be 32bit");
|
||||
(void)&MCII;
|
||||
MCInst &HMB = const_cast<MCInst &>(MI);
|
||||
|
||||
assert(HexagonMCInstrInfo::isBundle(HMB));
|
||||
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);
|
||||
++MCNumEmitted;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ class HexagonMCCodeEmitter : public MCCodeEmitter {
|
||||
MCInstrInfo const &MCII;
|
||||
std::unique_ptr<unsigned> Addend;
|
||||
std::unique_ptr<bool> Extended;
|
||||
std::unique_ptr<MCInst const *> CurrentBundle;
|
||||
|
||||
// helper routine for getMachineOpValue()
|
||||
unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
@ -39,12 +40,21 @@ class HexagonMCCodeEmitter : public MCCodeEmitter {
|
||||
public:
|
||||
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;
|
||||
|
||||
void encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
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
|
||||
// binary encoding for an instruction.
|
||||
uint64_t getBinaryCodeForInstr(MCInst const &MI,
|
||||
|
@ -11,13 +11,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonMCInstrInfo.h"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonBaseInfo.h"
|
||||
#include "HexagonMCInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
void HexagonMCInstrInfo::AppendImplicitOperands(MCInst &MCI) {
|
||||
MCI.addOperand(MCOperand::createImm(0));
|
||||
MCI.addOperand(MCOperand::createInst(nullptr));
|
||||
iterator_range<MCInst::const_iterator>
|
||||
HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) {
|
||||
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
|
||||
@ -58,12 +68,6 @@ unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII,
|
||||
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
|
||||
// without being extended.
|
||||
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
|
||||
@ -99,8 +103,13 @@ char const *HexagonMCInstrInfo::getName(MCInstrInfo const &MCII,
|
||||
return MCII.getName(MCI.getOpcode());
|
||||
}
|
||||
|
||||
// Return the operand that consumes or produces a new value.
|
||||
MCOperand const &HexagonMCInstrInfo::getNewValue(MCInstrInfo const &MCII,
|
||||
unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
|
||||
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;
|
||||
unsigned const O =
|
||||
@ -128,6 +137,12 @@ bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
|
||||
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.
|
||||
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return (!HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
|
||||
@ -187,6 +202,18 @@ bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII,
|
||||
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.
|
||||
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
@ -203,14 +230,23 @@ bool HexagonMCInstrInfo::isOperandExtended(MCInstrInfo const &MCII,
|
||||
OperandNum;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isPacketBegin(MCInst const &MCI) {
|
||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
||||
return Bits.test(packetBeginIndex);
|
||||
bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) {
|
||||
assert(isBundle(MCI));
|
||||
int64_t Flags = MCI.getOperand(0).getImm();
|
||||
return (Flags & outerLoopMask) != 0;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isPacketEnd(MCInst const &MCI) {
|
||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
||||
return Bits.test(packetEndIndex);
|
||||
bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
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.
|
||||
@ -224,25 +260,26 @@ bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
|
||||
}
|
||||
|
||||
void HexagonMCInstrInfo::resetPacket(MCInst &MCI) {
|
||||
setPacketBegin(MCI, false);
|
||||
setPacketEnd(MCI, false);
|
||||
void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {
|
||||
MCInst Nop;
|
||||
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) {
|
||||
SanityCheckImplicitOperands(MCI);
|
||||
MCI.getOperand(MCI.getNumOperands() - 2).setImm(Bits.to_ulong());
|
||||
void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) {
|
||||
assert(isBundle(MCI));
|
||||
MCOperand &Operand = MCI.getOperand(0);
|
||||
Operand.setImm(Operand.getImm() | innerLoopMask);
|
||||
}
|
||||
|
||||
void HexagonMCInstrInfo::setPacketBegin(MCInst &MCI, bool f) {
|
||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
||||
Bits.set(packetBeginIndex, f);
|
||||
SetImplicitBits(MCI, Bits);
|
||||
}
|
||||
|
||||
void HexagonMCInstrInfo::setPacketEnd(MCInst &MCI, bool f) {
|
||||
std::bitset<16> Bits(GetImplicitBits(MCI));
|
||||
Bits.set(packetEndIndex, f);
|
||||
SetImplicitBits(MCI, Bits);
|
||||
void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
|
||||
assert(isBundle(MCI));
|
||||
MCOperand &Operand = MCI.getOperand(0);
|
||||
Operand.setImm(Operand.getImm() | outerLoopMask);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,19 @@ namespace HexagonII {
|
||||
enum class MemAccessSize;
|
||||
}
|
||||
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
|
||||
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
|
||||
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
|
||||
// without being extended.
|
||||
int getMaxValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
@ -61,8 +71,11 @@ int getMinValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
// Return instruction name
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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,
|
||||
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.
|
||||
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.
|
||||
bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
static const size_t packetBeginIndex = 0;
|
||||
static const size_t packetEndIndex = 1;
|
||||
// Pad the bundle with nops to satisfy endloop requirements
|
||||
void padEndloop(MCInst &MCI);
|
||||
|
||||
void resetPacket(MCInst &MCI);
|
||||
// Marks a bundle as endloop0
|
||||
void setInnerLoop(MCInst &MCI);
|
||||
|
||||
inline void SanityCheckImplicitOperands(MCInst const &MCI) {
|
||||
assert(MCI.getNumOperands() >= 2 && "At least the two implicit operands");
|
||||
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);
|
||||
// Marks a bundle as endloop1
|
||||
void setOuterLoop(MCInst &MCI);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; XFAIL:
|
||||
|
||||
; Check that the packetizer generates valid packets with constant
|
||||
; extended instructions.
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; XFAIL:
|
||||
; Check that the packetizer generates valid packets with constant
|
||||
; extended add and base+offset store instructions.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
;; 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)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a, i32 %b)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a, i32 %b)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a, i32 %b)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a)
|
||||
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: | llvm-objdump -s - | FileCheck %s
|
||||
;; RUN: | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
define i1 @foo (i32 %a, i32 %b)
|
||||
{
|
||||
@ -7,4 +7,6 @@ define i1 @foo (i32 %a, i32 %b)
|
||||
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 {
|
||||
public:
|
||||
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,
|
||||
raw_ostream &OS, StringRef Annot,
|
||||
MCSubtargetInfo const &STI) {
|
||||
@ -218,8 +218,66 @@ public:
|
||||
}
|
||||
};
|
||||
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) {
|
||||
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),
|
||||
SectionAddr + Index, DebugOut,
|
||||
CommentStream)) {
|
||||
PIP.printInst(*IP, &Inst, !NoShowRawInsn,
|
||||
PIP.printInst(*IP, &Inst,
|
||||
Bytes.slice(Index, Size),
|
||||
SectionAddr + Index, outs(), "", *STI);
|
||||
outs() << CommentStream.str();
|
||||
|
Loading…
Reference in New Issue
Block a user