blob: 2185517e499be08cdf74f598b907a966c874b533 [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
Jacques Pienaar796975d2016-04-03 00:49:27 +000032void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
33 OS << StringRef(getRegisterName(RegNo)).lower();
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000034}
35
Jacques Pienaar796975d2016-04-03 00:49:27 +000036bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000037 StringRef Alias, unsigned OpNo0,
38 unsigned OpNo1) {
Jacques Pienaar796975d2016-04-03 00:49:27 +000039 OS << "\t" << Alias << " ";
40 printOperand(MI, OpNo0, OS);
41 OS << ", ";
42 printOperand(MI, OpNo1, OS);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000043 return true;
44}
45
46static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
47 unsigned AluCode = MI->getOperand(3).getImm();
48 return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
49 (MI->getOperand(2).getImm() == AddOffset ||
50 MI->getOperand(2).getImm() == -AddOffset);
51}
52
53static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
54 unsigned AluCode = MI->getOperand(3).getImm();
55 return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
56}
57
58static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
59 unsigned AluCode = MI->getOperand(3).getImm();
60 return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
61}
62
63static StringRef decIncOperator(const MCInst *MI) {
64 if (MI->getOperand(2).getImm() < 0)
65 return "--";
66 return "++";
67}
68
69bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
Jacques Pienaar796975d2016-04-03 00:49:27 +000070 raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000071 StringRef Opcode,
72 int AddOffset) {
73 if (isPreIncrementForm(MI, AddOffset)) {
Jacques Pienaar796975d2016-04-03 00:49:27 +000074 OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
75 << getRegisterName(MI->getOperand(1).getReg()) << "], %"
76 << getRegisterName(MI->getOperand(0).getReg());
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000077 return true;
78 }
79 if (isPostIncrementForm(MI, AddOffset)) {
Jacques Pienaar796975d2016-04-03 00:49:27 +000080 OS << "\t" << Opcode << "\t[%"
81 << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
82 << "], %" << getRegisterName(MI->getOperand(0).getReg());
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000083 return true;
84 }
85 return false;
86}
87
88bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
Jacques Pienaar796975d2016-04-03 00:49:27 +000089 raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000090 StringRef Opcode,
91 int AddOffset) {
92 if (isPreIncrementForm(MI, AddOffset)) {
Jacques Pienaar796975d2016-04-03 00:49:27 +000093 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
94 << ", [" << decIncOperator(MI) << "%"
95 << getRegisterName(MI->getOperand(1).getReg()) << "]";
Jacques Pienaarfcef3e42016-03-28 13:09:54 +000096 return true;
97 }
98 if (isPostIncrementForm(MI, AddOffset)) {
Jacques Pienaar796975d2016-04-03 00:49:27 +000099 OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
100 << ", [%" << getRegisterName(MI->getOperand(1).getReg())
101 << decIncOperator(MI) << "]";
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000102 return true;
103 }
104 return false;
105}
106
Jacques Pienaar796975d2016-04-03 00:49:27 +0000107bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000108 switch (MI->getOpcode()) {
109 case Lanai::LDW_RI:
110 // ld 4[*%rN], %rX => ld [++imm], %rX
111 // ld -4[*%rN], %rX => ld [--imm], %rX
112 // ld 4[%rN*], %rX => ld [imm++], %rX
113 // ld -4[%rN*], %rX => ld [imm--], %rX
Jacques Pienaar796975d2016-04-03 00:49:27 +0000114 return printMemoryLoadIncrement(MI, OS, "ld", 4);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000115 case Lanai::LDHs_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000116 return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000117 case Lanai::LDHz_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000118 return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000119 case Lanai::LDBs_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000120 return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000121 case Lanai::LDBz_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000122 return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000123 case Lanai::SW_RI:
124 // st %rX, 4[*%rN] => st %rX, [++imm]
125 // st %rX, -4[*%rN] => st %rX, [--imm]
126 // st %rX, 4[%rN*] => st %rX, [imm++]
127 // st %rX, -4[%rN*] => st %rX, [imm--]
Jacques Pienaar796975d2016-04-03 00:49:27 +0000128 return printMemoryStoreIncrement(MI, OS, "st", 4);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000129 case Lanai::STH_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000130 return printMemoryStoreIncrement(MI, OS, "st.h", 2);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000131 case Lanai::STB_RI:
Jacques Pienaar796975d2016-04-03 00:49:27 +0000132 return printMemoryStoreIncrement(MI, OS, "st.b", 1);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000133 default:
134 return false;
135 }
136}
137
Jacques Pienaar796975d2016-04-03 00:49:27 +0000138void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000139 StringRef Annotation,
140 const MCSubtargetInfo &STI) {
Jacques Pienaar796975d2016-04-03 00:49:27 +0000141 if (!printAlias(MI, OS) && !printAliasInstr(MI, OS)) printInstruction(MI, OS);
142 printAnnotation(OS, Annotation);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000143}
144
145void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000146 raw_ostream &OS, const char *Modifier) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000147 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
148 const MCOperand &Op = MI->getOperand(OpNo);
149 if (Op.isReg())
Jacques Pienaar796975d2016-04-03 00:49:27 +0000150 OS << "%" << getRegisterName(Op.getReg());
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000151 else if (Op.isImm())
Jacques Pienaar796975d2016-04-03 00:49:27 +0000152 OS << formatHex(Op.getImm());
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000153 else {
154 assert(Op.isExpr() && "Expected an expression");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000155 Op.getExpr()->print(OS, &MAI);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000156 }
157}
158
159void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000160 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000161 const MCOperand &Op = MI->getOperand(OpNo);
162 if (Op.isImm()) {
Jacques Pienaar796975d2016-04-03 00:49:27 +0000163 OS << '[' << formatHex(Op.getImm()) << ']';
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000164 } else {
165 // Symbolic operand will be lowered to immediate value by linker
166 assert(Op.isExpr() && "Expected an expression");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000167 OS << '[';
168 Op.getExpr()->print(OS, &MAI);
169 OS << ']';
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000170 }
171}
172
173void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000174 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000175 const MCOperand &Op = MI->getOperand(OpNo);
176 if (Op.isImm()) {
Jacques Pienaar796975d2016-04-03 00:49:27 +0000177 OS << formatHex(Op.getImm() << 16);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000178 } else {
179 // Symbolic operand will be lowered to immediate value by linker
180 assert(Op.isExpr() && "Expected an expression");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000181 Op.getExpr()->print(OS, &MAI);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000182 }
183}
184
185void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000186 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000187 const MCOperand &Op = MI->getOperand(OpNo);
188 if (Op.isImm()) {
Jacques Pienaar796975d2016-04-03 00:49:27 +0000189 OS << formatHex((Op.getImm() << 16) | 0xffff);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000190 } else {
191 // Symbolic operand will be lowered to immediate value by linker
192 assert(Op.isExpr() && "Expected an expression");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000193 Op.getExpr()->print(OS, &MAI);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000194 }
195}
196
197void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000198 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000199 const MCOperand &Op = MI->getOperand(OpNo);
200 if (Op.isImm()) {
Jacques Pienaar796975d2016-04-03 00:49:27 +0000201 OS << formatHex(0xffff0000 | Op.getImm());
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000202 } else {
203 // Symbolic operand will be lowered to immediate value by linker
204 assert(Op.isExpr() && "Expected an expression");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000205 Op.getExpr()->print(OS, &MAI);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000206 }
207}
208
Jacques Pienaar796975d2016-04-03 00:49:27 +0000209static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
210 const MCOperand &RegOp) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000211 assert(RegOp.isReg() && "Register operand expected");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000212 OS << "[";
213 if (LPAC::isPreOp(AluCode)) OS << "*";
214 OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
215 if (LPAC::isPostOp(AluCode)) OS << "*";
216 OS << "]";
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000217}
218
219template <unsigned SizeInBits>
220static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
221 const MCOperand &OffsetOp,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000222 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000223 assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
224 if (OffsetOp.isImm()) {
225 assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
Jacques Pienaar796975d2016-04-03 00:49:27 +0000226 OS << OffsetOp.getImm();
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000227 } else
Jacques Pienaar796975d2016-04-03 00:49:27 +0000228 OffsetOp.getExpr()->print(OS, &MAI);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000229}
230
231void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000232 raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000233 const char *Modifier) {
234 const MCOperand &RegOp = MI->getOperand(OpNo);
235 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
236 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
237 const unsigned AluCode = AluOp.getImm();
238
239 // Offset
Jacques Pienaar796975d2016-04-03 00:49:27 +0000240 printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000241
242 // Register
Jacques Pienaar796975d2016-04-03 00:49:27 +0000243 printMemoryBaseRegister(OS, AluCode, RegOp);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000244}
245
246void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000247 raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000248 const char *Modifier) {
249 const MCOperand &RegOp = MI->getOperand(OpNo);
250 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
251 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
252 const unsigned AluCode = AluOp.getImm();
253 assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
254
255 // [ Base OP Offset ]
Jacques Pienaar796975d2016-04-03 00:49:27 +0000256 OS << "[";
257 if (LPAC::isPreOp(AluCode)) OS << "*";
258 OS << "%" << getRegisterName(RegOp.getReg());
259 if (LPAC::isPostOp(AluCode)) OS << "*";
260 OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
261 OS << "%" << getRegisterName(OffsetOp.getReg());
262 OS << "]";
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000263}
264
265void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000266 raw_ostream &OS,
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000267 const char *Modifier) {
268 const MCOperand &RegOp = MI->getOperand(OpNo);
269 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
270 const MCOperand &AluOp = MI->getOperand(OpNo + 2);
271 const unsigned AluCode = AluOp.getImm();
272
273 // Offset
Jacques Pienaar796975d2016-04-03 00:49:27 +0000274 printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000275
276 // Register
Jacques Pienaar796975d2016-04-03 00:49:27 +0000277 printMemoryBaseRegister(OS, AluCode, RegOp);
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000278}
279
280void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
Jacques Pienaar796975d2016-04-03 00:49:27 +0000281 raw_ostream &OS) {
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000282 const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm());
Jacques Pienaar796975d2016-04-03 00:49:27 +0000283 OS << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC));
Jacques Pienaarfcef3e42016-03-28 13:09:54 +0000284}