1 //===- HexagonInstPrinter.cpp - Convert Hexagon MCInst to assembly syntax -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class prints an Hexagon MCInst to a .s file.
12 //===----------------------------------------------------------------------===//
14 #include "HexagonAsmPrinter.h"
16 #include "HexagonInstPrinter.h"
17 #include "MCTargetDesc/HexagonMCInstrInfo.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"
26 #define DEBUG_TYPE "asm-printer"
28 #define GET_INSTRUCTION_NAME
29 #include "HexagonGenAsmWriter.inc"
31 // Return the minimum value that a constant extendable operand can have
32 // without being extended.
33 static int getMinValue(uint64_t TSFlags) {
35 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
37 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
40 return -1U << (bits - 1);
45 // Return the maximum value that a constant extendable operand can have
46 // without being extended.
47 static int getMaxValue(uint64_t TSFlags) {
49 (TSFlags >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
51 (TSFlags >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
54 return ~(-1U << (bits - 1));
56 return ~(-1U << bits);
59 // Return true if the instruction must be extended.
60 static bool isExtended(uint64_t TSFlags) {
61 return (TSFlags >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
64 // Currently just used in an assert statement
65 static bool isExtendable(uint64_t TSFlags) LLVM_ATTRIBUTE_UNUSED;
66 // Return true if the instruction may be extended based on the operand value.
67 static bool isExtendable(uint64_t TSFlags) {
68 return (TSFlags >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
71 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
72 return MII.getName(Opcode);
75 void HexagonInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
76 OS << getRegisterName(RegNo);
79 void HexagonInstPrinter::setExtender(MCInst const &MCI) {
80 HasExtender = HexagonMCInstrInfo::isImmext(MCI);
83 void HexagonInstPrinter::printInst(MCInst const *MI, raw_ostream &OS,
85 MCSubtargetInfo const &STI) {
86 assert(HexagonMCInstrInfo::isBundle(*MI));
87 assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE);
89 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) {
90 MCInst const &MCI = *I.getInst();
91 if (HexagonMCInstrInfo::isDuplex(MII, MCI)) {
92 printInstruction(MCI.getOperand(1).getInst(), OS);
95 printInstruction(MCI.getOperand(0).getInst(), OS);
97 printInstruction(&MCI, OS);
103 if (HexagonMCInstrInfo::isInnerLoop(*MI)) {
107 ME.setOpcode(Hexagon::ENDLOOP0);
108 printInstruction(&ME, OS);
110 if (HexagonMCInstrInfo::isOuterLoop(*MI)) {
114 ME.setOpcode(Hexagon::ENDLOOP1);
115 printInstruction(&ME, OS);
119 void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
120 raw_ostream &O) const {
121 const MCOperand& MO = MI->getOperand(OpNo);
124 printRegName(O, MO.getReg());
125 } else if(MO.isExpr()) {
126 MO.getExpr()->print(O, &MAI);
127 } else if(MO.isImm()) {
128 printImmOperand(MI, OpNo, O);
130 llvm_unreachable("Unknown operand");
134 void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
135 raw_ostream &O) const {
136 const MCOperand& MO = MI->getOperand(OpNo);
139 MO.getExpr()->print(O, &MAI);
140 } else if(MO.isImm()) {
141 O << MI->getOperand(OpNo).getImm();
143 llvm_unreachable("Unknown operand");
147 void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
148 raw_ostream &O) const {
149 const MCOperand &MO = MI->getOperand(OpNo);
150 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
152 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
153 "Expecting an extendable operand");
155 if (MO.isExpr() || isExtended(MII.TSFlags)) {
157 } else if (MO.isImm()) {
158 int ImmValue = MO.getImm();
159 if (ImmValue < getMinValue(MII.TSFlags) ||
160 ImmValue > getMaxValue(MII.TSFlags))
163 printOperand(MI, OpNo, O);
166 void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
167 unsigned OpNo, raw_ostream &O) const {
168 O << MI->getOperand(OpNo).getImm();
171 void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
172 raw_ostream &O) const {
173 O << -MI->getOperand(OpNo).getImm();
176 void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
177 raw_ostream &O) const {
181 void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo,
182 raw_ostream &O) const {
183 const MCOperand& MO0 = MI->getOperand(OpNo);
184 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
186 printRegName(O, MO0.getReg());
187 O << " + #" << MO1.getImm();
190 void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
191 raw_ostream &O) const {
192 const MCOperand& MO0 = MI->getOperand(OpNo);
193 const MCOperand& MO1 = MI->getOperand(OpNo + 1);
195 printRegName(O, MO0.getReg());
196 O << ", #" << MO1.getImm();
199 void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo,
200 raw_ostream &O) const {
201 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
203 printOperand(MI, OpNo, O);
206 void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo,
207 raw_ostream &O) const {
208 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
210 printOperand(MI, OpNo, O);
213 void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo,
214 raw_ostream &O) const {
215 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression");
217 printOperand(MI, OpNo, O);
220 void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
221 raw_ostream &O) const {
222 // Branches can take an immediate operand. This is used by the branch
223 // selection pass to print $+8, an eight byte displacement from the PC.
224 llvm_unreachable("Unknown branch operand.");
227 void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo,
228 raw_ostream &O) const {
231 void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
232 raw_ostream &O) const {
235 void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
236 raw_ostream &O) const {
239 void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo,
240 raw_ostream &O, bool hi) const {
241 assert(MI->getOperand(OpNo).isImm() && "Unknown symbol operand");
243 O << '#' << (hi ? "HI" : "LO") << "(#";
244 printOperand(MI, OpNo, O);
248 void HexagonInstPrinter::printExtBrtarget(const MCInst *MI, unsigned OpNo,
249 raw_ostream &O) const {
250 const MCOperand &MO = MI->getOperand(OpNo);
251 const MCInstrDesc &MII = getMII().get(MI->getOpcode());
253 assert((isExtendable(MII.TSFlags) || isExtended(MII.TSFlags)) &&
254 "Expecting an extendable operand");
256 if (MO.isExpr() || isExtended(MII.TSFlags)) {
259 printOperand(MI, OpNo, O);