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 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 Op.getExpr()->print(O << '@', &MAI); 103 } 104 } 105 106 void R600InstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 107 raw_ostream &O) { 108 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '-'); 109 } 110 111 void R600InstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 112 raw_ostream &O) { 113 switch (MI->getOperand(OpNo).getImm()) { 114 default: 115 break; 116 case 1: 117 O << " * 2.0"; 118 break; 119 case 2: 120 O << " * 4.0"; 121 break; 122 case 3: 123 O << " / 2.0"; 124 break; 125 } 126 } 127 128 void R600InstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 129 raw_ostream &O) { 130 printOperand(MI, OpNo, O); 131 O << ", "; 132 printOperand(MI, OpNo + 1, O); 133 } 134 135 void R600InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 136 raw_ostream &O) { 137 if (OpNo >= MI->getNumOperands()) { 138 O << "/*Missing OP" << OpNo << "*/"; 139 return; 140 } 141 142 const MCOperand &Op = MI->getOperand(OpNo); 143 if (Op.isReg()) { 144 switch (Op.getReg()) { 145 // This is the default predicate state, so we don't need to print it. 146 case R600::PRED_SEL_OFF: 147 break; 148 149 default: 150 O << getRegisterName(Op.getReg()); 151 break; 152 } 153 } else if (Op.isImm()) { 154 O << Op.getImm(); 155 } else if (Op.isDFPImm()) { 156 // We special case 0.0 because otherwise it will be printed as an integer. 157 if (Op.getDFPImm() == 0.0) 158 O << "0.0"; 159 else { 160 O << bit_cast<double>(Op.getDFPImm()); 161 } 162 } else if (Op.isExpr()) { 163 const MCExpr *Exp = Op.getExpr(); 164 Exp->print(O, &MAI); 165 } else { 166 O << "/*INV_OP*/"; 167 } 168 } 169 170 void R600InstPrinter::printRel(const MCInst *MI, unsigned OpNo, 171 raw_ostream &O) { 172 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, '+'); 173 } 174 175 void R600InstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 176 raw_ostream &O) { 177 unsigned Sel = MI->getOperand(OpNo).getImm(); 178 switch (Sel) { 179 case 0: 180 O << 'X'; 181 break; 182 case 1: 183 O << 'Y'; 184 break; 185 case 2: 186 O << 'Z'; 187 break; 188 case 3: 189 O << 'W'; 190 break; 191 case 4: 192 O << '0'; 193 break; 194 case 5: 195 O << '1'; 196 break; 197 case 7: 198 O << '_'; 199 break; 200 default: 201 break; 202 } 203 } 204 205 void R600InstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 206 raw_ostream &O) { 207 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "ExecMask,"); 208 } 209 210 void R600InstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 211 raw_ostream &O) { 212 AMDGPUInstPrinter::printIfSet(MI, OpNo, O, "Pred,"); 213 } 214 215 void R600InstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 216 raw_ostream &O) { 217 const MCOperand &Op = MI->getOperand(OpNo); 218 if (Op.getImm() == 0) { 219 O << " (MASKED)"; 220 } 221 } 222 223 #include "R600GenAsmWriter.inc" 224