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