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