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