1*700637cbSDimitry Andric //=- SystemZInstPrinterCommon.cpp - Common SystemZ MCInst to assembly funcs -=//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric
9*700637cbSDimitry Andric #include "SystemZInstPrinterCommon.h"
10*700637cbSDimitry Andric #include "MCTargetDesc/SystemZMCAsmInfo.h"
11*700637cbSDimitry Andric #include "llvm/MC/MCExpr.h"
12*700637cbSDimitry Andric #include "llvm/MC/MCInst.h"
13*700637cbSDimitry Andric #include "llvm/MC/MCRegister.h"
14*700637cbSDimitry Andric #include "llvm/MC/MCSymbol.h"
15*700637cbSDimitry Andric #include "llvm/Support/Casting.h"
16*700637cbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
17*700637cbSDimitry Andric #include "llvm/Support/MathExtras.h"
18*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h"
19*700637cbSDimitry Andric #include <cassert>
20*700637cbSDimitry Andric #include <cstdint>
21*700637cbSDimitry Andric
22*700637cbSDimitry Andric using namespace llvm;
23*700637cbSDimitry Andric
24*700637cbSDimitry Andric #define DEBUG_TYPE "asm-printer"
25*700637cbSDimitry Andric
printAddress(const MCAsmInfo * MAI,MCRegister Base,const MCOperand & DispMO,MCRegister Index,raw_ostream & O)26*700637cbSDimitry Andric void SystemZInstPrinterCommon::printAddress(const MCAsmInfo *MAI,
27*700637cbSDimitry Andric MCRegister Base,
28*700637cbSDimitry Andric const MCOperand &DispMO,
29*700637cbSDimitry Andric MCRegister Index, raw_ostream &O) {
30*700637cbSDimitry Andric printOperand(DispMO, MAI, O);
31*700637cbSDimitry Andric if (Base || Index) {
32*700637cbSDimitry Andric O << '(';
33*700637cbSDimitry Andric if (Index) {
34*700637cbSDimitry Andric printRegName(O, Index);
35*700637cbSDimitry Andric O << ',';
36*700637cbSDimitry Andric }
37*700637cbSDimitry Andric if (Base)
38*700637cbSDimitry Andric printRegName(O, Base);
39*700637cbSDimitry Andric else
40*700637cbSDimitry Andric O << '0';
41*700637cbSDimitry Andric O << ')';
42*700637cbSDimitry Andric }
43*700637cbSDimitry Andric }
44*700637cbSDimitry Andric
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)45*700637cbSDimitry Andric void SystemZInstPrinterCommon::printOperand(const MCOperand &MO,
46*700637cbSDimitry Andric const MCAsmInfo *MAI,
47*700637cbSDimitry Andric raw_ostream &O) {
48*700637cbSDimitry Andric if (MO.isReg()) {
49*700637cbSDimitry Andric if (!MO.getReg())
50*700637cbSDimitry Andric O << '0';
51*700637cbSDimitry Andric else
52*700637cbSDimitry Andric printRegName(O, MO.getReg());
53*700637cbSDimitry Andric } else if (MO.isImm())
54*700637cbSDimitry Andric markup(O, Markup::Immediate) << MO.getImm();
55*700637cbSDimitry Andric else if (MO.isExpr())
56*700637cbSDimitry Andric MAI->printExpr(O, *MO.getExpr());
57*700637cbSDimitry Andric else
58*700637cbSDimitry Andric llvm_unreachable("Invalid operand");
59*700637cbSDimitry Andric }
60*700637cbSDimitry Andric
printRegName(raw_ostream & O,MCRegister Reg)61*700637cbSDimitry Andric void SystemZInstPrinterCommon::printRegName(raw_ostream &O, MCRegister Reg) {
62*700637cbSDimitry Andric printFormattedRegName(&MAI, Reg, O);
63*700637cbSDimitry Andric }
64*700637cbSDimitry Andric
65*700637cbSDimitry Andric template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)66*700637cbSDimitry Andric void SystemZInstPrinterCommon::printUImmOperand(const MCInst *MI, int OpNum,
67*700637cbSDimitry Andric raw_ostream &O) {
68*700637cbSDimitry Andric const MCOperand &MO = MI->getOperand(OpNum);
69*700637cbSDimitry Andric if (MO.isExpr()) {
70*700637cbSDimitry Andric MAI.printExpr(O, *MO.getExpr());
71*700637cbSDimitry Andric return;
72*700637cbSDimitry Andric }
73*700637cbSDimitry Andric uint64_t Value = static_cast<uint64_t>(MO.getImm());
74*700637cbSDimitry Andric assert(isUInt<N>(Value) && "Invalid uimm argument");
75*700637cbSDimitry Andric markup(O, Markup::Immediate) << Value;
76*700637cbSDimitry Andric }
77*700637cbSDimitry Andric
78*700637cbSDimitry Andric template <unsigned N>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)79*700637cbSDimitry Andric void SystemZInstPrinterCommon::printSImmOperand(const MCInst *MI, int OpNum,
80*700637cbSDimitry Andric raw_ostream &O) {
81*700637cbSDimitry Andric const MCOperand &MO = MI->getOperand(OpNum);
82*700637cbSDimitry Andric if (MO.isExpr()) {
83*700637cbSDimitry Andric MAI.printExpr(O, *MO.getExpr());
84*700637cbSDimitry Andric return;
85*700637cbSDimitry Andric }
86*700637cbSDimitry Andric int64_t Value = MI->getOperand(OpNum).getImm();
87*700637cbSDimitry Andric assert(isInt<N>(Value) && "Invalid simm argument");
88*700637cbSDimitry Andric markup(O, Markup::Immediate) << Value;
89*700637cbSDimitry Andric }
90*700637cbSDimitry Andric
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)91*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU1ImmOperand(const MCInst *MI, int OpNum,
92*700637cbSDimitry Andric raw_ostream &O) {
93*700637cbSDimitry Andric printUImmOperand<1>(MI, OpNum, O);
94*700637cbSDimitry Andric }
95*700637cbSDimitry Andric
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)96*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU2ImmOperand(const MCInst *MI, int OpNum,
97*700637cbSDimitry Andric raw_ostream &O) {
98*700637cbSDimitry Andric printUImmOperand<2>(MI, OpNum, O);
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)101*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU3ImmOperand(const MCInst *MI, int OpNum,
102*700637cbSDimitry Andric raw_ostream &O) {
103*700637cbSDimitry Andric printUImmOperand<3>(MI, OpNum, O);
104*700637cbSDimitry Andric }
105*700637cbSDimitry Andric
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)106*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU4ImmOperand(const MCInst *MI, int OpNum,
107*700637cbSDimitry Andric raw_ostream &O) {
108*700637cbSDimitry Andric printUImmOperand<4>(MI, OpNum, O);
109*700637cbSDimitry Andric }
110*700637cbSDimitry Andric
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)111*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS8ImmOperand(const MCInst *MI, int OpNum,
112*700637cbSDimitry Andric raw_ostream &O) {
113*700637cbSDimitry Andric printSImmOperand<8>(MI, OpNum, O);
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)116*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU8ImmOperand(const MCInst *MI, int OpNum,
117*700637cbSDimitry Andric raw_ostream &O) {
118*700637cbSDimitry Andric printUImmOperand<8>(MI, OpNum, O);
119*700637cbSDimitry Andric }
120*700637cbSDimitry Andric
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)121*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU12ImmOperand(const MCInst *MI, int OpNum,
122*700637cbSDimitry Andric raw_ostream &O) {
123*700637cbSDimitry Andric printUImmOperand<12>(MI, OpNum, O);
124*700637cbSDimitry Andric }
125*700637cbSDimitry Andric
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)126*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS16ImmOperand(const MCInst *MI, int OpNum,
127*700637cbSDimitry Andric raw_ostream &O) {
128*700637cbSDimitry Andric printSImmOperand<16>(MI, OpNum, O);
129*700637cbSDimitry Andric }
130*700637cbSDimitry Andric
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)131*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU16ImmOperand(const MCInst *MI, int OpNum,
132*700637cbSDimitry Andric raw_ostream &O) {
133*700637cbSDimitry Andric printUImmOperand<16>(MI, OpNum, O);
134*700637cbSDimitry Andric }
135*700637cbSDimitry Andric
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)136*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS32ImmOperand(const MCInst *MI, int OpNum,
137*700637cbSDimitry Andric raw_ostream &O) {
138*700637cbSDimitry Andric printSImmOperand<32>(MI, OpNum, O);
139*700637cbSDimitry Andric }
140*700637cbSDimitry Andric
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)141*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU32ImmOperand(const MCInst *MI, int OpNum,
142*700637cbSDimitry Andric raw_ostream &O) {
143*700637cbSDimitry Andric printUImmOperand<32>(MI, OpNum, O);
144*700637cbSDimitry Andric }
145*700637cbSDimitry Andric
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)146*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU48ImmOperand(const MCInst *MI, int OpNum,
147*700637cbSDimitry Andric raw_ostream &O) {
148*700637cbSDimitry Andric printUImmOperand<48>(MI, OpNum, O);
149*700637cbSDimitry Andric }
150*700637cbSDimitry Andric
printPCRelOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)151*700637cbSDimitry Andric void SystemZInstPrinterCommon::printPCRelOperand(const MCInst *MI,
152*700637cbSDimitry Andric uint64_t Address, int OpNum,
153*700637cbSDimitry Andric raw_ostream &O) {
154*700637cbSDimitry Andric const MCOperand &MO = MI->getOperand(OpNum);
155*700637cbSDimitry Andric
156*700637cbSDimitry Andric // If the label has already been resolved to an immediate offset (say, when
157*700637cbSDimitry Andric // we're running the disassembler), just print the immediate.
158*700637cbSDimitry Andric if (MO.isImm()) {
159*700637cbSDimitry Andric int64_t Offset = MO.getImm();
160*700637cbSDimitry Andric if (PrintBranchImmAsAddress)
161*700637cbSDimitry Andric markup(O, Markup::Target) << formatHex(Address + Offset);
162*700637cbSDimitry Andric else
163*700637cbSDimitry Andric markup(O, Markup::Immediate) << formatImm(Offset);
164*700637cbSDimitry Andric return;
165*700637cbSDimitry Andric }
166*700637cbSDimitry Andric
167*700637cbSDimitry Andric // If the branch target is simply an address then print it in hex.
168*700637cbSDimitry Andric const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(MO.getExpr());
169*700637cbSDimitry Andric int64_t TargetAddress;
170*700637cbSDimitry Andric if (BranchTarget && BranchTarget->evaluateAsAbsolute(TargetAddress)) {
171*700637cbSDimitry Andric markup(O, Markup::Target) << formatHex((uint64_t)TargetAddress);
172*700637cbSDimitry Andric } else {
173*700637cbSDimitry Andric // Otherwise, just print the expression.
174*700637cbSDimitry Andric MAI.printExpr(O, *MO.getExpr());
175*700637cbSDimitry Andric }
176*700637cbSDimitry Andric }
177*700637cbSDimitry Andric
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)178*700637cbSDimitry Andric void SystemZInstPrinterCommon::printPCRelTLSOperand(const MCInst *MI,
179*700637cbSDimitry Andric uint64_t Address, int OpNum,
180*700637cbSDimitry Andric raw_ostream &O) {
181*700637cbSDimitry Andric // Output the PC-relative operand.
182*700637cbSDimitry Andric printPCRelOperand(MI, Address, OpNum, O);
183*700637cbSDimitry Andric
184*700637cbSDimitry Andric // Output the TLS marker if present.
185*700637cbSDimitry Andric if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
186*700637cbSDimitry Andric const MCOperand &MO = MI->getOperand(OpNum + 1);
187*700637cbSDimitry Andric const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
188*700637cbSDimitry Andric switch (refExp.getSpecifier()) {
189*700637cbSDimitry Andric case SystemZ::S_TLSGD:
190*700637cbSDimitry Andric O << ":tls_gdcall:";
191*700637cbSDimitry Andric break;
192*700637cbSDimitry Andric case SystemZ::S_TLSLDM:
193*700637cbSDimitry Andric O << ":tls_ldcall:";
194*700637cbSDimitry Andric break;
195*700637cbSDimitry Andric default:
196*700637cbSDimitry Andric llvm_unreachable("Unexpected symbol kind");
197*700637cbSDimitry Andric }
198*700637cbSDimitry Andric O << refExp.getSymbol().getName();
199*700637cbSDimitry Andric }
200*700637cbSDimitry Andric }
201*700637cbSDimitry Andric
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)202*700637cbSDimitry Andric void SystemZInstPrinterCommon::printOperand(const MCInst *MI, int OpNum,
203*700637cbSDimitry Andric raw_ostream &O) {
204*700637cbSDimitry Andric printOperand(MI->getOperand(OpNum), &MAI, O);
205*700637cbSDimitry Andric }
206*700637cbSDimitry Andric
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)207*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDAddrOperand(const MCInst *MI, int OpNum,
208*700637cbSDimitry Andric raw_ostream &O) {
209*700637cbSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
210*700637cbSDimitry Andric 0, O);
211*700637cbSDimitry Andric }
212*700637cbSDimitry Andric
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)213*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDXAddrOperand(const MCInst *MI, int OpNum,
214*700637cbSDimitry Andric raw_ostream &O) {
215*700637cbSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
216*700637cbSDimitry Andric MI->getOperand(OpNum + 2).getReg(), O);
217*700637cbSDimitry Andric }
218*700637cbSDimitry Andric
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)219*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDLAddrOperand(const MCInst *MI, int OpNum,
220*700637cbSDimitry Andric raw_ostream &O) {
221*700637cbSDimitry Andric unsigned Base = MI->getOperand(OpNum).getReg();
222*700637cbSDimitry Andric const MCOperand &DispMO = MI->getOperand(OpNum + 1);
223*700637cbSDimitry Andric uint64_t Length = MI->getOperand(OpNum + 2).getImm();
224*700637cbSDimitry Andric printOperand(DispMO, &MAI, O);
225*700637cbSDimitry Andric O << '(' << Length;
226*700637cbSDimitry Andric if (Base) {
227*700637cbSDimitry Andric O << ",";
228*700637cbSDimitry Andric printRegName(O, Base);
229*700637cbSDimitry Andric }
230*700637cbSDimitry Andric O << ')';
231*700637cbSDimitry Andric }
232*700637cbSDimitry Andric
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)233*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDRAddrOperand(const MCInst *MI, int OpNum,
234*700637cbSDimitry Andric raw_ostream &O) {
235*700637cbSDimitry Andric unsigned Base = MI->getOperand(OpNum).getReg();
236*700637cbSDimitry Andric const MCOperand &DispMO = MI->getOperand(OpNum + 1);
237*700637cbSDimitry Andric unsigned Length = MI->getOperand(OpNum + 2).getReg();
238*700637cbSDimitry Andric printOperand(DispMO, &MAI, O);
239*700637cbSDimitry Andric O << "(";
240*700637cbSDimitry Andric printRegName(O, Length);
241*700637cbSDimitry Andric if (Base) {
242*700637cbSDimitry Andric O << ",";
243*700637cbSDimitry Andric printRegName(O, Base);
244*700637cbSDimitry Andric }
245*700637cbSDimitry Andric O << ')';
246*700637cbSDimitry Andric }
247*700637cbSDimitry Andric
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)248*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDVAddrOperand(const MCInst *MI, int OpNum,
249*700637cbSDimitry Andric raw_ostream &O) {
250*700637cbSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
251*700637cbSDimitry Andric MI->getOperand(OpNum + 2).getReg(), O);
252*700637cbSDimitry Andric }
253*700637cbSDimitry Andric
printLXAAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)254*700637cbSDimitry Andric void SystemZInstPrinterCommon::printLXAAddrOperand(const MCInst *MI, int OpNum,
255*700637cbSDimitry Andric raw_ostream &O) {
256*700637cbSDimitry Andric printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
257*700637cbSDimitry Andric MI->getOperand(OpNum + 2).getReg(), O);
258*700637cbSDimitry Andric }
259*700637cbSDimitry Andric
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)260*700637cbSDimitry Andric void SystemZInstPrinterCommon::printCond4Operand(const MCInst *MI, int OpNum,
261*700637cbSDimitry Andric raw_ostream &O) {
262*700637cbSDimitry Andric static const char *const CondNames[] = {"o", "h", "nle", "l", "nhe",
263*700637cbSDimitry Andric "lh", "ne", "e", "nlh", "he",
264*700637cbSDimitry Andric "nl", "le", "nh", "no"};
265*700637cbSDimitry Andric uint64_t Imm = MI->getOperand(OpNum).getImm();
266*700637cbSDimitry Andric assert(Imm > 0 && Imm < 15 && "Invalid condition");
267*700637cbSDimitry Andric O << CondNames[Imm - 1];
268*700637cbSDimitry Andric }
269