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