OSDN Git Service

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