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 20using namespace llvm; 21 22void 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 30void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, 31 raw_ostream &O) { 32 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff); 33} 34 35void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 36 raw_ostream &O) { 37 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff); 38} 39 40void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo, 41 raw_ostream &O) { 42 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff); 43} 44 45void AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo, 46 raw_ostream &O) { 47 O << formatDec(MI->getOperand(OpNo).getImm() & 0xff); 48} 49 50void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo, 51 raw_ostream &O) { 52 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff); 53} 54 55void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo, 56 raw_ostream &O) { 57 if (MI->getOperand(OpNo).getImm()) 58 O << " offen"; 59} 60 61void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo, 62 raw_ostream &O) { 63 if (MI->getOperand(OpNo).getImm()) 64 O << " idxen"; 65} 66 67void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo, 68 raw_ostream &O) { 69 if (MI->getOperand(OpNo).getImm()) 70 O << " addr64"; 71} 72 73void 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 81void 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 90void 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 98void 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 106void AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo, 107 raw_ostream &O) { 108 if (MI->getOperand(OpNo).getImm()) 109 O << " gds"; 110} 111 112void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo, 113 raw_ostream &O) { 114 if (MI->getOperand(OpNo).getImm()) 115 O << " glc"; 116} 117 118void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo, 119 raw_ostream &O) { 120 if (MI->getOperand(OpNo).getImm()) 121 O << " slc"; 122} 123 124void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo, 125 raw_ostream &O) { 126 if (MI->getOperand(OpNo).getImm()) 127 O << " tfe"; 128} 129 130void 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 222void 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 232void 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 261void 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 llvm_unreachable("64-bit literal constants not supported"); 288} 289 290void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 291 raw_ostream &O) { 292 293 const MCOperand &Op = MI->getOperand(OpNo); 294 if (Op.isReg()) { 295 switch (Op.getReg()) { 296 // This is the default predicate state, so we don't need to print it. 297 case AMDGPU::PRED_SEL_OFF: 298 break; 299 300 default: 301 printRegOperand(Op.getReg(), O, MRI); 302 break; 303 } 304 } else if (Op.isImm()) { 305 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 306 int RCID = Desc.OpInfo[OpNo].RegClass; 307 if (RCID != -1) { 308 const MCRegisterClass &ImmRC = MRI.getRegClass(RCID); 309 if (ImmRC.getSize() == 4) 310 printImmediate32(Op.getImm(), O); 311 else if (ImmRC.getSize() == 8) 312 printImmediate64(Op.getImm(), O); 313 else 314 llvm_unreachable("Invalid register class size"); 315 } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) { 316 printImmediate32(Op.getImm(), O); 317 } else { 318 // We hit this for the immediate instruction bits that don't yet have a 319 // custom printer. 320 // TODO: Eventually this should be unnecessary. 321 O << formatDec(Op.getImm()); 322 } 323 } else if (Op.isFPImm()) { 324 // We special case 0.0 because otherwise it will be printed as an integer. 325 if (Op.getFPImm() == 0.0) 326 O << "0.0"; 327 else { 328 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 329 const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass); 330 331 if (ImmRC.getSize() == 4) 332 printImmediate32(FloatToBits(Op.getFPImm()), O); 333 else if (ImmRC.getSize() == 8) 334 printImmediate64(DoubleToBits(Op.getFPImm()), O); 335 else 336 llvm_unreachable("Invalid register class size"); 337 } 338 } else if (Op.isExpr()) { 339 const MCExpr *Exp = Op.getExpr(); 340 Exp->print(O); 341 } else { 342 llvm_unreachable("unknown operand type in printOperand"); 343 } 344} 345 346void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo, 347 raw_ostream &O) { 348 unsigned InputModifiers = MI->getOperand(OpNo).getImm(); 349 if (InputModifiers & SISrcMods::NEG) 350 O << '-'; 351 if (InputModifiers & SISrcMods::ABS) 352 O << '|'; 353 printOperand(MI, OpNo + 1, O); 354 if (InputModifiers & SISrcMods::ABS) 355 O << '|'; 356} 357 358void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum, 359 raw_ostream &O) { 360 unsigned Imm = MI->getOperand(OpNum).getImm(); 361 362 if (Imm == 2) { 363 O << "P0"; 364 } else if (Imm == 1) { 365 O << "P20"; 366 } else if (Imm == 0) { 367 O << "P10"; 368 } else { 369 llvm_unreachable("Invalid interpolation parameter slot"); 370 } 371} 372 373void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, 374 raw_ostream &O) { 375 printOperand(MI, OpNo, O); 376 O << ", "; 377 printOperand(MI, OpNo + 1, O); 378} 379 380void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo, 381 raw_ostream &O, StringRef Asm, 382 StringRef Default) { 383 const MCOperand &Op = MI->getOperand(OpNo); 384 assert(Op.isImm()); 385 if (Op.getImm() == 1) { 386 O << Asm; 387 } else { 388 O << Default; 389 } 390} 391 392void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo, 393 raw_ostream &O) { 394 printIfSet(MI, OpNo, O, "|"); 395} 396 397void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo, 398 raw_ostream &O) { 399 printIfSet(MI, OpNo, O, "_SAT"); 400} 401 402void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo, 403 raw_ostream &O) { 404 if (MI->getOperand(OpNo).getImm()) 405 O << " clamp"; 406} 407 408void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo, 409 raw_ostream &O) { 410 int Imm = MI->getOperand(OpNo).getImm(); 411 if (Imm == SIOutMods::MUL2) 412 O << " mul:2"; 413 else if (Imm == SIOutMods::MUL4) 414 O << " mul:4"; 415 else if (Imm == SIOutMods::DIV2) 416 O << " div:2"; 417} 418 419void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo, 420 raw_ostream &O) { 421 int32_t Imm = MI->getOperand(OpNo).getImm(); 422 O << Imm << '(' << BitsToFloat(Imm) << ')'; 423} 424 425void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, 426 raw_ostream &O) { 427 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); 428} 429 430void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo, 431 raw_ostream &O) { 432 printIfSet(MI, OpNo, O, "-"); 433} 434 435void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo, 436 raw_ostream &O) { 437 switch (MI->getOperand(OpNo).getImm()) { 438 default: break; 439 case 1: 440 O << " * 2.0"; 441 break; 442 case 2: 443 O << " * 4.0"; 444 break; 445 case 3: 446 O << " / 2.0"; 447 break; 448 } 449} 450 451void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo, 452 raw_ostream &O) { 453 printIfSet(MI, OpNo, O, "+"); 454} 455 456void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo, 457 raw_ostream &O) { 458 printIfSet(MI, OpNo, O, "ExecMask,"); 459} 460 461void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo, 462 raw_ostream &O) { 463 printIfSet(MI, OpNo, O, "Pred,"); 464} 465 466void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo, 467 raw_ostream &O) { 468 const MCOperand &Op = MI->getOperand(OpNo); 469 if (Op.getImm() == 0) { 470 O << " (MASKED)"; 471 } 472} 473 474void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo, 475 raw_ostream &O) { 476 const char * chans = "XYZW"; 477 int sel = MI->getOperand(OpNo).getImm(); 478 479 int chan = sel & 3; 480 sel >>= 2; 481 482 if (sel >= 512) { 483 sel -= 512; 484 int cb = sel >> 12; 485 sel &= 4095; 486 O << cb << '[' << sel << ']'; 487 } else if (sel >= 448) { 488 sel -= 448; 489 O << sel; 490 } else if (sel >= 0){ 491 O << sel; 492 } 493 494 if (sel >= 0) 495 O << '.' << chans[chan]; 496} 497 498void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo, 499 raw_ostream &O) { 500 int BankSwizzle = MI->getOperand(OpNo).getImm(); 501 switch (BankSwizzle) { 502 case 1: 503 O << "BS:VEC_021/SCL_122"; 504 break; 505 case 2: 506 O << "BS:VEC_120/SCL_212"; 507 break; 508 case 3: 509 O << "BS:VEC_102/SCL_221"; 510 break; 511 case 4: 512 O << "BS:VEC_201"; 513 break; 514 case 5: 515 O << "BS:VEC_210"; 516 break; 517 default: 518 break; 519 } 520 return; 521} 522 523void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo, 524 raw_ostream &O) { 525 unsigned Sel = MI->getOperand(OpNo).getImm(); 526 switch (Sel) { 527 case 0: 528 O << 'X'; 529 break; 530 case 1: 531 O << 'Y'; 532 break; 533 case 2: 534 O << 'Z'; 535 break; 536 case 3: 537 O << 'W'; 538 break; 539 case 4: 540 O << '0'; 541 break; 542 case 5: 543 O << '1'; 544 break; 545 case 7: 546 O << '_'; 547 break; 548 default: 549 break; 550 } 551} 552 553void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo, 554 raw_ostream &O) { 555 unsigned CT = MI->getOperand(OpNo).getImm(); 556 switch (CT) { 557 case 0: 558 O << 'U'; 559 break; 560 case 1: 561 O << 'N'; 562 break; 563 default: 564 break; 565 } 566} 567 568void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo, 569 raw_ostream &O) { 570 int KCacheMode = MI->getOperand(OpNo).getImm(); 571 if (KCacheMode > 0) { 572 int KCacheBank = MI->getOperand(OpNo - 2).getImm(); 573 O << "CB" << KCacheBank << ':'; 574 int KCacheAddr = MI->getOperand(OpNo + 2).getImm(); 575 int LineSize = (KCacheMode == 1) ? 16 : 32; 576 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize; 577 } 578} 579 580void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, 581 raw_ostream &O) { 582 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 583 unsigned Msg = SImm16 & 0xF; 584 if (Msg == 2 || Msg == 3) { 585 unsigned Op = (SImm16 >> 4) & 0xF; 586 if (Msg == 3) 587 O << "Gs_done("; 588 else 589 O << "Gs("; 590 if (Op == 0) { 591 O << "nop"; 592 } else { 593 unsigned Stream = (SImm16 >> 8) & 0x3; 594 if (Op == 1) 595 O << "cut"; 596 else if (Op == 2) 597 O << "emit"; 598 else if (Op == 3) 599 O << "emit-cut"; 600 O << " stream " << Stream; 601 } 602 O << "), [m0] "; 603 } else if (Msg == 1) 604 O << "interrupt "; 605 else if (Msg == 15) 606 O << "system "; 607 else 608 O << "unknown(" << Msg << ") "; 609} 610 611void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 612 raw_ostream &O) { 613 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs 614 // SIInsertWaits.cpp bits usage does not match ISA docs description but it 615 // works so it might be a misprint in docs. 616 unsigned SImm16 = MI->getOperand(OpNo).getImm(); 617 unsigned Vmcnt = SImm16 & 0xF; 618 unsigned Expcnt = (SImm16 >> 4) & 0xF; 619 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF; 620 621 bool NeedSpace = false; 622 623 if (Vmcnt != 0xF) { 624 O << "vmcnt(" << Vmcnt << ')'; 625 NeedSpace = true; 626 } 627 628 if (Expcnt != 0x7) { 629 if (NeedSpace) 630 O << ' '; 631 O << "expcnt(" << Expcnt << ')'; 632 NeedSpace = true; 633 } 634 635 if (Lgkmcnt != 0x7) { 636 if (NeedSpace) 637 O << ' '; 638 O << "lgkmcnt(" << Lgkmcnt << ')'; 639 } 640} 641 642#include "AMDGPUGenAsmWriter.inc" 643