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