AMDGPUInstPrinter.cpp revision 287506
1//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
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// \file
9//===----------------------------------------------------------------------===//
10
11#include "AMDGPUInstPrinter.h"
12#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13#include "SIDefines.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCInstrInfo.h"
17#include "llvm/MC/MCRegisterInfo.h"
18#include "llvm/Support/MathExtras.h"
19
20using namespace llvm;
21
22void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
23                                  StringRef Annot, const MCSubtargetInfo &STI) {
24  OS.flush();
25  printInstruction(MI, OS);
26
27  printAnnotation(OS, Annot);
28}
29
30void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
31                                           raw_ostream &O) {
32  O << formatHex(MI->getOperand(OpNo).getImm() & 0xff);
33}
34
35void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
36                                           raw_ostream &O) {
37  O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff);
38}
39
40void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
41                                           raw_ostream &O) {
42  O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
43}
44
45void AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo,
46                                             raw_ostream &O) {
47  O << formatDec(MI->getOperand(OpNo).getImm() & 0xff);
48}
49
50void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
51                                              raw_ostream &O) {
52  O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
53}
54
55void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo,
56                                   raw_ostream &O) {
57  if (MI->getOperand(OpNo).getImm())
58    O << " offen";
59}
60
61void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo,
62                                   raw_ostream &O) {
63  if (MI->getOperand(OpNo).getImm())
64    O << " idxen";
65}
66
67void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo,
68                                    raw_ostream &O) {
69  if (MI->getOperand(OpNo).getImm())
70    O << " addr64";
71}
72
73void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo,
74                                        raw_ostream &O) {
75  if (MI->getOperand(OpNo).getImm()) {
76    O << " offset:";
77    printU16ImmDecOperand(MI, OpNo, O);
78  }
79}
80
81void AMDGPUInstPrinter::printDSOffset(const MCInst *MI, unsigned OpNo,
82                                      raw_ostream &O) {
83  uint16_t Imm = MI->getOperand(OpNo).getImm();
84  if (Imm != 0) {
85    O << " offset:";
86    printU16ImmDecOperand(MI, OpNo, O);
87  }
88}
89
90void AMDGPUInstPrinter::printDSOffset0(const MCInst *MI, unsigned OpNo,
91                                        raw_ostream &O) {
92  if (MI->getOperand(OpNo).getImm()) {
93    O << " offset0:";
94    printU8ImmDecOperand(MI, OpNo, O);
95  }
96}
97
98void AMDGPUInstPrinter::printDSOffset1(const MCInst *MI, unsigned OpNo,
99                                        raw_ostream &O) {
100  if (MI->getOperand(OpNo).getImm()) {
101    O << " offset1:";
102    printU8ImmDecOperand(MI, OpNo, O);
103  }
104}
105
106void AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo,
107                                 raw_ostream &O) {
108  if (MI->getOperand(OpNo).getImm())
109    O << " gds";
110}
111
112void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo,
113                                 raw_ostream &O) {
114  if (MI->getOperand(OpNo).getImm())
115    O << " glc";
116}
117
118void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo,
119                                 raw_ostream &O) {
120  if (MI->getOperand(OpNo).getImm())
121    O << " slc";
122}
123
124void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
125                                 raw_ostream &O) {
126  if (MI->getOperand(OpNo).getImm())
127    O << " tfe";
128}
129
130void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O,
131                                        const MCRegisterInfo &MRI) {
132  switch (reg) {
133  case AMDGPU::VCC:
134    O << "vcc";
135    return;
136  case AMDGPU::SCC:
137    O << "scc";
138    return;
139  case AMDGPU::EXEC:
140    O << "exec";
141    return;
142  case AMDGPU::M0:
143    O << "m0";
144    return;
145  case AMDGPU::FLAT_SCR:
146    O << "flat_scratch";
147    return;
148  case AMDGPU::VCC_LO:
149    O << "vcc_lo";
150    return;
151  case AMDGPU::VCC_HI:
152    O << "vcc_hi";
153    return;
154  case AMDGPU::EXEC_LO:
155    O << "exec_lo";
156    return;
157  case AMDGPU::EXEC_HI:
158    O << "exec_hi";
159    return;
160  case AMDGPU::FLAT_SCR_LO:
161    O << "flat_scratch_lo";
162    return;
163  case AMDGPU::FLAT_SCR_HI:
164    O << "flat_scratch_hi";
165    return;
166  default:
167    break;
168  }
169
170  char Type;
171  unsigned NumRegs;
172
173  if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
174    Type = 'v';
175    NumRegs = 1;
176  } else  if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
177    Type = 's';
178    NumRegs = 1;
179  } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
180    Type = 'v';
181    NumRegs = 2;
182  } else  if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) {
183    Type = 's';
184    NumRegs = 2;
185  } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
186    Type = 'v';
187    NumRegs = 4;
188  } else  if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) {
189    Type = 's';
190    NumRegs = 4;
191  } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
192    Type = 'v';
193    NumRegs = 3;
194  } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
195    Type = 'v';
196    NumRegs = 8;
197  } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
198    Type = 's';
199    NumRegs = 8;
200  } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
201    Type = 'v';
202    NumRegs = 16;
203  } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
204    Type = 's';
205    NumRegs = 16;
206  } else {
207    O << getRegisterName(reg);
208    return;
209  }
210
211  // The low 8 bits of the encoding value is the register index, for both VGPRs
212  // and SGPRs.
213  unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
214  if (NumRegs == 1) {
215    O << Type << RegIdx;
216    return;
217  }
218
219  O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
220}
221
222void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
223                                    raw_ostream &O) {
224  if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3)
225    O << "_e64 ";
226  else
227    O << "_e32 ";
228
229  printOperand(MI, OpNo, O);
230}
231
232void AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) {
233  int32_t SImm = static_cast<int32_t>(Imm);
234  if (SImm >= -16 && SImm <= 64) {
235    O << SImm;
236    return;
237  }
238
239  if (Imm == FloatToBits(0.0f))
240    O << "0.0";
241  else if (Imm == FloatToBits(1.0f))
242    O << "1.0";
243  else if (Imm == FloatToBits(-1.0f))
244    O << "-1.0";
245  else if (Imm == FloatToBits(0.5f))
246    O << "0.5";
247  else if (Imm == FloatToBits(-0.5f))
248    O << "-0.5";
249  else if (Imm == FloatToBits(2.0f))
250    O << "2.0";
251  else if (Imm == FloatToBits(-2.0f))
252    O << "-2.0";
253  else if (Imm == FloatToBits(4.0f))
254    O << "4.0";
255  else if (Imm == FloatToBits(-4.0f))
256    O << "-4.0";
257  else
258    O << formatHex(static_cast<uint64_t>(Imm));
259}
260
261void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) {
262  int64_t SImm = static_cast<int64_t>(Imm);
263  if (SImm >= -16 && SImm <= 64) {
264    O << SImm;
265    return;
266  }
267
268  if (Imm == DoubleToBits(0.0))
269    O << "0.0";
270  else if (Imm == DoubleToBits(1.0))
271    O << "1.0";
272  else if (Imm == DoubleToBits(-1.0))
273    O << "-1.0";
274  else if (Imm == DoubleToBits(0.5))
275    O << "0.5";
276  else if (Imm == DoubleToBits(-0.5))
277    O << "-0.5";
278  else if (Imm == DoubleToBits(2.0))
279    O << "2.0";
280  else if (Imm == DoubleToBits(-2.0))
281    O << "-2.0";
282  else if (Imm == DoubleToBits(4.0))
283    O << "4.0";
284  else if (Imm == DoubleToBits(-4.0))
285    O << "-4.0";
286  else
287    llvm_unreachable("64-bit literal constants not supported");
288}
289
290void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
291                                     raw_ostream &O) {
292
293  const MCOperand &Op = MI->getOperand(OpNo);
294  if (Op.isReg()) {
295    switch (Op.getReg()) {
296    // This is the default predicate state, so we don't need to print it.
297    case AMDGPU::PRED_SEL_OFF:
298      break;
299
300    default:
301      printRegOperand(Op.getReg(), O, MRI);
302      break;
303    }
304  } else if (Op.isImm()) {
305    const MCInstrDesc &Desc = MII.get(MI->getOpcode());
306    int RCID = Desc.OpInfo[OpNo].RegClass;
307    if (RCID != -1) {
308      const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
309      if (ImmRC.getSize() == 4)
310        printImmediate32(Op.getImm(), O);
311      else if (ImmRC.getSize() == 8)
312        printImmediate64(Op.getImm(), O);
313      else
314        llvm_unreachable("Invalid register class size");
315    } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
316      printImmediate32(Op.getImm(), O);
317    } else {
318      // We hit this for the immediate instruction bits that don't yet have a
319      // custom printer.
320      // TODO: Eventually this should be unnecessary.
321      O << formatDec(Op.getImm());
322    }
323  } else if (Op.isFPImm()) {
324    // We special case 0.0 because otherwise it will be printed as an integer.
325    if (Op.getFPImm() == 0.0)
326      O << "0.0";
327    else {
328      const MCInstrDesc &Desc = MII.get(MI->getOpcode());
329      const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
330
331      if (ImmRC.getSize() == 4)
332        printImmediate32(FloatToBits(Op.getFPImm()), O);
333      else if (ImmRC.getSize() == 8)
334        printImmediate64(DoubleToBits(Op.getFPImm()), O);
335      else
336        llvm_unreachable("Invalid register class size");
337    }
338  } else if (Op.isExpr()) {
339    const MCExpr *Exp = Op.getExpr();
340    Exp->print(O, &MAI);
341  } else {
342    llvm_unreachable("unknown operand type in printOperand");
343  }
344}
345
346void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
347                                            raw_ostream &O) {
348  unsigned InputModifiers = MI->getOperand(OpNo).getImm();
349  if (InputModifiers & SISrcMods::NEG)
350    O << '-';
351  if (InputModifiers & SISrcMods::ABS)
352    O << '|';
353  printOperand(MI, OpNo + 1, O);
354  if (InputModifiers & SISrcMods::ABS)
355    O << '|';
356}
357
358void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
359                                        raw_ostream &O) {
360  unsigned Imm = MI->getOperand(OpNum).getImm();
361
362  if (Imm == 2) {
363    O << "P0";
364  } else if (Imm == 1) {
365    O << "P20";
366  } else if (Imm == 0) {
367    O << "P10";
368  } else {
369    llvm_unreachable("Invalid interpolation parameter slot");
370  }
371}
372
373void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
374                                        raw_ostream &O) {
375  printOperand(MI, OpNo, O);
376  O  << ", ";
377  printOperand(MI, OpNo + 1, O);
378}
379
380void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
381                                   raw_ostream &O, StringRef Asm,
382                                   StringRef Default) {
383  const MCOperand &Op = MI->getOperand(OpNo);
384  assert(Op.isImm());
385  if (Op.getImm() == 1) {
386    O << Asm;
387  } else {
388    O << Default;
389  }
390}
391
392void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
393                                 raw_ostream &O) {
394  printIfSet(MI, OpNo, O, "|");
395}
396
397void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
398                                   raw_ostream &O) {
399  printIfSet(MI, OpNo, O, "_SAT");
400}
401
402void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
403                                     raw_ostream &O) {
404  if (MI->getOperand(OpNo).getImm())
405    O << " clamp";
406}
407
408void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
409                                     raw_ostream &O) {
410  int Imm = MI->getOperand(OpNo).getImm();
411  if (Imm == SIOutMods::MUL2)
412    O << " mul:2";
413  else if (Imm == SIOutMods::MUL4)
414    O << " mul:4";
415  else if (Imm == SIOutMods::DIV2)
416    O << " div:2";
417}
418
419void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
420                                     raw_ostream &O) {
421  int32_t Imm = MI->getOperand(OpNo).getImm();
422  O << Imm << '(' << BitsToFloat(Imm) << ')';
423}
424
425void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
426                                  raw_ostream &O) {
427  printIfSet(MI, OpNo, O, "*", " ");
428}
429
430void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
431                                 raw_ostream &O) {
432  printIfSet(MI, OpNo, O, "-");
433}
434
435void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
436                                  raw_ostream &O) {
437  switch (MI->getOperand(OpNo).getImm()) {
438  default: break;
439  case 1:
440    O << " * 2.0";
441    break;
442  case 2:
443    O << " * 4.0";
444    break;
445  case 3:
446    O << " / 2.0";
447    break;
448  }
449}
450
451void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
452                                 raw_ostream &O) {
453  printIfSet(MI, OpNo, O, "+");
454}
455
456void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
457                                            raw_ostream &O) {
458  printIfSet(MI, OpNo, O, "ExecMask,");
459}
460
461void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
462                                        raw_ostream &O) {
463  printIfSet(MI, OpNo, O, "Pred,");
464}
465
466void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
467                                       raw_ostream &O) {
468  const MCOperand &Op = MI->getOperand(OpNo);
469  if (Op.getImm() == 0) {
470    O << " (MASKED)";
471  }
472}
473
474void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
475                                  raw_ostream &O) {
476  const char * chans = "XYZW";
477  int sel = MI->getOperand(OpNo).getImm();
478
479  int chan = sel & 3;
480  sel >>= 2;
481
482  if (sel >= 512) {
483    sel -= 512;
484    int cb = sel >> 12;
485    sel &= 4095;
486    O << cb << '[' << sel << ']';
487  } else if (sel >= 448) {
488    sel -= 448;
489    O << sel;
490  } else if (sel >= 0){
491    O << sel;
492  }
493
494  if (sel >= 0)
495    O << '.' << chans[chan];
496}
497
498void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
499                                         raw_ostream &O) {
500  int BankSwizzle = MI->getOperand(OpNo).getImm();
501  switch (BankSwizzle) {
502  case 1:
503    O << "BS:VEC_021/SCL_122";
504    break;
505  case 2:
506    O << "BS:VEC_120/SCL_212";
507    break;
508  case 3:
509    O << "BS:VEC_102/SCL_221";
510    break;
511  case 4:
512    O << "BS:VEC_201";
513    break;
514  case 5:
515    O << "BS:VEC_210";
516    break;
517  default:
518    break;
519  }
520  return;
521}
522
523void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
524                                  raw_ostream &O) {
525  unsigned Sel = MI->getOperand(OpNo).getImm();
526  switch (Sel) {
527  case 0:
528    O << 'X';
529    break;
530  case 1:
531    O << 'Y';
532    break;
533  case 2:
534    O << 'Z';
535    break;
536  case 3:
537    O << 'W';
538    break;
539  case 4:
540    O << '0';
541    break;
542  case 5:
543    O << '1';
544    break;
545  case 7:
546    O << '_';
547    break;
548  default:
549    break;
550  }
551}
552
553void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
554                                  raw_ostream &O) {
555  unsigned CT = MI->getOperand(OpNo).getImm();
556  switch (CT) {
557  case 0:
558    O << 'U';
559    break;
560  case 1:
561    O << 'N';
562    break;
563  default:
564    break;
565  }
566}
567
568void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
569                                    raw_ostream &O) {
570  int KCacheMode = MI->getOperand(OpNo).getImm();
571  if (KCacheMode > 0) {
572    int KCacheBank = MI->getOperand(OpNo - 2).getImm();
573    O << "CB" << KCacheBank << ':';
574    int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
575    int LineSize = (KCacheMode == 1) ? 16 : 32;
576    O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
577  }
578}
579
580void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
581                                     raw_ostream &O) {
582  unsigned SImm16 = MI->getOperand(OpNo).getImm();
583  unsigned Msg = SImm16 & 0xF;
584  if (Msg == 2 || Msg == 3) {
585    unsigned Op = (SImm16 >> 4) & 0xF;
586    if (Msg == 3)
587      O << "Gs_done(";
588    else
589      O << "Gs(";
590    if (Op == 0) {
591      O << "nop";
592    } else {
593      unsigned Stream = (SImm16 >> 8) & 0x3;
594      if (Op == 1)
595	O << "cut";
596      else if (Op == 2)
597	O << "emit";
598      else if (Op == 3)
599	O << "emit-cut";
600      O << " stream " << Stream;
601    }
602    O << "), [m0] ";
603  } else if (Msg == 1)
604    O << "interrupt ";
605  else if (Msg == 15)
606    O << "system ";
607  else
608    O << "unknown(" << Msg << ") ";
609}
610
611void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
612                                      raw_ostream &O) {
613  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
614  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
615  // works so it might be a misprint in docs.
616  unsigned SImm16 = MI->getOperand(OpNo).getImm();
617  unsigned Vmcnt = SImm16 & 0xF;
618  unsigned Expcnt = (SImm16 >> 4) & 0xF;
619  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
620
621  bool NeedSpace = false;
622
623  if (Vmcnt != 0xF) {
624    O << "vmcnt(" << Vmcnt << ')';
625    NeedSpace = true;
626  }
627
628  if (Expcnt != 0x7) {
629    if (NeedSpace)
630      O << ' ';
631    O << "expcnt(" << Expcnt << ')';
632    NeedSpace = true;
633  }
634
635  if (Lgkmcnt != 0x7) {
636    if (NeedSpace)
637      O << ' ';
638    O << "lgkmcnt(" << Lgkmcnt << ')';
639  }
640}
641
642#include "AMDGPUGenAsmWriter.inc"
643