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 
18 using namespace llvm;
19 
20 #define DEBUG_TYPE "asm-printer"
21 
22 #include "SystemZGenAsmWriter.inc"
23 
24 void 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 
40 void 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 
52 void 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 
59 void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
60   O << '%' << getRegisterName(RegNo);
61 }
62 
63 template <unsigned N>
64 static 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 
70 template <unsigned N>
71 static 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 
77 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
78                                            raw_ostream &O) {
79   printUImmOperand<1>(MI, OpNum, O);
80 }
81 
82 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
83                                            raw_ostream &O) {
84   printUImmOperand<2>(MI, OpNum, O);
85 }
86 
87 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
88                                            raw_ostream &O) {
89   printUImmOperand<3>(MI, OpNum, O);
90 }
91 
92 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
93                                            raw_ostream &O) {
94   printUImmOperand<4>(MI, OpNum, O);
95 }
96 
97 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
98                                            raw_ostream &O) {
99   printUImmOperand<6>(MI, OpNum, O);
100 }
101 
102 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
103                                            raw_ostream &O) {
104   printSImmOperand<8>(MI, OpNum, O);
105 }
106 
107 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
108                                            raw_ostream &O) {
109   printUImmOperand<8>(MI, OpNum, O);
110 }
111 
112 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
113                                             raw_ostream &O) {
114   printUImmOperand<12>(MI, OpNum, O);
115 }
116 
117 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
118                                             raw_ostream &O) {
119   printSImmOperand<16>(MI, OpNum, O);
120 }
121 
122 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
123                                             raw_ostream &O) {
124   printUImmOperand<16>(MI, OpNum, O);
125 }
126 
127 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
128                                             raw_ostream &O) {
129   printSImmOperand<32>(MI, OpNum, O);
130 }
131 
132 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
133                                             raw_ostream &O) {
134   printUImmOperand<32>(MI, OpNum, O);
135 }
136 
137 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
138                                             raw_ostream &O) {
139   printUImmOperand<48>(MI, OpNum, O);
140 }
141 
142 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
143                                            raw_ostream &O) {
144   const MCOperand &MO = MI->getOperand(OpNum);
145   if (MO.isImm()) {
146     O << "0x";
147     O.write_hex(MO.getImm());
148   } else
149     MO.getExpr()->print(O, &MAI);
150 }
151 
152 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
153                                               raw_ostream &O) {
154   // Output the PC-relative operand.
155   printPCRelOperand(MI, OpNum, O);
156 
157   // Output the TLS marker if present.
158   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
159     const MCOperand &MO = MI->getOperand(OpNum + 1);
160     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
161     switch (refExp.getKind()) {
162       case MCSymbolRefExpr::VK_TLSGD:
163         O << ":tls_gdcall:";
164         break;
165       case MCSymbolRefExpr::VK_TLSLDM:
166         O << ":tls_ldcall:";
167         break;
168       default:
169         llvm_unreachable("Unexpected symbol kind");
170     }
171     O << refExp.getSymbol().getName();
172   }
173 }
174 
175 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
176                                       raw_ostream &O) {
177   printOperand(MI->getOperand(OpNum), &MAI, O);
178 }
179 
180 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
181                                             raw_ostream &O) {
182   printAddress(MI->getOperand(OpNum).getReg(),
183                MI->getOperand(OpNum + 1).getImm(), 0, O);
184 }
185 
186 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
187                                              raw_ostream &O) {
188   printAddress(MI->getOperand(OpNum).getReg(),
189                MI->getOperand(OpNum + 1).getImm(),
190                MI->getOperand(OpNum + 2).getReg(), O);
191 }
192 
193 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
194                                              raw_ostream &O) {
195   unsigned Base = MI->getOperand(OpNum).getReg();
196   uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
197   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
198   O << Disp << '(' << Length;
199   if (Base)
200     O << ",%" << getRegisterName(Base);
201   O << ')';
202 }
203 
204 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
205                                              raw_ostream &O) {
206   unsigned Base = MI->getOperand(OpNum).getReg();
207   uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
208   unsigned Length = MI->getOperand(OpNum + 2).getReg();
209   O << Disp << "(%" << getRegisterName(Length);
210   if (Base)
211     O << ",%" << getRegisterName(Base);
212   O << ')';
213 }
214 
215 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
216                                              raw_ostream &O) {
217   printAddress(MI->getOperand(OpNum).getReg(),
218                MI->getOperand(OpNum + 1).getImm(),
219                MI->getOperand(OpNum + 2).getReg(), O);
220 }
221 
222 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
223                                            raw_ostream &O) {
224   static const char *const CondNames[] = {
225     "o", "h", "nle", "l", "nhe", "lh", "ne",
226     "e", "nlh", "he", "nl", "le", "nh", "no"
227   };
228   uint64_t Imm = MI->getOperand(OpNum).getImm();
229   assert(Imm > 0 && Imm < 15 && "Invalid condition");
230   O << CondNames[Imm - 1];
231 }
232