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 "Hexagon.h" 16 #include "HexagonAsmPrinter.h" 17 #include "HexagonInstPrinter.h" 18 #include "HexagonMCInst.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCAsmInfo.h" 21 #include "llvm/MC/MCExpr.h" 22 #include "llvm/ADT/StringExtras.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <cstdio> 25 26 using namespace llvm; 27 28 #define GET_INSTRUCTION_NAME 29 #include "HexagonGenAsmWriter.inc" 30 31 StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const { 32 return MII.getName(Opcode); 33 } 34 35 StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const { 36 return getRegisterName(RegNo); 37 } 38 39 void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 40 StringRef Annot) { 41 printInst((const HexagonMCInst*)(MI), O, Annot); 42 } 43 44 void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O, 45 StringRef Annot) { 46 const char packetPadding[] = " "; 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->isEndPacket() && "Loop end must also end the packet"); 53 54 if (MI->isStartPacket()) { 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.setStartPacket (MI->isStartPacket()); 62 printInst (&Nop, O, NoAnnot); 63 } 64 65 // Close the packet. 66 if (MI->isEndPacket()) 67 O << packetPadding << endPacket; 68 69 printInstruction(MI, O); 70 } 71 else { 72 // Prefix the insn opening the packet. 73 if (MI->isStartPacket()) 74 O << packetPadding << startPacket << '\n'; 75 76 printInstruction(MI, O); 77 78 // Suffix the insn closing the packet. 79 if (MI->isEndPacket()) 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 88 void 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 103 void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo, 104 raw_ostream &O) const { 105 O << MI->getOperand(OpNo).getImm(); 106 } 107 108 void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo, 109 raw_ostream &O) const { 110 O << MI->getOperand(OpNo).getImm(); 111 } 112 113 void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI, 114 unsigned OpNo, raw_ostream &O) const { 115 O << MI->getOperand(OpNo).getImm(); 116 } 117 118 void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo, 119 raw_ostream &O) const { 120 O << -MI->getOperand(OpNo).getImm(); 121 } 122 123 void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo, 124 raw_ostream &O) const { 125 O << -1; 126 } 127 128 void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo, 129 raw_ostream &O) const { 130 const MCOperand& MO0 = MI->getOperand(OpNo); 131 const MCOperand& MO1 = MI->getOperand(OpNo + 1); 132 133 O << getRegisterName(MO0.getReg()); 134 O << " + #" << MO1.getImm(); 135 } 136 137 void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo, 138 raw_ostream &O) const { 139 const MCOperand& MO0 = MI->getOperand(OpNo); 140 const MCOperand& MO1 = MI->getOperand(OpNo + 1); 141 142 O << getRegisterName(MO0.getReg()) << ", #" << MO1.getImm(); 143 } 144 145 void HexagonInstPrinter::printGlobalOperand(const MCInst *MI, unsigned OpNo, 146 raw_ostream &O) const { 147 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); 148 149 printOperand(MI, OpNo, O); 150 } 151 152 void HexagonInstPrinter::printJumpTable(const MCInst *MI, unsigned OpNo, 153 raw_ostream &O) const { 154 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); 155 156 printOperand(MI, OpNo, O); 157 } 158 159 void HexagonInstPrinter::printConstantPool(const MCInst *MI, unsigned OpNo, 160 raw_ostream &O) const { 161 assert(MI->getOperand(OpNo).isExpr() && "Expecting expression"); 162 163 printOperand(MI, OpNo, O); 164 } 165 166 void HexagonInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, 167 raw_ostream &O) const { 168 // Branches can take an immediate operand. This is used by the branch 169 // selection pass to print $+8, an eight byte displacement from the PC. 170 assert("Unknown branch operand."); 171 } 172 173 void HexagonInstPrinter::printCallOperand(const MCInst *MI, unsigned OpNo, 174 raw_ostream &O) const { 175 } 176 177 void HexagonInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo, 178 raw_ostream &O) const { 179 } 180 181 void HexagonInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 182 raw_ostream &O) const { 183 } 184 185 void HexagonInstPrinter::printSymbol(const MCInst *MI, unsigned OpNo, 186 raw_ostream &O, bool hi) const { 187 const MCOperand& MO = MI->getOperand(OpNo); 188 189 O << '#' << (hi? "HI": "LO") << '('; 190 if (MO.isImm()) { 191 O << '#'; 192 printOperand(MI, OpNo, O); 193 } else { 194 assert("Unknown symbol operand"); 195 printOperand(MI, OpNo, O); 196 } 197 O << ')'; 198 } 199