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"
15 #include "MCTargetDesc/LanaiMCExpr.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/FormattedStream.h"
25 #define DEBUG_TYPE "asm-printer"
27 // Include the auto-generated portion of the assembly writer.
28 #define PRINT_ALIAS_INSTR
29 #include "LanaiGenAsmWriter.inc"
31 void LanaiInstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const {
32 OS
<< StringRef(getRegisterName(RegNo
)).lower();
35 bool LanaiInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&OS
,
36 StringRef Alias
, unsigned OpNo0
,
38 OS
<< "\t" << Alias
<< " ";
39 printOperand(MI
, OpNo0
, OS
);
41 printOperand(MI
, OpNo1
, OS
);
45 static bool usesGivenOffset(const MCInst
*MI
, int AddOffset
) {
46 unsigned AluCode
= MI
->getOperand(3).getImm();
47 return LPAC::encodeLanaiAluCode(AluCode
) == LPAC::ADD
&&
48 (MI
->getOperand(2).getImm() == AddOffset
||
49 MI
->getOperand(2).getImm() == -AddOffset
);
52 static bool isPreIncrementForm(const MCInst
*MI
, int AddOffset
) {
53 unsigned AluCode
= MI
->getOperand(3).getImm();
54 return LPAC::isPreOp(AluCode
) && usesGivenOffset(MI
, AddOffset
);
57 static bool isPostIncrementForm(const MCInst
*MI
, int AddOffset
) {
58 unsigned AluCode
= MI
->getOperand(3).getImm();
59 return LPAC::isPostOp(AluCode
) && usesGivenOffset(MI
, AddOffset
);
62 static StringRef
decIncOperator(const MCInst
*MI
) {
63 if (MI
->getOperand(2).getImm() < 0)
68 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst
*MI
,
72 if (isPreIncrementForm(MI
, AddOffset
)) {
73 OS
<< "\t" << Opcode
<< "\t[" << decIncOperator(MI
) << "%"
74 << getRegisterName(MI
->getOperand(1).getReg()) << "], %"
75 << getRegisterName(MI
->getOperand(0).getReg());
78 if (isPostIncrementForm(MI
, AddOffset
)) {
79 OS
<< "\t" << Opcode
<< "\t[%"
80 << getRegisterName(MI
->getOperand(1).getReg()) << decIncOperator(MI
)
81 << "], %" << getRegisterName(MI
->getOperand(0).getReg());
87 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst
*MI
,
91 if (isPreIncrementForm(MI
, AddOffset
)) {
92 OS
<< "\t" << Opcode
<< "\t%" << getRegisterName(MI
->getOperand(0).getReg())
93 << ", [" << decIncOperator(MI
) << "%"
94 << getRegisterName(MI
->getOperand(1).getReg()) << "]";
97 if (isPostIncrementForm(MI
, AddOffset
)) {
98 OS
<< "\t" << Opcode
<< "\t%" << getRegisterName(MI
->getOperand(0).getReg())
99 << ", [%" << getRegisterName(MI
->getOperand(1).getReg())
100 << decIncOperator(MI
) << "]";
106 bool LanaiInstPrinter::printAlias(const MCInst
*MI
, raw_ostream
&OS
) {
107 switch (MI
->getOpcode()) {
109 // ld 4[*%rN], %rX => ld [++imm], %rX
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 return printMemoryLoadIncrement(MI
, OS
, "ld", 4);
115 return printMemoryLoadIncrement(MI
, OS
, "ld.h", 2);
117 return printMemoryLoadIncrement(MI
, OS
, "uld.h", 2);
119 return printMemoryLoadIncrement(MI
, OS
, "ld.b", 1);
121 return printMemoryLoadIncrement(MI
, OS
, "uld.b", 1);
123 // st %rX, 4[*%rN] => st %rX, [++imm]
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 return printMemoryStoreIncrement(MI
, OS
, "st", 4);
129 return printMemoryStoreIncrement(MI
, OS
, "st.h", 2);
131 return printMemoryStoreIncrement(MI
, OS
, "st.b", 1);
137 void LanaiInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&OS
,
138 StringRef Annotation
,
139 const MCSubtargetInfo
& /*STI*/) {
140 if (!printAlias(MI
, OS
) && !printAliasInstr(MI
, OS
))
141 printInstruction(MI
, OS
);
142 printAnnotation(OS
, Annotation
);
145 void LanaiInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
146 raw_ostream
&OS
, const char *Modifier
) {
147 assert((Modifier
== 0 || Modifier
[0] == 0) && "No modifiers supported");
148 const MCOperand
&Op
= MI
->getOperand(OpNo
);
150 OS
<< "%" << getRegisterName(Op
.getReg());
152 OS
<< formatHex(Op
.getImm());
154 assert(Op
.isExpr() && "Expected an expression");
155 Op
.getExpr()->print(OS
, &MAI
);
159 void LanaiInstPrinter::printMemImmOperand(const MCInst
*MI
, unsigned OpNo
,
161 const MCOperand
&Op
= MI
->getOperand(OpNo
);
163 OS
<< '[' << formatHex(Op
.getImm()) << ']';
165 // Symbolic operand will be lowered to immediate value by linker
166 assert(Op
.isExpr() && "Expected an expression");
168 Op
.getExpr()->print(OS
, &MAI
);
173 void LanaiInstPrinter::printHi16ImmOperand(const MCInst
*MI
, unsigned OpNo
,
175 const MCOperand
&Op
= MI
->getOperand(OpNo
);
177 OS
<< formatHex(Op
.getImm() << 16);
179 // Symbolic operand will be lowered to immediate value by linker
180 assert(Op
.isExpr() && "Expected an expression");
181 Op
.getExpr()->print(OS
, &MAI
);
185 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst
*MI
, unsigned OpNo
,
187 const MCOperand
&Op
= MI
->getOperand(OpNo
);
189 OS
<< formatHex((Op
.getImm() << 16) | 0xffff);
191 // Symbolic operand will be lowered to immediate value by linker
192 assert(Op
.isExpr() && "Expected an expression");
193 Op
.getExpr()->print(OS
, &MAI
);
197 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst
*MI
, unsigned OpNo
,
199 const MCOperand
&Op
= MI
->getOperand(OpNo
);
201 OS
<< formatHex(0xffff0000 | Op
.getImm());
203 // Symbolic operand will be lowered to immediate value by linker
204 assert(Op
.isExpr() && "Expected an expression");
205 Op
.getExpr()->print(OS
, &MAI
);
209 static void printMemoryBaseRegister(raw_ostream
&OS
, const unsigned AluCode
,
210 const MCOperand
&RegOp
) {
211 assert(RegOp
.isReg() && "Register operand expected");
213 if (LPAC::isPreOp(AluCode
))
215 OS
<< "%" << LanaiInstPrinter::getRegisterName(RegOp
.getReg());
216 if (LPAC::isPostOp(AluCode
))
221 template <unsigned SizeInBits
>
222 static void printMemoryImmediateOffset(const MCAsmInfo
&MAI
,
223 const MCOperand
&OffsetOp
,
225 assert((OffsetOp
.isImm() || OffsetOp
.isExpr()) && "Immediate expected");
226 if (OffsetOp
.isImm()) {
227 assert(isInt
<SizeInBits
>(OffsetOp
.getImm()) && "Constant value truncated");
228 OS
<< OffsetOp
.getImm();
230 OffsetOp
.getExpr()->print(OS
, &MAI
);
233 void LanaiInstPrinter::printMemRiOperand(const MCInst
*MI
, int OpNo
,
235 const char * /*Modifier*/) {
236 const MCOperand
&RegOp
= MI
->getOperand(OpNo
);
237 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
238 const MCOperand
&AluOp
= MI
->getOperand(OpNo
+ 2);
239 const unsigned AluCode
= AluOp
.getImm();
242 printMemoryImmediateOffset
<16>(MAI
, OffsetOp
, OS
);
245 printMemoryBaseRegister(OS
, AluCode
, RegOp
);
248 void LanaiInstPrinter::printMemRrOperand(const MCInst
*MI
, int OpNo
,
250 const char * /*Modifier*/) {
251 const MCOperand
&RegOp
= MI
->getOperand(OpNo
);
252 const MCOperand
&OffsetOp
= MI
->getOperand(OpNo
+ 1);
253 const MCOperand
&AluOp
= MI
->getOperand(OpNo
+ 2);
254 const unsigned AluCode
= AluOp
.getImm();
255 assert(OffsetOp
.isReg() && RegOp
.isReg() && "Registers expected.");
257 // [ Base OP Offset ]
259 if (LPAC::isPreOp(AluCode
))
261 OS
<< "%" << getRegisterName(RegOp
.getReg());
262 if (LPAC::isPostOp(AluCode
))
264 OS
<< " " << LPAC::lanaiAluCodeToString(AluCode
) << " ";
265 OS
<< "%" << getRegisterName(OffsetOp
.getReg());
269 void LanaiInstPrinter::printMemSplsOperand(const MCInst
*MI
, int OpNo
,
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();
278 printMemoryImmediateOffset
<10>(MAI
, OffsetOp
, OS
);
281 printMemoryBaseRegister(OS
, AluCode
, RegOp
);
284 void LanaiInstPrinter::printCCOperand(const MCInst
*MI
, int OpNo
,
287 static_cast<LPCC::CondCode
>(MI
->getOperand(OpNo
).getImm());
288 // Handle the undefined value here for printing so we don't abort().
289 if (CC
>= LPCC::UNKNOWN
)
292 OS
<< lanaiCondCodeToString(CC
);
295 void LanaiInstPrinter::printPredicateOperand(const MCInst
*MI
, unsigned OpNo
,
298 static_cast<LPCC::CondCode
>(MI
->getOperand(OpNo
).getImm());
299 // Handle the undefined value here for printing so we don't abort().
300 if (CC
>= LPCC::UNKNOWN
)
302 else if (CC
!= LPCC::ICC_T
)
303 OS
<< "." << lanaiCondCodeToString(CC
);