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
printAddress(unsigned Base,int64_t Disp,unsigned Index,raw_ostream & O)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
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)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
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)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
printRegName(raw_ostream & O,unsigned RegNo) const59 void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
60 O << '%' << getRegisterName(RegNo);
61 }
62
63 template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)77 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
78 raw_ostream &O) {
79 printUImmOperand<1>(MI, OpNum, O);
80 }
81
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)82 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
83 raw_ostream &O) {
84 printUImmOperand<2>(MI, OpNum, O);
85 }
86
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)87 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
88 raw_ostream &O) {
89 printUImmOperand<3>(MI, OpNum, O);
90 }
91
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)92 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
93 raw_ostream &O) {
94 printUImmOperand<4>(MI, OpNum, O);
95 }
96
printU6ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)97 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
98 raw_ostream &O) {
99 printUImmOperand<6>(MI, OpNum, O);
100 }
101
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)102 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
103 raw_ostream &O) {
104 printSImmOperand<8>(MI, OpNum, O);
105 }
106
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)107 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
108 raw_ostream &O) {
109 printUImmOperand<8>(MI, OpNum, O);
110 }
111
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)112 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
113 raw_ostream &O) {
114 printUImmOperand<12>(MI, OpNum, O);
115 }
116
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)117 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
118 raw_ostream &O) {
119 printSImmOperand<16>(MI, OpNum, O);
120 }
121
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)122 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
123 raw_ostream &O) {
124 printUImmOperand<16>(MI, OpNum, O);
125 }
126
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)127 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
128 raw_ostream &O) {
129 printSImmOperand<32>(MI, OpNum, O);
130 }
131
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)132 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
133 raw_ostream &O) {
134 printUImmOperand<32>(MI, OpNum, O);
135 }
136
printAccessRegOperand(const MCInst * MI,int OpNum,raw_ostream & O)137 void 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
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)144 void 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
printPCRelTLSOperand(const MCInst * MI,int OpNum,raw_ostream & O)154 void 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
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)177 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
178 raw_ostream &O) {
179 printOperand(MI->getOperand(OpNum), &MAI, O);
180 }
181
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)182 void 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
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)188 void 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
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)195 void 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
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)206 void 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
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)213 void 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