xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
printAddress(const MCAsmInfo * MAI,MCRegister Base,const MCOperand & DispMO,MCRegister Index,raw_ostream & O)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 
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)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 
printFormattedRegName(const MCAsmInfo * MAI,MCRegister Reg,raw_ostream & O) const61fe6060f1SDimitry 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 
printRegName(raw_ostream & O,MCRegister Reg) const73bdd1243dSDimitry Andric void SystemZInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
74bdd1243dSDimitry Andric   printFormattedRegName(&MAI, Reg, O);
75fe6060f1SDimitry Andric }
76fe6060f1SDimitry Andric 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)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>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)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 
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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 
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)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