blob: 6460b88d142a66b371989b228e9dbbf84c86d7a5 [file] [log] [blame]
Jacques Pienaarfcef3e42016-03-28 13:09:54 +00001//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm 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// This class prints an Lanai MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Lanai.h"
15#include "LanaiInstPrinter.h"
16#include "MCTargetDesc/LanaiMCExpr.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCSymbol.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "llvm/Support/FormattedStream.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "asm-printer"
27
28// Include the auto-generated portion of the assembly writer.
29#define PRINT_ALIAS_INSTR
30#include "LanaiGenAsmWriter.inc"
31
32void LanaiInstPrinter::printRegName(raw_ostream &Ostream,
33 unsigned RegNo) const {
34 Ostream << StringRef(getRegisterName(RegNo)).lower();
35}
36
37bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
38 StringRef Alias, unsigned OpNo0,
39 unsigned OpNo1) {
40 Ostream << "\t" << Alias << " ";
41 printOperand(MI, OpNo0, Ostream);
42 Ostream << ", ";
43 printOperand(MI, OpNo1, Ostream);
44 return true;
45}
46
47static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
48 unsigned AluCode = MI->getOperand(3).getImm();
49 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
50 (MI->getOperand(2).getImm() == AddOffset ||
51 MI->getOperand(2).getImm() == -AddOffset);
52}
53
54static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
55 unsigned AluCode = MI->getOperand(3).getImm();
56 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
57}
58
59static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
60 unsigned AluCode = MI->getOperand(3).getImm();
61 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
62}
63
64static StringRef decIncOperator(const MCInst *MI) {
65 if (MI->getOperand(2).getImm() < 0)
66 return "--";
67 return "++";
68}
69
70bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
71 raw_ostream &Ostream,
72 StringRef Opcode,
73 int AddOffset) {
74 if (isPreIncrementForm(MI, AddOffset)) {
75 Ostream << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
76 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
77 << getRegisterName(MI->getOperand(0).getReg());
78 return true;
79 }
80 if (isPostIncrementForm(MI, AddOffset)) {
81 Ostream << "\t" << Opcode << "\t[%"
82 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
83 << "], %" << getRegisterName(MI->getOperand(0).getReg());
84 return true;
85 }
86 return false;
87}
88
89bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
90 raw_ostream &Ostream,
91 StringRef Opcode,
92 int AddOffset) {
93 if (isPreIncrementForm(MI, AddOffset)) {
94 Ostream << "\t" << Opcode << "\t%"
95 << getRegisterName(MI->getOperand(0).getReg()) << ", ["
96 << decIncOperator(MI) << "%"
97 << getRegisterName(MI->getOperand(1).getReg()) << "]";
98 return true;
99 }
100 if (isPostIncrementForm(MI, AddOffset)) {
101 Ostream << "\t" << Opcode << "\t%"
102 << getRegisterName(MI->getOperand(0).getReg()) << ", [%"
103 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
104 << "]";
105 return true;
106 }
107 return false;
108}
109
110bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &Ostream) {
111 switch (MI->getOpcode()) {
112 case Lanai::LDW_RI:
113 // ld 4[*%rN], %rX => ld [++imm], %rX
114 // ld -4[*%rN], %rX => ld [--imm], %rX
115 // ld 4[%rN*], %rX => ld [imm++], %rX
116 // ld -4[%rN*], %rX => ld [imm--], %rX
117 return printMemoryLoadIncrement(MI, Ostream, "ld", 4);
118 case Lanai::LDHs_RI:
119 return printMemoryLoadIncrement(MI, Ostream, "ld.h", 2);
120 case Lanai::LDHz_RI:
121 return printMemoryLoadIncrement(MI, Ostream, "uld.h", 2);
122 case Lanai::LDBs_RI:
123 return printMemoryLoadIncrement(MI, Ostream, "ld.b", 1);
124 case Lanai::LDBz_RI:
125 return printMemoryLoadIncrement(MI, Ostream, "uld.b", 1);
126 case Lanai::SW_RI:
127 // st %rX, 4[*%rN] => st %rX, [++imm]
128 // st %rX, -4[*%rN] => st %rX, [--imm]
129 // st %rX, 4[%rN*] => st %rX, [imm++]
130 // st %rX, -4[%rN*] => st %rX, [imm--]
131 return printMemoryStoreIncrement(MI, Ostream, "st", 4);
132 case Lanai::STH_RI:
133 return printMemoryStoreIncrement(MI, Ostream, "st.h", 2);
134 case Lanai::STB_RI:
135 return printMemoryStoreIncrement(MI, Ostream, "st.b", 1);
136 default:
137 return false;
138 }
139}
140
141void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
142 StringRef Annotation,
143 const MCSubtargetInfo &STI) {
144 if (!printAlias(MI, Ostream) && !printAliasInstr(MI, Ostream))
145 printInstruction(MI, Ostream);
146 printAnnotation(Ostream, Annotation);
147}
148
149static void printExpr(const MCAsmInfo &MAI, const MCExpr &Expr,
150 raw_ostream &Ostream) {
151 const MCExpr *SRE;
152
153 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(&Expr))
154 SRE = dyn_cast<LanaiMCExpr>(BE->getLHS());
155 else if (isa<LanaiMCExpr>(&Expr)) {
156 SRE = dyn_cast<LanaiMCExpr>(&Expr);
157 } else {
158 SRE = dyn_cast<MCSymbolRefExpr>(&Expr);
159 }
160 assert(SRE && "Unexpected MCExpr type.");
161
162 SRE->print(Ostream, &MAI);
163}
164
165void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
166 raw_ostream &Ostream,
167 const char *Modifier) {
168 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
169 const MCOperand &Op = MI->getOperand(OpNo);
170 if (Op.isReg())
171 Ostream << "%" << getRegisterName(Op.getReg());
172 else if (Op.isImm())
173 Ostream << formatHex(Op.getImm());
174 else {
175 assert(Op.isExpr() && "Expected an expression");
176 printExpr(MAI, *Op.getExpr(), Ostream);
177 }
178}
179
180void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
181 raw_ostream &Ostream) {
182 const MCOperand &Op = MI->getOperand(OpNo);
183 if (Op.isImm()) {
184 Ostream << '[' << formatHex(Op.getImm()) << ']';
185 } else {
186 // Symbolic operand will be lowered to immediate value by linker
187 assert(Op.isExpr() && "Expected an expression");
188 Ostream << '[';
189 printExpr(MAI, *Op.getExpr(), Ostream);
190 Ostream << ']';
191 }
192}
193
194void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
195 raw_ostream &Ostream) {
196 const MCOperand &Op = MI->getOperand(OpNo);
197 if (Op.isImm()) {
198 Ostream << formatHex(Op.getImm() << 16);
199 } else {
200 // Symbolic operand will be lowered to immediate value by linker
201 assert(Op.isExpr() && "Expected an expression");
202 printExpr(MAI, *Op.getExpr(), Ostream);
203 }
204}
205
206void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
207 raw_ostream &Ostream) {
208 const MCOperand &Op = MI->getOperand(OpNo);
209 if (Op.isImm()) {
210 Ostream << formatHex((Op.getImm() << 16) | 0xffff);
211 } else {
212 // Symbolic operand will be lowered to immediate value by linker
213 assert(Op.isExpr() && "Expected an expression");
214 printExpr(MAI, *Op.getExpr(), Ostream);
215 }
216}
217
218void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
219 raw_ostream &Ostream) {
220 const MCOperand &Op = MI->getOperand(OpNo);
221 if (Op.isImm()) {
222 Ostream << formatHex(0xffff0000 | Op.getImm());
223 } else {
224 // Symbolic operand will be lowered to immediate value by linker
225 assert(Op.isExpr() && "Expected an expression");
226 printExpr(MAI, *Op.getExpr(), Ostream);
227 }
228}
229
230static void printMemoryBaseRegister(raw_ostream &Ostream, const unsigned AluCode,
231 const MCOperand &RegOp) {
232 assert(RegOp.isReg() && "Register operand expected");
233 Ostream << "[";
234 if (LPAC::isPreOp(AluCode))
235 Ostream << "*";
236 Ostream << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
237 if (LPAC::isPostOp(AluCode))
238 Ostream << "*";
239 Ostream << "]";
240}
241
242template <unsigned SizeInBits>
243static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
244 const MCOperand &OffsetOp,
245 raw_ostream &Ostream) {
246 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
247 if (OffsetOp.isImm()) {
248 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
249 Ostream << OffsetOp.getImm();
250 } else
251 printExpr(MAI, *OffsetOp.getExpr(), Ostream);
252}
253
254void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
255 raw_ostream &Ostream,
256 const char *Modifier) {
257 const MCOperand &RegOp = MI->getOperand(OpNo);
258 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
259 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
260 const unsigned AluCode = AluOp.getImm();
261
262 // Offset
263 printMemoryImmediateOffset<16>(MAI, OffsetOp, Ostream);
264
265 // Register
266 printMemoryBaseRegister(Ostream, AluCode, RegOp);
267}
268
269void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
270 raw_ostream &Ostream,
271 const char *Modifier) {
272 const MCOperand &RegOp = MI->getOperand(OpNo);
273 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
274 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
275 const unsigned AluCode = AluOp.getImm();
276 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
277
278 // [ Base OP Offset ]
279 Ostream << "[";
280 if (LPAC::isPreOp(AluCode))
281 Ostream << "*";
282 Ostream << "%" << getRegisterName(RegOp.getReg());
283 if (LPAC::isPostOp(AluCode))
284 Ostream << "*";
285 Ostream << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
286 Ostream << "%" << getRegisterName(OffsetOp.getReg());
287 Ostream << "]";
288}
289
290void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
291 raw_ostream &Ostream,
292 const char *Modifier) {
293 const MCOperand &RegOp = MI->getOperand(OpNo);
294 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
295 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
296 const unsigned AluCode = AluOp.getImm();
297
298 // Offset
299 printMemoryImmediateOffset<10>(MAI, OffsetOp, Ostream);
300
301 // Register
302 printMemoryBaseRegister(Ostream, AluCode, RegOp);
303}
304
305void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
306 raw_ostream &Ostream) {
307 const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm());
308 Ostream << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC));
309}