LLVM API Documentation

AMDGPUInstPrinter.cpp
Go to the documentation of this file.
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"