AMDGPUInstPrinter.cpp revision 284734
1193323Sed//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed// \file
9193323Sed//===----------------------------------------------------------------------===//
10193323Sed
11212904Sdim#include "AMDGPUInstPrinter.h"
12193323Sed#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13193323Sed#include "SIDefines.h"
14193323Sed#include "llvm/MC/MCExpr.h"
15212904Sdim#include "llvm/MC/MCInst.h"
16212904Sdim#include "llvm/MC/MCInstrInfo.h"
17212904Sdim#include "llvm/MC/MCRegisterInfo.h"
18212904Sdim#include "llvm/Support/MathExtras.h"
19212904Sdim
20193323Sedusing namespace llvm;
21212904Sdim
22212904Sdimvoid AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
23193323Sed                                  StringRef Annot, const MCSubtargetInfo &STI) {
24193323Sed  OS.flush();
25193323Sed  printInstruction(MI, OS);
26193323Sed
27193323Sed  printAnnotation(OS, Annot);
28193323Sed}
29198090Srdivacky
30212904Sdimvoid AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
31198090Srdivacky                                           raw_ostream &O) {
32198090Srdivacky  O << formatHex(MI->getOperand(OpNo).getImm() & 0xff);
33198090Srdivacky}
34198090Srdivacky
35218893Sdimvoid AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
36193323Sed                                           raw_ostream &O) {
37193323Sed  O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff);
38193323Sed}
39193323Sed
40224145Sdimvoid AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
41198090Srdivacky                                           raw_ostream &O) {
42198090Srdivacky  O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
43198090Srdivacky}
44193323Sed
45193323Sedvoid AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo,
46193323Sed                                             raw_ostream &O) {
47193323Sed  O << formatDec(MI->getOperand(OpNo).getImm() & 0xff);
48193323Sed}
49193323Sed
50193323Sedvoid AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
51193323Sed                                              raw_ostream &O) {
52193323Sed  O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
53198892Srdivacky}
54193323Sed
55212904Sdimvoid AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo,
56218893Sdim                                   raw_ostream &O) {
57212904Sdim  if (MI->getOperand(OpNo).getImm())
58212904Sdim    O << " offen";
59212904Sdim}
60212904Sdim
61212904Sdimvoid AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo,
62193323Sed                                   raw_ostream &O) {
63193323Sed  if (MI->getOperand(OpNo).getImm())
64198090Srdivacky    O << " idxen";
65218893Sdim}
66193323Sed
67193323Sedvoid AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo,
68193323Sed                                    raw_ostream &O) {
69193323Sed  if (MI->getOperand(OpNo).getImm())
70193323Sed    O << " addr64";
71193323Sed}
72193323Sed
73193323Sedvoid AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo,
74193323Sed                                        raw_ostream &O) {
75193323Sed  if (MI->getOperand(OpNo).getImm()) {
76193323Sed    O << " offset:";
77212904Sdim    printU16ImmDecOperand(MI, OpNo, O);
78212904Sdim  }
79212904Sdim}
80212904Sdim
81212904Sdimvoid AMDGPUInstPrinter::printDSOffset(const MCInst *MI, unsigned OpNo,
82212904Sdim                                      raw_ostream &O) {
83212904Sdim  uint16_t Imm = MI->getOperand(OpNo).getImm();
84212904Sdim  if (Imm != 0) {
85212904Sdim    O << " offset:";
86212904Sdim    printU16ImmDecOperand(MI, OpNo, O);
87212904Sdim  }
88212904Sdim}
89212904Sdim
90212904Sdimvoid AMDGPUInstPrinter::printDSOffset0(const MCInst *MI, unsigned OpNo,
91212904Sdim                                        raw_ostream &O) {
92212904Sdim  if (MI->getOperand(OpNo).getImm()) {
93212904Sdim    O << " offset0:";
94212904Sdim    printU8ImmDecOperand(MI, OpNo, O);
95212904Sdim  }
96212904Sdim}
97212904Sdim
98212904Sdimvoid AMDGPUInstPrinter::printDSOffset1(const MCInst *MI, unsigned OpNo,
99212904Sdim                                        raw_ostream &O) {
100212904Sdim  if (MI->getOperand(OpNo).getImm()) {
101218893Sdim    O << " offset1:";
102212904Sdim    printU8ImmDecOperand(MI, OpNo, O);
103212904Sdim  }
104212904Sdim}
105212904Sdim
106212904Sdimvoid AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo,
107212904Sdim                                 raw_ostream &O) {
108212904Sdim  if (MI->getOperand(OpNo).getImm())
109212904Sdim    O << " gds";
110212904Sdim}
111218893Sdim
112218893Sdimvoid AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo,
113212904Sdim                                 raw_ostream &O) {
114212904Sdim  if (MI->getOperand(OpNo).getImm())
115212904Sdim    O << " glc";
116212904Sdim}
117212904Sdim
118212904Sdimvoid AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo,
119212904Sdim                                 raw_ostream &O) {
120212904Sdim  if (MI->getOperand(OpNo).getImm())
121212904Sdim    O << " slc";
122212904Sdim}
123212904Sdim
124212904Sdimvoid AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
125212904Sdim                                 raw_ostream &O) {
126212904Sdim  if (MI->getOperand(OpNo).getImm())
127212904Sdim    O << " tfe";
128212904Sdim}
129193323Sed
130224145Sdimvoid AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O,
131224145Sdim                                        const MCRegisterInfo &MRI) {
132224145Sdim  switch (reg) {
133224145Sdim  case AMDGPU::VCC:
134224145Sdim    O << "vcc";
135193323Sed    return;
136193323Sed  case AMDGPU::SCC:
137193323Sed    O << "scc";
138224145Sdim    return;
139224145Sdim  case AMDGPU::EXEC:
140224145Sdim    O << "exec";
141224145Sdim    return;
142224145Sdim  case AMDGPU::M0:
143224145Sdim    O << "m0";
144224145Sdim    return;
145224145Sdim  case AMDGPU::FLAT_SCR:
146224145Sdim    O << "flat_scratch";
147224145Sdim    return;
148224145Sdim  case AMDGPU::VCC_LO:
149224145Sdim    O << "vcc_lo";
150224145Sdim    return;
151224145Sdim  case AMDGPU::VCC_HI:
152224145Sdim    O << "vcc_hi";
153224145Sdim    return;
154224145Sdim  case AMDGPU::EXEC_LO:
155224145Sdim    O << "exec_lo";
156224145Sdim    return;
157224145Sdim  case AMDGPU::EXEC_HI:
158224145Sdim    O << "exec_hi";
159224145Sdim    return;
160224145Sdim  case AMDGPU::FLAT_SCR_LO:
161224145Sdim    O << "flat_scratch_lo";
162224145Sdim    return;
163224145Sdim  case AMDGPU::FLAT_SCR_HI:
164224145Sdim    O << "flat_scratch_hi";
165224145Sdim    return;
166224145Sdim  default:
167224145Sdim    break;
168224145Sdim  }
169212904Sdim
170212904Sdim  char Type;
171212904Sdim  unsigned NumRegs;
172212904Sdim
173212904Sdim  if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
174212904Sdim    Type = 'v';
175193323Sed    NumRegs = 1;
176202375Srdivacky  } else  if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
177193323Sed    Type = 's';
178202375Srdivacky    NumRegs = 1;
179193323Sed  } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
180193323Sed    Type = 'v';
181224145Sdim    NumRegs = 2;
182224145Sdim  } else  if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) {
183202375Srdivacky    Type = 's';
184193323Sed    NumRegs = 2;
185212904Sdim  } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
186212904Sdim    Type = 'v';
187212904Sdim    NumRegs = 4;
188193323Sed  } else  if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) {
189224145Sdim    Type = 's';
190193323Sed    NumRegs = 4;
191193323Sed  } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
192193323Sed    Type = 'v';
193212904Sdim    NumRegs = 3;
194212904Sdim  } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
195212904Sdim    Type = 'v';
196212904Sdim    NumRegs = 8;
197212904Sdim  } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
198212904Sdim    Type = 's';
199212904Sdim    NumRegs = 8;
200212904Sdim  } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
201224145Sdim    Type = 'v';
202212904Sdim    NumRegs = 16;
203212904Sdim  } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
204212904Sdim    Type = 's';
205212904Sdim    NumRegs = 16;
206212904Sdim  } else {
207224145Sdim    O << getRegisterName(reg);
208224145Sdim    return;
209224145Sdim  }
210224145Sdim
211224145Sdim  // The low 8 bits of the encoding value is the register index, for both VGPRs
212212904Sdim  // and SGPRs.
213193323Sed  unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
214218893Sdim  if (NumRegs == 1) {
215218893Sdim    O << Type << RegIdx;
216193323Sed    return;
217193323Sed  }
218193323Sed
219212904Sdim  O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
220212904Sdim}
221193323Sed
222193323Sedvoid AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
223193323Sed                                    raw_ostream &O) {
224193323Sed  if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3)
225193323Sed    O << "_e64 ";
226193323Sed  else
227224145Sdim    O << "_e32 ";
228218893Sdim
229218893Sdim  printOperand(MI, OpNo, O);
230193323Sed}
231193323Sed
232193323Sedvoid AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) {
233193323Sed  int32_t SImm = static_cast<int32_t>(Imm);
234193323Sed  if (SImm >= -16 && SImm <= 64) {
235193323Sed    O << SImm;
236212904Sdim    return;
237193323Sed  }
238212904Sdim
239193323Sed  if (Imm == FloatToBits(0.0f))
240193323Sed    O << "0.0";
241193323Sed  else if (Imm == FloatToBits(1.0f))
242193323Sed    O << "1.0";
243193323Sed  else if (Imm == FloatToBits(-1.0f))
244193323Sed    O << "-1.0";
245193323Sed  else if (Imm == FloatToBits(0.5f))
246218893Sdim    O << "0.5";
247218893Sdim  else if (Imm == FloatToBits(-0.5f))
248193323Sed    O << "-0.5";
249193323Sed  else if (Imm == FloatToBits(2.0f))
250193323Sed    O << "2.0";
251193323Sed  else if (Imm == FloatToBits(-2.0f))
252210299Sed    O << "-2.0";
253193323Sed  else if (Imm == FloatToBits(4.0f))
254193323Sed    O << "4.0";
255193323Sed  else if (Imm == FloatToBits(-4.0f))
256212904Sdim    O << "-4.0";
257193323Sed  else
258193323Sed    O << formatHex(static_cast<uint64_t>(Imm));
259193323Sed}
260193323Sed
261193323Sedvoid AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) {
262193323Sed  int64_t SImm = static_cast<int64_t>(Imm);
263226633Sdim  if (SImm >= -16 && SImm <= 64) {
264226633Sdim    O << SImm;
265226633Sdim    return;
266226633Sdim  }
267226633Sdim
268226633Sdim  if (Imm == DoubleToBits(0.0))
269226633Sdim    O << "0.0";
270226633Sdim  else if (Imm == DoubleToBits(1.0))
271226633Sdim    O << "1.0";
272226633Sdim  else if (Imm == DoubleToBits(-1.0))
273226633Sdim    O << "-1.0";
274226633Sdim  else if (Imm == DoubleToBits(0.5))
275226633Sdim    O << "0.5";
276226633Sdim  else if (Imm == DoubleToBits(-0.5))
277226633Sdim    O << "-0.5";
278212904Sdim  else if (Imm == DoubleToBits(2.0))
279212904Sdim    O << "2.0";
280193323Sed  else if (Imm == DoubleToBits(-2.0))
281193323Sed    O << "-2.0";
282212904Sdim  else if (Imm == DoubleToBits(4.0))
283212904Sdim    O << "4.0";
284212904Sdim  else if (Imm == DoubleToBits(-4.0))
285212904Sdim    O << "-4.0";
286212904Sdim  else
287193323Sed    llvm_unreachable("64-bit literal constants not supported");
288193323Sed}
289212904Sdim
290212904Sdimvoid AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
291212904Sdim                                     raw_ostream &O) {
292212904Sdim
293212904Sdim  const MCOperand &Op = MI->getOperand(OpNo);
294212904Sdim  if (Op.isReg()) {
295212904Sdim    switch (Op.getReg()) {
296212904Sdim    // This is the default predicate state, so we don't need to print it.
297224145Sdim    case AMDGPU::PRED_SEL_OFF:
298212904Sdim      break;
299212904Sdim
300212904Sdim    default:
301212904Sdim      printRegOperand(Op.getReg(), O, MRI);
302193323Sed      break;
303193323Sed    }
304193323Sed  } else if (Op.isImm()) {
305193323Sed    const MCInstrDesc &Desc = MII.get(MI->getOpcode());
306193323Sed    int RCID = Desc.OpInfo[OpNo].RegClass;
307193323Sed    if (RCID != -1) {
308193323Sed      const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
309193323Sed      if (ImmRC.getSize() == 4)
310193323Sed        printImmediate32(Op.getImm(), O);
311210299Sed      else if (ImmRC.getSize() == 8)
312224145Sdim        printImmediate64(Op.getImm(), O);
313224145Sdim      else
314224145Sdim        llvm_unreachable("Invalid register class size");
315224145Sdim    } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
316224145Sdim      printImmediate32(Op.getImm(), O);
317224145Sdim    } else {
318224145Sdim      // We hit this for the immediate instruction bits that don't yet have a
319224145Sdim      // custom printer.
320193323Sed      // TODO: Eventually this should be unnecessary.
321193323Sed      O << formatDec(Op.getImm());
322193323Sed    }
323193323Sed  } else if (Op.isFPImm()) {
324193323Sed    // We special case 0.0 because otherwise it will be printed as an integer.
325193323Sed    if (Op.getFPImm() == 0.0)
326193323Sed      O << "0.0";
327193323Sed    else {
328193323Sed      const MCInstrDesc &Desc = MII.get(MI->getOpcode());
329193323Sed      const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
330193323Sed
331193323Sed      if (ImmRC.getSize() == 4)
332193323Sed        printImmediate32(FloatToBits(Op.getFPImm()), O);
333193323Sed      else if (ImmRC.getSize() == 8)
334193323Sed        printImmediate64(DoubleToBits(Op.getFPImm()), O);
335193323Sed      else
336193323Sed        llvm_unreachable("Invalid register class size");
337193323Sed    }
338193323Sed  } else if (Op.isExpr()) {
339193323Sed    const MCExpr *Exp = Op.getExpr();
340193323Sed    Exp->print(O, &MAI);
341193323Sed  } else {
342193323Sed    llvm_unreachable("unknown operand type in printOperand");
343193323Sed  }
344193323Sed}
345193323Sed
346193323Sedvoid AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
347193323Sed                                            raw_ostream &O) {
348193323Sed  unsigned InputModifiers = MI->getOperand(OpNo).getImm();
349193323Sed  if (InputModifiers & SISrcMods::NEG)
350193323Sed    O << '-';
351193323Sed  if (InputModifiers & SISrcMods::ABS)
352193323Sed    O << '|';
353218893Sdim  printOperand(MI, OpNo + 1, O);
354193323Sed  if (InputModifiers & SISrcMods::ABS)
355212904Sdim    O << '|';
356212904Sdim}
357212904Sdim
358212904Sdimvoid AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
359193323Sed                                        raw_ostream &O) {
360193323Sed  unsigned Imm = MI->getOperand(OpNum).getImm();
361193323Sed
362193323Sed  if (Imm == 2) {
363193323Sed    O << "P0";
364193323Sed  } else if (Imm == 1) {
365193323Sed    O << "P20";
366193323Sed  } else if (Imm == 0) {
367193323Sed    O << "P10";
368193323Sed  } else {
369193323Sed    llvm_unreachable("Invalid interpolation parameter slot");
370193323Sed  }
371193323Sed}
372198090Srdivacky
373212904Sdimvoid AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
374212904Sdim                                        raw_ostream &O) {
375212904Sdim  printOperand(MI, OpNo, O);
376212904Sdim  O  << ", ";
377198090Srdivacky  printOperand(MI, OpNo + 1, O);
378212904Sdim}
379212904Sdim
380193323Sedvoid AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
381193323Sed                                   raw_ostream &O, StringRef Asm,
382193323Sed                                   StringRef Default) {
383212904Sdim  const MCOperand &Op = MI->getOperand(OpNo);
384212904Sdim  assert(Op.isImm());
385212904Sdim  if (Op.getImm() == 1) {
386212904Sdim    O << Asm;
387212904Sdim  } else {
388212904Sdim    O << Default;
389212904Sdim  }
390218893Sdim}
391212904Sdim
392218893Sdimvoid AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
393212904Sdim                                 raw_ostream &O) {
394212904Sdim  printIfSet(MI, OpNo, O, "|");
395212904Sdim}
396212904Sdim
397212904Sdimvoid AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
398218893Sdim                                   raw_ostream &O) {
399218893Sdim  printIfSet(MI, OpNo, O, "_SAT");
400212904Sdim}
401212904Sdim
402212904Sdimvoid AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
403193323Sed                                     raw_ostream &O) {
404193323Sed  if (MI->getOperand(OpNo).getImm())
405193323Sed    O << " clamp";
406193323Sed}
407193323Sed
408193323Sedvoid AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
409224145Sdim                                     raw_ostream &O) {
410193323Sed  int Imm = MI->getOperand(OpNo).getImm();
411212904Sdim  if (Imm == SIOutMods::MUL2)
412212904Sdim    O << " mul:2";
413193323Sed  else if (Imm == SIOutMods::MUL4)
414193323Sed    O << " mul:4";
415210299Sed  else if (Imm == SIOutMods::DIV2)
416212904Sdim    O << " div:2";
417193323Sed}
418203954Srdivacky
419193323Sedvoid AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
420210299Sed                                     raw_ostream &O) {
421224145Sdim  int32_t Imm = MI->getOperand(OpNo).getImm();
422210299Sed  O << Imm << '(' << BitsToFloat(Imm) << ')';
423210299Sed}
424226633Sdim
425226633Sdimvoid AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
426226633Sdim                                  raw_ostream &O) {
427226633Sdim  printIfSet(MI, OpNo, O, "*", " ");
428193323Sed}
429193323Sed
430193323Sedvoid AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
431193323Sed                                 raw_ostream &O) {
432193323Sed  printIfSet(MI, OpNo, O, "-");
433193323Sed}
434193323Sed
435193323Sedvoid AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
436202375Srdivacky                                  raw_ostream &O) {
437193323Sed  switch (MI->getOperand(OpNo).getImm()) {
438193323Sed  default: break;
439193323Sed  case 1:
440193323Sed    O << " * 2.0";
441193323Sed    break;
442193323Sed  case 2:
443193323Sed    O << " * 4.0";
444193323Sed    break;
445193323Sed  case 3:
446193323Sed    O << " / 2.0";
447193323Sed    break;
448193323Sed  }
449193323Sed}
450193323Sed
451193323Sedvoid AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
452193323Sed                                 raw_ostream &O) {
453193323Sed  printIfSet(MI, OpNo, O, "+");
454193323Sed}
455198090Srdivacky
456193323Sedvoid AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
457193323Sed                                            raw_ostream &O) {
458193323Sed  printIfSet(MI, OpNo, O, "ExecMask,");
459193323Sed}
460193323Sed
461193323Sedvoid AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
462193323Sed                                        raw_ostream &O) {
463202375Srdivacky  printIfSet(MI, OpNo, O, "Pred,");
464193323Sed}
465193323Sed
466193323Sedvoid AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
467193323Sed                                       raw_ostream &O) {
468193323Sed  const MCOperand &Op = MI->getOperand(OpNo);
469193323Sed  if (Op.getImm() == 0) {
470193323Sed    O << " (MASKED)";
471193323Sed  }
472202375Srdivacky}
473193323Sed
474193323Sedvoid AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
475193323Sed                                  raw_ostream &O) {
476193323Sed  const char * chans = "XYZW";
477202375Srdivacky  int sel = MI->getOperand(OpNo).getImm();
478202375Srdivacky
479200581Srdivacky  int chan = sel & 3;
480193323Sed  sel >>= 2;
481193323Sed
482193323Sed  if (sel >= 512) {
483226633Sdim    sel -= 512;
484193323Sed    int cb = sel >> 12;
485193323Sed    sel &= 4095;
486193323Sed    O << cb << '[' << sel << ']';
487193323Sed  } else if (sel >= 448) {
488212904Sdim    sel -= 448;
489212904Sdim    O << sel;
490193323Sed  } else if (sel >= 0){
491193323Sed    O << sel;
492193323Sed  }
493218893Sdim
494212904Sdim  if (sel >= 0)
495212904Sdim    O << '.' << chans[chan];
496212904Sdim}
497212904Sdim
498212904Sdimvoid AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
499218893Sdim                                         raw_ostream &O) {
500218893Sdim  int BankSwizzle = MI->getOperand(OpNo).getImm();
501218893Sdim  switch (BankSwizzle) {
502212904Sdim  case 1:
503212904Sdim    O << "BS:VEC_021/SCL_122";
504212904Sdim    break;
505212904Sdim  case 2:
506212904Sdim    O << "BS:VEC_120/SCL_212";
507212904Sdim    break;
508212904Sdim  case 3:
509212904Sdim    O << "BS:VEC_102/SCL_221";
510212904Sdim    break;
511212904Sdim  case 4:
512212904Sdim    O << "BS:VEC_201";
513212904Sdim    break;
514212904Sdim  case 5:
515212904Sdim    O << "BS:VEC_210";
516212904Sdim    break;
517212904Sdim  default:
518212904Sdim    break;
519212904Sdim  }
520212904Sdim  return;
521212904Sdim}
522212904Sdim
523212904Sdimvoid AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
524212904Sdim                                  raw_ostream &O) {
525212904Sdim  unsigned Sel = MI->getOperand(OpNo).getImm();
526212904Sdim  switch (Sel) {
527212904Sdim  case 0:
528212904Sdim    O << 'X';
529212904Sdim    break;
530212904Sdim  case 1:
531212904Sdim    O << 'Y';
532212904Sdim    break;
533212904Sdim  case 2:
534212904Sdim    O << 'Z';
535212904Sdim    break;
536212904Sdim  case 3:
537212904Sdim    O << 'W';
538218893Sdim    break;
539218893Sdim  case 4:
540212904Sdim    O << '0';
541212904Sdim    break;
542212904Sdim  case 5:
543212904Sdim    O << '1';
544212904Sdim    break;
545212904Sdim  case 7:
546212904Sdim    O << '_';
547212904Sdim    break;
548212904Sdim  default:
549212904Sdim    break;
550212904Sdim  }
551212904Sdim}
552212904Sdim
553212904Sdimvoid AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
554212904Sdim                                  raw_ostream &O) {
555212904Sdim  unsigned CT = MI->getOperand(OpNo).getImm();
556212904Sdim  switch (CT) {
557212904Sdim  case 0:
558212904Sdim    O << 'U';
559212904Sdim    break;
560212904Sdim  case 1:
561212904Sdim    O << 'N';
562212904Sdim    break;
563212904Sdim  default:
564212904Sdim    break;
565212904Sdim  }
566212904Sdim}
567193323Sed
568193323Sedvoid AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
569193323Sed                                    raw_ostream &O) {
570193323Sed  int KCacheMode = MI->getOperand(OpNo).getImm();
571193323Sed  if (KCacheMode > 0) {
572193323Sed    int KCacheBank = MI->getOperand(OpNo - 2).getImm();
573193323Sed    O << "CB" << KCacheBank << ':';
574193323Sed    int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
575193323Sed    int LineSize = (KCacheMode == 1) ? 16 : 32;
576193323Sed    O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
577193323Sed  }
578193323Sed}
579218893Sdim
580218893Sdimvoid AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
581193323Sed                                     raw_ostream &O) {
582193323Sed  unsigned SImm16 = MI->getOperand(OpNo).getImm();
583193323Sed  unsigned Msg = SImm16 & 0xF;
584193323Sed  if (Msg == 2 || Msg == 3) {
585193323Sed    unsigned Op = (SImm16 >> 4) & 0xF;
586193323Sed    if (Msg == 3)
587193323Sed      O << "Gs_done(";
588193323Sed    else
589193323Sed      O << "Gs(";
590193323Sed    if (Op == 0) {
591193323Sed      O << "nop";
592193323Sed    } else {
593193323Sed      unsigned Stream = (SImm16 >> 8) & 0x3;
594193323Sed      if (Op == 1)
595193323Sed	O << "cut";
596193323Sed      else if (Op == 2)
597193323Sed	O << "emit";
598193323Sed      else if (Op == 3)
599193323Sed	O << "emit-cut";
600193323Sed      O << " stream " << Stream;
601193323Sed    }
602193323Sed    O << "), [m0] ";
603193323Sed  } else if (Msg == 1)
604193323Sed    O << "interrupt ";
605193323Sed  else if (Msg == 15)
606193323Sed    O << "system ";
607193323Sed  else
608193323Sed    O << "unknown(" << Msg << ") ";
609193323Sed}
610193323Sed
611193323Sedvoid AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
612193323Sed                                      raw_ostream &O) {
613193323Sed  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
614193323Sed  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
615193323Sed  // works so it might be a misprint in docs.
616193323Sed  unsigned SImm16 = MI->getOperand(OpNo).getImm();
617193323Sed  unsigned Vmcnt = SImm16 & 0xF;
618193323Sed  unsigned Expcnt = (SImm16 >> 4) & 0xF;
619193323Sed  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
620193323Sed
621193323Sed  bool NeedSpace = false;
622193323Sed
623193323Sed  if (Vmcnt != 0xF) {
624193323Sed    O << "vmcnt(" << Vmcnt << ')';
625193323Sed    NeedSpace = true;
626193323Sed  }
627193323Sed
628193323Sed  if (Expcnt != 0x7) {
629193323Sed    if (NeedSpace)
630193323Sed      O << ' ';
631193323Sed    O << "expcnt(" << Expcnt << ')';
632193323Sed    NeedSpace = true;
633193323Sed  }
634193323Sed
635193323Sed  if (Lgkmcnt != 0x7) {
636193323Sed    if (NeedSpace)
637193323Sed      O << ' ';
638193323Sed    O << "lgkmcnt(" << Lgkmcnt << ')';
639193323Sed  }
640193323Sed}
641193323Sed
642193323Sed#include "AMDGPUGenAsmWriter.inc"
643193323Sed