1 //===- HexagonInstPrinter.cpp - Convert Hexagon MCInst to assembly syntax -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class prints an Hexagon MCInst to a .s file.
12 //===----------------------------------------------------------------------===//
14 #include "HexagonAsmPrinter.h"
16 #include "HexagonInstPrinter.h"
17 #include "MCTargetDesc/HexagonMCInstrInfo.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/Support/raw_ostream.h"
26 #define DEBUG_TYPE "asm-printer"
28 #define GET_INSTRUCTION_NAME
29 #include "HexagonGenAsmWriter.inc"
31 HexagonAsmInstPrinter::HexagonAsmInstPrinter(MCInstPrinter *RawPrinter)
32 : MCInstPrinter(*RawPrinter), RawPrinter(RawPrinter) {}
34 void HexagonAsmInstPrinter::printInst(MCInst const *MI, raw_ostream &O,
36 MCSubtargetInfo const &STI) {
37 assert(HexagonMCInstrInfo::isBundle(*MI));
38 assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
41 raw_string_ostream TempStream(Buffer);
42 RawPrinter->printInst(MI, TempStream, "", STI);
44 StringRef Contents(Buffer);
45 auto PacketBundle = Contents.rsplit('\n');
46 auto HeadTail = PacketBundle.first.split('\n');
47 auto Preamble = "\t{\n\t\t";
49 while(!HeadTail.first.empty()) {
52 auto Duplex = HeadTail.first.split('\v');
53 if(!Duplex.second.empty()){
54 O << Duplex.first << "\n";
61 HeadTail = HeadTail.second.split('\n');
65 O << "\n\t}" << PacketBundle.second;
68 void HexagonAsmInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
69 RawPrinter->printRegName(O, RegNo);
72 // Return the minimum value that a constant extendable operand can have
73 // without being extended.
74 static int getMinValue(uint64_t TSFlags) {
76 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
78 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
81 return -1U << (bits - 1);
86 // Return the maximum value that a constant extendable operand can have
87 // without being extended.
88 static int getMaxValue(uint64_t TSFlags) {
90 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
92 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
95 return ~(-1U << (bits - 1));
97 return ~(-1U << bits);
100 // Return true if the instruction must be extended.
101 static bool isExtended(uint64_t TSFlags) {
102 return (TSFlags >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
105 // Currently just used in an assert statement
106 static bool isExtendable(uint64_t TSFlags) LLVM_ATTRIBUTE_UNUSED;
107 // Return true if the instruction may be extended based on the operand value.
108 static bool isExtendable(uint64_t TSFlags) {
109 return (TSFlags >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
112 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
113 return MII.getName(Opcode);
116 void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
117 OS << getRegisterName(RegNo);
120 void HexagonInstPrinter::setExtender(MCInst const &MCI) {
121 HasExtender = HexagonMCInstrInfo::isImmext(MCI);
124 void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &OS,
126 MCSubtargetInfo const &STI) {
127 assert(HexagonMCInstrInfo::isBundle(*MI));
128 assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
130 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
131 MCInst const &MCI = *I.getInst();
132 printInstruction(&MCI, OS);
138 if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
142 ME.setOpcode(Hexagon::ENDLOOP0);
143 printInstruction(&ME, OS);
145 if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
149 ME.setOpcode(Hexagon::ENDLOOP1);
150 printInstruction(&ME, OS);
154 void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
155 raw_ostream &O) const {
156 const MCOperand& MO = MI->getOperand(OpNo);
159 printRegName(O, MO.getReg());
160 } else if(MO.isExpr()) {
162 } else if(MO.isImm()) {
163 printImmOperand(MI, OpNo, O);
165 llvm_unreachable("Unknown operand");
169 void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
170 raw_ostream &O) const {
171 const MCOperand& MO = MI->getOperand(OpNo);
175 } else if(MO.isImm()) {
176 O << MI->getOperand(OpNo).getImm();
178 llvm_unreachable("Unknown operand");
182 void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
183 raw_ostream &O) const {
184 const MCOperand &MO = MI->getOperand(OpNo);
185 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
187 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
188 "Expecting an extendable operand");
190 if (MO.isExpr() || isExtended(MII.TSFlags)) {
192 } else if (MO.isImm()) {
193 int ImmValue = MO.getImm();
194 if (ImmValue < getMinValue(MII.TSFlags) ||
195 ImmValue > getMaxValue(MII.TSFlags))
198 printOperand(MI, OpNo, O);
201 void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
202 unsigned OpNo, raw_ostream &O) const {
203 O << MI->getOperand(OpNo).getImm();
206 void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
207 raw_ostream &O) const {
208 O << -MI->getOperand(OpNo).getImm();
211 void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
212 raw_ostream &O) const {
216 void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo,
217 raw_ostream &O) const {
218 const MCOperand& MO0 = MI->getOperand(OpNo);
219 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
221 printRegName(O, MO0.getReg());
222 O << " + #" << MO1.getImm();
225 void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
226 raw_ostream &O) const {
227 const MCOperand& MO0 = MI->getOperand(OpNo);
228 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
230 printRegName(O, MO0.getReg());
231 O << ", #" << MO1.getImm();
234 void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo,
235 raw_ostream &O) const {
236 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
238 printOperand(MI, OpNo, O);
241 void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo,
242 raw_ostream &O) const {
243 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
245 printOperand(MI, OpNo, O);
248 void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo,
249 raw_ostream &O) const {
250 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
252 printOperand(MI, OpNo, O);
255 void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
256 raw_ostream &O) const {
257 // Branches can take an immediate operand. This is used by the branch
258 // selection pass to print $+8, an eight byte displacement from the PC.
259 llvm_unreachable("Unknown branch operand.");
262 void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo,
263 raw_ostream &O) const {
266 void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
267 raw_ostream &O) const {
270 void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
271 raw_ostream &O) const {
274 void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo,
275 raw_ostream &O, bool hi) const {
276 assert(MI->getOperand(OpNo).isImm() && "Unknown symbol operand");
278 O << '#' << (hi ? "HI" : "LO") << "(#";
279 printOperand(MI, OpNo, O);
283 void HexagonInstPrinter::printExtBrtarget(const MCInst *MI, unsigned OpNo,
284 raw_ostream &O) const {
285 const MCOperand &MO = MI->getOperand(OpNo);
286 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
288 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
289 "Expecting an extendable operand");
291 if (MO.isExpr() || isExtended(MII.TSFlags)) {
294 printOperand(MI, OpNo, O);