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