AMDGPUInstPrinter.cpp revision f3ef5332fa3f4d5ec72c178a2b19dac363a19383
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    assert(isUInt<32>(Imm));
288
289    // In rare situations, we will have a 32-bit literal in a 64-bit
290    // operand. This is technically allowed for the encoding of s_mov_b64.
291    O << formatHex(static_cast<uint64_t>(Imm));
292  }
293}
294
295void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
296                                     raw_ostream &O) {
297
298  const MCOperand &Op = MI->getOperand(OpNo);
299  if (Op.isReg()) {
300    switch (Op.getReg()) {
301    // This is the default predicate state, so we don't need to print it.
302    case AMDGPU::PRED_SEL_OFF:
303      break;
304
305    default:
306      printRegOperand(Op.getReg(), O, MRI);
307      break;
308    }
309  } else if (Op.isImm()) {
310    const MCInstrDesc &Desc = MII.get(MI->getOpcode());
311    int RCID = Desc.OpInfo[OpNo].RegClass;
312    if (RCID != -1) {
313      const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
314      if (ImmRC.getSize() == 4)
315        printImmediate32(Op.getImm(), O);
316      else if (ImmRC.getSize() == 8)
317        printImmediate64(Op.getImm(), O);
318      else
319        llvm_unreachable("Invalid register class size");
320    } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
321      printImmediate32(Op.getImm(), O);
322    } else {
323      // We hit this for the immediate instruction bits that don't yet have a
324      // custom printer.
325      // TODO: Eventually this should be unnecessary.
326      O << formatDec(Op.getImm());
327    }
328  } else if (Op.isFPImm()) {
329    // We special case 0.0 because otherwise it will be printed as an integer.
330    if (Op.getFPImm() == 0.0)
331      O << "0.0";
332    else {
333      const MCInstrDesc &Desc = MII.get(MI->getOpcode());
334      const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
335
336      if (ImmRC.getSize() == 4)
337        printImmediate32(FloatToBits(Op.getFPImm()), O);
338      else if (ImmRC.getSize() == 8)
339        printImmediate64(DoubleToBits(Op.getFPImm()), O);
340      else
341        llvm_unreachable("Invalid register class size");
342    }
343  } else if (Op.isExpr()) {
344    const MCExpr *Exp = Op.getExpr();
345    Exp->print(O, &MAI);
346  } else {
347    llvm_unreachable("unknown operand type in printOperand");
348  }
349}
350
351void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
352                                            raw_ostream &O) {
353  unsigned InputModifiers = MI->getOperand(OpNo).getImm();
354  if (InputModifiers & SISrcMods::NEG)
355    O << '-';
356  if (InputModifiers & SISrcMods::ABS)
357    O << '|';
358  printOperand(MI, OpNo + 1, O);
359  if (InputModifiers & SISrcMods::ABS)
360    O << '|';
361}
362
363void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
364                                        raw_ostream &O) {
365  unsigned Imm = MI->getOperand(OpNum).getImm();
366
367  if (Imm == 2) {
368    O << "P0";
369  } else if (Imm == 1) {
370    O << "P20";
371  } else if (Imm == 0) {
372    O << "P10";
373  } else {
374    llvm_unreachable("Invalid interpolation parameter slot");
375  }
376}
377
378void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
379                                        raw_ostream &O) {
380  printOperand(MI, OpNo, O);
381  O  << ", ";
382  printOperand(MI, OpNo + 1, O);
383}
384
385void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
386                                   raw_ostream &O, StringRef Asm,
387                                   StringRef Default) {
388  const MCOperand &Op = MI->getOperand(OpNo);
389  assert(Op.isImm());
390  if (Op.getImm() == 1) {
391    O << Asm;
392  } else {
393    O << Default;
394  }
395}
396
397void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
398                                 raw_ostream &O) {
399  printIfSet(MI, OpNo, O, "|");
400}
401
402void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
403                                   raw_ostream &O) {
404  printIfSet(MI, OpNo, O, "_SAT");
405}
406
407void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
408                                     raw_ostream &O) {
409  if (MI->getOperand(OpNo).getImm())
410    O << " clamp";
411}
412
413void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
414                                     raw_ostream &O) {
415  int Imm = MI->getOperand(OpNo).getImm();
416  if (Imm == SIOutMods::MUL2)
417    O << " mul:2";
418  else if (Imm == SIOutMods::MUL4)
419    O << " mul:4";
420  else if (Imm == SIOutMods::DIV2)
421    O << " div:2";
422}
423
424void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
425                                     raw_ostream &O) {
426  int32_t Imm = MI->getOperand(OpNo).getImm();
427  O << Imm << '(' << BitsToFloat(Imm) << ')';
428}
429
430void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
431                                  raw_ostream &O) {
432  printIfSet(MI, OpNo, O, "*", " ");
433}
434
435void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
436                                 raw_ostream &O) {
437  printIfSet(MI, OpNo, O, "-");
438}
439
440void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
441                                  raw_ostream &O) {
442  switch (MI->getOperand(OpNo).getImm()) {
443  default: break;
444  case 1:
445    O << " * 2.0";
446    break;
447  case 2:
448    O << " * 4.0";
449    break;
450  case 3:
451    O << " / 2.0";
452    break;
453  }
454}
455
456void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
457                                 raw_ostream &O) {
458  printIfSet(MI, OpNo, O, "+");
459}
460
461void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
462                                            raw_ostream &O) {
463  printIfSet(MI, OpNo, O, "ExecMask,");
464}
465
466void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
467                                        raw_ostream &O) {
468  printIfSet(MI, OpNo, O, "Pred,");
469}
470
471void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
472                                       raw_ostream &O) {
473  const MCOperand &Op = MI->getOperand(OpNo);
474  if (Op.getImm() == 0) {
475    O << " (MASKED)";
476  }
477}
478
479void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
480                                  raw_ostream &O) {
481  const char * chans = "XYZW";
482  int sel = MI->getOperand(OpNo).getImm();
483
484  int chan = sel & 3;
485  sel >>= 2;
486
487  if (sel >= 512) {
488    sel -= 512;
489    int cb = sel >> 12;
490    sel &= 4095;
491    O << cb << '[' << sel << ']';
492  } else if (sel >= 448) {
493    sel -= 448;
494    O << sel;
495  } else if (sel >= 0){
496    O << sel;
497  }
498
499  if (sel >= 0)
500    O << '.' << chans[chan];
501}
502
503void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
504                                         raw_ostream &O) {
505  int BankSwizzle = MI->getOperand(OpNo).getImm();
506  switch (BankSwizzle) {
507  case 1:
508    O << "BS:VEC_021/SCL_122";
509    break;
510  case 2:
511    O << "BS:VEC_120/SCL_212";
512    break;
513  case 3:
514    O << "BS:VEC_102/SCL_221";
515    break;
516  case 4:
517    O << "BS:VEC_201";
518    break;
519  case 5:
520    O << "BS:VEC_210";
521    break;
522  default:
523    break;
524  }
525  return;
526}
527
528void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
529                                  raw_ostream &O) {
530  unsigned Sel = MI->getOperand(OpNo).getImm();
531  switch (Sel) {
532  case 0:
533    O << 'X';
534    break;
535  case 1:
536    O << 'Y';
537    break;
538  case 2:
539    O << 'Z';
540    break;
541  case 3:
542    O << 'W';
543    break;
544  case 4:
545    O << '0';
546    break;
547  case 5:
548    O << '1';
549    break;
550  case 7:
551    O << '_';
552    break;
553  default:
554    break;
555  }
556}
557
558void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
559                                  raw_ostream &O) {
560  unsigned CT = MI->getOperand(OpNo).getImm();
561  switch (CT) {
562  case 0:
563    O << 'U';
564    break;
565  case 1:
566    O << 'N';
567    break;
568  default:
569    break;
570  }
571}
572
573void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
574                                    raw_ostream &O) {
575  int KCacheMode = MI->getOperand(OpNo).getImm();
576  if (KCacheMode > 0) {
577    int KCacheBank = MI->getOperand(OpNo - 2).getImm();
578    O << "CB" << KCacheBank << ':';
579    int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
580    int LineSize = (KCacheMode == 1) ? 16 : 32;
581    O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
582  }
583}
584
585void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
586                                     raw_ostream &O) {
587  unsigned SImm16 = MI->getOperand(OpNo).getImm();
588  unsigned Msg = SImm16 & 0xF;
589  if (Msg == 2 || Msg == 3) {
590    unsigned Op = (SImm16 >> 4) & 0xF;
591    if (Msg == 3)
592      O << "Gs_done(";
593    else
594      O << "Gs(";
595    if (Op == 0) {
596      O << "nop";
597    } else {
598      unsigned Stream = (SImm16 >> 8) & 0x3;
599      if (Op == 1)
600        O << "cut";
601      else if (Op == 2)
602        O << "emit";
603      else if (Op == 3)
604        O << "emit-cut";
605      O << " stream " << Stream;
606    }
607    O << "), [m0] ";
608  } else if (Msg == 1)
609    O << "interrupt ";
610  else if (Msg == 15)
611    O << "system ";
612  else
613    O << "unknown(" << Msg << ") ";
614}
615
616void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
617                                      raw_ostream &O) {
618  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
619  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
620  // works so it might be a misprint in docs.
621  unsigned SImm16 = MI->getOperand(OpNo).getImm();
622  unsigned Vmcnt = SImm16 & 0xF;
623  unsigned Expcnt = (SImm16 >> 4) & 0xF;
624  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
625
626  bool NeedSpace = false;
627
628  if (Vmcnt != 0xF) {
629    O << "vmcnt(" << Vmcnt << ')';
630    NeedSpace = true;
631  }
632
633  if (Expcnt != 0x7) {
634    if (NeedSpace)
635      O << ' ';
636    O << "expcnt(" << Expcnt << ')';
637    NeedSpace = true;
638  }
639
640  if (Lgkmcnt != 0x7) {
641    if (NeedSpace)
642      O << ' ';
643    O << "lgkmcnt(" << Lgkmcnt << ')';
644  }
645}
646
647#include "AMDGPUGenAsmWriter.inc"
648