1 | //===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly 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 PPC MCInst to a .s file. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MCTargetDesc/PPCInstPrinter.h" |
14 | #include "MCTargetDesc/PPCMCTargetDesc.h" |
15 | #include "MCTargetDesc/PPCPredicates.h" |
16 | #include "llvm/MC/MCAsmInfo.h" |
17 | #include "llvm/MC/MCExpr.h" |
18 | #include "llvm/MC/MCInst.h" |
19 | #include "llvm/MC/MCInstrInfo.h" |
20 | #include "llvm/MC/MCRegisterInfo.h" |
21 | #include "llvm/MC/MCSubtargetInfo.h" |
22 | #include "llvm/MC/MCSymbol.h" |
23 | #include "llvm/Support/Casting.h" |
24 | #include "llvm/Support/CommandLine.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | using namespace llvm; |
27 | |
28 | #define DEBUG_TYPE "asm-printer" |
29 | |
30 | // FIXME: Once the integrated assembler supports full register names, tie this |
31 | // to the verbose-asm setting. |
32 | static cl::opt<bool> |
33 | FullRegNames("ppc-asm-full-reg-names" , cl::Hidden, cl::init(Val: false), |
34 | cl::desc("Use full register names when printing assembly" )); |
35 | |
36 | // Useful for testing purposes. Prints vs{31-63} as v{0-31} respectively. |
37 | static cl::opt<bool> |
38 | ShowVSRNumsAsVR("ppc-vsr-nums-as-vr" , cl::Hidden, cl::init(Val: false), |
39 | cl::desc("Prints full register names with vs{31-63} as v{0-31}" )); |
40 | |
41 | // Prints full register names with percent symbol. |
42 | static cl::opt<bool> |
43 | FullRegNamesWithPercent("ppc-reg-with-percent-prefix" , cl::Hidden, |
44 | cl::init(Val: false), |
45 | cl::desc("Prints full register names with percent" )); |
46 | |
47 | #define PRINT_ALIAS_INSTR |
48 | #include "PPCGenAsmWriter.inc" |
49 | |
50 | void PPCInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { |
51 | const char *RegName = getRegisterName(Reg); |
52 | OS << RegName; |
53 | } |
54 | |
55 | void PPCInstPrinter::printInst(const MCInst *MI, uint64_t Address, |
56 | StringRef Annot, const MCSubtargetInfo &STI, |
57 | raw_ostream &O) { |
58 | // Customize printing of the addis instruction on AIX. When an operand is a |
59 | // symbol reference, the instruction syntax is changed to look like a load |
60 | // operation, i.e: |
61 | // Transform: addis $rD, $rA, $src --> addis $rD, $src($rA). |
62 | if (TT.isOSAIX() && |
63 | (MI->getOpcode() == PPC::ADDIS8 || MI->getOpcode() == PPC::ADDIS) && |
64 | MI->getOperand(i: 2).isExpr()) { |
65 | assert((MI->getOperand(0).isReg() && MI->getOperand(1).isReg()) && |
66 | "The first and the second operand of an addis instruction" |
67 | " should be registers." ); |
68 | |
69 | assert(isa<MCSymbolRefExpr>(MI->getOperand(2).getExpr()) && |
70 | "The third operand of an addis instruction should be a symbol " |
71 | "reference expression if it is an expression at all." ); |
72 | |
73 | O << "\taddis " ; |
74 | printOperand(MI, OpNo: 0, STI, O); |
75 | O << ", " ; |
76 | printOperand(MI, OpNo: 2, STI, O); |
77 | O << "(" ; |
78 | printOperand(MI, OpNo: 1, STI, O); |
79 | O << ")" ; |
80 | return; |
81 | } |
82 | |
83 | // Check if the last operand is an expression with the variant kind |
84 | // VK_PPC_PCREL_OPT. If this is the case then this is a linker optimization |
85 | // relocation and the .reloc directive needs to be added. |
86 | unsigned LastOp = MI->getNumOperands() - 1; |
87 | if (MI->getNumOperands() > 1) { |
88 | const MCOperand &Operand = MI->getOperand(i: LastOp); |
89 | if (Operand.isExpr()) { |
90 | const MCExpr *Expr = Operand.getExpr(); |
91 | const MCSymbolRefExpr *SymExpr = |
92 | static_cast<const MCSymbolRefExpr *>(Expr); |
93 | |
94 | if (SymExpr && SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT) { |
95 | const MCSymbol &Symbol = SymExpr->getSymbol(); |
96 | if (MI->getOpcode() == PPC::PLDpc) { |
97 | printInstruction(MI, Address, STI, O); |
98 | O << "\n" ; |
99 | Symbol.print(OS&: O, MAI: &MAI); |
100 | O << ":" ; |
101 | return; |
102 | } else { |
103 | O << "\t.reloc " ; |
104 | Symbol.print(OS&: O, MAI: &MAI); |
105 | O << "-8,R_PPC64_PCREL_OPT,.-(" ; |
106 | Symbol.print(OS&: O, MAI: &MAI); |
107 | O << "-8)\n" ; |
108 | } |
109 | } |
110 | } |
111 | } |
112 | |
113 | // Check for slwi/srwi mnemonics. |
114 | if (MI->getOpcode() == PPC::RLWINM) { |
115 | unsigned char SH = MI->getOperand(i: 2).getImm(); |
116 | unsigned char MB = MI->getOperand(i: 3).getImm(); |
117 | unsigned char ME = MI->getOperand(i: 4).getImm(); |
118 | bool useSubstituteMnemonic = false; |
119 | if (SH <= 31 && MB == 0 && ME == (31-SH)) { |
120 | O << "\tslwi " ; useSubstituteMnemonic = true; |
121 | } |
122 | if (SH <= 31 && MB == (32-SH) && ME == 31) { |
123 | O << "\tsrwi " ; useSubstituteMnemonic = true; |
124 | SH = 32-SH; |
125 | } |
126 | if (useSubstituteMnemonic) { |
127 | printOperand(MI, OpNo: 0, STI, O); |
128 | O << ", " ; |
129 | printOperand(MI, OpNo: 1, STI, O); |
130 | O << ", " << (unsigned int)SH; |
131 | |
132 | printAnnotation(OS&: O, Annot); |
133 | return; |
134 | } |
135 | } |
136 | |
137 | if (MI->getOpcode() == PPC::RLDICR || |
138 | MI->getOpcode() == PPC::RLDICR_32) { |
139 | unsigned char SH = MI->getOperand(i: 2).getImm(); |
140 | unsigned char ME = MI->getOperand(i: 3).getImm(); |
141 | // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH |
142 | if (63-SH == ME) { |
143 | O << "\tsldi " ; |
144 | printOperand(MI, OpNo: 0, STI, O); |
145 | O << ", " ; |
146 | printOperand(MI, OpNo: 1, STI, O); |
147 | O << ", " << (unsigned int)SH; |
148 | printAnnotation(OS&: O, Annot); |
149 | return; |
150 | } |
151 | } |
152 | |
153 | // dcbt[st] is printed manually here because: |
154 | // 1. The assembly syntax is different between embedded and server targets |
155 | // 2. We must print the short mnemonics for TH == 0 because the |
156 | // embedded/server syntax default will not be stable across assemblers |
157 | // The syntax for dcbt is: |
158 | // dcbt ra, rb, th [server] |
159 | // dcbt th, ra, rb [embedded] |
160 | // where th can be omitted when it is 0. dcbtst is the same. |
161 | // On AIX, only emit the extended mnemonics for dcbt and dcbtst if |
162 | // the "modern assembler" is available. |
163 | if ((MI->getOpcode() == PPC::DCBT || MI->getOpcode() == PPC::DCBTST) && |
164 | (!TT.isOSAIX() || STI.hasFeature(Feature: PPC::FeatureModernAIXAs))) { |
165 | unsigned char TH = MI->getOperand(i: 0).getImm(); |
166 | O << "\tdcbt" ; |
167 | if (MI->getOpcode() == PPC::DCBTST) |
168 | O << "st" ; |
169 | if (TH == 16) |
170 | O << "t" ; |
171 | O << " " ; |
172 | |
173 | bool IsBookE = STI.hasFeature(Feature: PPC::FeatureBookE); |
174 | if (IsBookE && TH != 0 && TH != 16) |
175 | O << (unsigned int) TH << ", " ; |
176 | |
177 | printOperand(MI, OpNo: 1, STI, O); |
178 | O << ", " ; |
179 | printOperand(MI, OpNo: 2, STI, O); |
180 | |
181 | if (!IsBookE && TH != 0 && TH != 16) |
182 | O << ", " << (unsigned int) TH; |
183 | |
184 | printAnnotation(OS&: O, Annot); |
185 | return; |
186 | } |
187 | |
188 | if (MI->getOpcode() == PPC::DCBF) { |
189 | unsigned char L = MI->getOperand(i: 0).getImm(); |
190 | if (!L || L == 1 || L == 3 || L == 4 || L == 6) { |
191 | O << "\tdcb" ; |
192 | if (L != 6) |
193 | O << "f" ; |
194 | if (L == 1) |
195 | O << "l" ; |
196 | if (L == 3) |
197 | O << "lp" ; |
198 | if (L == 4) |
199 | O << "ps" ; |
200 | if (L == 6) |
201 | O << "stps" ; |
202 | O << " " ; |
203 | |
204 | printOperand(MI, OpNo: 1, STI, O); |
205 | O << ", " ; |
206 | printOperand(MI, OpNo: 2, STI, O); |
207 | |
208 | printAnnotation(OS&: O, Annot); |
209 | return; |
210 | } |
211 | } |
212 | |
213 | if (!printAliasInstr(MI, Address, STI, OS&: O)) |
214 | printInstruction(MI, Address, STI, O); |
215 | printAnnotation(OS&: O, Annot); |
216 | } |
217 | |
218 | void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, |
219 | const MCSubtargetInfo &STI, |
220 | raw_ostream &O, |
221 | const char *Modifier) { |
222 | unsigned Code = MI->getOperand(i: OpNo).getImm(); |
223 | |
224 | if (StringRef(Modifier) == "cc" ) { |
225 | switch ((PPC::Predicate)Code) { |
226 | case PPC::PRED_LT_MINUS: |
227 | case PPC::PRED_LT_PLUS: |
228 | case PPC::PRED_LT: |
229 | O << "lt" ; |
230 | return; |
231 | case PPC::PRED_LE_MINUS: |
232 | case PPC::PRED_LE_PLUS: |
233 | case PPC::PRED_LE: |
234 | O << "le" ; |
235 | return; |
236 | case PPC::PRED_EQ_MINUS: |
237 | case PPC::PRED_EQ_PLUS: |
238 | case PPC::PRED_EQ: |
239 | O << "eq" ; |
240 | return; |
241 | case PPC::PRED_GE_MINUS: |
242 | case PPC::PRED_GE_PLUS: |
243 | case PPC::PRED_GE: |
244 | O << "ge" ; |
245 | return; |
246 | case PPC::PRED_GT_MINUS: |
247 | case PPC::PRED_GT_PLUS: |
248 | case PPC::PRED_GT: |
249 | O << "gt" ; |
250 | return; |
251 | case PPC::PRED_NE_MINUS: |
252 | case PPC::PRED_NE_PLUS: |
253 | case PPC::PRED_NE: |
254 | O << "ne" ; |
255 | return; |
256 | case PPC::PRED_UN_MINUS: |
257 | case PPC::PRED_UN_PLUS: |
258 | case PPC::PRED_UN: |
259 | O << "un" ; |
260 | return; |
261 | case PPC::PRED_NU_MINUS: |
262 | case PPC::PRED_NU_PLUS: |
263 | case PPC::PRED_NU: |
264 | O << "nu" ; |
265 | return; |
266 | case PPC::PRED_BIT_SET: |
267 | case PPC::PRED_BIT_UNSET: |
268 | llvm_unreachable("Invalid use of bit predicate code" ); |
269 | } |
270 | llvm_unreachable("Invalid predicate code" ); |
271 | } |
272 | |
273 | if (StringRef(Modifier) == "pm" ) { |
274 | switch ((PPC::Predicate)Code) { |
275 | case PPC::PRED_LT: |
276 | case PPC::PRED_LE: |
277 | case PPC::PRED_EQ: |
278 | case PPC::PRED_GE: |
279 | case PPC::PRED_GT: |
280 | case PPC::PRED_NE: |
281 | case PPC::PRED_UN: |
282 | case PPC::PRED_NU: |
283 | return; |
284 | case PPC::PRED_LT_MINUS: |
285 | case PPC::PRED_LE_MINUS: |
286 | case PPC::PRED_EQ_MINUS: |
287 | case PPC::PRED_GE_MINUS: |
288 | case PPC::PRED_GT_MINUS: |
289 | case PPC::PRED_NE_MINUS: |
290 | case PPC::PRED_UN_MINUS: |
291 | case PPC::PRED_NU_MINUS: |
292 | O << "-" ; |
293 | return; |
294 | case PPC::PRED_LT_PLUS: |
295 | case PPC::PRED_LE_PLUS: |
296 | case PPC::PRED_EQ_PLUS: |
297 | case PPC::PRED_GE_PLUS: |
298 | case PPC::PRED_GT_PLUS: |
299 | case PPC::PRED_NE_PLUS: |
300 | case PPC::PRED_UN_PLUS: |
301 | case PPC::PRED_NU_PLUS: |
302 | O << "+" ; |
303 | return; |
304 | case PPC::PRED_BIT_SET: |
305 | case PPC::PRED_BIT_UNSET: |
306 | llvm_unreachable("Invalid use of bit predicate code" ); |
307 | } |
308 | llvm_unreachable("Invalid predicate code" ); |
309 | } |
310 | |
311 | assert(StringRef(Modifier) == "reg" && |
312 | "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!" ); |
313 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
314 | } |
315 | |
316 | void PPCInstPrinter::printATBitsAsHint(const MCInst *MI, unsigned OpNo, |
317 | const MCSubtargetInfo &STI, |
318 | raw_ostream &O) { |
319 | unsigned Code = MI->getOperand(i: OpNo).getImm(); |
320 | if (Code == 2) |
321 | O << "-" ; |
322 | else if (Code == 3) |
323 | O << "+" ; |
324 | } |
325 | |
326 | void PPCInstPrinter::printU1ImmOperand(const MCInst *MI, unsigned OpNo, |
327 | const MCSubtargetInfo &STI, |
328 | raw_ostream &O) { |
329 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
330 | assert(Value <= 1 && "Invalid u1imm argument!" ); |
331 | O << (unsigned int)Value; |
332 | } |
333 | |
334 | void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo, |
335 | const MCSubtargetInfo &STI, |
336 | raw_ostream &O) { |
337 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
338 | assert(Value <= 3 && "Invalid u2imm argument!" ); |
339 | O << (unsigned int)Value; |
340 | } |
341 | |
342 | void PPCInstPrinter::printU3ImmOperand(const MCInst *MI, unsigned OpNo, |
343 | const MCSubtargetInfo &STI, |
344 | raw_ostream &O) { |
345 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
346 | assert(Value <= 8 && "Invalid u3imm argument!" ); |
347 | O << (unsigned int)Value; |
348 | } |
349 | |
350 | void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo, |
351 | const MCSubtargetInfo &STI, |
352 | raw_ostream &O) { |
353 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
354 | assert(Value <= 15 && "Invalid u4imm argument!" ); |
355 | O << (unsigned int)Value; |
356 | } |
357 | |
358 | void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, |
359 | const MCSubtargetInfo &STI, |
360 | raw_ostream &O) { |
361 | int Value = MI->getOperand(i: OpNo).getImm(); |
362 | Value = SignExtend32<5>(X: Value); |
363 | O << (int)Value; |
364 | } |
365 | |
366 | void PPCInstPrinter::printImmZeroOperand(const MCInst *MI, unsigned OpNo, |
367 | const MCSubtargetInfo &STI, |
368 | raw_ostream &O) { |
369 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
370 | assert(Value == 0 && "Operand must be zero" ); |
371 | O << (unsigned int)Value; |
372 | } |
373 | |
374 | void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, |
375 | const MCSubtargetInfo &STI, |
376 | raw_ostream &O) { |
377 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
378 | assert(Value <= 31 && "Invalid u5imm argument!" ); |
379 | O << (unsigned int)Value; |
380 | } |
381 | |
382 | void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, |
383 | const MCSubtargetInfo &STI, |
384 | raw_ostream &O) { |
385 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
386 | assert(Value <= 63 && "Invalid u6imm argument!" ); |
387 | O << (unsigned int)Value; |
388 | } |
389 | |
390 | void PPCInstPrinter::printU7ImmOperand(const MCInst *MI, unsigned OpNo, |
391 | const MCSubtargetInfo &STI, |
392 | raw_ostream &O) { |
393 | unsigned int Value = MI->getOperand(i: OpNo).getImm(); |
394 | assert(Value <= 127 && "Invalid u7imm argument!" ); |
395 | O << (unsigned int)Value; |
396 | } |
397 | |
398 | // Operands of BUILD_VECTOR are signed and we use this to print operands |
399 | // of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and |
400 | // print as unsigned. |
401 | void PPCInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, |
402 | const MCSubtargetInfo &STI, |
403 | raw_ostream &O) { |
404 | unsigned char Value = MI->getOperand(i: OpNo).getImm(); |
405 | O << (unsigned int)Value; |
406 | } |
407 | |
408 | void PPCInstPrinter::printU10ImmOperand(const MCInst *MI, unsigned OpNo, |
409 | const MCSubtargetInfo &STI, |
410 | raw_ostream &O) { |
411 | unsigned short Value = MI->getOperand(i: OpNo).getImm(); |
412 | assert(Value <= 1023 && "Invalid u10imm argument!" ); |
413 | O << (unsigned short)Value; |
414 | } |
415 | |
416 | void PPCInstPrinter::printU12ImmOperand(const MCInst *MI, unsigned OpNo, |
417 | const MCSubtargetInfo &STI, |
418 | raw_ostream &O) { |
419 | unsigned short Value = MI->getOperand(i: OpNo).getImm(); |
420 | assert(Value <= 4095 && "Invalid u12imm argument!" ); |
421 | O << (unsigned short)Value; |
422 | } |
423 | |
424 | void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo, |
425 | const MCSubtargetInfo &STI, |
426 | raw_ostream &O) { |
427 | if (MI->getOperand(i: OpNo).isImm()) |
428 | O << (short)MI->getOperand(i: OpNo).getImm(); |
429 | else |
430 | printOperand(MI, OpNo, STI, O); |
431 | } |
432 | |
433 | void PPCInstPrinter::printS34ImmOperand(const MCInst *MI, unsigned OpNo, |
434 | const MCSubtargetInfo &STI, |
435 | raw_ostream &O) { |
436 | if (MI->getOperand(i: OpNo).isImm()) { |
437 | long long Value = MI->getOperand(i: OpNo).getImm(); |
438 | assert(isInt<34>(Value) && "Invalid s34imm argument!" ); |
439 | O << (long long)Value; |
440 | } |
441 | else |
442 | printOperand(MI, OpNo, STI, O); |
443 | } |
444 | |
445 | void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, |
446 | const MCSubtargetInfo &STI, |
447 | raw_ostream &O) { |
448 | if (MI->getOperand(i: OpNo).isImm()) |
449 | O << (unsigned short)MI->getOperand(i: OpNo).getImm(); |
450 | else |
451 | printOperand(MI, OpNo, STI, O); |
452 | } |
453 | |
454 | void PPCInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address, |
455 | unsigned OpNo, |
456 | const MCSubtargetInfo &STI, |
457 | raw_ostream &O) { |
458 | if (!MI->getOperand(i: OpNo).isImm()) |
459 | return printOperand(MI, OpNo, STI, O); |
460 | int32_t Imm = SignExtend32<32>(X: (unsigned)MI->getOperand(i: OpNo).getImm() << 2); |
461 | if (PrintBranchImmAsAddress) { |
462 | uint64_t Target = Address + Imm; |
463 | if (!TT.isPPC64()) |
464 | Target &= 0xffffffff; |
465 | O << formatHex(Value: Target); |
466 | } else { |
467 | // Branches can take an immediate operand. This is used by the branch |
468 | // selection pass to print, for example `.+8` (for ELF) or `$+8` (for AIX) |
469 | // to express an eight byte displacement from the program counter. |
470 | if (!TT.isOSAIX()) |
471 | O << "." ; |
472 | else |
473 | O << "$" ; |
474 | |
475 | if (Imm >= 0) |
476 | O << "+" ; |
477 | O << Imm; |
478 | } |
479 | } |
480 | |
481 | void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, |
482 | const MCSubtargetInfo &STI, |
483 | raw_ostream &O) { |
484 | if (!MI->getOperand(i: OpNo).isImm()) |
485 | return printOperand(MI, OpNo, STI, O); |
486 | |
487 | uint64_t Imm = static_cast<uint64_t>(MI->getOperand(i: OpNo).getImm()) << 2; |
488 | if (!TT.isPPC64()) |
489 | Imm = static_cast<uint32_t>(Imm); |
490 | O << formatHex(Value: Imm); |
491 | } |
492 | |
493 | void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, |
494 | const MCSubtargetInfo &STI, raw_ostream &O) { |
495 | unsigned CCReg = MI->getOperand(i: OpNo).getReg(); |
496 | unsigned RegNo; |
497 | switch (CCReg) { |
498 | default: llvm_unreachable("Unknown CR register" ); |
499 | case PPC::CR0: RegNo = 0; break; |
500 | case PPC::CR1: RegNo = 1; break; |
501 | case PPC::CR2: RegNo = 2; break; |
502 | case PPC::CR3: RegNo = 3; break; |
503 | case PPC::CR4: RegNo = 4; break; |
504 | case PPC::CR5: RegNo = 5; break; |
505 | case PPC::CR6: RegNo = 6; break; |
506 | case PPC::CR7: RegNo = 7; break; |
507 | } |
508 | O << (0x80 >> RegNo); |
509 | } |
510 | |
511 | void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, |
512 | const MCSubtargetInfo &STI, |
513 | raw_ostream &O) { |
514 | printS16ImmOperand(MI, OpNo, STI, O); |
515 | O << '('; |
516 | if (MI->getOperand(i: OpNo+1).getReg() == PPC::R0) |
517 | O << "0" ; |
518 | else |
519 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
520 | O << ')'; |
521 | } |
522 | |
523 | void PPCInstPrinter::printMemRegImmHash(const MCInst *MI, unsigned OpNo, |
524 | const MCSubtargetInfo &STI, |
525 | raw_ostream &O) { |
526 | O << MI->getOperand(i: OpNo).getImm(); |
527 | O << '('; |
528 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
529 | O << ')'; |
530 | } |
531 | |
532 | void PPCInstPrinter::printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo, |
533 | const MCSubtargetInfo &STI, |
534 | raw_ostream &O) { |
535 | printS34ImmOperand(MI, OpNo, STI, O); |
536 | O << '('; |
537 | printImmZeroOperand(MI, OpNo: OpNo + 1, STI, O); |
538 | O << ')'; |
539 | } |
540 | |
541 | void PPCInstPrinter::printMemRegImm34(const MCInst *MI, unsigned OpNo, |
542 | const MCSubtargetInfo &STI, |
543 | raw_ostream &O) { |
544 | printS34ImmOperand(MI, OpNo, STI, O); |
545 | O << '('; |
546 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
547 | O << ')'; |
548 | } |
549 | |
550 | void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, |
551 | const MCSubtargetInfo &STI, |
552 | raw_ostream &O) { |
553 | // When used as the base register, r0 reads constant zero rather than |
554 | // the value contained in the register. For this reason, the darwin |
555 | // assembler requires that we print r0 as 0 (no r) when used as the base. |
556 | if (MI->getOperand(i: OpNo).getReg() == PPC::R0) |
557 | O << "0" ; |
558 | else |
559 | printOperand(MI, OpNo, STI, O); |
560 | O << ", " ; |
561 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
562 | } |
563 | |
564 | void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo, |
565 | const MCSubtargetInfo &STI, raw_ostream &O) { |
566 | // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must |
567 | // come at the _end_ of the expression. |
568 | const MCOperand &Op = MI->getOperand(i: OpNo); |
569 | const MCSymbolRefExpr *RefExp = nullptr; |
570 | const MCExpr *Rhs = nullptr; |
571 | if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Val: Op.getExpr())) { |
572 | RefExp = cast<MCSymbolRefExpr>(Val: BinExpr->getLHS()); |
573 | Rhs = BinExpr->getRHS(); |
574 | } else |
575 | RefExp = cast<MCSymbolRefExpr>(Val: Op.getExpr()); |
576 | |
577 | O << RefExp->getSymbol().getName(); |
578 | // The variant kind VK_PPC_NOTOC needs to be handled as a special case |
579 | // because we do not want the assembly to print out the @notoc at the |
580 | // end like __tls_get_addr(x@tlsgd)@notoc. Instead we want it to look |
581 | // like __tls_get_addr@notoc(x@tlsgd). |
582 | if (RefExp->getKind() == MCSymbolRefExpr::VK_PPC_NOTOC) |
583 | O << '@' << MCSymbolRefExpr::getVariantKindName(Kind: RefExp->getKind()); |
584 | O << '('; |
585 | printOperand(MI, OpNo: OpNo + 1, STI, O); |
586 | O << ')'; |
587 | if (RefExp->getKind() != MCSymbolRefExpr::VK_None && |
588 | RefExp->getKind() != MCSymbolRefExpr::VK_PPC_NOTOC) |
589 | O << '@' << MCSymbolRefExpr::getVariantKindName(Kind: RefExp->getKind()); |
590 | if (Rhs) { |
591 | SmallString<0> Buf; |
592 | raw_svector_ostream Tmp(Buf); |
593 | Rhs->print(OS&: Tmp, MAI: &MAI); |
594 | if (isdigit(Buf[0])) |
595 | O << '+'; |
596 | O << Buf; |
597 | } |
598 | } |
599 | |
600 | /// showRegistersWithPercentPrefix - Check if this register name should be |
601 | /// printed with a percentage symbol as prefix. |
602 | bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const { |
603 | if ((!FullRegNamesWithPercent && !MAI.useFullRegisterNames()) || |
604 | TT.getOS() == Triple::AIX) |
605 | return false; |
606 | |
607 | switch (RegName[0]) { |
608 | default: |
609 | return false; |
610 | case 'r': |
611 | case 'f': |
612 | case 'q': |
613 | case 'v': |
614 | case 'c': |
615 | return true; |
616 | } |
617 | } |
618 | |
619 | /// getVerboseConditionalRegName - This method expands the condition register |
620 | /// when requested explicitly or targetting Darwin. |
621 | const char * |
622 | PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum, |
623 | unsigned RegEncoding) const { |
624 | if (!FullRegNames && !MAI.useFullRegisterNames()) |
625 | return nullptr; |
626 | if (RegNum < PPC::CR0EQ || RegNum > PPC::CR7UN) |
627 | return nullptr; |
628 | const char *CRBits[] = { |
629 | "lt" , "gt" , "eq" , "un" , |
630 | "4*cr1+lt" , "4*cr1+gt" , "4*cr1+eq" , "4*cr1+un" , |
631 | "4*cr2+lt" , "4*cr2+gt" , "4*cr2+eq" , "4*cr2+un" , |
632 | "4*cr3+lt" , "4*cr3+gt" , "4*cr3+eq" , "4*cr3+un" , |
633 | "4*cr4+lt" , "4*cr4+gt" , "4*cr4+eq" , "4*cr4+un" , |
634 | "4*cr5+lt" , "4*cr5+gt" , "4*cr5+eq" , "4*cr5+un" , |
635 | "4*cr6+lt" , "4*cr6+gt" , "4*cr6+eq" , "4*cr6+un" , |
636 | "4*cr7+lt" , "4*cr7+gt" , "4*cr7+eq" , "4*cr7+un" |
637 | }; |
638 | return CRBits[RegEncoding]; |
639 | } |
640 | |
641 | // showRegistersWithPrefix - This method determines whether registers |
642 | // should be number-only or include the prefix. |
643 | bool PPCInstPrinter::showRegistersWithPrefix() const { |
644 | return FullRegNamesWithPercent || FullRegNames || MAI.useFullRegisterNames(); |
645 | } |
646 | |
647 | void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
648 | const MCSubtargetInfo &STI, raw_ostream &O) { |
649 | const MCOperand &Op = MI->getOperand(i: OpNo); |
650 | if (Op.isReg()) { |
651 | unsigned Reg = Op.getReg(); |
652 | if (!ShowVSRNumsAsVR) |
653 | Reg = PPC::getRegNumForOperand(Desc: MII.get(Opcode: MI->getOpcode()), Reg, OpNo); |
654 | |
655 | const char *RegName; |
656 | RegName = getVerboseConditionRegName(RegNum: Reg, RegEncoding: MRI.getEncodingValue(RegNo: Reg)); |
657 | if (RegName == nullptr) |
658 | RegName = getRegisterName(Reg); |
659 | if (showRegistersWithPercentPrefix(RegName)) |
660 | O << "%" ; |
661 | if (!showRegistersWithPrefix()) |
662 | RegName = PPC::stripRegisterPrefix(RegName); |
663 | |
664 | O << RegName; |
665 | return; |
666 | } |
667 | |
668 | if (Op.isImm()) { |
669 | O << Op.getImm(); |
670 | return; |
671 | } |
672 | |
673 | assert(Op.isExpr() && "unknown operand kind in printOperand" ); |
674 | Op.getExpr()->print(OS&: O, MAI: &MAI); |
675 | } |
676 | |