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#include "llvm/MC/MCRegisterInfo.h" 16#include "llvm/Support/MathExtras.h" 17 18using namespace llvm; 19 20void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 21 StringRef Annot) { 22 OS.flush(); 23 printInstruction(MI, OS); 24 25 printAnnotation(OS, Annot); 26} 27 28void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, 29 raw_ostream &O) { 30 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff); 31} 32 33void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 34 raw_ostream &O) { 35 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff); 36} 37 38void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo, 39 raw_ostream &O) { 40 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff); 41} 42 43void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) { 44 switch (reg) { 45 case AMDGPU::VCC: 46 O << "vcc"; 47 return; 48 case AMDGPU::SCC: 49 O << "scc"; 50 return; 51 case AMDGPU::EXEC: 52 O << "exec"; 53 return; 54 case AMDGPU::M0: 55 O << "m0"; 56 return; 57 default: 58 break; 59 } 60 61 char Type; 62 unsigned NumRegs; 63 64 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) { 65 Type = 'v'; 66 NumRegs = 1; 67 } else if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) { 68 Type = 's'; 69 NumRegs = 1; 70 } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) { 71 Type = 'v'; 72 NumRegs = 2; 73 } else if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) { 74 Type = 's'; 75 NumRegs = 2; 76 } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) { 77 Type = 'v'; 78 NumRegs = 4; 79 } else if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) { 80 Type = 's'; 81 NumRegs = 4; 82 } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) { 83 Type = 'v'; 84 NumRegs = 3; 85 } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) { 86 Type = 'v'; 87 NumRegs = 8; 88 } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) { 89 Type = 's'; 90 NumRegs = 8; 91 } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) { 92 Type = 'v'; 93 NumRegs = 16; 94 } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) { 95 Type = 's'; 96 NumRegs = 16; 97 } else { 98 O << getRegisterName(reg); 99 return; 100 } 101 102 // The low 8 bits of the encoding value is the register index, for both VGPRs 103 // and SGPRs. 104 unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1); 105 if (NumRegs == 1) { 106 O << Type << RegIdx; 107 return; 108 } 109 110 O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']'; 111} 112 113void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) { 114 int32_t SImm = static_cast<int32_t>(Imm); 115 if (SImm >= -16 && SImm <= 64) { 116 O << SImm; 117 return; 118 } 119 120 if (Imm == FloatToBits(1.0f) || 121 Imm == FloatToBits(-1.0f) || 122 Imm == FloatToBits(0.5f) || 123 Imm == FloatToBits(-0.5f) || 124 Imm == FloatToBits(2.0f) || 125 Imm == FloatToBits(-2.0f) || 126 Imm == FloatToBits(4.0f) || 127 Imm == FloatToBits(-4.0f)) { 128 O << BitsToFloat(Imm); 129 return; 130 } 131 132 O << formatHex(static_cast<uint64_t>(Imm)); 133} 134 135void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 136 raw_ostream &O) { 137 138 const MCOperand &Op = MI->getOperand(OpNo); 139 if (Op.isReg()) { 140 switch (Op.getReg()) { 141 // This is the default predicate state, so we don't need to print it. 142 case AMDGPU::PRED_SEL_OFF: 143 break; 144 145 default: 146 printRegOperand(Op.getReg(), O); 147 break; 148 } 149 } else if (Op.isImm()) { 150 printImmediate(Op.getImm(), O); 151 } else if (Op.isFPImm()) { 152 O << Op.getFPImm(); 153 } else if (Op.isExpr()) { 154 const MCExpr *Exp = Op.getExpr(); 155 Exp->print(O); 156 } else { 157 assert(!"unknown operand type in printOperand"); 158 } 159} 160 161void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo, 162 raw_ostream &O) { 163 unsigned InputModifiers = MI->getOperand(OpNo).getImm(); 164 if (InputModifiers & 0x1) 165 O << "-"; 166 if (InputModifiers & 0x2) 167 O << "|"; 168 printOperand(MI, OpNo + 1, O); 169 if (InputModifiers & 0x2) 170 O << "|"; 171} 172 173void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 174 raw_ostream &O) { 175 unsigned Imm = MI->getOperand(OpNum).getImm(); 176 177 if (Imm == 2) { 178 O << "P0"; 179 } else if (Imm == 1) { 180 O << "P20"; 181 } else if (Imm == 0) { 182 O << "P10"; 183 } else { 184 assert(!"Invalid interpolation parameter slot"); 185 } 186} 187 188void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 189 raw_ostream &O) { 190 printOperand(MI, OpNo, O); 191 O << ", "; 192 printOperand(MI, OpNo + 1, O); 193} 194 195void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 196 raw_ostream &O, StringRef Asm, 197 StringRef Default) { 198 const MCOperand &Op = MI->getOperand(OpNo); 199 assert(Op.isImm()); 200 if (Op.getImm() == 1) { 201 O << Asm; 202 } else { 203 O << Default; 204 } 205} 206 207void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 208 raw_ostream &O) { 209 printIfSet(MI, OpNo, O, "|"); 210} 211 212void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 213 raw_ostream &O) { 214 printIfSet(MI, OpNo, O, "_SAT"); 215} 216 217void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 218 raw_ostream &O) { 219 int32_t Imm = MI->getOperand(OpNo).getImm(); 220 O << Imm << '(' << BitsToFloat(Imm) << ')'; 221} 222 223void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 224 raw_ostream &O) { 225 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); 226} 227 228void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 229 raw_ostream &O) { 230 printIfSet(MI, OpNo, O, "-"); 231} 232 233void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 234 raw_ostream &O) { 235 switch (MI->getOperand(OpNo).getImm()) { 236 default: break; 237 case 1: 238 O << " * 2.0"; 239 break; 240 case 2: 241 O << " * 4.0"; 242 break; 243 case 3: 244 O << " / 2.0"; 245 break; 246 } 247} 248 249void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 250 raw_ostream &O) { 251 printIfSet(MI, OpNo, O, "+"); 252} 253 254void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 255 raw_ostream &O) { 256 printIfSet(MI, OpNo, O, "ExecMask,"); 257} 258 259void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 260 raw_ostream &O) { 261 printIfSet(MI, OpNo, O, "Pred,"); 262} 263 264void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 265 raw_ostream &O) { 266 const MCOperand &Op = MI->getOperand(OpNo); 267 if (Op.getImm() == 0) { 268 O << " (MASKED)"; 269 } 270} 271 272void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 273 raw_ostream &O) { 274 const char * chans = "XYZW"; 275 int sel = MI->getOperand(OpNo).getImm(); 276 277 int chan = sel & 3; 278 sel >>= 2; 279 280 if (sel >= 512) { 281 sel -= 512; 282 int cb = sel >> 12; 283 sel &= 4095; 284 O << cb << "[" << sel << "]"; 285 } else if (sel >= 448) { 286 sel -= 448; 287 O << sel; 288 } else if (sel >= 0){ 289 O << sel; 290 } 291 292 if (sel >= 0) 293 O << "." << chans[chan]; 294} 295 296void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 297 raw_ostream &O) { 298 int BankSwizzle = MI->getOperand(OpNo).getImm(); 299 switch (BankSwizzle) { 300 case 1: 301 O << "BS:VEC_021/SCL_122"; 302 break; 303 case 2: 304 O << "BS:VEC_120/SCL_212"; 305 break; 306 case 3: 307 O << "BS:VEC_102/SCL_221"; 308 break; 309 case 4: 310 O << "BS:VEC_201"; 311 break; 312 case 5: 313 O << "BS:VEC_210"; 314 break; 315 default: 316 break; 317 } 318 return; 319} 320 321void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 322 raw_ostream &O) { 323 unsigned Sel = MI->getOperand(OpNo).getImm(); 324 switch (Sel) { 325 case 0: 326 O << "X"; 327 break; 328 case 1: 329 O << "Y"; 330 break; 331 case 2: 332 O << "Z"; 333 break; 334 case 3: 335 O << "W"; 336 break; 337 case 4: 338 O << "0"; 339 break; 340 case 5: 341 O << "1"; 342 break; 343 case 7: 344 O << "_"; 345 break; 346 default: 347 break; 348 } 349} 350 351void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 352 raw_ostream &O) { 353 unsigned CT = MI->getOperand(OpNo).getImm(); 354 switch (CT) { 355 case 0: 356 O << "U"; 357 break; 358 case 1: 359 O << "N"; 360 break; 361 default: 362 break; 363 } 364} 365 366void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 367 raw_ostream &O) { 368 int KCacheMode = MI->getOperand(OpNo).getImm(); 369 if (KCacheMode > 0) { 370 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 371 O << "CB" << KCacheBank <<":"; 372 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 373 int LineSize = (KCacheMode == 1)?16:32; 374 O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize; 375 } 376} 377 378void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, 379 raw_ostream &O) { 380 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 381 unsigned Msg = SImm16 & 0xF; 382 if (Msg == 2 || Msg == 3) { 383 unsigned Op = (SImm16 >> 4) & 0xF; 384 if (Msg == 3) 385 O << "Gs_done("; 386 else 387 O << "Gs("; 388 if (Op == 0) { 389 O << "nop"; 390 } else { 391 unsigned Stream = (SImm16 >> 8) & 0x3; 392 if (Op == 1) 393 O << "cut"; 394 else if (Op == 2) 395 O << "emit"; 396 else if (Op == 3) 397 O << "emit-cut"; 398 O << " stream " << Stream; 399 } 400 O << "), [m0] "; 401 } else if (Msg == 1) 402 O << "interrupt "; 403 else if (Msg == 15) 404 O << "system "; 405 else 406 O << "unknown(" << Msg << ") "; 407} 408 409void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 410 raw_ostream &O) { 411 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 412 // SIInsertWaits.cpp bits usage does not match ISA docs description but it 413 // works so it might be a misprint in docs. 414 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 415 unsigned Vmcnt = SImm16 & 0xF; 416 unsigned Expcnt = (SImm16 >> 4) & 0xF; 417 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 418 if (Vmcnt != 0xF) 419 O << "vmcnt(" << Vmcnt << ") "; 420 if (Expcnt != 0x7) 421 O << "expcnt(" << Expcnt << ") "; 422 if (Lgkmcnt != 0x7) 423 O << "lgkmcnt(" << Lgkmcnt << ")"; 424} 425 426#include "AMDGPUGenAsmWriter.inc" 427