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