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