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, 159 uint64_t Address, int OpNum, 160 raw_ostream &O) { 161 // Output the PC-relative operand. 162 printPCRelOperand(MI, OpNum, O); 163 164 // Output the TLS marker if present. 165 if ((unsigned)OpNum + 1 < MI->getNumOperands()) { 166 const MCOperand &MO = MI->getOperand(OpNum + 1); 167 const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr()); 168 switch (refExp.getKind()) { 169 case MCSymbolRefExpr::VK_TLSGD: 170 O << ":tls_gdcall:"; 171 break; 172 case MCSymbolRefExpr::VK_TLSLDM: 173 O << ":tls_ldcall:"; 174 break; 175 default: 176 llvm_unreachable("Unexpected symbol kind"); 177 } 178 O << refExp.getSymbol().getName(); 179 } 180 } 181 182 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, 183 raw_ostream &O) { 184 printOperand(MI->getOperand(OpNum), &MAI, O); 185 } 186 187 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum, 188 raw_ostream &O) { 189 printAddress(MI->getOperand(OpNum).getReg(), 190 MI->getOperand(OpNum + 1).getImm(), 0, O); 191 } 192 193 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum, 194 raw_ostream &O) { 195 printAddress(MI->getOperand(OpNum).getReg(), 196 MI->getOperand(OpNum + 1).getImm(), 197 MI->getOperand(OpNum + 2).getReg(), O); 198 } 199 200 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum, 201 raw_ostream &O) { 202 unsigned Base = MI->getOperand(OpNum).getReg(); 203 uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); 204 uint64_t Length = MI->getOperand(OpNum + 2).getImm(); 205 O << Disp << '(' << Length; 206 if (Base) 207 O << ",%" << getRegisterName(Base); 208 O << ')'; 209 } 210 211 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum, 212 raw_ostream &O) { 213 unsigned Base = MI->getOperand(OpNum).getReg(); 214 uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); 215 unsigned Length = MI->getOperand(OpNum + 2).getReg(); 216 O << Disp << "(%" << getRegisterName(Length); 217 if (Base) 218 O << ",%" << getRegisterName(Base); 219 O << ')'; 220 } 221 222 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum, 223 raw_ostream &O) { 224 printAddress(MI->getOperand(OpNum).getReg(), 225 MI->getOperand(OpNum + 1).getImm(), 226 MI->getOperand(OpNum + 2).getReg(), O); 227 } 228 229 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum, 230 raw_ostream &O) { 231 static const char *const CondNames[] = { 232 "o", "h", "nle", "l", "nhe", "lh", "ne", 233 "e", "nlh", "he", "nl", "le", "nh", "no" 234 }; 235 uint64_t Imm = MI->getOperand(OpNum).getImm(); 236 assert(Imm > 0 && Imm < 15 && "Invalid condition"); 237 O << CondNames[Imm - 1]; 238 } 239