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 const MCOperand &MO = MI->getOperand(OpNum); 87 if (MO.isExpr()) { 88 O << *MO.getExpr(); 89 return; 90 } 91 uint64_t Value = static_cast<uint64_t>(MO.getImm()); 92 assert(isUInt<N>(Value) && "Invalid uimm argument"); 93 O << markup("<imm:") << Value << markup(">"); 94 } 95 96 template <unsigned N> 97 void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum, 98 raw_ostream &O) { 99 const MCOperand &MO = MI->getOperand(OpNum); 100 if (MO.isExpr()) { 101 O << *MO.getExpr(); 102 return; 103 } 104 int64_t Value = MI->getOperand(OpNum).getImm(); 105 assert(isInt<N>(Value) && "Invalid simm argument"); 106 O << markup("<imm:") << Value << markup(">"); 107 } 108 109 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum, 110 raw_ostream &O) { 111 printUImmOperand<1>(MI, OpNum, O); 112 } 113 114 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum, 115 raw_ostream &O) { 116 printUImmOperand<2>(MI, OpNum, O); 117 } 118 119 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum, 120 raw_ostream &O) { 121 printUImmOperand<3>(MI, OpNum, O); 122 } 123 124 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum, 125 raw_ostream &O) { 126 printUImmOperand<4>(MI, OpNum, O); 127 } 128 129 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum, 130 raw_ostream &O) { 131 printSImmOperand<8>(MI, OpNum, O); 132 } 133 134 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum, 135 raw_ostream &O) { 136 printUImmOperand<8>(MI, OpNum, O); 137 } 138 139 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum, 140 raw_ostream &O) { 141 printUImmOperand<12>(MI, OpNum, O); 142 } 143 144 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum, 145 raw_ostream &O) { 146 printSImmOperand<16>(MI, OpNum, O); 147 } 148 149 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum, 150 raw_ostream &O) { 151 printUImmOperand<16>(MI, OpNum, O); 152 } 153 154 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum, 155 raw_ostream &O) { 156 printSImmOperand<32>(MI, OpNum, O); 157 } 158 159 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum, 160 raw_ostream &O) { 161 printUImmOperand<32>(MI, OpNum, O); 162 } 163 164 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum, 165 raw_ostream &O) { 166 printUImmOperand<48>(MI, OpNum, O); 167 } 168 169 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum, 170 raw_ostream &O) { 171 const MCOperand &MO = MI->getOperand(OpNum); 172 if (MO.isImm()) { 173 O << markup("<imm:") << "0x"; 174 O.write_hex(MO.getImm()); 175 O << markup(">"); 176 } else 177 MO.getExpr()->print(O, &MAI); 178 } 179 180 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, 181 uint64_t Address, int OpNum, 182 raw_ostream &O) { 183 // Output the PC-relative operand. 184 printPCRelOperand(MI, OpNum, O); 185 186 // Output the TLS marker if present. 187 if ((unsigned)OpNum + 1 < MI->getNumOperands()) { 188 const MCOperand &MO = MI->getOperand(OpNum + 1); 189 const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr()); 190 switch (refExp.getKind()) { 191 case MCSymbolRefExpr::VK_TLSGD: 192 O << ":tls_gdcall:"; 193 break; 194 case MCSymbolRefExpr::VK_TLSLDM: 195 O << ":tls_ldcall:"; 196 break; 197 default: 198 llvm_unreachable("Unexpected symbol kind"); 199 } 200 O << refExp.getSymbol().getName(); 201 } 202 } 203 204 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, 205 raw_ostream &O) { 206 printOperand(MI->getOperand(OpNum), &MAI, O); 207 } 208 209 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum, 210 raw_ostream &O) { 211 printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 212 0, O); 213 } 214 215 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum, 216 raw_ostream &O) { 217 printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 218 MI->getOperand(OpNum + 2).getReg(), O); 219 } 220 221 void SystemZInstPrinter::printBDLAddrOperand(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 uint64_t Length = MI->getOperand(OpNum + 2).getImm(); 226 printOperand(DispMO, &MAI, O); 227 O << '(' << Length; 228 if (Base) { 229 O << ","; 230 printRegName(O, Base); 231 } 232 O << ')'; 233 } 234 235 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum, 236 raw_ostream &O) { 237 unsigned Base = MI->getOperand(OpNum).getReg(); 238 const MCOperand &DispMO = MI->getOperand(OpNum + 1); 239 unsigned Length = MI->getOperand(OpNum + 2).getReg(); 240 printOperand(DispMO, &MAI, O); 241 O << "("; 242 printRegName(O, Length); 243 if (Base) { 244 O << ","; 245 printRegName(O, Base); 246 } 247 O << ')'; 248 } 249 250 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum, 251 raw_ostream &O) { 252 printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 253 MI->getOperand(OpNum + 2).getReg(), O); 254 } 255 256 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum, 257 raw_ostream &O) { 258 static const char *const CondNames[] = { 259 "o", "h", "nle", "l", "nhe", "lh", "ne", 260 "e", "nlh", "he", "nl", "le", "nh", "no" 261 }; 262 uint64_t Imm = MI->getOperand(OpNum).getImm(); 263 assert(Imm > 0 && Imm < 15 && "Invalid condition"); 264 O << CondNames[Imm - 1]; 265 } 266