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 "SIDefines.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCInst.h" 16 #include "llvm/MC/MCInstrInfo.h" 17 #include "llvm/MC/MCRegisterInfo.h" 18 #include "llvm/Support/MathExtras.h" 19 20 using namespace llvm; 21 22 void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 23 StringRef Annot, const MCSubtargetInfo &STI) { 24 OS.flush(); 25 printInstruction(MI, OS); 26 27 printAnnotation(OS, Annot); 28 } 29 30 void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, 31 raw_ostream &O) { 32 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff); 33 } 34 35 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 36 raw_ostream &O) { 37 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff); 38 } 39 40 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo, 41 raw_ostream &O) { 42 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff); 43 } 44 45 void AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo, 46 raw_ostream &O) { 47 O << formatDec(MI->getOperand(OpNo).getImm() & 0xff); 48 } 49 50 void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo, 51 raw_ostream &O) { 52 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff); 53 } 54 55 void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo, 56 raw_ostream &O) { 57 if (MI->getOperand(OpNo).getImm()) 58 O << " offen"; 59 } 60 61 void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo, 62 raw_ostream &O) { 63 if (MI->getOperand(OpNo).getImm()) 64 O << " idxen"; 65 } 66 67 void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo, 68 raw_ostream &O) { 69 if (MI->getOperand(OpNo).getImm()) 70 O << " addr64"; 71 } 72 73 void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo, 74 raw_ostream &O) { 75 if (MI->getOperand(OpNo).getImm()) { 76 O << " offset:"; 77 printU16ImmDecOperand(MI, OpNo, O); 78 } 79 } 80 81 void AMDGPUInstPrinter::printDSOffset(const MCInst *MI, unsigned OpNo, 82 raw_ostream &O) { 83 uint16_t Imm = MI->getOperand(OpNo).getImm(); 84 if (Imm != 0) { 85 O << " offset:"; 86 printU16ImmDecOperand(MI, OpNo, O); 87 } 88 } 89 90 void AMDGPUInstPrinter::printDSOffset0(const MCInst *MI, unsigned OpNo, 91 raw_ostream &O) { 92 if (MI->getOperand(OpNo).getImm()) { 93 O << " offset0:"; 94 printU8ImmDecOperand(MI, OpNo, O); 95 } 96 } 97 98 void AMDGPUInstPrinter::printDSOffset1(const MCInst *MI, unsigned OpNo, 99 raw_ostream &O) { 100 if (MI->getOperand(OpNo).getImm()) { 101 O << " offset1:"; 102 printU8ImmDecOperand(MI, OpNo, O); 103 } 104 } 105 106 void AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo, 107 raw_ostream &O) { 108 if (MI->getOperand(OpNo).getImm()) 109 O << " gds"; 110 } 111 112 void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo, 113 raw_ostream &O) { 114 if (MI->getOperand(OpNo).getImm()) 115 O << " glc"; 116 } 117 118 void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo, 119 raw_ostream &O) { 120 if (MI->getOperand(OpNo).getImm()) 121 O << " slc"; 122 } 123 124 void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo, 125 raw_ostream &O) { 126 if (MI->getOperand(OpNo).getImm()) 127 O << " tfe"; 128 } 129 130 void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O, 131 const MCRegisterInfo &MRI) { 132 switch (reg) { 133 case AMDGPU::VCC: 134 O << "vcc"; 135 return; 136 case AMDGPU::SCC: 137 O << "scc"; 138 return; 139 case AMDGPU::EXEC: 140 O << "exec"; 141 return; 142 case AMDGPU::M0: 143 O << "m0"; 144 return; 145 case AMDGPU::FLAT_SCR: 146 O << "flat_scratch"; 147 return; 148 case AMDGPU::VCC_LO: 149 O << "vcc_lo"; 150 return; 151 case AMDGPU::VCC_HI: 152 O << "vcc_hi"; 153 return; 154 case AMDGPU::EXEC_LO: 155 O << "exec_lo"; 156 return; 157 case AMDGPU::EXEC_HI: 158 O << "exec_hi"; 159 return; 160 case AMDGPU::FLAT_SCR_LO: 161 O << "flat_scratch_lo"; 162 return; 163 case AMDGPU::FLAT_SCR_HI: 164 O << "flat_scratch_hi"; 165 return; 166 default: 167 break; 168 } 169 170 char Type; 171 unsigned NumRegs; 172 173 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) { 174 Type = 'v'; 175 NumRegs = 1; 176 } else if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) { 177 Type = 's'; 178 NumRegs = 1; 179 } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) { 180 Type = 'v'; 181 NumRegs = 2; 182 } else if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) { 183 Type = 's'; 184 NumRegs = 2; 185 } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) { 186 Type = 'v'; 187 NumRegs = 4; 188 } else if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) { 189 Type = 's'; 190 NumRegs = 4; 191 } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) { 192 Type = 'v'; 193 NumRegs = 3; 194 } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) { 195 Type = 'v'; 196 NumRegs = 8; 197 } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) { 198 Type = 's'; 199 NumRegs = 8; 200 } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) { 201 Type = 'v'; 202 NumRegs = 16; 203 } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) { 204 Type = 's'; 205 NumRegs = 16; 206 } else { 207 O << getRegisterName(reg); 208 return; 209 } 210 211 // The low 8 bits of the encoding value is the register index, for both VGPRs 212 // and SGPRs. 213 unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1); 214 if (NumRegs == 1) { 215 O << Type << RegIdx; 216 return; 217 } 218 219 O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']'; 220 } 221 222 void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo, 223 raw_ostream &O) { 224 if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3) 225 O << "_e64 "; 226 else 227 O << "_e32 "; 228 229 printOperand(MI, OpNo, O); 230 } 231 232 void AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) { 233 int32_t SImm = static_cast<int32_t>(Imm); 234 if (SImm >= -16 && SImm <= 64) { 235 O << SImm; 236 return; 237 } 238 239 if (Imm == FloatToBits(0.0f)) 240 O << "0.0"; 241 else if (Imm == FloatToBits(1.0f)) 242 O << "1.0"; 243 else if (Imm == FloatToBits(-1.0f)) 244 O << "-1.0"; 245 else if (Imm == FloatToBits(0.5f)) 246 O << "0.5"; 247 else if (Imm == FloatToBits(-0.5f)) 248 O << "-0.5"; 249 else if (Imm == FloatToBits(2.0f)) 250 O << "2.0"; 251 else if (Imm == FloatToBits(-2.0f)) 252 O << "-2.0"; 253 else if (Imm == FloatToBits(4.0f)) 254 O << "4.0"; 255 else if (Imm == FloatToBits(-4.0f)) 256 O << "-4.0"; 257 else 258 O << formatHex(static_cast<uint64_t>(Imm)); 259 } 260 261 void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) { 262 int64_t SImm = static_cast<int64_t>(Imm); 263 if (SImm >= -16 && SImm <= 64) { 264 O << SImm; 265 return; 266 } 267 268 if (Imm == DoubleToBits(0.0)) 269 O << "0.0"; 270 else if (Imm == DoubleToBits(1.0)) 271 O << "1.0"; 272 else if (Imm == DoubleToBits(-1.0)) 273 O << "-1.0"; 274 else if (Imm == DoubleToBits(0.5)) 275 O << "0.5"; 276 else if (Imm == DoubleToBits(-0.5)) 277 O << "-0.5"; 278 else if (Imm == DoubleToBits(2.0)) 279 O << "2.0"; 280 else if (Imm == DoubleToBits(-2.0)) 281 O << "-2.0"; 282 else if (Imm == DoubleToBits(4.0)) 283 O << "4.0"; 284 else if (Imm == DoubleToBits(-4.0)) 285 O << "-4.0"; 286 else { 287 assert(isUInt<32>(Imm)); 288 289 // In rare situations, we will have a 32-bit literal in a 64-bit 290 // operand. This is technically allowed for the encoding of s_mov_b64. 291 O << formatHex(static_cast<uint64_t>(Imm)); 292 } 293 } 294 295 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 296 raw_ostream &O) { 297 298 const MCOperand &Op = MI->getOperand(OpNo); 299 if (Op.isReg()) { 300 switch (Op.getReg()) { 301 // This is the default predicate state, so we don't need to print it. 302 case AMDGPU::PRED_SEL_OFF: 303 break; 304 305 default: 306 printRegOperand(Op.getReg(), O, MRI); 307 break; 308 } 309 } else if (Op.isImm()) { 310 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 311 int RCID = Desc.OpInfo[OpNo].RegClass; 312 if (RCID != -1) { 313 const MCRegisterClass &ImmRC = MRI.getRegClass(RCID); 314 if (ImmRC.getSize() == 4) 315 printImmediate32(Op.getImm(), O); 316 else if (ImmRC.getSize() == 8) 317 printImmediate64(Op.getImm(), O); 318 else 319 llvm_unreachable("Invalid register class size"); 320 } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) { 321 printImmediate32(Op.getImm(), O); 322 } else { 323 // We hit this for the immediate instruction bits that don't yet have a 324 // custom printer. 325 // TODO: Eventually this should be unnecessary. 326 O << formatDec(Op.getImm()); 327 } 328 } else if (Op.isFPImm()) { 329 // We special case 0.0 because otherwise it will be printed as an integer. 330 if (Op.getFPImm() == 0.0) 331 O << "0.0"; 332 else { 333 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 334 const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass); 335 336 if (ImmRC.getSize() == 4) 337 printImmediate32(FloatToBits(Op.getFPImm()), O); 338 else if (ImmRC.getSize() == 8) 339 printImmediate64(DoubleToBits(Op.getFPImm()), O); 340 else 341 llvm_unreachable("Invalid register class size"); 342 } 343 } else if (Op.isExpr()) { 344 const MCExpr *Exp = Op.getExpr(); 345 Exp->print(O, &MAI); 346 } else { 347 llvm_unreachable("unknown operand type in printOperand"); 348 } 349 } 350 351 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo, 352 raw_ostream &O) { 353 unsigned InputModifiers = MI->getOperand(OpNo).getImm(); 354 if (InputModifiers & SISrcMods::NEG) 355 O << '-'; 356 if (InputModifiers & SISrcMods::ABS) 357 O << '|'; 358 printOperand(MI, OpNo + 1, O); 359 if (InputModifiers & SISrcMods::ABS) 360 O << '|'; 361 } 362 363 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 364 raw_ostream &O) { 365 unsigned Imm = MI->getOperand(OpNum).getImm(); 366 367 if (Imm == 2) { 368 O << "P0"; 369 } else if (Imm == 1) { 370 O << "P20"; 371 } else if (Imm == 0) { 372 O << "P10"; 373 } else { 374 llvm_unreachable("Invalid interpolation parameter slot"); 375 } 376 } 377 378 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 379 raw_ostream &O) { 380 printOperand(MI, OpNo, O); 381 O << ", "; 382 printOperand(MI, OpNo + 1, O); 383 } 384 385 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 386 raw_ostream &O, StringRef Asm, 387 StringRef Default) { 388 const MCOperand &Op = MI->getOperand(OpNo); 389 assert(Op.isImm()); 390 if (Op.getImm() == 1) { 391 O << Asm; 392 } else { 393 O << Default; 394 } 395 } 396 397 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 398 raw_ostream &O) { 399 printIfSet(MI, OpNo, O, "|"); 400 } 401 402 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 403 raw_ostream &O) { 404 printIfSet(MI, OpNo, O, "_SAT"); 405 } 406 407 void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo, 408 raw_ostream &O) { 409 if (MI->getOperand(OpNo).getImm()) 410 O << " clamp"; 411 } 412 413 void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo, 414 raw_ostream &O) { 415 int Imm = MI->getOperand(OpNo).getImm(); 416 if (Imm == SIOutMods::MUL2) 417 O << " mul:2"; 418 else if (Imm == SIOutMods::MUL4) 419 O << " mul:4"; 420 else if (Imm == SIOutMods::DIV2) 421 O << " div:2"; 422 } 423 424 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 425 raw_ostream &O) { 426 int32_t Imm = MI->getOperand(OpNo).getImm(); 427 O << Imm << '(' << BitsToFloat(Imm) << ')'; 428 } 429 430 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 431 raw_ostream &O) { 432 printIfSet(MI, OpNo, O, "*", " "); 433 } 434 435 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 436 raw_ostream &O) { 437 printIfSet(MI, OpNo, O, "-"); 438 } 439 440 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 441 raw_ostream &O) { 442 switch (MI->getOperand(OpNo).getImm()) { 443 default: break; 444 case 1: 445 O << " * 2.0"; 446 break; 447 case 2: 448 O << " * 4.0"; 449 break; 450 case 3: 451 O << " / 2.0"; 452 break; 453 } 454 } 455 456 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 457 raw_ostream &O) { 458 printIfSet(MI, OpNo, O, "+"); 459 } 460 461 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 462 raw_ostream &O) { 463 printIfSet(MI, OpNo, O, "ExecMask,"); 464 } 465 466 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 467 raw_ostream &O) { 468 printIfSet(MI, OpNo, O, "Pred,"); 469 } 470 471 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 472 raw_ostream &O) { 473 const MCOperand &Op = MI->getOperand(OpNo); 474 if (Op.getImm() == 0) { 475 O << " (MASKED)"; 476 } 477 } 478 479 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 480 raw_ostream &O) { 481 const char * chans = "XYZW"; 482 int sel = MI->getOperand(OpNo).getImm(); 483 484 int chan = sel & 3; 485 sel >>= 2; 486 487 if (sel >= 512) { 488 sel -= 512; 489 int cb = sel >> 12; 490 sel &= 4095; 491 O << cb << '[' << sel << ']'; 492 } else if (sel >= 448) { 493 sel -= 448; 494 O << sel; 495 } else if (sel >= 0){ 496 O << sel; 497 } 498 499 if (sel >= 0) 500 O << '.' << chans[chan]; 501 } 502 503 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 504 raw_ostream &O) { 505 int BankSwizzle = MI->getOperand(OpNo).getImm(); 506 switch (BankSwizzle) { 507 case 1: 508 O << "BS:VEC_021/SCL_122"; 509 break; 510 case 2: 511 O << "BS:VEC_120/SCL_212"; 512 break; 513 case 3: 514 O << "BS:VEC_102/SCL_221"; 515 break; 516 case 4: 517 O << "BS:VEC_201"; 518 break; 519 case 5: 520 O << "BS:VEC_210"; 521 break; 522 default: 523 break; 524 } 525 return; 526 } 527 528 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 529 raw_ostream &O) { 530 unsigned Sel = MI->getOperand(OpNo).getImm(); 531 switch (Sel) { 532 case 0: 533 O << 'X'; 534 break; 535 case 1: 536 O << 'Y'; 537 break; 538 case 2: 539 O << 'Z'; 540 break; 541 case 3: 542 O << 'W'; 543 break; 544 case 4: 545 O << '0'; 546 break; 547 case 5: 548 O << '1'; 549 break; 550 case 7: 551 O << '_'; 552 break; 553 default: 554 break; 555 } 556 } 557 558 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 559 raw_ostream &O) { 560 unsigned CT = MI->getOperand(OpNo).getImm(); 561 switch (CT) { 562 case 0: 563 O << 'U'; 564 break; 565 case 1: 566 O << 'N'; 567 break; 568 default: 569 break; 570 } 571 } 572 573 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 574 raw_ostream &O) { 575 int KCacheMode = MI->getOperand(OpNo).getImm(); 576 if (KCacheMode > 0) { 577 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 578 O << "CB" << KCacheBank << ':'; 579 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 580 int LineSize = (KCacheMode == 1) ? 16 : 32; 581 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize; 582 } 583 } 584 585 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, 586 raw_ostream &O) { 587 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 588 unsigned Msg = SImm16 & 0xF; 589 if (Msg == 2 || Msg == 3) { 590 unsigned Op = (SImm16 >> 4) & 0xF; 591 if (Msg == 3) 592 O << "Gs_done("; 593 else 594 O << "Gs("; 595 if (Op == 0) { 596 O << "nop"; 597 } else { 598 unsigned Stream = (SImm16 >> 8) & 0x3; 599 if (Op == 1) 600 O << "cut"; 601 else if (Op == 2) 602 O << "emit"; 603 else if (Op == 3) 604 O << "emit-cut"; 605 O << " stream " << Stream; 606 } 607 O << "), [m0] "; 608 } else if (Msg == 1) 609 O << "interrupt "; 610 else if (Msg == 15) 611 O << "system "; 612 else 613 O << "unknown(" << Msg << ") "; 614 } 615 616 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 617 raw_ostream &O) { 618 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 619 // SIInsertWaits.cpp bits usage does not match ISA docs description but it 620 // works so it might be a misprint in docs. 621 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 622 unsigned Vmcnt = SImm16 & 0xF; 623 unsigned Expcnt = (SImm16 >> 4) & 0xF; 624 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 625 626 bool NeedSpace = false; 627 628 if (Vmcnt != 0xF) { 629 O << "vmcnt(" << Vmcnt << ')'; 630 NeedSpace = true; 631 } 632 633 if (Expcnt != 0x7) { 634 if (NeedSpace) 635 O << ' '; 636 O << "expcnt(" << Expcnt << ')'; 637 NeedSpace = true; 638 } 639 640 if (Lgkmcnt != 0x7) { 641 if (NeedSpace) 642 O << ' '; 643 O << "lgkmcnt(" << Lgkmcnt << ')'; 644 } 645 } 646 647 #include "AMDGPUGenAsmWriter.inc" 648