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