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