1//===-- PTXInstPrinter.cpp - Convert PTX MCInst to assembly 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 a PTX MCInst to a .ptx file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "PTXInstPrinter.h"
16#include "MCTargetDesc/PTXBaseInfo.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/ADT/StringExtras.h"
22#include "llvm/Support/ErrorHandling.h"
23#include "llvm/Support/raw_ostream.h"
24using namespace llvm;
25
26#define GET_INSTRUCTION_NAME
27#include "PTXGenAsmWriter.inc"
28
29PTXInstPrinter::PTXInstPrinter(const MCAsmInfo &MAI,
30                               const MCSubtargetInfo &STI) :
31  MCInstPrinter(MAI) {
32  // Initialize the set of available features.
33  setAvailableFeatures(STI.getFeatureBits());
34}
35
36StringRef PTXInstPrinter::getOpcodeName(unsigned Opcode) const {
37  return getInstructionName(Opcode);
38}
39
40void PTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
41  OS << getRegisterName(RegNo);
42}
43
44void PTXInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
45                               StringRef Annot) {
46  printPredicate(MI, O);
47  switch (MI->getOpcode()) {
48  default:
49    printInstruction(MI, O);
50    break;
51  case PTX::CALL:
52    printCall(MI, O);
53  }
54  O << ";";
55  printAnnotation(O, Annot);
56}
57
58void PTXInstPrinter::printPredicate(const MCInst *MI, raw_ostream &O) {
59  // The last two operands are the predicate operands
60  int RegIndex;
61  int OpIndex;
62
63  if (MI->getOpcode() == PTX::CALL) {
64    RegIndex = 0;
65    OpIndex  = 1;
66  } else {
67    RegIndex = MI->getNumOperands()-2;
68    OpIndex = MI->getNumOperands()-1;
69  }
70
71  int PredOp = MI->getOperand(OpIndex).getImm();
72  if (PredOp == PTXPredicate::None)
73    return;
74
75  if (PredOp == PTXPredicate::Negate)
76    O << '!';
77  else
78    O << '@';
79
80  printOperand(MI, RegIndex, O);
81}
82
83void PTXInstPrinter::printCall(const MCInst *MI, raw_ostream &O) {
84  O << "\tcall.uni\t";
85  // The first two operands are the predicate slot
86  unsigned Index = 2;
87  unsigned NumRets = MI->getOperand(Index++).getImm();
88
89  if (NumRets > 0) {
90    O << "(";
91    printOperand(MI, Index++, O);
92    for (unsigned i = 1; i < NumRets; ++i) {
93      O << ", ";
94      printOperand(MI, Index++, O);
95    }
96    O << "), ";
97  }
98
99  O << *(MI->getOperand(Index++).getExpr()) << ", (";
100
101  unsigned NumArgs = MI->getOperand(Index++).getImm();
102  if (NumArgs > 0) {
103    printOperand(MI, Index++, O);
104    for (unsigned i = 1; i < NumArgs; ++i) {
105      O << ", ";
106      printOperand(MI, Index++, O);
107    }
108  }
109  O << ")";
110}
111
112void PTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
113                                  raw_ostream &O) {
114  const MCOperand &Op = MI->getOperand(OpNo);
115  if (Op.isImm()) {
116    O << Op.getImm();
117  } else if (Op.isFPImm()) {
118    double Imm = Op.getFPImm();
119    APFloat FPImm(Imm);
120    APInt FPIntImm = FPImm.bitcastToAPInt();
121    O << "0D";
122    // PTX requires us to output the full 64 bits, even if the number is zero
123    if (FPIntImm.getZExtValue() > 0) {
124      O << FPIntImm.toString(16, false);
125    } else {
126      O << "0000000000000000";
127    }
128  } else {
129    assert(Op.isExpr() && "unknown operand kind in printOperand");
130    const MCExpr *Expr = Op.getExpr();
131    if (const MCSymbolRefExpr *SymRefExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
132      const MCSymbol &Sym = SymRefExpr->getSymbol();
133      O << Sym.getName();
134    } else {
135      O << *Op.getExpr();
136    }
137  }
138}
139
140void PTXInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
141                                     raw_ostream &O) {
142  // By definition, operand OpNo+1 is an i32imm
143  const MCOperand &Op2 = MI->getOperand(OpNo+1);
144  printOperand(MI, OpNo, O);
145  if (Op2.getImm() == 0)
146    return; // don't print "+0"
147  O << "+" << Op2.getImm();
148}
149
150void PTXInstPrinter::printRoundingMode(const MCInst *MI, unsigned OpNo,
151                                       raw_ostream &O) {
152  const MCOperand &Op = MI->getOperand(OpNo);
153  assert (Op.isImm() && "Rounding modes must be immediate values");
154  switch (Op.getImm()) {
155  default:
156    llvm_unreachable("Unknown rounding mode!");
157  case PTXRoundingMode::RndDefault:
158    llvm_unreachable("FP rounding-mode pass did not handle instruction!");
159    break;
160  case PTXRoundingMode::RndNone:
161    // Do not print anything.
162    break;
163  case PTXRoundingMode::RndNearestEven:
164    O << ".rn";
165    break;
166  case PTXRoundingMode::RndTowardsZero:
167    O << ".rz";
168    break;
169  case PTXRoundingMode::RndNegInf:
170    O << ".rm";
171    break;
172  case PTXRoundingMode::RndPosInf:
173    O << ".rp";
174    break;
175  case PTXRoundingMode::RndApprox:
176    O << ".approx";
177    break;
178  case PTXRoundingMode::RndNearestEvenInt:
179    O << ".rni";
180    break;
181  case PTXRoundingMode::RndTowardsZeroInt:
182    O << ".rzi";
183    break;
184  case PTXRoundingMode::RndNegInfInt:
185    O << ".rmi";
186    break;
187  case PTXRoundingMode::RndPosInfInt:
188    O << ".rpi";
189    break;
190  }
191}
192
193