1349cc55cSDimitry Andric //===-- R600InstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric // \file
8349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
9349cc55cSDimitry Andric
10349cc55cSDimitry Andric #include "R600InstPrinter.h"
11349cc55cSDimitry Andric #include "AMDGPUInstPrinter.h"
12349cc55cSDimitry Andric #include "R600MCTargetDesc.h"
13349cc55cSDimitry Andric #include "llvm/MC/MCExpr.h"
14349cc55cSDimitry Andric #include "llvm/MC/MCInst.h"
15349cc55cSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
16349cc55cSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
17349cc55cSDimitry Andric #include "llvm/Support/CommandLine.h"
18349cc55cSDimitry Andric
19349cc55cSDimitry Andric using namespace llvm;
20349cc55cSDimitry Andric
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)21349cc55cSDimitry Andric void R600InstPrinter::printInst(const MCInst *MI, uint64_t Address,
22349cc55cSDimitry Andric StringRef Annot, const MCSubtargetInfo &STI,
23349cc55cSDimitry Andric raw_ostream &O) {
24349cc55cSDimitry Andric printInstruction(MI, Address, O);
25349cc55cSDimitry Andric printAnnotation(O, Annot);
26349cc55cSDimitry Andric }
27349cc55cSDimitry Andric
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)28349cc55cSDimitry Andric void R600InstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
29349cc55cSDimitry Andric raw_ostream &O) {
30349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '|');
31349cc55cSDimitry Andric }
32349cc55cSDimitry Andric
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)33349cc55cSDimitry Andric void R600InstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
34349cc55cSDimitry Andric raw_ostream &O) {
35349cc55cSDimitry Andric int BankSwizzle = MI->getOperand(OpNo).getImm();
36349cc55cSDimitry Andric switch (BankSwizzle) {
37349cc55cSDimitry Andric case 1:
38349cc55cSDimitry Andric O << "BS:VEC_021/SCL_122";
39349cc55cSDimitry Andric break;
40349cc55cSDimitry Andric case 2:
41349cc55cSDimitry Andric O << "BS:VEC_120/SCL_212";
42349cc55cSDimitry Andric break;
43349cc55cSDimitry Andric case 3:
44349cc55cSDimitry Andric O << "BS:VEC_102/SCL_221";
45349cc55cSDimitry Andric break;
46349cc55cSDimitry Andric case 4:
47349cc55cSDimitry Andric O << "BS:VEC_201";
48349cc55cSDimitry Andric break;
49349cc55cSDimitry Andric case 5:
50349cc55cSDimitry Andric O << "BS:VEC_210";
51349cc55cSDimitry Andric break;
52349cc55cSDimitry Andric default:
53349cc55cSDimitry Andric break;
54349cc55cSDimitry Andric }
55349cc55cSDimitry Andric }
56349cc55cSDimitry Andric
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)57349cc55cSDimitry Andric void R600InstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
58349cc55cSDimitry Andric raw_ostream &O) {
59349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "_SAT");
60349cc55cSDimitry Andric }
61349cc55cSDimitry Andric
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)62349cc55cSDimitry Andric void R600InstPrinter::printCT(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
63349cc55cSDimitry Andric unsigned CT = MI->getOperand(OpNo).getImm();
64349cc55cSDimitry Andric switch (CT) {
65349cc55cSDimitry Andric case 0:
66349cc55cSDimitry Andric O << 'U';
67349cc55cSDimitry Andric break;
68349cc55cSDimitry Andric case 1:
69349cc55cSDimitry Andric O << 'N';
70349cc55cSDimitry Andric break;
71349cc55cSDimitry Andric default:
72349cc55cSDimitry Andric break;
73349cc55cSDimitry Andric }
74349cc55cSDimitry Andric }
75349cc55cSDimitry Andric
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)76349cc55cSDimitry Andric void R600InstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
77349cc55cSDimitry Andric raw_ostream &O) {
78349cc55cSDimitry Andric int KCacheMode = MI->getOperand(OpNo).getImm();
79349cc55cSDimitry Andric if (KCacheMode > 0) {
80349cc55cSDimitry Andric int KCacheBank = MI->getOperand(OpNo - 2).getImm();
81349cc55cSDimitry Andric O << "CB" << KCacheBank << ':';
82349cc55cSDimitry Andric int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
83349cc55cSDimitry Andric int LineSize = (KCacheMode == 1) ? 16 : 32;
84349cc55cSDimitry Andric O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
85349cc55cSDimitry Andric }
86349cc55cSDimitry Andric }
87349cc55cSDimitry Andric
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)88349cc55cSDimitry Andric void R600InstPrinter::printLast(const MCInst *MI, unsigned OpNo,
89349cc55cSDimitry Andric raw_ostream &O) {
90349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "*", " ");
91349cc55cSDimitry Andric }
92349cc55cSDimitry Andric
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)93349cc55cSDimitry Andric void R600InstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
94349cc55cSDimitry Andric raw_ostream &O) {
95349cc55cSDimitry Andric const MCOperand &Op = MI->getOperand(OpNo);
96349cc55cSDimitry Andric assert(Op.isImm() || Op.isExpr());
97349cc55cSDimitry Andric if (Op.isImm()) {
98349cc55cSDimitry Andric int64_t Imm = Op.getImm();
99*06c3fb27SDimitry Andric O << Imm << '(' << llvm::bit_cast<float>(static_cast<uint32_t>(Imm)) << ')';
100349cc55cSDimitry Andric }
101349cc55cSDimitry Andric if (Op.isExpr()) {
102349cc55cSDimitry Andric Op.getExpr()->print(O << '@', &MAI);
103349cc55cSDimitry Andric }
104349cc55cSDimitry Andric }
105349cc55cSDimitry Andric
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)106349cc55cSDimitry Andric void R600InstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
107349cc55cSDimitry Andric raw_ostream &O) {
108349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '-');
109349cc55cSDimitry Andric }
110349cc55cSDimitry Andric
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)111349cc55cSDimitry Andric void R600InstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
112349cc55cSDimitry Andric raw_ostream &O) {
113349cc55cSDimitry Andric switch (MI->getOperand(OpNo).getImm()) {
114349cc55cSDimitry Andric default:
115349cc55cSDimitry Andric break;
116349cc55cSDimitry Andric case 1:
117349cc55cSDimitry Andric O << " * 2.0";
118349cc55cSDimitry Andric break;
119349cc55cSDimitry Andric case 2:
120349cc55cSDimitry Andric O << " * 4.0";
121349cc55cSDimitry Andric break;
122349cc55cSDimitry Andric case 3:
123349cc55cSDimitry Andric O << " / 2.0";
124349cc55cSDimitry Andric break;
125349cc55cSDimitry Andric }
126349cc55cSDimitry Andric }
127349cc55cSDimitry Andric
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)128349cc55cSDimitry Andric void R600InstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
129349cc55cSDimitry Andric raw_ostream &O) {
130349cc55cSDimitry Andric printOperand(MI, OpNo, O);
131349cc55cSDimitry Andric O << ", ";
132349cc55cSDimitry Andric printOperand(MI, OpNo + 1, O);
133349cc55cSDimitry Andric }
134349cc55cSDimitry Andric
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)135349cc55cSDimitry Andric void R600InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
136349cc55cSDimitry Andric raw_ostream &O) {
137349cc55cSDimitry Andric if (OpNo >= MI->getNumOperands()) {
138349cc55cSDimitry Andric O << "/*Missing OP" << OpNo << "*/";
139349cc55cSDimitry Andric return;
140349cc55cSDimitry Andric }
141349cc55cSDimitry Andric
142349cc55cSDimitry Andric const MCOperand &Op = MI->getOperand(OpNo);
143349cc55cSDimitry Andric if (Op.isReg()) {
144349cc55cSDimitry Andric switch (Op.getReg()) {
145349cc55cSDimitry Andric // This is the default predicate state, so we don't need to print it.
146349cc55cSDimitry Andric case R600::PRED_SEL_OFF:
147349cc55cSDimitry Andric break;
148349cc55cSDimitry Andric
149349cc55cSDimitry Andric default:
150349cc55cSDimitry Andric O << getRegisterName(Op.getReg());
151349cc55cSDimitry Andric break;
152349cc55cSDimitry Andric }
153349cc55cSDimitry Andric } else if (Op.isImm()) {
154349cc55cSDimitry Andric O << Op.getImm();
155349cc55cSDimitry Andric } else if (Op.isDFPImm()) {
156349cc55cSDimitry Andric // We special case 0.0 because otherwise it will be printed as an integer.
157349cc55cSDimitry Andric if (Op.getDFPImm() == 0.0)
158349cc55cSDimitry Andric O << "0.0";
159349cc55cSDimitry Andric else {
160349cc55cSDimitry Andric O << bit_cast<double>(Op.getDFPImm());
161349cc55cSDimitry Andric }
162349cc55cSDimitry Andric } else if (Op.isExpr()) {
163349cc55cSDimitry Andric const MCExpr *Exp = Op.getExpr();
164349cc55cSDimitry Andric Exp->print(O, &MAI);
165349cc55cSDimitry Andric } else {
166349cc55cSDimitry Andric O << "/*INV_OP*/";
167349cc55cSDimitry Andric }
168349cc55cSDimitry Andric }
169349cc55cSDimitry Andric
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)170349cc55cSDimitry Andric void R600InstPrinter::printRel(const MCInst *MI, unsigned OpNo,
171349cc55cSDimitry Andric raw_ostream &O) {
172349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '+');
173349cc55cSDimitry Andric }
174349cc55cSDimitry Andric
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)175349cc55cSDimitry Andric void R600InstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
176349cc55cSDimitry Andric raw_ostream &O) {
177349cc55cSDimitry Andric unsigned Sel = MI->getOperand(OpNo).getImm();
178349cc55cSDimitry Andric switch (Sel) {
179349cc55cSDimitry Andric case 0:
180349cc55cSDimitry Andric O << 'X';
181349cc55cSDimitry Andric break;
182349cc55cSDimitry Andric case 1:
183349cc55cSDimitry Andric O << 'Y';
184349cc55cSDimitry Andric break;
185349cc55cSDimitry Andric case 2:
186349cc55cSDimitry Andric O << 'Z';
187349cc55cSDimitry Andric break;
188349cc55cSDimitry Andric case 3:
189349cc55cSDimitry Andric O << 'W';
190349cc55cSDimitry Andric break;
191349cc55cSDimitry Andric case 4:
192349cc55cSDimitry Andric O << '0';
193349cc55cSDimitry Andric break;
194349cc55cSDimitry Andric case 5:
195349cc55cSDimitry Andric O << '1';
196349cc55cSDimitry Andric break;
197349cc55cSDimitry Andric case 7:
198349cc55cSDimitry Andric O << '_';
199349cc55cSDimitry Andric break;
200349cc55cSDimitry Andric default:
201349cc55cSDimitry Andric break;
202349cc55cSDimitry Andric }
203349cc55cSDimitry Andric }
204349cc55cSDimitry Andric
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)205349cc55cSDimitry Andric void R600InstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
206349cc55cSDimitry Andric raw_ostream &O) {
207349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "ExecMask,");
208349cc55cSDimitry Andric }
209349cc55cSDimitry Andric
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)210349cc55cSDimitry Andric void R600InstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
211349cc55cSDimitry Andric raw_ostream &O) {
212349cc55cSDimitry Andric AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "Pred,");
213349cc55cSDimitry Andric }
214349cc55cSDimitry Andric
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)215349cc55cSDimitry Andric void R600InstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
216349cc55cSDimitry Andric raw_ostream &O) {
217349cc55cSDimitry Andric const MCOperand &Op = MI->getOperand(OpNo);
218349cc55cSDimitry Andric if (Op.getImm() == 0) {
219349cc55cSDimitry Andric O << " (MASKED)";
220349cc55cSDimitry Andric }
221349cc55cSDimitry Andric }
222349cc55cSDimitry Andric
223349cc55cSDimitry Andric #include "R600GenAsmWriter.inc"
224