1 //===-- R600InstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // \file
8 //===----------------------------------------------------------------------===//
9 
10 #include "R600InstPrinter.h"
11 #include "AMDGPUInstPrinter.h"
12 #include "R600MCTargetDesc.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCInst.h"
15 #include "llvm/MC/MCInstrInfo.h"
16 #include "llvm/MC/MCSubtargetInfo.h"
17 #include "llvm/Support/CommandLine.h"
18 
19 using namespace llvm;
20 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)21 void R600InstPrinter::printInst(const MCInst *MI, uint64_t Address,
22                                 StringRef Annot, const MCSubtargetInfo &STI,
23                                 raw_ostream &O) {
24   O.flush();
25   printInstruction(MI, Address, O);
26   printAnnotation(O, Annot);
27 }
28 
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)29 void R600InstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
30                                raw_ostream &O) {
31   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '|');
32 }
33 
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)34 void R600InstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
35                                        raw_ostream &O) {
36   int BankSwizzle = MI->getOperand(OpNo).getImm();
37   switch (BankSwizzle) {
38   case 1:
39     O << "BS:VEC_021/SCL_122";
40     break;
41   case 2:
42     O << "BS:VEC_120/SCL_212";
43     break;
44   case 3:
45     O << "BS:VEC_102/SCL_221";
46     break;
47   case 4:
48     O << "BS:VEC_201";
49     break;
50   case 5:
51     O << "BS:VEC_210";
52     break;
53   default:
54     break;
55   }
56 }
57 
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)58 void R600InstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
59                                  raw_ostream &O) {
60   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "_SAT");
61 }
62 
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)63 void R600InstPrinter::printCT(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
64   unsigned CT = MI->getOperand(OpNo).getImm();
65   switch (CT) {
66   case 0:
67     O << 'U';
68     break;
69   case 1:
70     O << 'N';
71     break;
72   default:
73     break;
74   }
75 }
76 
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)77 void R600InstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
78                                   raw_ostream &O) {
79   int KCacheMode = MI->getOperand(OpNo).getImm();
80   if (KCacheMode > 0) {
81     int KCacheBank = MI->getOperand(OpNo - 2).getImm();
82     O << "CB" << KCacheBank << ':';
83     int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
84     int LineSize = (KCacheMode == 1) ? 16 : 32;
85     O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
86   }
87 }
88 
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)89 void R600InstPrinter::printLast(const MCInst *MI, unsigned OpNo,
90                                 raw_ostream &O) {
91   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "*", " ");
92 }
93 
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)94 void R600InstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
95                                    raw_ostream &O) {
96   const MCOperand &Op = MI->getOperand(OpNo);
97   assert(Op.isImm() || Op.isExpr());
98   if (Op.isImm()) {
99     int64_t Imm = Op.getImm();
100     O << Imm << '(' << llvm::bit_cast<float>(static_cast<uint32_t>(Imm)) << ')';
101   }
102   if (Op.isExpr()) {
103     Op.getExpr()->print(O << '@', &MAI);
104   }
105 }
106 
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)107 void R600InstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
108                                raw_ostream &O) {
109   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '-');
110 }
111 
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)112 void R600InstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
113                                 raw_ostream &O) {
114   switch (MI->getOperand(OpNo).getImm()) {
115   default:
116     break;
117   case 1:
118     O << " * 2.0";
119     break;
120   case 2:
121     O << " * 4.0";
122     break;
123   case 3:
124     O << " / 2.0";
125     break;
126   }
127 }
128 
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)129 void R600InstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
130                                       raw_ostream &O) {
131   printOperand(MI, OpNo, O);
132   O << ", ";
133   printOperand(MI, OpNo + 1, O);
134 }
135 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)136 void R600InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
137                                    raw_ostream &O) {
138   if (OpNo >= MI->getNumOperands()) {
139     O << "/*Missing OP" << OpNo << "*/";
140     return;
141   }
142 
143   const MCOperand &Op = MI->getOperand(OpNo);
144   if (Op.isReg()) {
145     switch (Op.getReg()) {
146     // This is the default predicate state, so we don't need to print it.
147     case R600::PRED_SEL_OFF:
148       break;
149 
150     default:
151       O << getRegisterName(Op.getReg());
152       break;
153     }
154   } else if (Op.isImm()) {
155     O << Op.getImm();
156   } else if (Op.isDFPImm()) {
157     // We special case 0.0 because otherwise it will be printed as an integer.
158     if (Op.getDFPImm() == 0.0)
159       O << "0.0";
160     else {
161       O << bit_cast<double>(Op.getDFPImm());
162     }
163   } else if (Op.isExpr()) {
164     const MCExpr *Exp = Op.getExpr();
165     Exp->print(O, &MAI);
166   } else {
167     O << "/*INV_OP*/";
168   }
169 }
170 
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)171 void R600InstPrinter::printRel(const MCInst *MI, unsigned OpNo,
172                                raw_ostream &O) {
173   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '+');
174 }
175 
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)176 void R600InstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
177                                 raw_ostream &O) {
178   unsigned Sel = MI->getOperand(OpNo).getImm();
179   switch (Sel) {
180   case 0:
181     O << 'X';
182     break;
183   case 1:
184     O << 'Y';
185     break;
186   case 2:
187     O << 'Z';
188     break;
189   case 3:
190     O << 'W';
191     break;
192   case 4:
193     O << '0';
194     break;
195   case 5:
196     O << '1';
197     break;
198   case 7:
199     O << '_';
200     break;
201   default:
202     break;
203   }
204 }
205 
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)206 void R600InstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
207                                           raw_ostream &O) {
208   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "ExecMask,");
209 }
210 
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)211 void R600InstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
212                                       raw_ostream &O) {
213   AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "Pred,");
214 }
215 
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)216 void R600InstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
217                                  raw_ostream &O) {
218   const MCOperand &Op = MI->getOperand(OpNo);
219   if (Op.getImm() == 0) {
220     O << " (MASKED)";
221   }
222 }
223 
224 #include "R600GenAsmWriter.inc"
225