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 "HexagonInstPrinter.h"
16 #include "MCTargetDesc/HexagonBaseInfo.h"
17 #include "MCTargetDesc/HexagonMCInstrInfo.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/Support/Debug.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 
HexagonInstPrinter(MCAsmInfo const & MAI,MCInstrInfo const & MII,MCRegisterInfo const & MRI)31 HexagonInstPrinter::HexagonInstPrinter(MCAsmInfo const &MAI,
32                                        MCInstrInfo const &MII,
33                                        MCRegisterInfo const &MRI)
34     : MCInstPrinter(MAI, MII, MRI), MII(MII), HasExtender(false) {
35 }
36 
getOpcodeName(unsigned Opcode) const37 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
38   return MII.getName(Opcode);
39 }
40 
printRegName(raw_ostream & O,unsigned RegNo) const41 void HexagonInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
42   O << getRegName(RegNo);
43 }
44 
getRegName(unsigned RegNo) const45 StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const {
46   return getRegisterName(RegNo);
47 }
48 
setExtender(MCInst const & MCI)49 void HexagonInstPrinter::setExtender(MCInst const &MCI) {
50   HasExtender = HexagonMCInstrInfo::isImmext(MCI);
51 }
52 
printInst(const MCInst * MI,raw_ostream & OS,StringRef Annot,const MCSubtargetInfo & STI)53 void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
54                                    StringRef Annot, const MCSubtargetInfo &STI) {
55   assert(HexagonMCInstrInfo::isBundle(*MI));
56   assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
57   assert(HexagonMCInstrInfo::bundleSize(*MI) > 0);
58   HasExtender = false;
59   for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
60     MCInst const &MCI = *I.getInst();
61     if (HexagonMCInstrInfo::isDuplex(MII, MCI)) {
62       printInstruction(MCI.getOperand(1).getInst(), OS);
63       OS << '\v';
64       HasExtender = false;
65       printInstruction(MCI.getOperand(0).getInst(), OS);
66     } else
67       printInstruction(&MCI, OS);
68     setExtender(MCI);
69     OS << "\n";
70   }
71 
72   auto Separator = "";
73   if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
74     OS << Separator;
75     Separator = " ";
76     MCInst ME;
77     ME.setOpcode(Hexagon::ENDLOOP0);
78     printInstruction(&ME, OS);
79   }
80   if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
81     OS << Separator;
82     Separator = " ";
83     MCInst ME;
84     ME.setOpcode(Hexagon::ENDLOOP1);
85     printInstruction(&ME, OS);
86   }
87 }
88 
printOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const89 void HexagonInstPrinter::printOperand(MCInst const *MI, unsigned OpNo,
90                                       raw_ostream &O) const {
91   if (HexagonMCInstrInfo::getExtendableOp(MII, *MI) == OpNo &&
92       (HasExtender || HexagonMCInstrInfo::isConstExtended(MII, *MI)))
93     O << "#";
94   MCOperand const &MO = MI->getOperand(OpNo);
95   if (MO.isReg()) {
96     O << getRegisterName(MO.getReg());
97   } else if (MO.isExpr()) {
98     int64_t Value;
99     if (MO.getExpr()->evaluateAsAbsolute(Value))
100       O << formatImm(Value);
101     else
102       O << *MO.getExpr();
103   } else {
104     llvm_unreachable("Unknown operand");
105   }
106 }
107 
printExtOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const108 void HexagonInstPrinter::printExtOperand(MCInst const *MI, unsigned OpNo,
109                                          raw_ostream &O) const {
110   printOperand(MI, OpNo, O);
111 }
112 
printUnsignedImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const113 void HexagonInstPrinter::printUnsignedImmOperand(MCInst const *MI,
114                                                  unsigned OpNo,
115                                                  raw_ostream &O) const {
116   O << MI->getOperand(OpNo).getImm();
117 }
118 
printNegImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const119 void HexagonInstPrinter::printNegImmOperand(MCInst const *MI, unsigned OpNo,
120                                             raw_ostream &O) const {
121   O << -MI->getOperand(OpNo).getImm();
122 }
123 
printNOneImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const124 void HexagonInstPrinter::printNOneImmOperand(MCInst const *MI, unsigned OpNo,
125                                              raw_ostream &O) const {
126   O << -1;
127 }
128 
prints3_6ImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const129 void HexagonInstPrinter::prints3_6ImmOperand(MCInst const *MI, unsigned OpNo,
130                                              raw_ostream &O) const {
131   int64_t Imm;
132   bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
133   Imm = SignExtend64<9>(Imm);
134   assert(Success); (void)Success;
135   assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
136   O << formatImm(Imm/64);
137 }
138 
prints3_7ImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const139 void HexagonInstPrinter::prints3_7ImmOperand(MCInst const *MI, unsigned OpNo,
140                                              raw_ostream &O) const {
141   int64_t Imm;
142   bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
143   Imm = SignExtend64<10>(Imm);
144   assert(Success); (void)Success;
145   assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
146   O << formatImm(Imm/128);
147 }
148 
prints4_6ImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const149 void HexagonInstPrinter::prints4_6ImmOperand(MCInst const *MI, unsigned OpNo,
150                                              raw_ostream &O) const {
151   int64_t Imm;
152   bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
153   Imm = SignExtend64<10>(Imm);
154   assert(Success); (void)Success;
155   assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
156   O << formatImm(Imm/64);
157 }
158 
prints4_7ImmOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const159 void HexagonInstPrinter::prints4_7ImmOperand(MCInst const *MI, unsigned OpNo,
160                                              raw_ostream &O) const {
161   int64_t Imm;
162   bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
163   Imm = SignExtend64<11>(Imm);
164   assert(Success); (void)Success;
165   assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
166   O << formatImm(Imm/128);
167 }
168 
printGlobalOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const169 void HexagonInstPrinter::printGlobalOperand(MCInst const *MI, unsigned OpNo,
170                                             raw_ostream &O) const {
171   printOperand(MI, OpNo, O);
172 }
173 
printJumpTable(MCInst const * MI,unsigned OpNo,raw_ostream & O) const174 void HexagonInstPrinter::printJumpTable(MCInst const *MI, unsigned OpNo,
175                                         raw_ostream &O) const {
176   assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
177 
178   printOperand(MI, OpNo, O);
179 }
180 
printConstantPool(MCInst const * MI,unsigned OpNo,raw_ostream & O) const181 void HexagonInstPrinter::printConstantPool(MCInst const *MI, unsigned OpNo,
182                                            raw_ostream &O) const {
183   assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
184 
185   printOperand(MI, OpNo, O);
186 }
187 
printBranchOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const188 void HexagonInstPrinter::printBranchOperand(MCInst const *MI, unsigned OpNo,
189                                             raw_ostream &O) const {
190   // Branches can take an immediate operand.  This is used by the branch
191   // selection pass to print $+8, an eight byte displacement from the PC.
192   llvm_unreachable("Unknown branch operand.");
193 }
194 
printCallOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const195 void HexagonInstPrinter::printCallOperand(MCInst const *MI, unsigned OpNo,
196                                           raw_ostream &O) const {}
197 
printAbsAddrOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const198 void HexagonInstPrinter::printAbsAddrOperand(MCInst const *MI, unsigned OpNo,
199                                              raw_ostream &O) const {}
200 
printPredicateOperand(MCInst const * MI,unsigned OpNo,raw_ostream & O) const201 void HexagonInstPrinter::printPredicateOperand(MCInst const *MI, unsigned OpNo,
202                                                raw_ostream &O) const {}
203 
printSymbol(MCInst const * MI,unsigned OpNo,raw_ostream & O,bool hi) const204 void HexagonInstPrinter::printSymbol(MCInst const *MI, unsigned OpNo,
205                                      raw_ostream &O, bool hi) const {
206   MCOperand const &MO = MI->getOperand(OpNo);
207 
208   O << '#' << (hi ? "HI" : "LO") << '(';
209   if (MO.isImm()) {
210     O << '#';
211     printOperand(MI, OpNo, O);
212   } else {
213     printOperand(MI, OpNo, O);
214     assert("Unknown symbol operand");
215   }
216   O << ')';
217 }
218 
printBrtarget(MCInst const * MI,unsigned OpNo,raw_ostream & O) const219 void HexagonInstPrinter::printBrtarget(MCInst const *MI, unsigned OpNo,
220                                        raw_ostream &O) const {
221   MCOperand const &MO = MI->getOperand(OpNo);
222   assert (MO.isExpr());
223   MCExpr const &Expr = *MO.getExpr();
224   int64_t Value;
225   if (Expr.evaluateAsAbsolute(Value))
226     O << format("0x%" PRIx64, Value);
227   else {
228     if (HasExtender || HexagonMCInstrInfo::isConstExtended(MII, *MI))
229       if (HexagonMCInstrInfo::getExtendableOp(MII, *MI) == OpNo)
230         O << "##";
231     O << Expr;
232   }
233 }
234