1 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This class prints an Lanai MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiInstPrinter.h"
14 #include "LanaiMCExpr.h"
15 #include "LanaiAluCode.h"
16 #include "LanaiCondCode.h"
17 #include "MCTargetDesc/LanaiMCTargetDesc.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/FormattedStream.h"
28 #define DEBUG_TYPE "asm-printer"
30 // Include the auto-generated portion of the assembly writer.
31 #define PRINT_ALIAS_INSTR
32 #include "LanaiGenAsmWriter.inc"
34 void LanaiInstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const {
35 OS
<< StringRef(getRegisterName(RegNo
)).lower();
38 bool LanaiInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&OS
,
39 StringRef Alias
, unsigned OpNo0
,
41 OS
<< "\t" << Alias
<< " ";
42 printOperand(MI
, OpNo0
, OS
);
44 printOperand(MI
, OpNo1
, OS
);
48 static bool usesGivenOffset(const MCInst
*MI
, int AddOffset
) {
49 unsigned AluCode
= MI
->getOperand(3).getImm();
50 return LPAC::encodeLanaiAluCode(AluCode
) == LPAC::ADD
&&
51 (MI
->getOperand(2).getImm() == AddOffset
||
52 MI
->getOperand(2).getImm() == -AddOffset
);
55 static bool isPreIncrementForm(const MCInst
*MI
, int AddOffset
) {
56 unsigned AluCode
= MI
->getOperand(3).getImm();
57 return LPAC::isPreOp(AluCode
) && usesGivenOffset(MI
, AddOffset
);
60 static bool isPostIncrementForm(const MCInst
*MI
, int AddOffset
) {
61 unsigned AluCode
= MI
->getOperand(3).getImm();
62 return LPAC::isPostOp(AluCode
) && usesGivenOffset(MI
, AddOffset
);
65 static StringRef
decIncOperator(const MCInst
*MI
) {
66 if (MI
->getOperand(2).getImm() < 0)
71 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst
*MI
,
75 if (isPreIncrementForm(MI
, AddOffset
)) {
76 OS
<< "\t" << Opcode
<< "\t[" << decIncOperator(MI
) << "%"
77 << getRegisterName(MI
->getOperand(1).getReg()) << "], %"
78 << getRegisterName(MI
->getOperand(0).getReg());
81 if (isPostIncrementForm(MI
, AddOffset
)) {
82 OS
<< "\t" << Opcode
<< "\t[%"
83 << getRegisterName(MI
->getOperand(1).getReg()) << decIncOperator(MI
)
84 << "], %" << getRegisterName(MI
->getOperand(0).getReg());
90 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst
*MI
,
94 if (isPreIncrementForm(MI
, AddOffset
)) {
95 OS
<< "\t" << Opcode
<< "\t%" << getRegisterName(MI
->getOperand(0).getReg())
96 << ", [" << decIncOperator(MI
) << "%"
97 << getRegisterName(MI
->getOperand(1).getReg()) << "]";
100 if (isPostIncrementForm(MI
, AddOffset
)) {
101 OS
<< "\t" << Opcode
<< "\t%" << getRegisterName(MI
->getOperand(0).getReg())
102 << ", [%" << getRegisterName(MI
->getOperand(1).getReg())
103 << decIncOperator(MI
) << "]";
109 bool LanaiInstPrinter::printAlias(const MCInst
*MI
, raw_ostream
&OS
) {
110 switch (MI
->getOpcode()) {
112 // ld 4[*%rN], %rX => ld [++imm], %rX
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 return printMemoryLoadIncrement(MI
, OS
, "ld", 4);
118 return printMemoryLoadIncrement(MI
, OS
, "ld.h", 2);
120 return printMemoryLoadIncrement(MI
, OS
, "uld.h", 2);
122 return printMemoryLoadIncrement(MI
, OS
, "ld.b", 1);
124 return printMemoryLoadIncrement(MI
, OS
, "uld.b", 1);
126 // st %rX, 4[*%rN] => st %rX, [++imm]
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 return printMemoryStoreIncrement(MI
, OS
, "st", 4);
132 return printMemoryStoreIncrement(MI
, OS
, "st.h", 2);
134 return printMemoryStoreIncrement(MI
, OS
, "st.b", 1);
140 void LanaiInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&OS
,
141 StringRef Annotation
,
142 const MCSubtargetInfo
& /*STI*/) {
143 if (!printAlias(MI
, OS
) && !printAliasInstr(MI
, OS
))
144 printInstruction(MI
, OS
);
145 printAnnotation(OS
, Annotation
);
148 void LanaiInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
149 raw_ostream
&OS
, const char *Modifier
) {
150 assert((Modifier
== 0 || Modifier
[0] == 0) && "No modifiers supported");
151 const MCOperand
&Op
= MI
->getOperand(OpNo
);
153 OS
<< "%" << getRegisterName(Op
.getReg());
155 OS
<< formatHex(Op
.getImm());
157 assert(Op
.isExpr() && "Expected an expression");
158 Op
.getExpr()->print(OS
, &MAI
);
162 void LanaiInstPrinter::printMemImmOperand(const MCInst
*MI
, unsigned OpNo
,
164 const MCOperand
&Op
= MI
->getOperand(OpNo
);
166 OS
<< '[' << formatHex(Op
.getImm()) << ']';
168 // Symbolic operand will be lowered to immediate value by linker
169 assert(Op
.isExpr() && "Expected an expression");
171 Op
.getExpr()->print(OS
, &MAI
);
176 void LanaiInstPrinter::printHi16ImmOperand(const MCInst
*MI
, unsigned OpNo
,
178 const MCOperand
&Op
= MI
->getOperand(OpNo
);
180 OS
<< formatHex(Op
.getImm() << 16);
182 // Symbolic operand will be lowered to immediate value by linker
183 assert(Op
.isExpr() && "Expected an expression");
184 Op
.getExpr()->print(OS
, &MAI
);
188 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst
*MI
, unsigned OpNo
,
190 const MCOperand
&Op
= MI
->getOperand(OpNo
);
192 OS
<< formatHex((Op
.getImm() << 16) | 0xffff);
194 // Symbolic operand will be lowered to immediate value by linker
195 assert(Op
.isExpr() && "Expected an expression");
196 Op
.getExpr()->print(OS
, &MAI
);
200 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst
*MI
, unsigned OpNo
,
202 const MCOperand
&Op
= MI
->getOperand(OpNo
);
204 OS
<< formatHex(0xffff0000 | Op
.getImm());
206 // Symbolic operand will be lowered to immediate value by linker
207 assert(Op
.isExpr() && "Expected an expression");
208 Op
.getExpr()->print(OS
, &MAI
);
212 static void printMemoryBaseRegister(raw_ostream
&OS
, const unsigned AluCode
,
213 const MCOperand
&RegOp
) {
214 assert(RegOp
.isReg() && "Register operand expected");
216 if (LPAC::isPreOp(AluCode
))
218 OS
<< "%" << LanaiInstPrinter::getRegisterName(RegOp
.getReg());
219 if (LPAC::isPostOp(AluCode
))
224 template <unsigned SizeInBits
>
225 static void printMemoryImmediateOffset(const MCAsmInfo
&MAI
,
226 const MCOperand
&OffsetOp
,
228 assert((OffsetOp
.isImm() || OffsetOp
.isExpr()) && "Immediate expected");
229 if (OffsetOp
.isImm()) {
230 assert(isInt
<SizeInBits
>(OffsetOp
.getImm()) && "Constant value truncated");
231 OS
<< OffsetOp
.getImm();
233 OffsetOp
.getExpr()->print(OS
, &MAI
);
236 void LanaiInstPrinter::printMemRiOperand(const MCInst
*MI
, int OpNo
,
238 const char * /*Modifier*/) {
239 const MCOperand
&RegOp
= MI
->getOperand(OpNo
);
240 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
241 const MCOperand
&AluOp
= MI
->getOperand(OpNo
+ 2);
242 const unsigned AluCode
= AluOp
.getImm();
245 printMemoryImmediateOffset
<16>(MAI
, OffsetOp
, OS
);
248 printMemoryBaseRegister(OS
, AluCode
, RegOp
);
251 void LanaiInstPrinter::printMemRrOperand(const MCInst
*MI
, int OpNo
,
253 const char * /*Modifier*/) {
254 const MCOperand
&RegOp
= MI
->getOperand(OpNo
);
255 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
256 const MCOperand
&AluOp
= MI
->getOperand(OpNo
+ 2);
257 const unsigned AluCode
= AluOp
.getImm();
258 assert(OffsetOp
.isReg() && RegOp
.isReg() && "Registers expected.");
260 // [ Base OP Offset ]
262 if (LPAC::isPreOp(AluCode
))
264 OS
<< "%" << getRegisterName(RegOp
.getReg());
265 if (LPAC::isPostOp(AluCode
))
267 OS
<< " " << LPAC::lanaiAluCodeToString(AluCode
) << " ";
268 OS
<< "%" << getRegisterName(OffsetOp
.getReg());
272 void LanaiInstPrinter::printMemSplsOperand(const MCInst
*MI
, int OpNo
,
274 const char * /*Modifier*/) {
275 const MCOperand
&RegOp
= MI
->getOperand(OpNo
);
276 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
277 const MCOperand
&AluOp
= MI
->getOperand(OpNo
+ 2);
278 const unsigned AluCode
= AluOp
.getImm();
281 printMemoryImmediateOffset
<10>(MAI
, OffsetOp
, OS
);
284 printMemoryBaseRegister(OS
, AluCode
, RegOp
);
287 void LanaiInstPrinter::printCCOperand(const MCInst
*MI
, int OpNo
,
290 static_cast<LPCC::CondCode
>(MI
->getOperand(OpNo
).getImm());
291 // Handle the undefined value here for printing so we don't abort().
292 if (CC
>= LPCC::UNKNOWN
)
295 OS
<< lanaiCondCodeToString(CC
);
298 void LanaiInstPrinter::printPredicateOperand(const MCInst
*MI
, unsigned OpNo
,
301 static_cast<LPCC::CondCode
>(MI
->getOperand(OpNo
).getImm());
302 // Handle the undefined value here for printing so we don't abort().
303 if (CC
>= LPCC::UNKNOWN
)
305 else if (CC
!= LPCC::ICC_T
)
306 OS
<< "." << lanaiCondCodeToString(CC
);