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/MCAsmInfo.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCInst.h" 16 #include "llvm/MC/MCInstrInfo.h" 17 #include "llvm/MC/MCSubtargetInfo.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 printInstruction(MI, Address, O); 25 printAnnotation(O, Annot); 26 } 27 28 void R600InstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 29 raw_ostream &O) { 30 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '|'); 31 } 32 33 void R600InstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 34 raw_ostream &O) { 35 int BankSwizzle = MI->getOperand(OpNo).getImm(); 36 switch (BankSwizzle) { 37 case 1: 38 O << "BS:VEC_021/SCL_122"; 39 break; 40 case 2: 41 O << "BS:VEC_120/SCL_212"; 42 break; 43 case 3: 44 O << "BS:VEC_102/SCL_221"; 45 break; 46 case 4: 47 O << "BS:VEC_201"; 48 break; 49 case 5: 50 O << "BS:VEC_210"; 51 break; 52 default: 53 break; 54 } 55 } 56 57 void R600InstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 58 raw_ostream &O) { 59 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "_SAT"); 60 } 61 62 void R600InstPrinter::printCT(const MCInst *MI, unsigned OpNo, raw_ostream &O) { 63 unsigned CT = MI->getOperand(OpNo).getImm(); 64 switch (CT) { 65 case 0: 66 O << 'U'; 67 break; 68 case 1: 69 O << 'N'; 70 break; 71 default: 72 break; 73 } 74 } 75 76 void R600InstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 77 raw_ostream &O) { 78 int KCacheMode = MI->getOperand(OpNo).getImm(); 79 if (KCacheMode > 0) { 80 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 81 O << "CB" << KCacheBank << ':'; 82 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 83 int LineSize = (KCacheMode == 1) ? 16 : 32; 84 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize; 85 } 86 } 87 88 void R600InstPrinter::printLast(const MCInst *MI, unsigned OpNo, 89 raw_ostream &O) { 90 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "*", " "); 91 } 92 93 void R600InstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 94 raw_ostream &O) { 95 const MCOperand &Op = MI->getOperand(OpNo); 96 assert(Op.isImm() || Op.isExpr()); 97 if (Op.isImm()) { 98 int64_t Imm = Op.getImm(); 99 O << Imm << '(' << llvm::bit_cast<float>(static_cast<uint32_t>(Imm)) << ')'; 100 } 101 if (Op.isExpr()) { 102 O << '@'; 103 MAI.printExpr(O, *Op.getExpr()); 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().id()) { 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 MAI.printExpr(O, *Exp); 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