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