[Hexagon] Disassembling, printing, and emitting instructions a whole-bundle at a...
[oota-llvm.git] / lib / Target / Hexagon / MCTargetDesc / HexagonInstPrinter.cpp
1 //===- HexagonInstPrinter.cpp - Convert Hexagon MCInst to assembly syntax -===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an Hexagon MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "HexagonAsmPrinter.h"
15 #include "Hexagon.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"
23
24 using namespace llvm;
25
26 #define DEBUG_TYPE "asm-printer"
27
28 #define GET_INSTRUCTION_NAME
29 #include "HexagonGenAsmWriter.inc"
30
31 HexagonAsmInstPrinter::HexagonAsmInstPrinter(MCInstPrinter *RawPrinter)
32     : MCInstPrinter(*RawPrinter), RawPrinter(RawPrinter) {}
33
34 void HexagonAsmInstPrinter::printInst(MCInst const *MI, raw_ostream &O,
35                                       StringRef Annot,
36                                       MCSubtargetInfo const &STI) {
37   assert(HexagonMCInstrInfo::isBundle(*MI));
38   assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
39   std::string Buffer;
40   {
41     raw_string_ostream TempStream(Buffer);
42     RawPrinter->printInst(MI, TempStream, "", STI);
43   }
44   StringRef Contents(Buffer);
45   auto PacketBundle = Contents.rsplit('\n');
46   auto HeadTail = PacketBundle.first.split('\n');
47   auto Preamble = "\t{\n\t\t";
48   auto Separator = "";
49   while(!HeadTail.first.empty()) {
50     O << Separator;
51     StringRef Inst;
52     auto Duplex = HeadTail.first.split('\v');
53     if(!Duplex.second.empty()){
54       O << Duplex.first << "\n";
55       Inst = Duplex.second;
56     }
57     else
58       Inst = Duplex.first;
59     O << Preamble;
60     O << Inst;
61     HeadTail = HeadTail.second.split('\n');
62     Preamble = "";
63     Separator = "\n\t\t";
64   }
65   O << "\n\t}" << PacketBundle.second;
66 }
67
68 void HexagonAsmInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
69   RawPrinter->printRegName(O, RegNo);
70 }
71
72 // Return the minimum value that a constant extendable operand can have
73 // without being extended.
74 static int getMinValue(uint64_t TSFlags) {
75   unsigned isSigned =
76       (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
77   unsigned bits =
78       (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
79
80   if (isSigned)
81     return -1U << (bits - 1);
82
83   return 0;
84 }
85
86 // Return the maximum value that a constant extendable operand can have
87 // without being extended.
88 static int getMaxValue(uint64_t TSFlags) {
89   unsigned isSigned =
90       (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
91   unsigned bits =
92       (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
93
94   if (isSigned)
95     return ~(-1U << (bits - 1));
96
97   return ~(-1U << bits);
98 }
99
100 // Return true if the instruction must be extended.
101 static bool isExtended(uint64_t TSFlags) {
102   return (TSFlags >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
103 }
104
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;
110 }
111
112 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
113   return MII.getName(Opcode);
114 }
115
116 void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
117   OS << getRegisterName(RegNo);
118 }
119
120 void HexagonInstPrinter::setExtender(MCInst const &MCI) {
121   HasExtender = HexagonMCInstrInfo::isImmext(MCI);
122 }
123
124 void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &OS,
125                                    StringRef Annot,
126                                    MCSubtargetInfo const &STI) {
127   assert(HexagonMCInstrInfo::isBundle(*MI));
128   assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
129   HasExtender = false;
130   for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
131     MCInst const &MCI = *I.getInst();
132     printInstruction(&MCI, OS);
133     setExtender(MCI);
134     OS << "\n";
135   }
136
137   auto Separator = "";
138   if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
139     OS << Separator;
140     Separator = " ";
141     MCInst ME;
142     ME.setOpcode(Hexagon::ENDLOOP0);
143     printInstruction(&ME, OS);
144   }
145   if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
146     OS << Separator;
147     Separator = " ";
148     MCInst ME;
149     ME.setOpcode(Hexagon::ENDLOOP1);
150     printInstruction(&ME, OS);
151   }
152 }
153
154 void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
155                                       raw_ostream &O) const {
156   const MCOperand& MO = MI->getOperand(OpNo);
157
158   if (MO.isReg()) {
159     printRegName(O, MO.getReg());
160   } else if(MO.isExpr()) {
161     O << *MO.getExpr();
162   } else if(MO.isImm()) {
163     printImmOperand(MI, OpNo, O);
164   } else {
165     llvm_unreachable("Unknown operand");
166   }
167 }
168
169 void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
170                                          raw_ostream &O) const {
171   const MCOperand& MO = MI->getOperand(OpNo);
172
173   if(MO.isExpr()) {
174     O << *MO.getExpr();
175   } else if(MO.isImm()) {
176     O << MI->getOperand(OpNo).getImm();
177   } else {
178     llvm_unreachable("Unknown operand");
179   }
180 }
181
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());
186
187   assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
188          "Expecting an extendable operand");
189
190   if (MO.isExpr() || isExtended(MII.TSFlags)) {
191     O << "#";
192   } else if (MO.isImm()) {
193     int ImmValue = MO.getImm();
194     if (ImmValue < getMinValue(MII.TSFlags) ||
195         ImmValue > getMaxValue(MII.TSFlags))
196       O << "#";
197   }
198   printOperand(MI, OpNo, O);
199 }
200
201 void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
202                                     unsigned OpNo, raw_ostream &O) const {
203   O << MI->getOperand(OpNo).getImm();
204 }
205
206 void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
207                                             raw_ostream &O) const {
208   O << -MI->getOperand(OpNo).getImm();
209 }
210
211 void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
212                                              raw_ostream &O) const {
213   O << -1;
214 }
215
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);
220
221   printRegName(O, MO0.getReg());
222   O << " + #" << MO1.getImm();
223 }
224
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);
229
230   printRegName(O, MO0.getReg());
231   O << ", #" << MO1.getImm();
232 }
233
234 void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo,
235                                             raw_ostream &O) const {
236   assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
237
238   printOperand(MI, OpNo, O);
239 }
240
241 void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo,
242                                         raw_ostream &O) const {
243   assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
244
245   printOperand(MI, OpNo, O);
246 }
247
248 void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo,
249                                            raw_ostream &O) const {
250   assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
251
252   printOperand(MI, OpNo, O);
253 }
254
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.");
260 }
261
262 void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo,
263                                           raw_ostream &O) const {
264 }
265
266 void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
267                                              raw_ostream &O) const {
268 }
269
270 void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
271                                                raw_ostream &O) const {
272 }
273
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");
277
278   O << '#' << (hi ? "HI" : "LO") << "(#";
279   printOperand(MI, OpNo, O);
280   O << ')';
281 }
282
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());
287
288   assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
289          "Expecting an extendable operand");
290
291   if (MO.isExpr() || isExtended(MII.TSFlags)) {
292     O << "##";
293   }
294   printOperand(MI, OpNo, O);
295 }