1*7a7e6055SDimitry Andric //===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===//
2284c1978SDimitry Andric //
3284c1978SDimitry Andric //                     The LLVM Compiler Infrastructure
4284c1978SDimitry Andric //
5284c1978SDimitry Andric // This file is distributed under the University of Illinois Open Source
6284c1978SDimitry Andric // License. See LICENSE.TXT for details.
7284c1978SDimitry Andric //
8284c1978SDimitry Andric //===----------------------------------------------------------------------===//
9284c1978SDimitry Andric 
10284c1978SDimitry Andric #include "SystemZInstPrinter.h"
11284c1978SDimitry Andric #include "llvm/MC/MCExpr.h"
12ff0cc061SDimitry Andric #include "llvm/MC/MCInst.h"
13ff0cc061SDimitry Andric #include "llvm/MC/MCSymbol.h"
14*7a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
15ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h"
16*7a7e6055SDimitry Andric #include "llvm/Support/MathExtras.h"
17284c1978SDimitry Andric #include "llvm/Support/raw_ostream.h"
18*7a7e6055SDimitry Andric #include <cassert>
19*7a7e6055SDimitry Andric #include <cstdint>
20284c1978SDimitry Andric 
21284c1978SDimitry Andric using namespace llvm;
22284c1978SDimitry Andric 
2391bc56edSDimitry Andric #define DEBUG_TYPE "asm-printer"
2491bc56edSDimitry Andric 
25284c1978SDimitry Andric #include "SystemZGenAsmWriter.inc"
26284c1978SDimitry Andric 
printAddress(unsigned Base,int64_t Disp,unsigned Index,raw_ostream & O)27284c1978SDimitry Andric void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
28284c1978SDimitry Andric                                       unsigned Index, raw_ostream &O) {
29284c1978SDimitry Andric   O << Disp;
30ff0cc061SDimitry Andric   if (Base || Index) {
31284c1978SDimitry Andric     O << '(';
32ff0cc061SDimitry Andric     if (Index) {
33ff0cc061SDimitry Andric       O << '%' << getRegisterName(Index);
34ff0cc061SDimitry Andric       if (Base)
35ff0cc061SDimitry Andric         O << ',';
36ff0cc061SDimitry Andric     }
37ff0cc061SDimitry Andric     if (Base)
38ff0cc061SDimitry Andric       O << '%' << getRegisterName(Base);
39ff0cc061SDimitry Andric     O << ')';
40ff0cc061SDimitry Andric   }
41284c1978SDimitry Andric }
42284c1978SDimitry Andric 
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)4397bc6c73SDimitry Andric void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI,
4497bc6c73SDimitry Andric                                       raw_ostream &O) {
45284c1978SDimitry Andric   if (MO.isReg())
46284c1978SDimitry Andric     O << '%' << getRegisterName(MO.getReg());
47284c1978SDimitry Andric   else if (MO.isImm())
48284c1978SDimitry Andric     O << MO.getImm();
49284c1978SDimitry Andric   else if (MO.isExpr())
5097bc6c73SDimitry Andric     MO.getExpr()->print(O, MAI);
51284c1978SDimitry Andric   else
52284c1978SDimitry Andric     llvm_unreachable("Invalid operand");
53284c1978SDimitry Andric }
54284c1978SDimitry Andric 
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)55284c1978SDimitry Andric void SystemZInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
56ff0cc061SDimitry Andric                                    StringRef Annot,
57ff0cc061SDimitry Andric                                    const MCSubtargetInfo &STI) {
58284c1978SDimitry Andric   printInstruction(MI, O);
59284c1978SDimitry Andric   printAnnotation(O, Annot);
60284c1978SDimitry Andric }
61284c1978SDimitry Andric 
printRegName(raw_ostream & O,unsigned RegNo) const62284c1978SDimitry Andric void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
63284c1978SDimitry Andric   O << '%' << getRegisterName(RegNo);
64284c1978SDimitry Andric }
65284c1978SDimitry Andric 
66ff0cc061SDimitry Andric template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)677d523365SDimitry Andric static void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
68ff0cc061SDimitry Andric   int64_t Value = MI->getOperand(OpNum).getImm();
69ff0cc061SDimitry Andric   assert(isUInt<N>(Value) && "Invalid uimm argument");
70ff0cc061SDimitry Andric   O << Value;
71ff0cc061SDimitry Andric }
72ff0cc061SDimitry Andric 
73ff0cc061SDimitry Andric template <unsigned N>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)747d523365SDimitry Andric static void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
75ff0cc061SDimitry Andric   int64_t Value = MI->getOperand(OpNum).getImm();
76ff0cc061SDimitry Andric   assert(isInt<N>(Value) && "Invalid simm argument");
77ff0cc061SDimitry Andric   O << Value;
78ff0cc061SDimitry Andric }
79ff0cc061SDimitry Andric 
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)80ff0cc061SDimitry Andric void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
81ff0cc061SDimitry Andric                                            raw_ostream &O) {
82ff0cc061SDimitry Andric   printUImmOperand<1>(MI, OpNum, O);
83ff0cc061SDimitry Andric }
84ff0cc061SDimitry Andric 
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)85ff0cc061SDimitry Andric void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
86ff0cc061SDimitry Andric                                            raw_ostream &O) {
87ff0cc061SDimitry Andric   printUImmOperand<2>(MI, OpNum, O);
88ff0cc061SDimitry Andric }
89ff0cc061SDimitry Andric 
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)90ff0cc061SDimitry Andric void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
91ff0cc061SDimitry Andric                                            raw_ostream &O) {
92ff0cc061SDimitry Andric   printUImmOperand<3>(MI, OpNum, O);
93ff0cc061SDimitry Andric }
94ff0cc061SDimitry Andric 
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)95284c1978SDimitry Andric void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
96284c1978SDimitry Andric                                            raw_ostream &O) {
97ff0cc061SDimitry Andric   printUImmOperand<4>(MI, OpNum, O);
98284c1978SDimitry Andric }
99284c1978SDimitry Andric 
printU6ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)100284c1978SDimitry Andric void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
101284c1978SDimitry Andric                                            raw_ostream &O) {
102ff0cc061SDimitry Andric   printUImmOperand<6>(MI, OpNum, O);
103284c1978SDimitry Andric }
104284c1978SDimitry Andric 
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)105284c1978SDimitry Andric void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
106284c1978SDimitry Andric                                            raw_ostream &O) {
107ff0cc061SDimitry Andric   printSImmOperand<8>(MI, OpNum, O);
108284c1978SDimitry Andric }
109284c1978SDimitry Andric 
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)110284c1978SDimitry Andric void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
111284c1978SDimitry Andric                                            raw_ostream &O) {
112ff0cc061SDimitry Andric   printUImmOperand<8>(MI, OpNum, O);
113ff0cc061SDimitry Andric }
114ff0cc061SDimitry Andric 
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)115ff0cc061SDimitry Andric void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
116ff0cc061SDimitry Andric                                             raw_ostream &O) {
117ff0cc061SDimitry Andric   printUImmOperand<12>(MI, OpNum, O);
118284c1978SDimitry Andric }
119284c1978SDimitry Andric 
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)120284c1978SDimitry Andric void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
121284c1978SDimitry Andric                                             raw_ostream &O) {
122ff0cc061SDimitry Andric   printSImmOperand<16>(MI, OpNum, O);
123284c1978SDimitry Andric }
124284c1978SDimitry Andric 
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)125284c1978SDimitry Andric void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
126284c1978SDimitry Andric                                             raw_ostream &O) {
127ff0cc061SDimitry Andric   printUImmOperand<16>(MI, OpNum, O);
128284c1978SDimitry Andric }
129284c1978SDimitry Andric 
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)130284c1978SDimitry Andric void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
131284c1978SDimitry Andric                                             raw_ostream &O) {
132ff0cc061SDimitry Andric   printSImmOperand<32>(MI, OpNum, O);
133284c1978SDimitry Andric }
134284c1978SDimitry Andric 
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)135284c1978SDimitry Andric void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
136284c1978SDimitry Andric                                             raw_ostream &O) {
137ff0cc061SDimitry Andric   printUImmOperand<32>(MI, OpNum, O);
138284c1978SDimitry Andric }
139284c1978SDimitry Andric 
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)140d88c1a5aSDimitry Andric void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
141284c1978SDimitry Andric                                             raw_ostream &O) {
142d88c1a5aSDimitry Andric   printUImmOperand<48>(MI, OpNum, O);
143284c1978SDimitry Andric }
144284c1978SDimitry Andric 
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)145f785676fSDimitry Andric void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
146284c1978SDimitry Andric                                            raw_ostream &O) {
147f785676fSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
148f785676fSDimitry Andric   if (MO.isImm()) {
149f785676fSDimitry Andric     O << "0x";
150f785676fSDimitry Andric     O.write_hex(MO.getImm());
151f785676fSDimitry Andric   } else
15297bc6c73SDimitry Andric     MO.getExpr()->print(O, &MAI);
153284c1978SDimitry Andric }
154284c1978SDimitry Andric 
printPCRelTLSOperand(const MCInst * MI,int OpNum,raw_ostream & O)155ff0cc061SDimitry Andric void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
156ff0cc061SDimitry Andric                                               raw_ostream &O) {
157ff0cc061SDimitry Andric   // Output the PC-relative operand.
158ff0cc061SDimitry Andric   printPCRelOperand(MI, OpNum, O);
159ff0cc061SDimitry Andric 
160ff0cc061SDimitry Andric   // Output the TLS marker if present.
161ff0cc061SDimitry Andric   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
162ff0cc061SDimitry Andric     const MCOperand &MO = MI->getOperand(OpNum + 1);
163ff0cc061SDimitry Andric     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
164ff0cc061SDimitry Andric     switch (refExp.getKind()) {
165ff0cc061SDimitry Andric       case MCSymbolRefExpr::VK_TLSGD:
166ff0cc061SDimitry Andric         O << ":tls_gdcall:";
167ff0cc061SDimitry Andric         break;
168ff0cc061SDimitry Andric       case MCSymbolRefExpr::VK_TLSLDM:
169ff0cc061SDimitry Andric         O << ":tls_ldcall:";
170ff0cc061SDimitry Andric         break;
171ff0cc061SDimitry Andric       default:
172ff0cc061SDimitry Andric         llvm_unreachable("Unexpected symbol kind");
173ff0cc061SDimitry Andric     }
174ff0cc061SDimitry Andric     O << refExp.getSymbol().getName();
175ff0cc061SDimitry Andric   }
176ff0cc061SDimitry Andric }
177ff0cc061SDimitry Andric 
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)178284c1978SDimitry Andric void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
179284c1978SDimitry Andric                                       raw_ostream &O) {
18097bc6c73SDimitry Andric   printOperand(MI->getOperand(OpNum), &MAI, O);
181284c1978SDimitry Andric }
182284c1978SDimitry Andric 
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)183284c1978SDimitry Andric void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
184284c1978SDimitry Andric                                             raw_ostream &O) {
185284c1978SDimitry Andric   printAddress(MI->getOperand(OpNum).getReg(),
186284c1978SDimitry Andric                MI->getOperand(OpNum + 1).getImm(), 0, O);
187284c1978SDimitry Andric }
188284c1978SDimitry Andric 
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)189284c1978SDimitry Andric void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
190284c1978SDimitry Andric                                              raw_ostream &O) {
191284c1978SDimitry Andric   printAddress(MI->getOperand(OpNum).getReg(),
192284c1978SDimitry Andric                MI->getOperand(OpNum + 1).getImm(),
193284c1978SDimitry Andric                MI->getOperand(OpNum + 2).getReg(), O);
194284c1978SDimitry Andric }
195284c1978SDimitry Andric 
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)196f785676fSDimitry Andric void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
197f785676fSDimitry Andric                                              raw_ostream &O) {
198f785676fSDimitry Andric   unsigned Base = MI->getOperand(OpNum).getReg();
199f785676fSDimitry Andric   uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
200f785676fSDimitry Andric   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
201f785676fSDimitry Andric   O << Disp << '(' << Length;
202f785676fSDimitry Andric   if (Base)
203f785676fSDimitry Andric     O << ",%" << getRegisterName(Base);
204f785676fSDimitry Andric   O << ')';
205f785676fSDimitry Andric }
206f785676fSDimitry Andric 
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)207d88c1a5aSDimitry Andric void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
208d88c1a5aSDimitry Andric                                              raw_ostream &O) {
209d88c1a5aSDimitry Andric   unsigned Base = MI->getOperand(OpNum).getReg();
210d88c1a5aSDimitry Andric   uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
211d88c1a5aSDimitry Andric   unsigned Length = MI->getOperand(OpNum + 2).getReg();
212d88c1a5aSDimitry Andric   O << Disp << "(%" << getRegisterName(Length);
213d88c1a5aSDimitry Andric   if (Base)
214d88c1a5aSDimitry Andric     O << ",%" << getRegisterName(Base);
215d88c1a5aSDimitry Andric   O << ')';
216d88c1a5aSDimitry Andric }
217d88c1a5aSDimitry Andric 
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)218ff0cc061SDimitry Andric void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
219ff0cc061SDimitry Andric                                              raw_ostream &O) {
220ff0cc061SDimitry Andric   printAddress(MI->getOperand(OpNum).getReg(),
221ff0cc061SDimitry Andric                MI->getOperand(OpNum + 1).getImm(),
222ff0cc061SDimitry Andric                MI->getOperand(OpNum + 2).getReg(), O);
223ff0cc061SDimitry Andric }
224ff0cc061SDimitry Andric 
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)225284c1978SDimitry Andric void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
226284c1978SDimitry Andric                                            raw_ostream &O) {
227284c1978SDimitry Andric   static const char *const CondNames[] = {
228284c1978SDimitry Andric     "o", "h", "nle", "l", "nhe", "lh", "ne",
229284c1978SDimitry Andric     "e", "nlh", "he", "nl", "le", "nh", "no"
230284c1978SDimitry Andric   };
231284c1978SDimitry Andric   uint64_t Imm = MI->getOperand(OpNum).getImm();
232284c1978SDimitry Andric   assert(Imm > 0 && Imm < 15 && "Invalid condition");
233284c1978SDimitry Andric   O << CondNames[Imm - 1];
234284c1978SDimitry Andric }
235