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
24using namespace llvm;
25
26#define DEBUG_TYPE "asm-printer"
27
28#define GET_INSTRUCTION_NAME
29#include "HexagonGenAsmWriter.inc"
30
31HexagonInstPrinter::HexagonInstPrinter(MCAsmInfo const &MAI,
32                                       MCInstrInfo const &MII,
33                                       MCRegisterInfo const &MRI)
34    : MCInstPrinter(MAI, MII, MRI), MII(MII), HasExtender(false) {
35}
36
37StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
38  return MII.getName(Opcode);
39}
40
41void HexagonInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
42  O << getRegName(RegNo);
43}
44
45StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const {
46  return getRegisterName(RegNo);
47}
48
49void HexagonInstPrinter::setExtender(MCInst const &MCI) {
50  HasExtender = HexagonMCInstrInfo::isImmext(MCI);
51}
52
53void 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    MCInst ME;
83    ME.setOpcode(Hexagon::ENDLOOP1);
84    printInstruction(&ME, OS);
85  }
86}
87
88void HexagonInstPrinter::printOperand(MCInst const *MI, unsigned OpNo,
89                                      raw_ostream &O) const {
90  if (HexagonMCInstrInfo::getExtendableOp(MII, *MI) == OpNo &&
91      (HasExtender || HexagonMCInstrInfo::isConstExtended(MII, *MI)))
92    O << "#";
93  MCOperand const &MO = MI->getOperand(OpNo);
94  if (MO.isReg()) {
95    O << getRegisterName(MO.getReg());
96  } else if (MO.isExpr()) {
97    int64_t Value;
98    if (MO.getExpr()->evaluateAsAbsolute(Value))
99      O << formatImm(Value);
100    else
101      O << *MO.getExpr();
102  } else {
103    llvm_unreachable("Unknown operand");
104  }
105}
106
107void HexagonInstPrinter::printExtOperand(MCInst const *MI, unsigned OpNo,
108                                         raw_ostream &O) const {
109  printOperand(MI, OpNo, O);
110}
111
112void HexagonInstPrinter::printUnsignedImmOperand(MCInst const *MI,
113                                                 unsigned OpNo,
114                                                 raw_ostream &O) const {
115  O << MI->getOperand(OpNo).getImm();
116}
117
118void HexagonInstPrinter::printNegImmOperand(MCInst const *MI, unsigned OpNo,
119                                            raw_ostream &O) const {
120  O << -MI->getOperand(OpNo).getImm();
121}
122
123void HexagonInstPrinter::printNOneImmOperand(MCInst const *MI, unsigned OpNo,
124                                             raw_ostream &O) const {
125  O << -1;
126}
127
128void HexagonInstPrinter::prints3_6ImmOperand(MCInst const *MI, unsigned OpNo,
129                                             raw_ostream &O) const {
130  int64_t Imm;
131  bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
132  Imm = SignExtend64<9>(Imm);
133  assert(Success); (void)Success;
134  assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
135  O << formatImm(Imm/64);
136}
137
138void HexagonInstPrinter::prints3_7ImmOperand(MCInst const *MI, unsigned OpNo,
139                                             raw_ostream &O) const {
140  int64_t Imm;
141  bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
142  Imm = SignExtend64<10>(Imm);
143  assert(Success); (void)Success;
144  assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
145  O << formatImm(Imm/128);
146}
147
148void HexagonInstPrinter::prints4_6ImmOperand(MCInst const *MI, unsigned OpNo,
149                                             raw_ostream &O) const {
150  int64_t Imm;
151  bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
152  Imm = SignExtend64<10>(Imm);
153  assert(Success); (void)Success;
154  assert(((Imm & 0x3f) == 0) && "Lower 6 bits must be ZERO.");
155  O << formatImm(Imm/64);
156}
157
158void HexagonInstPrinter::prints4_7ImmOperand(MCInst const *MI, unsigned OpNo,
159                                             raw_ostream &O) const {
160  int64_t Imm;
161  bool Success = MI->getOperand(OpNo).getExpr()->evaluateAsAbsolute(Imm);
162  Imm = SignExtend64<11>(Imm);
163  assert(Success); (void)Success;
164  assert(((Imm & 0x7f) == 0) && "Lower 7 bits must be ZERO.");
165  O << formatImm(Imm/128);
166}
167
168void HexagonInstPrinter::printGlobalOperand(MCInst const *MI, unsigned OpNo,
169                                            raw_ostream &O) const {
170  printOperand(MI, OpNo, O);
171}
172
173void HexagonInstPrinter::printJumpTable(MCInst const *MI, unsigned OpNo,
174                                        raw_ostream &O) const {
175  assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
176
177  printOperand(MI, OpNo, O);
178}
179
180void HexagonInstPrinter::printConstantPool(MCInst const *MI, unsigned OpNo,
181                                           raw_ostream &O) const {
182  assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
183
184  printOperand(MI, OpNo, O);
185}
186
187void HexagonInstPrinter::printBranchOperand(MCInst const *MI, unsigned OpNo,
188                                            raw_ostream &O) const {
189  // Branches can take an immediate operand.  This is used by the branch
190  // selection pass to print $+8, an eight byte displacement from the PC.
191  llvm_unreachable("Unknown branch operand.");
192}
193
194void HexagonInstPrinter::printCallOperand(MCInst const *MI, unsigned OpNo,
195                                          raw_ostream &O) const {}
196
197void HexagonInstPrinter::printAbsAddrOperand(MCInst const *MI, unsigned OpNo,
198                                             raw_ostream &O) const {}
199
200void HexagonInstPrinter::printPredicateOperand(MCInst const *MI, unsigned OpNo,
201                                               raw_ostream &O) const {}
202
203void HexagonInstPrinter::printSymbol(MCInst const *MI, unsigned OpNo,
204                                     raw_ostream &O, bool hi) const {
205  assert(MI->getOperand(OpNo).isImm() && "Unknown symbol operand");
206
207  O << '#' << (hi ? "HI" : "LO") << '(';
208  O << '#';
209  printOperand(MI, OpNo, O);
210  O << ')';
211}
212
213void HexagonInstPrinter::printBrtarget(MCInst const *MI, unsigned OpNo,
214                                       raw_ostream &O) const {
215  MCOperand const &MO = MI->getOperand(OpNo);
216  assert (MO.isExpr());
217  MCExpr const &Expr = *MO.getExpr();
218  int64_t Value;
219  if (Expr.evaluateAsAbsolute(Value))
220    O << format("0x%" PRIx64, Value);
221  else {
222    if (HasExtender || HexagonMCInstrInfo::isConstExtended(MII, *MI))
223      if (HexagonMCInstrInfo::getExtendableOp(MII, *MI) == OpNo)
224        O << "##";
225    O << Expr;
226  }
227}
228