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