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/MCInstrInfo.h"
13 #include "llvm/MC/MCSymbol.h"
14 #include "llvm/Support/raw_ostream.h"
15 
16 using namespace llvm;
17 
18 #define DEBUG_TYPE "asm-printer"
19 
20 #include "SystemZGenAsmWriter.inc"
21 
printAddress(unsigned Base,int64_t Disp,unsigned Index,raw_ostream & O)22 void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
23                                       unsigned Index, raw_ostream &O) {
24   O << Disp;
25   if (Base) {
26     O << '(';
27     if (Index)
28       O << '%' << getRegisterName(Index) << ',';
29     O << '%' << getRegisterName(Base) << ')';
30   } else
31     assert(!Index && "Shouldn't have an index without a base");
32 }
33 
printOperand(const MCOperand & MO,raw_ostream & O)34 void SystemZInstPrinter::printOperand(const MCOperand &MO, raw_ostream &O) {
35   if (MO.isReg())
36     O << '%' << getRegisterName(MO.getReg());
37   else if (MO.isImm())
38     O << MO.getImm();
39   else if (MO.isExpr())
40     O << *MO.getExpr();
41   else
42     llvm_unreachable("Invalid operand");
43 }
44 
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)45 void SystemZInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
46                                    StringRef Annot,
47                                    const MCSubtargetInfo &STI) {
48   printInstruction(MI, O);
49   printAnnotation(O, Annot);
50 }
51 
printRegName(raw_ostream & O,unsigned RegNo) const52 void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
53   O << '%' << getRegisterName(RegNo);
54 }
55 
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)56 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
57                                            raw_ostream &O) {
58   int64_t Value = MI->getOperand(OpNum).getImm();
59   assert(isUInt<4>(Value) && "Invalid u4imm argument");
60   O << Value;
61 }
62 
printU6ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)63 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
64                                            raw_ostream &O) {
65   int64_t Value = MI->getOperand(OpNum).getImm();
66   assert(isUInt<6>(Value) && "Invalid u6imm argument");
67   O << Value;
68 }
69 
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)70 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
71                                            raw_ostream &O) {
72   int64_t Value = MI->getOperand(OpNum).getImm();
73   assert(isInt<8>(Value) && "Invalid s8imm argument");
74   O << Value;
75 }
76 
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)77 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
78                                            raw_ostream &O) {
79   int64_t Value = MI->getOperand(OpNum).getImm();
80   assert(isUInt<8>(Value) && "Invalid u8imm argument");
81   O << Value;
82 }
83 
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)84 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
85                                             raw_ostream &O) {
86   int64_t Value = MI->getOperand(OpNum).getImm();
87   assert(isInt<16>(Value) && "Invalid s16imm argument");
88   O << Value;
89 }
90 
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)91 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
92                                             raw_ostream &O) {
93   int64_t Value = MI->getOperand(OpNum).getImm();
94   assert(isUInt<16>(Value) && "Invalid u16imm argument");
95   O << Value;
96 }
97 
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)98 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
99                                             raw_ostream &O) {
100   int64_t Value = MI->getOperand(OpNum).getImm();
101   assert(isInt<32>(Value) && "Invalid s32imm argument");
102   O << Value;
103 }
104 
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)105 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
106                                             raw_ostream &O) {
107   int64_t Value = MI->getOperand(OpNum).getImm();
108   assert(isUInt<32>(Value) && "Invalid u32imm argument");
109   O << Value;
110 }
111 
printAccessRegOperand(const MCInst * MI,int OpNum,raw_ostream & O)112 void SystemZInstPrinter::printAccessRegOperand(const MCInst *MI, int OpNum,
113                                                raw_ostream &O) {
114   uint64_t Value = MI->getOperand(OpNum).getImm();
115   assert(Value < 16 && "Invalid access register number");
116   O << "%a" << (unsigned int)Value;
117 }
118 
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)119 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
120                                            raw_ostream &O) {
121   const MCOperand &MO = MI->getOperand(OpNum);
122   if (MO.isImm()) {
123     O << "0x";
124     O.write_hex(MO.getImm());
125   } else
126     O << *MO.getExpr();
127 }
128 
printPCRelTLSOperand(const MCInst * MI,int OpNum,raw_ostream & O)129 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
130                                               raw_ostream &O) {
131   // Output the PC-relative operand.
132   printPCRelOperand(MI, OpNum, O);
133 
134   // Output the TLS marker if present.
135   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
136     const MCOperand &MO = MI->getOperand(OpNum + 1);
137     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
138     switch (refExp.getKind()) {
139       case MCSymbolRefExpr::VK_TLSGD:
140         O << ":tls_gdcall:";
141         break;
142       case MCSymbolRefExpr::VK_TLSLDM:
143         O << ":tls_ldcall:";
144         break;
145       default:
146         llvm_unreachable("Unexpected symbol kind");
147     }
148     O << refExp.getSymbol().getName();
149   }
150 }
151 
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)152 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
153                                       raw_ostream &O) {
154   printOperand(MI->getOperand(OpNum), O);
155 }
156 
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)157 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
158                                             raw_ostream &O) {
159   printAddress(MI->getOperand(OpNum).getReg(),
160                MI->getOperand(OpNum + 1).getImm(), 0, O);
161 }
162 
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)163 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
164                                              raw_ostream &O) {
165   printAddress(MI->getOperand(OpNum).getReg(),
166                MI->getOperand(OpNum + 1).getImm(),
167                MI->getOperand(OpNum + 2).getReg(), O);
168 }
169 
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)170 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
171                                              raw_ostream &O) {
172   unsigned Base = MI->getOperand(OpNum).getReg();
173   uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
174   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
175   O << Disp << '(' << Length;
176   if (Base)
177     O << ",%" << getRegisterName(Base);
178   O << ')';
179 }
180 
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)181 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
182                                            raw_ostream &O) {
183   static const char *const CondNames[] = {
184     "o", "h", "nle", "l", "nhe", "lh", "ne",
185     "e", "nlh", "he", "nl", "le", "nh", "no"
186   };
187   uint64_t Imm = MI->getOperand(OpNum).getImm();
188   assert(Imm > 0 && Imm < 15 && "Invalid condition");
189   O << CondNames[Imm - 1];
190 }
191