LLVM API Documentation
00001 //===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 // \file 00009 //===----------------------------------------------------------------------===// 00010 00011 #include "AMDGPUInstPrinter.h" 00012 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 00013 #include "llvm/MC/MCExpr.h" 00014 #include "llvm/MC/MCInst.h" 00015 #include "llvm/MC/MCRegisterInfo.h" 00016 #include "llvm/Support/MathExtras.h" 00017 00018 using namespace llvm; 00019 00020 void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 00021 StringRef Annot) { 00022 OS.flush(); 00023 printInstruction(MI, OS); 00024 00025 printAnnotation(OS, Annot); 00026 } 00027 00028 void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, 00029 raw_ostream &O) { 00030 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff); 00031 } 00032 00033 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 00034 raw_ostream &O) { 00035 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff); 00036 } 00037 00038 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo, 00039 raw_ostream &O) { 00040 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff); 00041 } 00042 00043 void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo, 00044 raw_ostream &O) { 00045 if (MI->getOperand(OpNo).getImm()) 00046 O << " offen"; 00047 } 00048 00049 void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo, 00050 raw_ostream &O) { 00051 if (MI->getOperand(OpNo).getImm()) 00052 O << " idxen"; 00053 } 00054 00055 void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo, 00056 raw_ostream &O) { 00057 if (MI->getOperand(OpNo).getImm()) 00058 O << " addr64"; 00059 } 00060 00061 void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo, 00062 raw_ostream &O) { 00063 if (MI->getOperand(OpNo).getImm()) { 00064 O << " offset:"; 00065 printU16ImmOperand(MI, OpNo, O); 00066 } 00067 } 00068 00069 void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo, 00070 raw_ostream &O) { 00071 if (MI->getOperand(OpNo).getImm()) 00072 O << " glc"; 00073 } 00074 00075 void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo, 00076 raw_ostream &O) { 00077 if (MI->getOperand(OpNo).getImm()) 00078 O << " slc"; 00079 } 00080 00081 void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo, 00082 raw_ostream &O) { 00083 if (MI->getOperand(OpNo).getImm()) 00084 O << " tfe"; 00085 } 00086 00087 void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) { 00088 switch (reg) { 00089 case AMDGPU::VCC: 00090 O << "vcc"; 00091 return; 00092 case AMDGPU::SCC: 00093 O << "scc"; 00094 return; 00095 case AMDGPU::EXEC: 00096 O << "exec"; 00097 return; 00098 case AMDGPU::M0: 00099 O << "m0"; 00100 return; 00101 case AMDGPU::FLAT_SCR: 00102 O << "flat_scratch"; 00103 return; 00104 case AMDGPU::VCC_LO: 00105 O << "vcc_lo"; 00106 return; 00107 case AMDGPU::VCC_HI: 00108 O << "vcc_hi"; 00109 return; 00110 case AMDGPU::EXEC_LO: 00111 O << "exec_lo"; 00112 return; 00113 case AMDGPU::EXEC_HI: 00114 O << "exec_hi"; 00115 return; 00116 case AMDGPU::FLAT_SCR_LO: 00117 O << "flat_scratch_lo"; 00118 return; 00119 case AMDGPU::FLAT_SCR_HI: 00120 O << "flat_scratch_hi"; 00121 return; 00122 default: 00123 break; 00124 } 00125 00126 char Type; 00127 unsigned NumRegs; 00128 00129 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) { 00130 Type = 'v'; 00131 NumRegs = 1; 00132 } else if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) { 00133 Type = 's'; 00134 NumRegs = 1; 00135 } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) { 00136 Type = 'v'; 00137 NumRegs = 2; 00138 } else if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) { 00139 Type = 's'; 00140 NumRegs = 2; 00141 } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) { 00142 Type = 'v'; 00143 NumRegs = 4; 00144 } else if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) { 00145 Type = 's'; 00146 NumRegs = 4; 00147 } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) { 00148 Type = 'v'; 00149 NumRegs = 3; 00150 } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) { 00151 Type = 'v'; 00152 NumRegs = 8; 00153 } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) { 00154 Type = 's'; 00155 NumRegs = 8; 00156 } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) { 00157 Type = 'v'; 00158 NumRegs = 16; 00159 } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) { 00160 Type = 's'; 00161 NumRegs = 16; 00162 } else { 00163 O << getRegisterName(reg); 00164 return; 00165 } 00166 00167 // The low 8 bits of the encoding value is the register index, for both VGPRs 00168 // and SGPRs. 00169 unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1); 00170 if (NumRegs == 1) { 00171 O << Type << RegIdx; 00172 return; 00173 } 00174 00175 O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']'; 00176 } 00177 00178 void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) { 00179 int32_t SImm = static_cast<int32_t>(Imm); 00180 if (SImm >= -16 && SImm <= 64) { 00181 O << SImm; 00182 return; 00183 } 00184 00185 if (Imm == FloatToBits(0.0f)) 00186 O << "0.0"; 00187 else if (Imm == FloatToBits(1.0f)) 00188 O << "1.0"; 00189 else if (Imm == FloatToBits(-1.0f)) 00190 O << "-1.0"; 00191 else if (Imm == FloatToBits(0.5f)) 00192 O << "0.5"; 00193 else if (Imm == FloatToBits(-0.5f)) 00194 O << "-0.5"; 00195 else if (Imm == FloatToBits(2.0f)) 00196 O << "2.0"; 00197 else if (Imm == FloatToBits(-2.0f)) 00198 O << "-2.0"; 00199 else if (Imm == FloatToBits(4.0f)) 00200 O << "4.0"; 00201 else if (Imm == FloatToBits(-4.0f)) 00202 O << "-4.0"; 00203 else { 00204 O << formatHex(static_cast<uint64_t>(Imm)); 00205 } 00206 } 00207 00208 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 00209 raw_ostream &O) { 00210 00211 const MCOperand &Op = MI->getOperand(OpNo); 00212 if (Op.isReg()) { 00213 switch (Op.getReg()) { 00214 // This is the default predicate state, so we don't need to print it. 00215 case AMDGPU::PRED_SEL_OFF: 00216 break; 00217 00218 default: 00219 printRegOperand(Op.getReg(), O); 00220 break; 00221 } 00222 } else if (Op.isImm()) { 00223 printImmediate(Op.getImm(), O); 00224 } else if (Op.isFPImm()) { 00225 00226 // We special case 0.0 because otherwise it will be printed as an integer. 00227 if (Op.getFPImm() == 0.0) 00228 O << "0.0"; 00229 else 00230 printImmediate(FloatToBits(Op.getFPImm()), O); 00231 } else if (Op.isExpr()) { 00232 const MCExpr *Exp = Op.getExpr(); 00233 Exp->print(O); 00234 } else { 00235 assert(!"unknown operand type in printOperand"); 00236 } 00237 } 00238 00239 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo, 00240 raw_ostream &O) { 00241 unsigned InputModifiers = MI->getOperand(OpNo).getImm(); 00242 if (InputModifiers & 0x1) 00243 O << "-"; 00244 if (InputModifiers & 0x2) 00245 O << "|"; 00246 printOperand(MI, OpNo + 1, O); 00247 if (InputModifiers & 0x2) 00248 O << "|"; 00249 } 00250 00251 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 00252 raw_ostream &O) { 00253 unsigned Imm = MI->getOperand(OpNum).getImm(); 00254 00255 if (Imm == 2) { 00256 O << "P0"; 00257 } else if (Imm == 1) { 00258 O << "P20"; 00259 } else if (Imm == 0) { 00260 O << "P10"; 00261 } else { 00262 assert(!"Invalid interpolation parameter slot"); 00263 } 00264 } 00265 00266 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 00267 raw_ostream &O) { 00268 printOperand(MI, OpNo, O); 00269 O << ", "; 00270 printOperand(MI, OpNo + 1, O); 00271 } 00272 00273 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 00274 raw_ostream &O, StringRef Asm, 00275 StringRef Default) { 00276 const MCOperand &Op = MI->getOperand(OpNo); 00277 assert(Op.isImm()); 00278 if (Op.getImm() == 1) { 00279 O << Asm; 00280 } else { 00281 O << Default; 00282 } 00283 } 00284 00285 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 00286 raw_ostream &O) { 00287 printIfSet(MI, OpNo, O, "|"); 00288 } 00289 00290 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 00291 raw_ostream &O) { 00292 printIfSet(MI, OpNo, O, "_SAT"); 00293 } 00294 00295 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 00296 raw_ostream &O) { 00297 int32_t Imm = MI->getOperand(OpNo).getImm(); 00298 O << Imm << '(' << BitsToFloat(Imm) << ')'; 00299 } 00300 00301 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 00302 raw_ostream &O) { 00303 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); 00304 } 00305 00306 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 00307 raw_ostream &O) { 00308 printIfSet(MI, OpNo, O, "-"); 00309 } 00310 00311 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 00312 raw_ostream &O) { 00313 switch (MI->getOperand(OpNo).getImm()) { 00314 default: break; 00315 case 1: 00316 O << " * 2.0"; 00317 break; 00318 case 2: 00319 O << " * 4.0"; 00320 break; 00321 case 3: 00322 O << " / 2.0"; 00323 break; 00324 } 00325 } 00326 00327 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 00328 raw_ostream &O) { 00329 printIfSet(MI, OpNo, O, "+"); 00330 } 00331 00332 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 00333 raw_ostream &O) { 00334 printIfSet(MI, OpNo, O, "ExecMask,"); 00335 } 00336 00337 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 00338 raw_ostream &O) { 00339 printIfSet(MI, OpNo, O, "Pred,"); 00340 } 00341 00342 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 00343 raw_ostream &O) { 00344 const MCOperand &Op = MI->getOperand(OpNo); 00345 if (Op.getImm() == 0) { 00346 O << " (MASKED)"; 00347 } 00348 } 00349 00350 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 00351 raw_ostream &O) { 00352 const char * chans = "XYZW"; 00353 int sel = MI->getOperand(OpNo).getImm(); 00354 00355 int chan = sel & 3; 00356 sel >>= 2; 00357 00358 if (sel >= 512) { 00359 sel -= 512; 00360 int cb = sel >> 12; 00361 sel &= 4095; 00362 O << cb << "[" << sel << "]"; 00363 } else if (sel >= 448) { 00364 sel -= 448; 00365 O << sel; 00366 } else if (sel >= 0){ 00367 O << sel; 00368 } 00369 00370 if (sel >= 0) 00371 O << "." << chans[chan]; 00372 } 00373 00374 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 00375 raw_ostream &O) { 00376 int BankSwizzle = MI->getOperand(OpNo).getImm(); 00377 switch (BankSwizzle) { 00378 case 1: 00379 O << "BS:VEC_021/SCL_122"; 00380 break; 00381 case 2: 00382 O << "BS:VEC_120/SCL_212"; 00383 break; 00384 case 3: 00385 O << "BS:VEC_102/SCL_221"; 00386 break; 00387 case 4: 00388 O << "BS:VEC_201"; 00389 break; 00390 case 5: 00391 O << "BS:VEC_210"; 00392 break; 00393 default: 00394 break; 00395 } 00396 return; 00397 } 00398 00399 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 00400 raw_ostream &O) { 00401 unsigned Sel = MI->getOperand(OpNo).getImm(); 00402 switch (Sel) { 00403 case 0: 00404 O << "X"; 00405 break; 00406 case 1: 00407 O << "Y"; 00408 break; 00409 case 2: 00410 O << "Z"; 00411 break; 00412 case 3: 00413 O << "W"; 00414 break; 00415 case 4: 00416 O << "0"; 00417 break; 00418 case 5: 00419 O << "1"; 00420 break; 00421 case 7: 00422 O << "_"; 00423 break; 00424 default: 00425 break; 00426 } 00427 } 00428 00429 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 00430 raw_ostream &O) { 00431 unsigned CT = MI->getOperand(OpNo).getImm(); 00432 switch (CT) { 00433 case 0: 00434 O << "U"; 00435 break; 00436 case 1: 00437 O << "N"; 00438 break; 00439 default: 00440 break; 00441 } 00442 } 00443 00444 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 00445 raw_ostream &O) { 00446 int KCacheMode = MI->getOperand(OpNo).getImm(); 00447 if (KCacheMode > 0) { 00448 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 00449 O << "CB" << KCacheBank <<":"; 00450 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 00451 int LineSize = (KCacheMode == 1)?16:32; 00452 O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize; 00453 } 00454 } 00455 00456 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, 00457 raw_ostream &O) { 00458 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 00459 unsigned Msg = SImm16 & 0xF; 00460 if (Msg == 2 || Msg == 3) { 00461 unsigned Op = (SImm16 >> 4) & 0xF; 00462 if (Msg == 3) 00463 O << "Gs_done("; 00464 else 00465 O << "Gs("; 00466 if (Op == 0) { 00467 O << "nop"; 00468 } else { 00469 unsigned Stream = (SImm16 >> 8) & 0x3; 00470 if (Op == 1) 00471 O << "cut"; 00472 else if (Op == 2) 00473 O << "emit"; 00474 else if (Op == 3) 00475 O << "emit-cut"; 00476 O << " stream " << Stream; 00477 } 00478 O << "), [m0] "; 00479 } else if (Msg == 1) 00480 O << "interrupt "; 00481 else if (Msg == 15) 00482 O << "system "; 00483 else 00484 O << "unknown(" << Msg << ") "; 00485 } 00486 00487 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 00488 raw_ostream &O) { 00489 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 00490 // SIInsertWaits.cpp bits usage does not match ISA docs description but it 00491 // works so it might be a misprint in docs. 00492 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 00493 unsigned Vmcnt = SImm16 & 0xF; 00494 unsigned Expcnt = (SImm16 >> 4) & 0xF; 00495 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 00496 if (Vmcnt != 0xF) 00497 O << "vmcnt(" << Vmcnt << ") "; 00498 if (Expcnt != 0x7) 00499 O << "expcnt(" << Expcnt << ") "; 00500 if (Lgkmcnt != 0x7) 00501 O << "lgkmcnt(" << Lgkmcnt << ")"; 00502 } 00503 00504 #include "AMDGPUGenAsmWriter.inc"