1249259Sdim//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim// \file 9249259Sdim//===----------------------------------------------------------------------===// 10249259Sdim 11249259Sdim#include "AMDGPUInstPrinter.h" 12249259Sdim#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 13263508Sdim#include "llvm/MC/MCExpr.h" 14249259Sdim#include "llvm/MC/MCInst.h" 15249259Sdim 16249259Sdimusing namespace llvm; 17249259Sdim 18249259Sdimvoid AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 19249259Sdim StringRef Annot) { 20251662Sdim OS.flush(); 21249259Sdim printInstruction(MI, OS); 22249259Sdim 23249259Sdim printAnnotation(OS, Annot); 24249259Sdim} 25249259Sdim 26263508Sdimvoid AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) { 27263508Sdim switch (reg) { 28263508Sdim case AMDGPU::VCC: 29263508Sdim O << "vcc"; 30263508Sdim return; 31263508Sdim case AMDGPU::SCC: 32263508Sdim O << "scc"; 33263508Sdim return; 34263508Sdim case AMDGPU::EXEC: 35263508Sdim O << "exec"; 36263508Sdim return; 37263508Sdim case AMDGPU::M0: 38263508Sdim O << "m0"; 39263508Sdim return; 40263508Sdim default: 41263508Sdim break; 42263508Sdim } 43263508Sdim 44263508Sdim // It's seems there's no way to use SIRegisterInfo here, and dealing with the 45263508Sdim // giant enum of all the different shifted sets of registers is pretty 46263508Sdim // unmanagable, so parse the name and reformat it to be prettier. 47263508Sdim StringRef Name(getRegisterName(reg)); 48263508Sdim 49263508Sdim std::pair<StringRef, StringRef> Split = Name.split('_'); 50263508Sdim StringRef SubRegName = Split.first; 51263508Sdim StringRef Rest = Split.second; 52263508Sdim 53263508Sdim if (SubRegName.size() <= 4) { // Must at least be as long as "SGPR"/"VGPR". 54263508Sdim O << Name; 55263508Sdim return; 56263508Sdim } 57263508Sdim 58263508Sdim unsigned RegIndex; 59263508Sdim StringRef RegIndexStr = SubRegName.drop_front(4); 60263508Sdim 61263508Sdim if (RegIndexStr.getAsInteger(10, RegIndex)) { 62263508Sdim O << Name; 63263508Sdim return; 64263508Sdim } 65263508Sdim 66263508Sdim if (SubRegName.front() == 'V') 67263508Sdim O << 'v'; 68263508Sdim else if (SubRegName.front() == 'S') 69263508Sdim O << 's'; 70263508Sdim else { 71263508Sdim O << Name; 72263508Sdim return; 73263508Sdim } 74263508Sdim 75263508Sdim if (Rest.empty()) // Only 1 32-bit register 76263508Sdim O << RegIndex; 77263508Sdim else { 78263508Sdim unsigned NumReg = Rest.count('_') + 2; 79263508Sdim O << '[' << RegIndex << ':' << (RegIndex + NumReg - 1) << ']'; 80263508Sdim } 81263508Sdim} 82263508Sdim 83249259Sdimvoid AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 84249259Sdim raw_ostream &O) { 85249259Sdim 86249259Sdim const MCOperand &Op = MI->getOperand(OpNo); 87249259Sdim if (Op.isReg()) { 88249259Sdim switch (Op.getReg()) { 89249259Sdim // This is the default predicate state, so we don't need to print it. 90263508Sdim case AMDGPU::PRED_SEL_OFF: 91263508Sdim break; 92263508Sdim 93263508Sdim default: 94263508Sdim printRegOperand(Op.getReg(), O); 95263508Sdim break; 96249259Sdim } 97249259Sdim } else if (Op.isImm()) { 98249259Sdim O << Op.getImm(); 99249259Sdim } else if (Op.isFPImm()) { 100249259Sdim O << Op.getFPImm(); 101249259Sdim } else if (Op.isExpr()) { 102249259Sdim const MCExpr *Exp = Op.getExpr(); 103249259Sdim Exp->print(O); 104249259Sdim } else { 105249259Sdim assert(!"unknown operand type in printOperand"); 106249259Sdim } 107249259Sdim} 108249259Sdim 109249259Sdimvoid AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 110249259Sdim raw_ostream &O) { 111249259Sdim unsigned Imm = MI->getOperand(OpNum).getImm(); 112249259Sdim 113249259Sdim if (Imm == 2) { 114249259Sdim O << "P0"; 115249259Sdim } else if (Imm == 1) { 116249259Sdim O << "P20"; 117249259Sdim } else if (Imm == 0) { 118249259Sdim O << "P10"; 119249259Sdim } else { 120249259Sdim assert(!"Invalid interpolation parameter slot"); 121249259Sdim } 122249259Sdim} 123249259Sdim 124249259Sdimvoid AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 125249259Sdim raw_ostream &O) { 126249259Sdim printOperand(MI, OpNo, O); 127249259Sdim O << ", "; 128249259Sdim printOperand(MI, OpNo + 1, O); 129249259Sdim} 130249259Sdim 131249259Sdimvoid AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 132251662Sdim raw_ostream &O, StringRef Asm, 133251662Sdim StringRef Default) { 134249259Sdim const MCOperand &Op = MI->getOperand(OpNo); 135249259Sdim assert(Op.isImm()); 136249259Sdim if (Op.getImm() == 1) { 137249259Sdim O << Asm; 138251662Sdim } else { 139251662Sdim O << Default; 140249259Sdim } 141249259Sdim} 142249259Sdim 143249259Sdimvoid AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 144249259Sdim raw_ostream &O) { 145249259Sdim printIfSet(MI, OpNo, O, "|"); 146249259Sdim} 147249259Sdim 148249259Sdimvoid AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 149249259Sdim raw_ostream &O) { 150249259Sdim printIfSet(MI, OpNo, O, "_SAT"); 151249259Sdim} 152249259Sdim 153249259Sdimvoid AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 154249259Sdim raw_ostream &O) { 155249259Sdim union Literal { 156249259Sdim float f; 157249259Sdim int32_t i; 158249259Sdim } L; 159249259Sdim 160249259Sdim L.i = MI->getOperand(OpNo).getImm(); 161249259Sdim O << L.i << "(" << L.f << ")"; 162249259Sdim} 163249259Sdim 164249259Sdimvoid AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 165249259Sdim raw_ostream &O) { 166263508Sdim printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); 167249259Sdim} 168249259Sdim 169249259Sdimvoid AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 170249259Sdim raw_ostream &O) { 171249259Sdim printIfSet(MI, OpNo, O, "-"); 172249259Sdim} 173249259Sdim 174249259Sdimvoid AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 175249259Sdim raw_ostream &O) { 176249259Sdim switch (MI->getOperand(OpNo).getImm()) { 177249259Sdim default: break; 178249259Sdim case 1: 179249259Sdim O << " * 2.0"; 180249259Sdim break; 181249259Sdim case 2: 182249259Sdim O << " * 4.0"; 183249259Sdim break; 184249259Sdim case 3: 185249259Sdim O << " / 2.0"; 186249259Sdim break; 187249259Sdim } 188249259Sdim} 189249259Sdim 190249259Sdimvoid AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 191249259Sdim raw_ostream &O) { 192249259Sdim printIfSet(MI, OpNo, O, "+"); 193249259Sdim} 194249259Sdim 195249259Sdimvoid AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 196249259Sdim raw_ostream &O) { 197249259Sdim printIfSet(MI, OpNo, O, "ExecMask,"); 198249259Sdim} 199249259Sdim 200249259Sdimvoid AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 201249259Sdim raw_ostream &O) { 202249259Sdim printIfSet(MI, OpNo, O, "Pred,"); 203249259Sdim} 204249259Sdim 205249259Sdimvoid AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 206249259Sdim raw_ostream &O) { 207249259Sdim const MCOperand &Op = MI->getOperand(OpNo); 208249259Sdim if (Op.getImm() == 0) { 209249259Sdim O << " (MASKED)"; 210249259Sdim } 211249259Sdim} 212249259Sdim 213249259Sdimvoid AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 214249259Sdim raw_ostream &O) { 215249259Sdim const char * chans = "XYZW"; 216249259Sdim int sel = MI->getOperand(OpNo).getImm(); 217249259Sdim 218249259Sdim int chan = sel & 3; 219249259Sdim sel >>= 2; 220249259Sdim 221249259Sdim if (sel >= 512) { 222249259Sdim sel -= 512; 223249259Sdim int cb = sel >> 12; 224249259Sdim sel &= 4095; 225249259Sdim O << cb << "[" << sel << "]"; 226249259Sdim } else if (sel >= 448) { 227249259Sdim sel -= 448; 228249259Sdim O << sel; 229249259Sdim } else if (sel >= 0){ 230249259Sdim O << sel; 231249259Sdim } 232249259Sdim 233249259Sdim if (sel >= 0) 234249259Sdim O << "." << chans[chan]; 235249259Sdim} 236249259Sdim 237251662Sdimvoid AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 238251662Sdim raw_ostream &O) { 239251662Sdim int BankSwizzle = MI->getOperand(OpNo).getImm(); 240251662Sdim switch (BankSwizzle) { 241251662Sdim case 1: 242263508Sdim O << "BS:VEC_021/SCL_122"; 243251662Sdim break; 244251662Sdim case 2: 245263508Sdim O << "BS:VEC_120/SCL_212"; 246251662Sdim break; 247251662Sdim case 3: 248263508Sdim O << "BS:VEC_102/SCL_221"; 249251662Sdim break; 250251662Sdim case 4: 251251662Sdim O << "BS:VEC_201"; 252251662Sdim break; 253251662Sdim case 5: 254251662Sdim O << "BS:VEC_210"; 255251662Sdim break; 256251662Sdim default: 257251662Sdim break; 258251662Sdim } 259251662Sdim return; 260251662Sdim} 261251662Sdim 262263508Sdimvoid AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 263263508Sdim raw_ostream &O) { 264263508Sdim unsigned Sel = MI->getOperand(OpNo).getImm(); 265263508Sdim switch (Sel) { 266263508Sdim case 0: 267263508Sdim O << "X"; 268263508Sdim break; 269263508Sdim case 1: 270263508Sdim O << "Y"; 271263508Sdim break; 272263508Sdim case 2: 273263508Sdim O << "Z"; 274263508Sdim break; 275263508Sdim case 3: 276263508Sdim O << "W"; 277263508Sdim break; 278263508Sdim case 4: 279263508Sdim O << "0"; 280263508Sdim break; 281263508Sdim case 5: 282263508Sdim O << "1"; 283263508Sdim break; 284263508Sdim case 7: 285263508Sdim O << "_"; 286263508Sdim break; 287263508Sdim default: 288263508Sdim break; 289263508Sdim } 290263508Sdim} 291263508Sdim 292263508Sdimvoid AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 293263508Sdim raw_ostream &O) { 294263508Sdim unsigned CT = MI->getOperand(OpNo).getImm(); 295263508Sdim switch (CT) { 296263508Sdim case 0: 297263508Sdim O << "U"; 298263508Sdim break; 299263508Sdim case 1: 300263508Sdim O << "N"; 301263508Sdim break; 302263508Sdim default: 303263508Sdim break; 304263508Sdim } 305263508Sdim} 306263508Sdim 307251662Sdimvoid AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 308251662Sdim raw_ostream &O) { 309251662Sdim int KCacheMode = MI->getOperand(OpNo).getImm(); 310251662Sdim if (KCacheMode > 0) { 311251662Sdim int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 312251662Sdim O << "CB" << KCacheBank <<":"; 313251662Sdim int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 314251662Sdim int LineSize = (KCacheMode == 1)?16:32; 315251662Sdim O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize; 316251662Sdim } 317251662Sdim} 318251662Sdim 319263508Sdimvoid AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 320263508Sdim raw_ostream &O) { 321263508Sdim // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 322263508Sdim // SIInsertWaits.cpp bits usage does not match ISA docs description but it 323263508Sdim // works so it might be a misprint in docs. 324263508Sdim unsigned SImm16 = MI->getOperand(OpNo).getImm(); 325263508Sdim unsigned Vmcnt = SImm16 & 0xF; 326263508Sdim unsigned Expcnt = (SImm16 >> 4) & 0xF; 327263508Sdim unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 328263508Sdim if (Vmcnt != 0xF) 329263508Sdim O << "vmcnt(" << Vmcnt << ") "; 330263508Sdim if (Expcnt != 0x7) 331263508Sdim O << "expcnt(" << Expcnt << ") "; 332263508Sdim if (Lgkmcnt != 0x7) 333263508Sdim O << "lgkmcnt(" << Lgkmcnt << ")"; 334263508Sdim} 335263508Sdim 336249259Sdim#include "AMDGPUGenAsmWriter.inc" 337