HexagonInstPrinter.cpp revision 263508
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#define DEBUG_TYPE "asm-printer"
15#include "HexagonAsmPrinter.h"
16#include "Hexagon.h"
17#include "HexagonInstPrinter.h"
18#include "MCTargetDesc/HexagonMCInst.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/MC/MCAsmInfo.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/Support/raw_ostream.h"
24
25using namespace llvm;
26
27#define GET_INSTRUCTION_NAME
28#include "HexagonGenAsmWriter.inc"
29
30const char HexagonInstPrinter::PacketPadding = '\t';
31
32StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
33  return MII.getName(Opcode);
34}
35
36StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const {
37  return getRegisterName(RegNo);
38}
39
40void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
41                                   StringRef Annot) {
42  printInst((const HexagonMCInst*)(MI), O, Annot);
43}
44
45void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O,
46                                   StringRef Annot) {
47  const char startPacket = '{',
48             endPacket = '}';
49  // TODO: add outer HW loop when it's supported too.
50  if (MI->getOpcode() == Hexagon::ENDLOOP0) {
51    // Ending a harware loop is different from ending an regular packet.
52    assert(MI->isPacketEnd() && "Loop-end must also end the packet");
53
54    if (MI->isPacketStart()) {
55      // There must be a packet to end a loop.
56      // FIXME: when shuffling is always run, this shouldn't be needed.
57      HexagonMCInst Nop;
58      StringRef NoAnnot;
59
60      Nop.setOpcode (Hexagon::NOP);
61      Nop.setPacketStart (MI->isPacketStart());
62      printInst (&Nop, O, NoAnnot);
63    }
64
65    // Close the packet.
66    if (MI->isPacketEnd())
67      O << PacketPadding << endPacket;
68
69    printInstruction(MI, O);
70  }
71  else {
72    // Prefix the insn opening the packet.
73    if (MI->isPacketStart())
74      O << PacketPadding << startPacket << '\n';
75
76    printInstruction(MI, O);
77
78    // Suffix the insn closing the packet.
79    if (MI->isPacketEnd())
80      // Suffix the packet in a new line always, since the GNU assembler has
81      // issues with a closing brace on the same line as CONST{32,64}.
82      O << '\n' << PacketPadding << endPacket;
83  }
84
85  printAnnotation(O, Annot);
86}
87
88void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
89                                      raw_ostream &O) const {
90  const MCOperand& MO = MI->getOperand(OpNo);
91
92  if (MO.isReg()) {
93    O << getRegisterName(MO.getReg());
94  } else if(MO.isExpr()) {
95    O << *MO.getExpr();
96  } else if(MO.isImm()) {
97    printImmOperand(MI, OpNo, O);
98  } else {
99    llvm_unreachable("Unknown operand");
100  }
101}
102
103void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
104                                         raw_ostream &O) const {
105  const MCOperand& MO = MI->getOperand(OpNo);
106
107  if(MO.isExpr()) {
108    O << *MO.getExpr();
109  } else if(MO.isImm()) {
110    O << MI->getOperand(OpNo).getImm();
111  } else {
112    llvm_unreachable("Unknown operand");
113  }
114}
115
116void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
117                                         raw_ostream &O) const {
118  const HexagonMCInst *HMCI = static_cast<const HexagonMCInst*>(MI);
119  if (HMCI->isConstExtended())
120    O << "#";
121  printOperand(MI, OpNo, O);
122}
123
124void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
125                                    unsigned OpNo, raw_ostream &O) const {
126  O << MI->getOperand(OpNo).getImm();
127}
128
129void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
130                                            raw_ostream &O) const {
131  O << -MI->getOperand(OpNo).getImm();
132}
133
134void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
135                                             raw_ostream &O) const {
136  O << -1;
137}
138
139void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo,
140                                           raw_ostream &O) const {
141  const MCOperand& MO0 = MI->getOperand(OpNo);
142  const MCOperand& MO1 = MI->getOperand(OpNo + 1);
143
144  O << getRegisterName(MO0.getReg());
145  O << " + #" << MO1.getImm();
146}
147
148void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
149                                                raw_ostream &O) const {
150  const MCOperand& MO0 = MI->getOperand(OpNo);
151  const MCOperand& MO1 = MI->getOperand(OpNo + 1);
152
153  O << getRegisterName(MO0.getReg()) << ", #" << MO1.getImm();
154}
155
156void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo,
157                                            raw_ostream &O) const {
158  assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
159
160  printOperand(MI, OpNo, O);
161}
162
163void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo,
164                                        raw_ostream &O) const {
165  assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
166
167  printOperand(MI, OpNo, O);
168}
169
170void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo,
171                                           raw_ostream &O) const {
172  assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
173
174  printOperand(MI, OpNo, O);
175}
176
177void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
178                                            raw_ostream &O) const {
179  // Branches can take an immediate operand.  This is used by the branch
180  // selection pass to print $+8, an eight byte displacement from the PC.
181  llvm_unreachable("Unknown branch operand.");
182}
183
184void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo,
185                                          raw_ostream &O) const {
186}
187
188void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
189                                             raw_ostream &O) const {
190}
191
192void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
193                                               raw_ostream &O) const {
194}
195
196void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo,
197                                     raw_ostream &O, bool hi) const {
198  assert(MI->getOperand(OpNo).isImm() && "Unknown symbol operand");
199
200  O << '#' << (hi ? "HI" : "LO") << "(#";
201  printOperand(MI, OpNo, O);
202  O << ')';
203}
204