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    Separator = " ";
83    MCInst ME;
84    ME.setOpcode(Hexagon::ENDLOOP1);
85    printInstruction(&ME, OS);
86  }
87}
88
89void 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
108void HexagonInstPrinter::printExtOperand(MCInst const *MI, unsigned OpNo,
109                                         raw_ostream &O) const {
110  printOperand(MI, OpNo, O);
111}
112
113void HexagonInstPrinter::printUnsignedImmOperand(MCInst const *MI,
114                                                 unsigned OpNo,
115                                                 raw_ostream &O) const {
116  O << MI->getOperand(OpNo).getImm();
117}
118
119void HexagonInstPrinter::printNegImmOperand(MCInst const *MI, unsigned OpNo,
120                                            raw_ostream &O) const {
121  O << -MI->getOperand(OpNo).getImm();
122}
123
124void HexagonInstPrinter::printNOneImmOperand(MCInst const *MI, unsigned OpNo,
125                                             raw_ostream &O) const {
126  O << -1;
127}
128
129void 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
139void 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
149void 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
159void 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
169void HexagonInstPrinter::printGlobalOperand(MCInst const *MI, unsigned OpNo,
170                                            raw_ostream &O) const {
171  printOperand(MI, OpNo, O);
172}
173
174void 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
181void 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
188void 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
195void HexagonInstPrinter::printCallOperand(MCInst const *MI, unsigned OpNo,
196                                          raw_ostream &O) const {}
197
198void HexagonInstPrinter::printAbsAddrOperand(MCInst const *MI, unsigned OpNo,
199                                             raw_ostream &O) const {}
200
201void HexagonInstPrinter::printPredicateOperand(MCInst const *MI, unsigned OpNo,
202                                               raw_ostream &O) const {}
203
204void 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
219void 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