AMDGPUInstPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8// \file 9//===----------------------------------------------------------------------===// 10 11#include "AMDGPUInstPrinter.h" 12#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 13#include "llvm/MC/MCExpr.h" 14#include "llvm/MC/MCInst.h" 15 16using namespace llvm; 17 18void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 19 StringRef Annot) { 20 OS.flush(); 21 printInstruction(MI, OS); 22 23 printAnnotation(OS, Annot); 24} 25 26void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) { 27 switch (reg) { 28 case AMDGPU::VCC: 29 O << "vcc"; 30 return; 31 case AMDGPU::SCC: 32 O << "scc"; 33 return; 34 case AMDGPU::EXEC: 35 O << "exec"; 36 return; 37 case AMDGPU::M0: 38 O << "m0"; 39 return; 40 default: 41 break; 42 } 43 44 // It's seems there's no way to use SIRegisterInfo here, and dealing with the 45 // giant enum of all the different shifted sets of registers is pretty 46 // unmanagable, so parse the name and reformat it to be prettier. 47 StringRef Name(getRegisterName(reg)); 48 49 std::pair<StringRef, StringRef> Split = Name.split('_'); 50 StringRef SubRegName = Split.first; 51 StringRef Rest = Split.second; 52 53 if (SubRegName.size() <= 4) { // Must at least be as long as "SGPR"/"VGPR". 54 O << Name; 55 return; 56 } 57 58 unsigned RegIndex; 59 StringRef RegIndexStr = SubRegName.drop_front(4); 60 61 if (RegIndexStr.getAsInteger(10, RegIndex)) { 62 O << Name; 63 return; 64 } 65 66 if (SubRegName.front() == 'V') 67 O << 'v'; 68 else if (SubRegName.front() == 'S') 69 O << 's'; 70 else { 71 O << Name; 72 return; 73 } 74 75 if (Rest.empty()) // Only 1 32-bit register 76 O << RegIndex; 77 else { 78 unsigned NumReg = Rest.count('_') + 2; 79 O << '[' << RegIndex << ':' << (RegIndex + NumReg - 1) << ']'; 80 } 81} 82 83void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 84 raw_ostream &O) { 85 86 const MCOperand &Op = MI->getOperand(OpNo); 87 if (Op.isReg()) { 88 switch (Op.getReg()) { 89 // This is the default predicate state, so we don't need to print it. 90 case AMDGPU::PRED_SEL_OFF: 91 break; 92 93 default: 94 printRegOperand(Op.getReg(), O); 95 break; 96 } 97 } else if (Op.isImm()) { 98 O << Op.getImm(); 99 } else if (Op.isFPImm()) { 100 O << Op.getFPImm(); 101 } else if (Op.isExpr()) { 102 const MCExpr *Exp = Op.getExpr(); 103 Exp->print(O); 104 } else { 105 assert(!"unknown operand type in printOperand"); 106 } 107} 108 109void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 110 raw_ostream &O) { 111 unsigned Imm = MI->getOperand(OpNum).getImm(); 112 113 if (Imm == 2) { 114 O << "P0"; 115 } else if (Imm == 1) { 116 O << "P20"; 117 } else if (Imm == 0) { 118 O << "P10"; 119 } else { 120 assert(!"Invalid interpolation parameter slot"); 121 } 122} 123 124void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 125 raw_ostream &O) { 126 printOperand(MI, OpNo, O); 127 O << ", "; 128 printOperand(MI, OpNo + 1, O); 129} 130 131void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 132 raw_ostream &O, StringRef Asm, 133 StringRef Default) { 134 const MCOperand &Op = MI->getOperand(OpNo); 135 assert(Op.isImm()); 136 if (Op.getImm() == 1) { 137 O << Asm; 138 } else { 139 O << Default; 140 } 141} 142 143void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 144 raw_ostream &O) { 145 printIfSet(MI, OpNo, O, "|"); 146} 147 148void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 149 raw_ostream &O) { 150 printIfSet(MI, OpNo, O, "_SAT"); 151} 152 153void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 154 raw_ostream &O) { 155 union Literal { 156 float f; 157 int32_t i; 158 } L; 159 160 L.i = MI->getOperand(OpNo).getImm(); 161 O << L.i << "(" << L.f << ")"; 162} 163 164void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 165 raw_ostream &O) { 166 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); 167} 168 169void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 170 raw_ostream &O) { 171 printIfSet(MI, OpNo, O, "-"); 172} 173 174void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 175 raw_ostream &O) { 176 switch (MI->getOperand(OpNo).getImm()) { 177 default: break; 178 case 1: 179 O << " * 2.0"; 180 break; 181 case 2: 182 O << " * 4.0"; 183 break; 184 case 3: 185 O << " / 2.0"; 186 break; 187 } 188} 189 190void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 191 raw_ostream &O) { 192 printIfSet(MI, OpNo, O, "+"); 193} 194 195void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 196 raw_ostream &O) { 197 printIfSet(MI, OpNo, O, "ExecMask,"); 198} 199 200void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 201 raw_ostream &O) { 202 printIfSet(MI, OpNo, O, "Pred,"); 203} 204 205void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 206 raw_ostream &O) { 207 const MCOperand &Op = MI->getOperand(OpNo); 208 if (Op.getImm() == 0) { 209 O << " (MASKED)"; 210 } 211} 212 213void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 214 raw_ostream &O) { 215 const char * chans = "XYZW"; 216 int sel = MI->getOperand(OpNo).getImm(); 217 218 int chan = sel & 3; 219 sel >>= 2; 220 221 if (sel >= 512) { 222 sel -= 512; 223 int cb = sel >> 12; 224 sel &= 4095; 225 O << cb << "[" << sel << "]"; 226 } else if (sel >= 448) { 227 sel -= 448; 228 O << sel; 229 } else if (sel >= 0){ 230 O << sel; 231 } 232 233 if (sel >= 0) 234 O << "." << chans[chan]; 235} 236 237void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 238 raw_ostream &O) { 239 int BankSwizzle = MI->getOperand(OpNo).getImm(); 240 switch (BankSwizzle) { 241 case 1: 242 O << "BS:VEC_021/SCL_122"; 243 break; 244 case 2: 245 O << "BS:VEC_120/SCL_212"; 246 break; 247 case 3: 248 O << "BS:VEC_102/SCL_221"; 249 break; 250 case 4: 251 O << "BS:VEC_201"; 252 break; 253 case 5: 254 O << "BS:VEC_210"; 255 break; 256 default: 257 break; 258 } 259 return; 260} 261 262void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 263 raw_ostream &O) { 264 unsigned Sel = MI->getOperand(OpNo).getImm(); 265 switch (Sel) { 266 case 0: 267 O << "X"; 268 break; 269 case 1: 270 O << "Y"; 271 break; 272 case 2: 273 O << "Z"; 274 break; 275 case 3: 276 O << "W"; 277 break; 278 case 4: 279 O << "0"; 280 break; 281 case 5: 282 O << "1"; 283 break; 284 case 7: 285 O << "_"; 286 break; 287 default: 288 break; 289 } 290} 291 292void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 293 raw_ostream &O) { 294 unsigned CT = MI->getOperand(OpNo).getImm(); 295 switch (CT) { 296 case 0: 297 O << "U"; 298 break; 299 case 1: 300 O << "N"; 301 break; 302 default: 303 break; 304 } 305} 306 307void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 308 raw_ostream &O) { 309 int KCacheMode = MI->getOperand(OpNo).getImm(); 310 if (KCacheMode > 0) { 311 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 312 O << "CB" << KCacheBank <<":"; 313 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 314 int LineSize = (KCacheMode == 1)?16:32; 315 O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize; 316 } 317} 318 319void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, 320 raw_ostream &O) { 321 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 322 unsigned Msg = SImm16 & 0xF; 323 if (Msg == 2 || Msg == 3) { 324 unsigned Op = (SImm16 >> 4) & 0xF; 325 if (Msg == 3) 326 O << "Gs_done("; 327 else 328 O << "Gs("; 329 if (Op == 0) { 330 O << "nop"; 331 } else { 332 unsigned Stream = (SImm16 >> 8) & 0x3; 333 if (Op == 1) 334 O << "cut"; 335 else if (Op == 2) 336 O << "emit"; 337 else if (Op == 3) 338 O << "emit-cut"; 339 O << " stream " << Stream; 340 } 341 O << "), [m0] "; 342 } else if (Msg == 1) 343 O << "interrupt "; 344 else if (Msg == 15) 345 O << "system "; 346 else 347 O << "unknown(" << Msg << ") "; 348} 349 350void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 351 raw_ostream &O) { 352 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 353 // SIInsertWaits.cpp bits usage does not match ISA docs description but it 354 // works so it might be a misprint in docs. 355 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 356 unsigned Vmcnt = SImm16 & 0xF; 357 unsigned Expcnt = (SImm16 >> 4) & 0xF; 358 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 359 if (Vmcnt != 0xF) 360 O << "vmcnt(" << Vmcnt << ") "; 361 if (Expcnt != 0x7) 362 O << "expcnt(" << Expcnt << ") "; 363 if (Lgkmcnt != 0x7) 364 O << "lgkmcnt(" << Lgkmcnt << ")"; 365} 366 367#include "AMDGPUGenAsmWriter.inc" 368