1 //===-- SystemZInstPrinter.cpp - Convert SystemZ 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 #include "SystemZInstPrinter.h" 11 #include "llvm/MC/MCExpr.h" 12 #include "llvm/MC/MCInst.h" 13 #include "llvm/MC/MCInstrInfo.h" 14 #include "llvm/MC/MCSymbol.h" 15 #include "llvm/Support/ErrorHandling.h" 16 #include "llvm/Support/raw_ostream.h" 17 18 using namespace llvm; 19 20 #define DEBUG_TYPE "asm-printer" 21 22 #include "SystemZGenAsmWriter.inc" 23 24 void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp, 25 unsigned Index, raw_ostream &O) { 26 O << Disp; 27 if (Base || Index) { 28 O << '('; 29 if (Index) { 30 O << '%' << getRegisterName(Index); 31 if (Base) 32 O << ','; 33 } 34 if (Base) 35 O << '%' << getRegisterName(Base); 36 O << ')'; 37 } 38 } 39 40 void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI, 41 raw_ostream &O) { 42 if (MO.isReg()) 43 O << '%' << getRegisterName(MO.getReg()); 44 else if (MO.isImm()) 45 O << MO.getImm(); 46 else if (MO.isExpr()) 47 MO.getExpr()->print(O, MAI); 48 else 49 llvm_unreachable("Invalid operand"); 50 } 51 52 void SystemZInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 53 StringRef Annot, 54 const MCSubtargetInfo &STI) { 55 printInstruction(MI, O); 56 printAnnotation(O, Annot); 57 } 58 59 void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { 60 O << '%' << getRegisterName(RegNo); 61 } 62 63 template <unsigned N> 64 static void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { 65 int64_t Value = MI->getOperand(OpNum).getImm(); 66 assert(isUInt<N>(Value) && "Invalid uimm argument"); 67 O << Value; 68 } 69 70 template <unsigned N> 71 static void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { 72 int64_t Value = MI->getOperand(OpNum).getImm(); 73 assert(isInt<N>(Value) && "Invalid simm argument"); 74 O << Value; 75 } 76 77 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum, 78 raw_ostream &O) { 79 printUImmOperand<1>(MI, OpNum, O); 80 } 81 82 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum, 83 raw_ostream &O) { 84 printUImmOperand<2>(MI, OpNum, O); 85 } 86 87 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum, 88 raw_ostream &O) { 89 printUImmOperand<3>(MI, OpNum, O); 90 } 91 92 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum, 93 raw_ostream &O) { 94 printUImmOperand<4>(MI, OpNum, O); 95 } 96 97 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum, 98 raw_ostream &O) { 99 printUImmOperand<6>(MI, OpNum, O); 100 } 101 102 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum, 103 raw_ostream &O) { 104 printSImmOperand<8>(MI, OpNum, O); 105 } 106 107 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum, 108 raw_ostream &O) { 109 printUImmOperand<8>(MI, OpNum, O); 110 } 111 112 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum, 113 raw_ostream &O) { 114 printUImmOperand<12>(MI, OpNum, O); 115 } 116 117 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum, 118 raw_ostream &O) { 119 printSImmOperand<16>(MI, OpNum, O); 120 } 121 122 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum, 123 raw_ostream &O) { 124 printUImmOperand<16>(MI, OpNum, O); 125 } 126 127 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum, 128 raw_ostream &O) { 129 printSImmOperand<32>(MI, OpNum, O); 130 } 131 132 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum, 133 raw_ostream &O) { 134 printUImmOperand<32>(MI, OpNum, O); 135 } 136 137 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum, 138 raw_ostream &O) { 139 printUImmOperand<48>(MI, OpNum, O); 140 } 141 142 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum, 143 raw_ostream &O) { 144 const MCOperand &MO = MI->getOperand(OpNum); 145 if (MO.isImm()) { 146 O << "0x"; 147 O.write_hex(MO.getImm()); 148 } else 149 MO.getExpr()->print(O, &MAI); 150 } 151 152 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum, 153 raw_ostream &O) { 154 // Output the PC-relative operand. 155 printPCRelOperand(MI, OpNum, O); 156 157 // Output the TLS marker if present. 158 if ((unsigned)OpNum + 1 < MI->getNumOperands()) { 159 const MCOperand &MO = MI->getOperand(OpNum + 1); 160 const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr()); 161 switch (refExp.getKind()) { 162 case MCSymbolRefExpr::VK_TLSGD: 163 O << ":tls_gdcall:"; 164 break; 165 case MCSymbolRefExpr::VK_TLSLDM: 166 O << ":tls_ldcall:"; 167 break; 168 default: 169 llvm_unreachable("Unexpected symbol kind"); 170 } 171 O << refExp.getSymbol().getName(); 172 } 173 } 174 175 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, 176 raw_ostream &O) { 177 printOperand(MI->getOperand(OpNum), &MAI, O); 178 } 179 180 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum, 181 raw_ostream &O) { 182 printAddress(MI->getOperand(OpNum).getReg(), 183 MI->getOperand(OpNum + 1).getImm(), 0, O); 184 } 185 186 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum, 187 raw_ostream &O) { 188 printAddress(MI->getOperand(OpNum).getReg(), 189 MI->getOperand(OpNum + 1).getImm(), 190 MI->getOperand(OpNum + 2).getReg(), O); 191 } 192 193 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum, 194 raw_ostream &O) { 195 unsigned Base = MI->getOperand(OpNum).getReg(); 196 uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); 197 uint64_t Length = MI->getOperand(OpNum + 2).getImm(); 198 O << Disp << '(' << Length; 199 if (Base) 200 O << ",%" << getRegisterName(Base); 201 O << ')'; 202 } 203 204 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum, 205 raw_ostream &O) { 206 unsigned Base = MI->getOperand(OpNum).getReg(); 207 uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); 208 unsigned Length = MI->getOperand(OpNum + 2).getReg(); 209 O << Disp << "(%" << getRegisterName(Length); 210 if (Base) 211 O << ",%" << getRegisterName(Base); 212 O << ')'; 213 } 214 215 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum, 216 raw_ostream &O) { 217 printAddress(MI->getOperand(OpNum).getReg(), 218 MI->getOperand(OpNum + 1).getImm(), 219 MI->getOperand(OpNum + 2).getReg(), O); 220 } 221 222 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum, 223 raw_ostream &O) { 224 static const char *const CondNames[] = { 225 "o", "h", "nle", "l", "nhe", "lh", "ne", 226 "e", "nlh", "he", "nl", "le", "nh", "no" 227 }; 228 uint64_t Imm = MI->getOperand(OpNum).getImm(); 229 assert(Imm > 0 && Imm < 15 && "Invalid condition"); 230 O << CondNames[Imm - 1]; 231 } 232