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