]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/Lanai/MCTargetDesc/LanaiInstPrinter.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / Lanai / MCTargetDesc / LanaiInstPrinter.cpp
1 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints an Lanai MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12
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"
25
26 using namespace llvm;
27
28 #define DEBUG_TYPE "asm-printer"
29
30 // Include the auto-generated portion of the assembly writer.
31 #define PRINT_ALIAS_INSTR
32 #include "LanaiGenAsmWriter.inc"
33
34 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
35   OS << StringRef(getRegisterName(RegNo)).lower();
36 }
37
38 bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
39                                  StringRef Alias, unsigned OpNo0,
40                                  unsigned OpNo1) {
41   OS << "\t" << Alias << " ";
42   printOperand(MI, OpNo0, OS);
43   OS << ", ";
44   printOperand(MI, OpNo1, OS);
45   return true;
46 }
47
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);
53 }
54
55 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
56   unsigned AluCode = MI->getOperand(3).getImm();
57   return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
58 }
59
60 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
61   unsigned AluCode = MI->getOperand(3).getImm();
62   return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
63 }
64
65 static StringRef decIncOperator(const MCInst *MI) {
66   if (MI->getOperand(2).getImm() < 0)
67     return "--";
68   return "++";
69 }
70
71 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
72                                                 raw_ostream &OS,
73                                                 StringRef Opcode,
74                                                 int AddOffset) {
75   if (isPreIncrementForm(MI, AddOffset)) {
76     OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
77        << getRegisterName(MI->getOperand(1).getReg()) << "], %"
78        << getRegisterName(MI->getOperand(0).getReg());
79     return true;
80   }
81   if (isPostIncrementForm(MI, AddOffset)) {
82     OS << "\t" << Opcode << "\t[%"
83        << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
84        << "], %" << getRegisterName(MI->getOperand(0).getReg());
85     return true;
86   }
87   return false;
88 }
89
90 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
91                                                  raw_ostream &OS,
92                                                  StringRef Opcode,
93                                                  int AddOffset) {
94   if (isPreIncrementForm(MI, AddOffset)) {
95     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
96        << ", [" << decIncOperator(MI) << "%"
97        << getRegisterName(MI->getOperand(1).getReg()) << "]";
98     return true;
99   }
100   if (isPostIncrementForm(MI, AddOffset)) {
101     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
102        << ", [%" << getRegisterName(MI->getOperand(1).getReg())
103        << decIncOperator(MI) << "]";
104     return true;
105   }
106   return false;
107 }
108
109 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
110   switch (MI->getOpcode()) {
111   case Lanai::LDW_RI:
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);
117   case Lanai::LDHs_RI:
118     return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
119   case Lanai::LDHz_RI:
120     return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
121   case Lanai::LDBs_RI:
122     return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
123   case Lanai::LDBz_RI:
124     return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
125   case Lanai::SW_RI:
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);
131   case Lanai::STH_RI:
132     return printMemoryStoreIncrement(MI, OS, "st.h", 2);
133   case Lanai::STB_RI:
134     return printMemoryStoreIncrement(MI, OS, "st.b", 1);
135   default:
136     return false;
137   }
138 }
139
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);
146 }
147
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);
152   if (Op.isReg())
153     OS << "%" << getRegisterName(Op.getReg());
154   else if (Op.isImm())
155     OS << formatHex(Op.getImm());
156   else {
157     assert(Op.isExpr() && "Expected an expression");
158     Op.getExpr()->print(OS, &MAI);
159   }
160 }
161
162 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
163                                           raw_ostream &OS) {
164   const MCOperand &Op = MI->getOperand(OpNo);
165   if (Op.isImm()) {
166     OS << '[' << formatHex(Op.getImm()) << ']';
167   } else {
168     // Symbolic operand will be lowered to immediate value by linker
169     assert(Op.isExpr() && "Expected an expression");
170     OS << '[';
171     Op.getExpr()->print(OS, &MAI);
172     OS << ']';
173   }
174 }
175
176 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
177                                            raw_ostream &OS) {
178   const MCOperand &Op = MI->getOperand(OpNo);
179   if (Op.isImm()) {
180     OS << formatHex(Op.getImm() << 16);
181   } else {
182     // Symbolic operand will be lowered to immediate value by linker
183     assert(Op.isExpr() && "Expected an expression");
184     Op.getExpr()->print(OS, &MAI);
185   }
186 }
187
188 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
189                                               raw_ostream &OS) {
190   const MCOperand &Op = MI->getOperand(OpNo);
191   if (Op.isImm()) {
192     OS << formatHex((Op.getImm() << 16) | 0xffff);
193   } else {
194     // Symbolic operand will be lowered to immediate value by linker
195     assert(Op.isExpr() && "Expected an expression");
196     Op.getExpr()->print(OS, &MAI);
197   }
198 }
199
200 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
201                                               raw_ostream &OS) {
202   const MCOperand &Op = MI->getOperand(OpNo);
203   if (Op.isImm()) {
204     OS << formatHex(0xffff0000 | Op.getImm());
205   } else {
206     // Symbolic operand will be lowered to immediate value by linker
207     assert(Op.isExpr() && "Expected an expression");
208     Op.getExpr()->print(OS, &MAI);
209   }
210 }
211
212 static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
213                                     const MCOperand &RegOp) {
214   assert(RegOp.isReg() && "Register operand expected");
215   OS << "[";
216   if (LPAC::isPreOp(AluCode))
217     OS << "*";
218   OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
219   if (LPAC::isPostOp(AluCode))
220     OS << "*";
221   OS << "]";
222 }
223
224 template <unsigned SizeInBits>
225 static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
226                                        const MCOperand &OffsetOp,
227                                        raw_ostream &OS) {
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();
232   } else
233     OffsetOp.getExpr()->print(OS, &MAI);
234 }
235
236 void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
237                                          raw_ostream &OS,
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();
243
244   // Offset
245   printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
246
247   // Register
248   printMemoryBaseRegister(OS, AluCode, RegOp);
249 }
250
251 void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
252                                          raw_ostream &OS,
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.");
259
260   // [ Base OP Offset ]
261   OS << "[";
262   if (LPAC::isPreOp(AluCode))
263     OS << "*";
264   OS << "%" << getRegisterName(RegOp.getReg());
265   if (LPAC::isPostOp(AluCode))
266     OS << "*";
267   OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
268   OS << "%" << getRegisterName(OffsetOp.getReg());
269   OS << "]";
270 }
271
272 void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
273                                            raw_ostream &OS,
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();
279
280   // Offset
281   printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
282
283   // Register
284   printMemoryBaseRegister(OS, AluCode, RegOp);
285 }
286
287 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
288                                       raw_ostream &OS) {
289   LPCC::CondCode CC =
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)
293     OS << "<und>";
294   else
295     OS << lanaiCondCodeToString(CC);
296 }
297
298 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
299                                              raw_ostream &OS) {
300   LPCC::CondCode CC =
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)
304     OS << "<und>";
305   else if (CC != LPCC::ICC_T)
306     OS << "." << lanaiCondCodeToString(CC);
307 }