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 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 29 void R600InstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 30 raw_ostream &O) { 31 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '|'); 32 } 33 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 58 void R600InstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 59 raw_ostream &O) { 60 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "_SAT"); 61 } 62 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 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 89 void R600InstPrinter::printLast(const MCInst *MI, unsigned OpNo, 90 raw_ostream &O) { 91 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "*", " "); 92 } 93 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 107 void R600InstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 108 raw_ostream &O) { 109 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '-'); 110 } 111 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 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 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 171 void R600InstPrinter::printRel(const MCInst *MI, unsigned OpNo, 172 raw_ostream &O) { 173 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '+'); 174 } 175 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 206 void R600InstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 207 raw_ostream &O) { 208 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "ExecMask,"); 209 } 210 211 void R600InstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 212 raw_ostream &O) { 213 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "Pred,"); 214 } 215 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