1d0124bd7SRichard Trieu //===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===//
2d0124bd7SRichard Trieu //
3d0124bd7SRichard Trieu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d0124bd7SRichard Trieu // See https://llvm.org/LICENSE.txt for license information.
5d0124bd7SRichard Trieu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d0124bd7SRichard Trieu //
7d0124bd7SRichard Trieu //===----------------------------------------------------------------------===//
8d0124bd7SRichard Trieu 
9d0124bd7SRichard Trieu #include "SystemZInstPrinter.h"
10d0124bd7SRichard Trieu #include "llvm/MC/MCExpr.h"
11d0124bd7SRichard Trieu #include "llvm/MC/MCInst.h"
12d0124bd7SRichard Trieu #include "llvm/MC/MCSymbol.h"
13d0124bd7SRichard Trieu #include "llvm/Support/Casting.h"
14d0124bd7SRichard Trieu #include "llvm/Support/ErrorHandling.h"
15d0124bd7SRichard Trieu #include "llvm/Support/MathExtras.h"
16d0124bd7SRichard Trieu #include "llvm/Support/raw_ostream.h"
17d0124bd7SRichard Trieu #include <cassert>
18d0124bd7SRichard Trieu #include <cstdint>
19d0124bd7SRichard Trieu 
20d0124bd7SRichard Trieu using namespace llvm;
21d0124bd7SRichard Trieu 
22d0124bd7SRichard Trieu #define DEBUG_TYPE "asm-printer"
23d0124bd7SRichard Trieu 
24d0124bd7SRichard Trieu #include "SystemZGenAsmWriter.inc"
25d0124bd7SRichard Trieu 
printAddress(const MCAsmInfo * MAI,unsigned Base,const MCOperand & DispMO,unsigned Index,raw_ostream & O)2621db4cc2SAnirudh Prasad void SystemZInstPrinter::printAddress(const MCAsmInfo *MAI, unsigned Base,
27*1c3ef9efSJonas Paulsson                                       const MCOperand &DispMO, unsigned Index,
2821db4cc2SAnirudh Prasad                                       raw_ostream &O) {
29*1c3ef9efSJonas Paulsson   printOperand(DispMO, MAI, O);
30d0124bd7SRichard Trieu   if (Base || Index) {
31d0124bd7SRichard Trieu     O << '(';
32d0124bd7SRichard Trieu     if (Index) {
3321db4cc2SAnirudh Prasad       printFormattedRegName(MAI, Index, O);
34d0124bd7SRichard Trieu       if (Base)
35d0124bd7SRichard Trieu         O << ',';
36d0124bd7SRichard Trieu     }
37d0124bd7SRichard Trieu     if (Base)
3821db4cc2SAnirudh Prasad       printFormattedRegName(MAI, Base, O);
39d0124bd7SRichard Trieu     O << ')';
40d0124bd7SRichard Trieu   }
41d0124bd7SRichard Trieu }
42d0124bd7SRichard Trieu 
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)43d0124bd7SRichard Trieu void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI,
44d0124bd7SRichard Trieu                                       raw_ostream &O) {
453ec193fbSJonas Paulsson   if (MO.isReg()) {
463ec193fbSJonas Paulsson     if (!MO.getReg())
473ec193fbSJonas Paulsson       O << '0';
483ec193fbSJonas Paulsson     else
4921db4cc2SAnirudh Prasad       printFormattedRegName(MAI, MO.getReg(), O);
503ec193fbSJonas Paulsson   }
51d0124bd7SRichard Trieu   else if (MO.isImm())
52d0124bd7SRichard Trieu     O << MO.getImm();
53d0124bd7SRichard Trieu   else if (MO.isExpr())
54d0124bd7SRichard Trieu     MO.getExpr()->print(O, MAI);
55d0124bd7SRichard Trieu   else
56d0124bd7SRichard Trieu     llvm_unreachable("Invalid operand");
57d0124bd7SRichard Trieu }
58d0124bd7SRichard Trieu 
printFormattedRegName(const MCAsmInfo * MAI,unsigned RegNo,raw_ostream & O)5921db4cc2SAnirudh Prasad void SystemZInstPrinter::printFormattedRegName(const MCAsmInfo *MAI,
6021db4cc2SAnirudh Prasad                                                unsigned RegNo, raw_ostream &O) {
6121db4cc2SAnirudh Prasad   const char *RegName = getRegisterName(RegNo);
6221db4cc2SAnirudh Prasad   if (MAI->getAssemblerDialect() == AD_HLASM) {
6321db4cc2SAnirudh Prasad     // Skip register prefix so that only register number is left
6421db4cc2SAnirudh Prasad     assert(isalpha(RegName[0]) && isdigit(RegName[1]));
6521db4cc2SAnirudh Prasad     O << (RegName + 1);
6621db4cc2SAnirudh Prasad   } else
6721db4cc2SAnirudh Prasad     O << '%' << RegName;
6821db4cc2SAnirudh Prasad }
6921db4cc2SAnirudh Prasad 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)70aa708763SFangrui Song void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address,
71aa708763SFangrui Song                                    StringRef Annot, const MCSubtargetInfo &STI,
72aa708763SFangrui Song                                    raw_ostream &O) {
733d87d0b9SFangrui Song   printInstruction(MI, Address, O);
74d0124bd7SRichard Trieu   printAnnotation(O, Annot);
75d0124bd7SRichard Trieu }
76d0124bd7SRichard Trieu 
77d0124bd7SRichard Trieu template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)78d0124bd7SRichard Trieu static void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
79d0124bd7SRichard Trieu   int64_t Value = MI->getOperand(OpNum).getImm();
80d0124bd7SRichard Trieu   assert(isUInt<N>(Value) && "Invalid uimm argument");
81d0124bd7SRichard Trieu   O << Value;
82d0124bd7SRichard Trieu }
83d0124bd7SRichard Trieu 
84d0124bd7SRichard Trieu template <unsigned N>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)85d0124bd7SRichard Trieu static void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
86d0124bd7SRichard Trieu   int64_t Value = MI->getOperand(OpNum).getImm();
87d0124bd7SRichard Trieu   assert(isInt<N>(Value) && "Invalid simm argument");
88d0124bd7SRichard Trieu   O << Value;
89d0124bd7SRichard Trieu }
90d0124bd7SRichard Trieu 
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)91d0124bd7SRichard Trieu void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
92d0124bd7SRichard Trieu                                            raw_ostream &O) {
93d0124bd7SRichard Trieu   printUImmOperand<1>(MI, OpNum, O);
94d0124bd7SRichard Trieu }
95d0124bd7SRichard Trieu 
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)96d0124bd7SRichard Trieu void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
97d0124bd7SRichard Trieu                                            raw_ostream &O) {
98d0124bd7SRichard Trieu   printUImmOperand<2>(MI, OpNum, O);
99d0124bd7SRichard Trieu }
100d0124bd7SRichard Trieu 
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)101d0124bd7SRichard Trieu void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
102d0124bd7SRichard Trieu                                            raw_ostream &O) {
103d0124bd7SRichard Trieu   printUImmOperand<3>(MI, OpNum, O);
104d0124bd7SRichard Trieu }
105d0124bd7SRichard Trieu 
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)106d0124bd7SRichard Trieu void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
107d0124bd7SRichard Trieu                                            raw_ostream &O) {
108d0124bd7SRichard Trieu   printUImmOperand<4>(MI, OpNum, O);
109d0124bd7SRichard Trieu }
110d0124bd7SRichard Trieu 
printU6ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)111d0124bd7SRichard Trieu void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
112d0124bd7SRichard Trieu                                            raw_ostream &O) {
113d0124bd7SRichard Trieu   printUImmOperand<6>(MI, OpNum, O);
114d0124bd7SRichard Trieu }
115d0124bd7SRichard Trieu 
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)116d0124bd7SRichard Trieu void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
117d0124bd7SRichard Trieu                                            raw_ostream &O) {
118d0124bd7SRichard Trieu   printSImmOperand<8>(MI, OpNum, O);
119d0124bd7SRichard Trieu }
120d0124bd7SRichard Trieu 
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)121d0124bd7SRichard Trieu void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
122d0124bd7SRichard Trieu                                            raw_ostream &O) {
123d0124bd7SRichard Trieu   printUImmOperand<8>(MI, OpNum, O);
124d0124bd7SRichard Trieu }
125d0124bd7SRichard Trieu 
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)126d0124bd7SRichard Trieu void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
127d0124bd7SRichard Trieu                                             raw_ostream &O) {
128d0124bd7SRichard Trieu   printUImmOperand<12>(MI, OpNum, O);
129d0124bd7SRichard Trieu }
130d0124bd7SRichard Trieu 
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)131d0124bd7SRichard Trieu void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
132d0124bd7SRichard Trieu                                             raw_ostream &O) {
133d0124bd7SRichard Trieu   printSImmOperand<16>(MI, OpNum, O);
134d0124bd7SRichard Trieu }
135d0124bd7SRichard Trieu 
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)136d0124bd7SRichard Trieu void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
137d0124bd7SRichard Trieu                                             raw_ostream &O) {
138d0124bd7SRichard Trieu   printUImmOperand<16>(MI, OpNum, O);
139d0124bd7SRichard Trieu }
140d0124bd7SRichard Trieu 
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)141d0124bd7SRichard Trieu void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
142d0124bd7SRichard Trieu                                             raw_ostream &O) {
143d0124bd7SRichard Trieu   printSImmOperand<32>(MI, OpNum, O);
144d0124bd7SRichard Trieu }
145d0124bd7SRichard Trieu 
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)146d0124bd7SRichard Trieu void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
147d0124bd7SRichard Trieu                                             raw_ostream &O) {
148d0124bd7SRichard Trieu   printUImmOperand<32>(MI, OpNum, O);
149d0124bd7SRichard Trieu }
150d0124bd7SRichard Trieu 
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)151d0124bd7SRichard Trieu void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
152d0124bd7SRichard Trieu                                             raw_ostream &O) {
153d0124bd7SRichard Trieu   printUImmOperand<48>(MI, OpNum, O);
154d0124bd7SRichard Trieu }
155d0124bd7SRichard Trieu 
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)156d0124bd7SRichard Trieu void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
157d0124bd7SRichard Trieu                                            raw_ostream &O) {
158d0124bd7SRichard Trieu   const MCOperand &MO = MI->getOperand(OpNum);
159d0124bd7SRichard Trieu   if (MO.isImm()) {
160d0124bd7SRichard Trieu     O << "0x";
161d0124bd7SRichard Trieu     O.write_hex(MO.getImm());
162d0124bd7SRichard Trieu   } else
163d0124bd7SRichard Trieu     MO.getExpr()->print(O, &MAI);
164d0124bd7SRichard Trieu }
165d0124bd7SRichard Trieu 
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)1665fad05e8SFangrui Song void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI,
1675fad05e8SFangrui Song                                               uint64_t Address, int OpNum,
168d0124bd7SRichard Trieu                                               raw_ostream &O) {
169d0124bd7SRichard Trieu   // Output the PC-relative operand.
170d0124bd7SRichard Trieu   printPCRelOperand(MI, OpNum, O);
171d0124bd7SRichard Trieu 
172d0124bd7SRichard Trieu   // Output the TLS marker if present.
173d0124bd7SRichard Trieu   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
174d0124bd7SRichard Trieu     const MCOperand &MO = MI->getOperand(OpNum + 1);
175d0124bd7SRichard Trieu     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
176d0124bd7SRichard Trieu     switch (refExp.getKind()) {
177d0124bd7SRichard Trieu       case MCSymbolRefExpr::VK_TLSGD:
178d0124bd7SRichard Trieu         O << ":tls_gdcall:";
179d0124bd7SRichard Trieu         break;
180d0124bd7SRichard Trieu       case MCSymbolRefExpr::VK_TLSLDM:
181d0124bd7SRichard Trieu         O << ":tls_ldcall:";
182d0124bd7SRichard Trieu         break;
183d0124bd7SRichard Trieu       default:
184d0124bd7SRichard Trieu         llvm_unreachable("Unexpected symbol kind");
185d0124bd7SRichard Trieu     }
186d0124bd7SRichard Trieu     O << refExp.getSymbol().getName();
187d0124bd7SRichard Trieu   }
188d0124bd7SRichard Trieu }
189d0124bd7SRichard Trieu 
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)190d0124bd7SRichard Trieu void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
191d0124bd7SRichard Trieu                                       raw_ostream &O) {
192d0124bd7SRichard Trieu   printOperand(MI->getOperand(OpNum), &MAI, O);
193d0124bd7SRichard Trieu }
194d0124bd7SRichard Trieu 
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)195d0124bd7SRichard Trieu void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
196d0124bd7SRichard Trieu                                             raw_ostream &O) {
197*1c3ef9efSJonas Paulsson   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
198*1c3ef9efSJonas Paulsson                0, O);
199d0124bd7SRichard Trieu }
200d0124bd7SRichard Trieu 
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)201d0124bd7SRichard Trieu void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
202d0124bd7SRichard Trieu                                              raw_ostream &O) {
203*1c3ef9efSJonas Paulsson   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
204d0124bd7SRichard Trieu                MI->getOperand(OpNum + 2).getReg(), O);
205d0124bd7SRichard Trieu }
206d0124bd7SRichard Trieu 
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)207d0124bd7SRichard Trieu void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
208d0124bd7SRichard Trieu                                              raw_ostream &O) {
209d0124bd7SRichard Trieu   unsigned Base = MI->getOperand(OpNum).getReg();
210*1c3ef9efSJonas Paulsson   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
211d0124bd7SRichard Trieu   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
212*1c3ef9efSJonas Paulsson   printOperand(DispMO, &MAI, O);
213*1c3ef9efSJonas Paulsson   O << '(' << Length;
21421db4cc2SAnirudh Prasad   if (Base) {
21521db4cc2SAnirudh Prasad     O << ",";
21621db4cc2SAnirudh Prasad     printRegName(O, Base);
21721db4cc2SAnirudh Prasad   }
218d0124bd7SRichard Trieu   O << ')';
219d0124bd7SRichard Trieu }
220d0124bd7SRichard Trieu 
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)221d0124bd7SRichard Trieu void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
222d0124bd7SRichard Trieu                                              raw_ostream &O) {
223d0124bd7SRichard Trieu   unsigned Base = MI->getOperand(OpNum).getReg();
224*1c3ef9efSJonas Paulsson   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
225d0124bd7SRichard Trieu   unsigned Length = MI->getOperand(OpNum + 2).getReg();
226*1c3ef9efSJonas Paulsson   printOperand(DispMO, &MAI, O);
227*1c3ef9efSJonas Paulsson   O << "(";
22821db4cc2SAnirudh Prasad   printRegName(O, Length);
22921db4cc2SAnirudh Prasad   if (Base) {
23021db4cc2SAnirudh Prasad     O << ",";
23121db4cc2SAnirudh Prasad     printRegName(O, Base);
23221db4cc2SAnirudh Prasad   }
233d0124bd7SRichard Trieu   O << ')';
234d0124bd7SRichard Trieu }
235d0124bd7SRichard Trieu 
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)236d0124bd7SRichard Trieu void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
237d0124bd7SRichard Trieu                                              raw_ostream &O) {
238*1c3ef9efSJonas Paulsson   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
239d0124bd7SRichard Trieu                MI->getOperand(OpNum + 2).getReg(), O);
240d0124bd7SRichard Trieu }
241d0124bd7SRichard Trieu 
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)242d0124bd7SRichard Trieu void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
243d0124bd7SRichard Trieu                                            raw_ostream &O) {
244d0124bd7SRichard Trieu   static const char *const CondNames[] = {
245d0124bd7SRichard Trieu     "o", "h", "nle", "l", "nhe", "lh", "ne",
246d0124bd7SRichard Trieu     "e", "nlh", "he", "nl", "le", "nh", "no"
247d0124bd7SRichard Trieu   };
248d0124bd7SRichard Trieu   uint64_t Imm = MI->getOperand(OpNum).getImm();
249d0124bd7SRichard Trieu   assert(Imm > 0 && Imm < 15 && "Invalid condition");
250d0124bd7SRichard Trieu   O << CondNames[Imm - 1];
251d0124bd7SRichard Trieu }
252