SystemZInstPrinter.cpp revision 360784
1//===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===//
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 "SystemZInstPrinter.h"
10#include "llvm/MC/MCExpr.h"
11#include "llvm/MC/MCInst.h"
12#include "llvm/MC/MCSymbol.h"
13#include "llvm/Support/Casting.h"
14#include "llvm/Support/ErrorHandling.h"
15#include "llvm/Support/MathExtras.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cassert>
18#include <cstdint>
19
20using namespace llvm;
21
22#define DEBUG_TYPE "asm-printer"
23
24#include "SystemZGenAsmWriter.inc"
25
26void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
27                                      unsigned Index, raw_ostream &O) {
28  O << Disp;
29  if (Base || Index) {
30    O << '(';
31    if (Index) {
32      O << '%' << getRegisterName(Index);
33      if (Base)
34        O << ',';
35    }
36    if (Base)
37      O << '%' << getRegisterName(Base);
38    O << ')';
39  }
40}
41
42void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI,
43                                      raw_ostream &O) {
44  if (MO.isReg()) {
45    if (!MO.getReg())
46      O << '0';
47    else
48      O << '%' << getRegisterName(MO.getReg());
49  }
50  else if (MO.isImm())
51    O << MO.getImm();
52  else if (MO.isExpr())
53    MO.getExpr()->print(O, MAI);
54  else
55    llvm_unreachable("Invalid operand");
56}
57
58void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address,
59                                   StringRef Annot, const MCSubtargetInfo &STI,
60                                   raw_ostream &O) {
61  printInstruction(MI, Address, O);
62  printAnnotation(O, Annot);
63}
64
65void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
66  O << '%' << getRegisterName(RegNo);
67}
68
69template <unsigned N>
70static void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
71  int64_t Value = MI->getOperand(OpNum).getImm();
72  assert(isUInt<N>(Value) && "Invalid uimm argument");
73  O << Value;
74}
75
76template <unsigned N>
77static void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
78  int64_t Value = MI->getOperand(OpNum).getImm();
79  assert(isInt<N>(Value) && "Invalid simm argument");
80  O << Value;
81}
82
83void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
84                                           raw_ostream &O) {
85  printUImmOperand<1>(MI, OpNum, O);
86}
87
88void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
89                                           raw_ostream &O) {
90  printUImmOperand<2>(MI, OpNum, O);
91}
92
93void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
94                                           raw_ostream &O) {
95  printUImmOperand<3>(MI, OpNum, O);
96}
97
98void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
99                                           raw_ostream &O) {
100  printUImmOperand<4>(MI, OpNum, O);
101}
102
103void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
104                                           raw_ostream &O) {
105  printUImmOperand<6>(MI, OpNum, O);
106}
107
108void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
109                                           raw_ostream &O) {
110  printSImmOperand<8>(MI, OpNum, O);
111}
112
113void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
114                                           raw_ostream &O) {
115  printUImmOperand<8>(MI, OpNum, O);
116}
117
118void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
119                                            raw_ostream &O) {
120  printUImmOperand<12>(MI, OpNum, O);
121}
122
123void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
124                                            raw_ostream &O) {
125  printSImmOperand<16>(MI, OpNum, O);
126}
127
128void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
129                                            raw_ostream &O) {
130  printUImmOperand<16>(MI, OpNum, O);
131}
132
133void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
134                                            raw_ostream &O) {
135  printSImmOperand<32>(MI, OpNum, O);
136}
137
138void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
139                                            raw_ostream &O) {
140  printUImmOperand<32>(MI, OpNum, O);
141}
142
143void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
144                                            raw_ostream &O) {
145  printUImmOperand<48>(MI, OpNum, O);
146}
147
148void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
149                                           raw_ostream &O) {
150  const MCOperand &MO = MI->getOperand(OpNum);
151  if (MO.isImm()) {
152    O << "0x";
153    O.write_hex(MO.getImm());
154  } else
155    MO.getExpr()->print(O, &MAI);
156}
157
158void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
159                                              raw_ostream &O) {
160  // Output the PC-relative operand.
161  printPCRelOperand(MI, OpNum, O);
162
163  // Output the TLS marker if present.
164  if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
165    const MCOperand &MO = MI->getOperand(OpNum + 1);
166    const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
167    switch (refExp.getKind()) {
168      case MCSymbolRefExpr::VK_TLSGD:
169        O << ":tls_gdcall:";
170        break;
171      case MCSymbolRefExpr::VK_TLSLDM:
172        O << ":tls_ldcall:";
173        break;
174      default:
175        llvm_unreachable("Unexpected symbol kind");
176    }
177    O << refExp.getSymbol().getName();
178  }
179}
180
181void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
182                                      raw_ostream &O) {
183  printOperand(MI->getOperand(OpNum), &MAI, O);
184}
185
186void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
187                                            raw_ostream &O) {
188  printAddress(MI->getOperand(OpNum).getReg(),
189               MI->getOperand(OpNum + 1).getImm(), 0, O);
190}
191
192void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
193                                             raw_ostream &O) {
194  printAddress(MI->getOperand(OpNum).getReg(),
195               MI->getOperand(OpNum + 1).getImm(),
196               MI->getOperand(OpNum + 2).getReg(), O);
197}
198
199void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
200                                             raw_ostream &O) {
201  unsigned Base = MI->getOperand(OpNum).getReg();
202  uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
203  uint64_t Length = MI->getOperand(OpNum + 2).getImm();
204  O << Disp << '(' << Length;
205  if (Base)
206    O << ",%" << getRegisterName(Base);
207  O << ')';
208}
209
210void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
211                                             raw_ostream &O) {
212  unsigned Base = MI->getOperand(OpNum).getReg();
213  uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
214  unsigned Length = MI->getOperand(OpNum + 2).getReg();
215  O << Disp << "(%" << getRegisterName(Length);
216  if (Base)
217    O << ",%" << getRegisterName(Base);
218  O << ')';
219}
220
221void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
222                                             raw_ostream &O) {
223  printAddress(MI->getOperand(OpNum).getReg(),
224               MI->getOperand(OpNum + 1).getImm(),
225               MI->getOperand(OpNum + 2).getReg(), O);
226}
227
228void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
229                                           raw_ostream &O) {
230  static const char *const CondNames[] = {
231    "o", "h", "nle", "l", "nhe", "lh", "ne",
232    "e", "nlh", "he", "nl", "le", "nh", "no"
233  };
234  uint64_t Imm = MI->getOperand(OpNum).getImm();
235  assert(Imm > 0 && Imm < 15 && "Invalid condition");
236  O << CondNames[Imm - 1];
237}
238