10b57cec5SDimitry Andric //===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "SystemZInstPrinter.h" 100b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 110b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 12bdd1243dSDimitry Andric #include "llvm/MC/MCRegister.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 140b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 150b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 160b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 170b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 180b57cec5SDimitry Andric #include <cassert> 190b57cec5SDimitry Andric #include <cstdint> 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #include "SystemZGenAsmWriter.inc" 260b57cec5SDimitry Andric 27bdd1243dSDimitry Andric void SystemZInstPrinter::printAddress(const MCAsmInfo *MAI, MCRegister Base, 28bdd1243dSDimitry Andric const MCOperand &DispMO, MCRegister Index, 29fe6060f1SDimitry Andric raw_ostream &O) { 30349cc55cSDimitry Andric printOperand(DispMO, MAI, O); 310b57cec5SDimitry Andric if (Base || Index) { 320b57cec5SDimitry Andric O << '('; 330b57cec5SDimitry Andric if (Index) { 34fe6060f1SDimitry Andric printFormattedRegName(MAI, Index, O); 350b57cec5SDimitry Andric O << ','; 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric if (Base) 38fe6060f1SDimitry Andric printFormattedRegName(MAI, Base, O); 39*5f757f3fSDimitry Andric else 40*5f757f3fSDimitry Andric O << '0'; 410b57cec5SDimitry Andric O << ')'; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI, 460b57cec5SDimitry Andric raw_ostream &O) { 47480093f4SDimitry Andric if (MO.isReg()) { 48480093f4SDimitry Andric if (!MO.getReg()) 49480093f4SDimitry Andric O << '0'; 50480093f4SDimitry Andric else 51fe6060f1SDimitry Andric printFormattedRegName(MAI, MO.getReg(), O); 52480093f4SDimitry Andric } 530b57cec5SDimitry Andric else if (MO.isImm()) 54*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << MO.getImm(); 550b57cec5SDimitry Andric else if (MO.isExpr()) 560b57cec5SDimitry Andric MO.getExpr()->print(O, MAI); 570b57cec5SDimitry Andric else 580b57cec5SDimitry Andric llvm_unreachable("Invalid operand"); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 61fe6060f1SDimitry Andric void SystemZInstPrinter::printFormattedRegName(const MCAsmInfo *MAI, 62bdd1243dSDimitry Andric MCRegister Reg, 63bdd1243dSDimitry Andric raw_ostream &O) const { 64bdd1243dSDimitry Andric const char *RegName = getRegisterName(Reg); 65fe6060f1SDimitry Andric if (MAI->getAssemblerDialect() == AD_HLASM) { 66fe6060f1SDimitry Andric // Skip register prefix so that only register number is left 67fe6060f1SDimitry Andric assert(isalpha(RegName[0]) && isdigit(RegName[1])); 68*5f757f3fSDimitry Andric markup(O, Markup::Register) << (RegName + 1); 69fe6060f1SDimitry Andric } else 70*5f757f3fSDimitry Andric markup(O, Markup::Register) << '%' << RegName; 71bdd1243dSDimitry Andric } 72bdd1243dSDimitry Andric 73bdd1243dSDimitry Andric void SystemZInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const { 74bdd1243dSDimitry Andric printFormattedRegName(&MAI, Reg, O); 75fe6060f1SDimitry Andric } 76fe6060f1SDimitry Andric 77480093f4SDimitry Andric void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address, 78480093f4SDimitry Andric StringRef Annot, const MCSubtargetInfo &STI, 79480093f4SDimitry Andric raw_ostream &O) { 80480093f4SDimitry Andric printInstruction(MI, Address, O); 810b57cec5SDimitry Andric printAnnotation(O, Annot); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric template <unsigned N> 85bdd1243dSDimitry Andric void SystemZInstPrinter::printUImmOperand(const MCInst *MI, int OpNum, 86bdd1243dSDimitry Andric raw_ostream &O) { 8706c3fb27SDimitry Andric const MCOperand &MO = MI->getOperand(OpNum); 8806c3fb27SDimitry Andric if (MO.isExpr()) { 8906c3fb27SDimitry Andric O << *MO.getExpr(); 9006c3fb27SDimitry Andric return; 9106c3fb27SDimitry Andric } 9206c3fb27SDimitry Andric uint64_t Value = static_cast<uint64_t>(MO.getImm()); 930b57cec5SDimitry Andric assert(isUInt<N>(Value) && "Invalid uimm argument"); 94*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << Value; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric template <unsigned N> 98bdd1243dSDimitry Andric void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum, 99bdd1243dSDimitry Andric raw_ostream &O) { 10006c3fb27SDimitry Andric const MCOperand &MO = MI->getOperand(OpNum); 10106c3fb27SDimitry Andric if (MO.isExpr()) { 10206c3fb27SDimitry Andric O << *MO.getExpr(); 10306c3fb27SDimitry Andric return; 10406c3fb27SDimitry Andric } 1050b57cec5SDimitry Andric int64_t Value = MI->getOperand(OpNum).getImm(); 1060b57cec5SDimitry Andric assert(isInt<N>(Value) && "Invalid simm argument"); 107*5f757f3fSDimitry Andric markup(O, Markup::Immediate) << Value; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum, 1110b57cec5SDimitry Andric raw_ostream &O) { 1120b57cec5SDimitry Andric printUImmOperand<1>(MI, OpNum, O); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum, 1160b57cec5SDimitry Andric raw_ostream &O) { 1170b57cec5SDimitry Andric printUImmOperand<2>(MI, OpNum, O); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum, 1210b57cec5SDimitry Andric raw_ostream &O) { 1220b57cec5SDimitry Andric printUImmOperand<3>(MI, OpNum, O); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum, 1260b57cec5SDimitry Andric raw_ostream &O) { 1270b57cec5SDimitry Andric printUImmOperand<4>(MI, OpNum, O); 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum, 1310b57cec5SDimitry Andric raw_ostream &O) { 1320b57cec5SDimitry Andric printSImmOperand<8>(MI, OpNum, O); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum, 1360b57cec5SDimitry Andric raw_ostream &O) { 1370b57cec5SDimitry Andric printUImmOperand<8>(MI, OpNum, O); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum, 1410b57cec5SDimitry Andric raw_ostream &O) { 1420b57cec5SDimitry Andric printUImmOperand<12>(MI, OpNum, O); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum, 1460b57cec5SDimitry Andric raw_ostream &O) { 1470b57cec5SDimitry Andric printSImmOperand<16>(MI, OpNum, O); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum, 1510b57cec5SDimitry Andric raw_ostream &O) { 1520b57cec5SDimitry Andric printUImmOperand<16>(MI, OpNum, O); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum, 1560b57cec5SDimitry Andric raw_ostream &O) { 1570b57cec5SDimitry Andric printSImmOperand<32>(MI, OpNum, O); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum, 1610b57cec5SDimitry Andric raw_ostream &O) { 1620b57cec5SDimitry Andric printUImmOperand<32>(MI, OpNum, O); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum, 1660b57cec5SDimitry Andric raw_ostream &O) { 1670b57cec5SDimitry Andric printUImmOperand<48>(MI, OpNum, O); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum, 1710b57cec5SDimitry Andric raw_ostream &O) { 1720b57cec5SDimitry Andric const MCOperand &MO = MI->getOperand(OpNum); 1730b57cec5SDimitry Andric if (MO.isImm()) { 174*5f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate); 175*5f757f3fSDimitry Andric O << "0x"; 1760b57cec5SDimitry Andric O.write_hex(MO.getImm()); 1770b57cec5SDimitry Andric } else 1780b57cec5SDimitry Andric MO.getExpr()->print(O, &MAI); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1815ffd83dbSDimitry Andric void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, 1825ffd83dbSDimitry Andric uint64_t Address, int OpNum, 1830b57cec5SDimitry Andric raw_ostream &O) { 1840b57cec5SDimitry Andric // Output the PC-relative operand. 1850b57cec5SDimitry Andric printPCRelOperand(MI, OpNum, O); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // Output the TLS marker if present. 1880b57cec5SDimitry Andric if ((unsigned)OpNum + 1 < MI->getNumOperands()) { 1890b57cec5SDimitry Andric const MCOperand &MO = MI->getOperand(OpNum + 1); 1900b57cec5SDimitry Andric const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr()); 1910b57cec5SDimitry Andric switch (refExp.getKind()) { 1920b57cec5SDimitry Andric case MCSymbolRefExpr::VK_TLSGD: 1930b57cec5SDimitry Andric O << ":tls_gdcall:"; 1940b57cec5SDimitry Andric break; 1950b57cec5SDimitry Andric case MCSymbolRefExpr::VK_TLSLDM: 1960b57cec5SDimitry Andric O << ":tls_ldcall:"; 1970b57cec5SDimitry Andric break; 1980b57cec5SDimitry Andric default: 1990b57cec5SDimitry Andric llvm_unreachable("Unexpected symbol kind"); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric O << refExp.getSymbol().getName(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, 2060b57cec5SDimitry Andric raw_ostream &O) { 2070b57cec5SDimitry Andric printOperand(MI->getOperand(OpNum), &MAI, O); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum, 2110b57cec5SDimitry Andric raw_ostream &O) { 212349cc55cSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 213349cc55cSDimitry Andric 0, O); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum, 2170b57cec5SDimitry Andric raw_ostream &O) { 218349cc55cSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 2190b57cec5SDimitry Andric MI->getOperand(OpNum + 2).getReg(), O); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum, 2230b57cec5SDimitry Andric raw_ostream &O) { 2240b57cec5SDimitry Andric unsigned Base = MI->getOperand(OpNum).getReg(); 225349cc55cSDimitry Andric const MCOperand &DispMO = MI->getOperand(OpNum + 1); 2260b57cec5SDimitry Andric uint64_t Length = MI->getOperand(OpNum + 2).getImm(); 227349cc55cSDimitry Andric printOperand(DispMO, &MAI, O); 228349cc55cSDimitry Andric O << '(' << Length; 229fe6060f1SDimitry Andric if (Base) { 230fe6060f1SDimitry Andric O << ","; 231fe6060f1SDimitry Andric printRegName(O, Base); 232fe6060f1SDimitry Andric } 2330b57cec5SDimitry Andric O << ')'; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum, 2370b57cec5SDimitry Andric raw_ostream &O) { 2380b57cec5SDimitry Andric unsigned Base = MI->getOperand(OpNum).getReg(); 239349cc55cSDimitry Andric const MCOperand &DispMO = MI->getOperand(OpNum + 1); 2400b57cec5SDimitry Andric unsigned Length = MI->getOperand(OpNum + 2).getReg(); 241349cc55cSDimitry Andric printOperand(DispMO, &MAI, O); 242349cc55cSDimitry Andric O << "("; 243fe6060f1SDimitry Andric printRegName(O, Length); 244fe6060f1SDimitry Andric if (Base) { 245fe6060f1SDimitry Andric O << ","; 246fe6060f1SDimitry Andric printRegName(O, Base); 247fe6060f1SDimitry Andric } 2480b57cec5SDimitry Andric O << ')'; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum, 2520b57cec5SDimitry Andric raw_ostream &O) { 253349cc55cSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), 2540b57cec5SDimitry Andric MI->getOperand(OpNum + 2).getReg(), O); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum, 2580b57cec5SDimitry Andric raw_ostream &O) { 2590b57cec5SDimitry Andric static const char *const CondNames[] = { 2600b57cec5SDimitry Andric "o", "h", "nle", "l", "nhe", "lh", "ne", 2610b57cec5SDimitry Andric "e", "nlh", "he", "nl", "le", "nh", "no" 2620b57cec5SDimitry Andric }; 2630b57cec5SDimitry Andric uint64_t Imm = MI->getOperand(OpNum).getImm(); 2640b57cec5SDimitry Andric assert(Imm > 0 && Imm < 15 && "Invalid condition"); 2650b57cec5SDimitry Andric O << CondNames[Imm - 1]; 2660b57cec5SDimitry Andric } 267