]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
MFC r355070:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Lanai / InstPrinter / LanaiInstPrinter.cpp
1 //===-- 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 "LanaiInstPrinter.h"
15 #include "Lanai.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
24 using 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
32 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
33   OS << StringRef(getRegisterName(RegNo)).lower();
34 }
35
36 bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
37                                  StringRef Alias, unsigned OpNo0,
38                                  unsigned OpNo1) {
39   OS << "\t" << Alias << " ";
40   printOperand(MI, OpNo0, OS);
41   OS << ", ";
42   printOperand(MI, OpNo1, OS);
43   return true;
44 }
45
46 static 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
53 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
54   unsigned AluCode = MI->getOperand(3).getImm();
55   return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
56 }
57
58 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
59   unsigned AluCode = MI->getOperand(3).getImm();
60   return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
61 }
62
63 static StringRef decIncOperator(const MCInst *MI) {
64   if (MI->getOperand(2).getImm() < 0)
65     return "--";
66   return "++";
67 }
68
69 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
70                                                 raw_ostream &OS,
71                                                 StringRef Opcode,
72                                                 int AddOffset) {
73   if (isPreIncrementForm(MI, AddOffset)) {
74     OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
75        << getRegisterName(MI->getOperand(1).getReg()) << "], %"
76        << getRegisterName(MI->getOperand(0).getReg());
77     return true;
78   }
79   if (isPostIncrementForm(MI, AddOffset)) {
80     OS << "\t" << Opcode << "\t[%"
81        << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
82        << "], %" << getRegisterName(MI->getOperand(0).getReg());
83     return true;
84   }
85   return false;
86 }
87
88 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
89                                                  raw_ostream &OS,
90                                                  StringRef Opcode,
91                                                  int AddOffset) {
92   if (isPreIncrementForm(MI, AddOffset)) {
93     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
94        << ", [" << decIncOperator(MI) << "%"
95        << getRegisterName(MI->getOperand(1).getReg()) << "]";
96     return true;
97   }
98   if (isPostIncrementForm(MI, AddOffset)) {
99     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
100        << ", [%" << getRegisterName(MI->getOperand(1).getReg())
101        << decIncOperator(MI) << "]";
102     return true;
103   }
104   return false;
105 }
106
107 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
108   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
114     return printMemoryLoadIncrement(MI, OS, "ld", 4);
115   case Lanai::LDHs_RI:
116     return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
117   case Lanai::LDHz_RI:
118     return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
119   case Lanai::LDBs_RI:
120     return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
121   case Lanai::LDBz_RI:
122     return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
123   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--]
128     return printMemoryStoreIncrement(MI, OS, "st", 4);
129   case Lanai::STH_RI:
130     return printMemoryStoreIncrement(MI, OS, "st.h", 2);
131   case Lanai::STB_RI:
132     return printMemoryStoreIncrement(MI, OS, "st.b", 1);
133   default:
134     return false;
135   }
136 }
137
138 void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
139                                  StringRef Annotation,
140                                  const MCSubtargetInfo & /*STI*/) {
141   if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
142     printInstruction(MI, OS);
143   printAnnotation(OS, Annotation);
144 }
145
146 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
147                                     raw_ostream &OS, const char *Modifier) {
148   assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
149   const MCOperand &Op = MI->getOperand(OpNo);
150   if (Op.isReg())
151     OS << "%" << getRegisterName(Op.getReg());
152   else if (Op.isImm())
153     OS << formatHex(Op.getImm());
154   else {
155     assert(Op.isExpr() && "Expected an expression");
156     Op.getExpr()->print(OS, &MAI);
157   }
158 }
159
160 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
161                                           raw_ostream &OS) {
162   const MCOperand &Op = MI->getOperand(OpNo);
163   if (Op.isImm()) {
164     OS << '[' << formatHex(Op.getImm()) << ']';
165   } else {
166     // Symbolic operand will be lowered to immediate value by linker
167     assert(Op.isExpr() && "Expected an expression");
168     OS << '[';
169     Op.getExpr()->print(OS, &MAI);
170     OS << ']';
171   }
172 }
173
174 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
175                                            raw_ostream &OS) {
176   const MCOperand &Op = MI->getOperand(OpNo);
177   if (Op.isImm()) {
178     OS << formatHex(Op.getImm() << 16);
179   } else {
180     // Symbolic operand will be lowered to immediate value by linker
181     assert(Op.isExpr() && "Expected an expression");
182     Op.getExpr()->print(OS, &MAI);
183   }
184 }
185
186 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
187                                               raw_ostream &OS) {
188   const MCOperand &Op = MI->getOperand(OpNo);
189   if (Op.isImm()) {
190     OS << formatHex((Op.getImm() << 16) | 0xffff);
191   } else {
192     // Symbolic operand will be lowered to immediate value by linker
193     assert(Op.isExpr() && "Expected an expression");
194     Op.getExpr()->print(OS, &MAI);
195   }
196 }
197
198 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
199                                               raw_ostream &OS) {
200   const MCOperand &Op = MI->getOperand(OpNo);
201   if (Op.isImm()) {
202     OS << formatHex(0xffff0000 | Op.getImm());
203   } else {
204     // Symbolic operand will be lowered to immediate value by linker
205     assert(Op.isExpr() && "Expected an expression");
206     Op.getExpr()->print(OS, &MAI);
207   }
208 }
209
210 static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
211                                     const MCOperand &RegOp) {
212   assert(RegOp.isReg() && "Register operand expected");
213   OS << "[";
214   if (LPAC::isPreOp(AluCode))
215     OS << "*";
216   OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
217   if (LPAC::isPostOp(AluCode))
218     OS << "*";
219   OS << "]";
220 }
221
222 template <unsigned SizeInBits>
223 static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
224                                        const MCOperand &OffsetOp,
225                                        raw_ostream &OS) {
226   assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
227   if (OffsetOp.isImm()) {
228     assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
229     OS << OffsetOp.getImm();
230   } else
231     OffsetOp.getExpr()->print(OS, &MAI);
232 }
233
234 void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
235                                          raw_ostream &OS,
236                                          const char * /*Modifier*/) {
237   const MCOperand &RegOp = MI->getOperand(OpNo);
238   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
239   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
240   const unsigned AluCode = AluOp.getImm();
241
242   // Offset
243   printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
244
245   // Register
246   printMemoryBaseRegister(OS, AluCode, RegOp);
247 }
248
249 void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
250                                          raw_ostream &OS,
251                                          const char * /*Modifier*/) {
252   const MCOperand &RegOp = MI->getOperand(OpNo);
253   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
254   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
255   const unsigned AluCode = AluOp.getImm();
256   assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
257
258   // [ Base OP Offset ]
259   OS << "[";
260   if (LPAC::isPreOp(AluCode))
261     OS << "*";
262   OS << "%" << getRegisterName(RegOp.getReg());
263   if (LPAC::isPostOp(AluCode))
264     OS << "*";
265   OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
266   OS << "%" << getRegisterName(OffsetOp.getReg());
267   OS << "]";
268 }
269
270 void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
271                                            raw_ostream &OS,
272                                            const char * /*Modifier*/) {
273   const MCOperand &RegOp = MI->getOperand(OpNo);
274   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
275   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
276   const unsigned AluCode = AluOp.getImm();
277
278   // Offset
279   printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
280
281   // Register
282   printMemoryBaseRegister(OS, AluCode, RegOp);
283 }
284
285 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
286                                       raw_ostream &OS) {
287   LPCC::CondCode CC =
288       static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
289   // Handle the undefined value here for printing so we don't abort().
290   if (CC >= LPCC::UNKNOWN)
291     OS << "<und>";
292   else
293     OS << lanaiCondCodeToString(CC);
294 }
295
296 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
297                                              raw_ostream &OS) {
298   LPCC::CondCode CC =
299       static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
300   // Handle the undefined value here for printing so we don't abort().
301   if (CC >= LPCC::UNKNOWN)
302     OS << "<und>";
303   else if (CC != LPCC::ICC_T)
304     OS << "." << lanaiCondCodeToString(CC);
305 }