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