NVPTXInstPrinter.cpp revision 4d748eb0e4b55262619305c96a89c55c30bffe6c
1//===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
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// Print MCInst instructions to .ptx format.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "InstPrinter/NVPTXInstPrinter.h"
16#include "NVPTX.h"
17#include "MCTargetDesc/NVPTXBaseInfo.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/MC/MCSubtargetInfo.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/FormattedStream.h"
25#include <cctype>
26using namespace llvm;
27
28#include "NVPTXGenAsmWriter.inc"
29
30
31NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
32                                   const MCRegisterInfo &MRI,
33                                   const MCSubtargetInfo &STI)
34  : MCInstPrinter(MAI, MII, MRI) {
35  setAvailableFeatures(STI.getFeatureBits());
36}
37
38void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
39  // Decode the virtual register
40  // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
41  unsigned RCId = (RegNo >> 28);
42  switch (RCId) {
43  default: report_fatal_error("Bad virtual register encoding");
44  case 0:
45    // This is actually a physical register, so defer to the autogenerated
46    // register printer
47    OS << getRegisterName(RegNo);
48    return;
49  case 1:
50    OS << "%p";
51    break;
52  case 2:
53    OS << "%rs";
54    break;
55  case 3:
56    OS << "%r";
57    break;
58  case 4:
59    OS << "%rl";
60    break;
61  case 5:
62    OS << "%f";
63    break;
64  case 6:
65    OS << "%fl";
66    break;
67  }
68
69  unsigned VReg = RegNo & 0x0FFFFFFF;
70  OS << VReg;
71}
72
73void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
74                                 StringRef Annot) {
75  printInstruction(MI, OS);
76
77  // Next always print the annotation.
78  printAnnotation(OS, Annot);
79}
80
81void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
82                                    raw_ostream &O) {
83  const MCOperand &Op = MI->getOperand(OpNo);
84  if (Op.isReg()) {
85    unsigned Reg = Op.getReg();
86    printRegName(O, Reg);
87  } else if (Op.isImm()) {
88    O << markup("<imm:") << formatImm(Op.getImm()) << markup(">");
89  } else {
90    assert(Op.isExpr() && "Unknown operand kind in printOperand");
91    O << *Op.getExpr();
92  }
93}
94
95void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
96                                    const char *Modifier) {
97  const MCOperand &MO = MI->getOperand(OpNum);
98  int64_t Imm = MO.getImm();
99
100  if (strcmp(Modifier, "ftz") == 0) {
101    // FTZ flag
102    if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
103      O << ".ftz";
104  } else if (strcmp(Modifier, "sat") == 0) {
105    // SAT flag
106    if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
107      O << ".sat";
108  } else if (strcmp(Modifier, "base") == 0) {
109    // Default operand
110    switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
111    default:
112      return;
113    case NVPTX::PTXCvtMode::NONE:
114      break;
115    case NVPTX::PTXCvtMode::RNI:
116      O << ".rni";
117      break;
118    case NVPTX::PTXCvtMode::RZI:
119      O << ".rzi";
120      break;
121    case NVPTX::PTXCvtMode::RMI:
122      O << ".rmi";
123      break;
124    case NVPTX::PTXCvtMode::RPI:
125      O << ".rpi";
126      break;
127    case NVPTX::PTXCvtMode::RN:
128      O << ".rn";
129      break;
130    case NVPTX::PTXCvtMode::RZ:
131      O << ".rz";
132      break;
133    case NVPTX::PTXCvtMode::RM:
134      O << ".rm";
135      break;
136    case NVPTX::PTXCvtMode::RP:
137      O << ".rp";
138      break;
139    }
140  } else {
141    llvm_unreachable("Invalid conversion modifier");
142  }
143}
144
145void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
146                                    const char *Modifier) {
147  const MCOperand &MO = MI->getOperand(OpNum);
148  int64_t Imm = MO.getImm();
149
150  if (strcmp(Modifier, "ftz") == 0) {
151    // FTZ flag
152    if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
153      O << ".ftz";
154  } else if (strcmp(Modifier, "base") == 0) {
155    switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
156    default:
157      return;
158    case NVPTX::PTXCmpMode::EQ:
159      O << ".eq";
160      break;
161    case NVPTX::PTXCmpMode::NE:
162      O << ".ne";
163      break;
164    case NVPTX::PTXCmpMode::LT:
165      O << ".lt";
166      break;
167    case NVPTX::PTXCmpMode::LE:
168      O << ".le";
169      break;
170    case NVPTX::PTXCmpMode::GT:
171      O << ".gt";
172      break;
173    case NVPTX::PTXCmpMode::GE:
174      O << ".ge";
175      break;
176    case NVPTX::PTXCmpMode::LO:
177      O << ".lo";
178      break;
179    case NVPTX::PTXCmpMode::LS:
180      O << ".ls";
181      break;
182    case NVPTX::PTXCmpMode::HI:
183      O << ".hi";
184      break;
185    case NVPTX::PTXCmpMode::HS:
186      O << ".hs";
187      break;
188    case NVPTX::PTXCmpMode::EQU:
189      O << ".equ";
190      break;
191    case NVPTX::PTXCmpMode::NEU:
192      O << ".neu";
193      break;
194    case NVPTX::PTXCmpMode::LTU:
195      O << ".ltu";
196      break;
197    case NVPTX::PTXCmpMode::LEU:
198      O << ".leu";
199      break;
200    case NVPTX::PTXCmpMode::GTU:
201      O << ".gtu";
202      break;
203    case NVPTX::PTXCmpMode::GEU:
204      O << ".geu";
205      break;
206    case NVPTX::PTXCmpMode::NUM:
207      O << ".num";
208      break;
209    case NVPTX::PTXCmpMode::NotANumber:
210      O << ".nan";
211      break;
212    }
213  } else {
214    llvm_unreachable("Empty Modifier");
215  }
216}
217
218void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
219                                     raw_ostream &O, const char *Modifier) {
220  if (Modifier) {
221    const MCOperand &MO = MI->getOperand(OpNum);
222    int Imm = (int) MO.getImm();
223    if (!strcmp(Modifier, "volatile")) {
224      if (Imm)
225        O << ".volatile";
226    } else if (!strcmp(Modifier, "addsp")) {
227      switch (Imm) {
228      case NVPTX::PTXLdStInstCode::GLOBAL:
229        O << ".global";
230        break;
231      case NVPTX::PTXLdStInstCode::SHARED:
232        O << ".shared";
233        break;
234      case NVPTX::PTXLdStInstCode::LOCAL:
235        O << ".local";
236        break;
237      case NVPTX::PTXLdStInstCode::PARAM:
238        O << ".param";
239        break;
240      case NVPTX::PTXLdStInstCode::CONSTANT:
241        O << ".const";
242        break;
243      case NVPTX::PTXLdStInstCode::GENERIC:
244        break;
245      default:
246        llvm_unreachable("Wrong Address Space");
247      }
248    } else if (!strcmp(Modifier, "sign")) {
249      if (Imm == NVPTX::PTXLdStInstCode::Signed)
250        O << "s";
251      else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
252        O << "u";
253      else
254        O << "f";
255    } else if (!strcmp(Modifier, "vec")) {
256      if (Imm == NVPTX::PTXLdStInstCode::V2)
257        O << ".v2";
258      else if (Imm == NVPTX::PTXLdStInstCode::V4)
259        O << ".v4";
260    } else
261      llvm_unreachable("Unknown Modifier");
262  } else
263    llvm_unreachable("Empty Modifier");
264}
265
266void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
267                                       raw_ostream &O, const char *Modifier) {
268  printOperand(MI, OpNum, O);
269
270  if (Modifier && !strcmp(Modifier, "add")) {
271    O << ", ";
272    printOperand(MI, OpNum + 1, O);
273  } else {
274    if (MI->getOperand(OpNum + 1).isImm() &&
275        MI->getOperand(OpNum + 1).getImm() == 0)
276      return; // don't print ',0' or '+0'
277    O << "+";
278    printOperand(MI, OpNum + 1, O);
279  }
280}
281
282void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
283                                       raw_ostream &O, const char *Modifier) {
284  const MCOperand &Op = MI->getOperand(OpNum);
285  assert(Op.isExpr() && "Call prototype is not an MCExpr?");
286  const MCExpr *Expr = Op.getExpr();
287  const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
288  O << Sym.getName();
289}
290