1 //===-- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA --------------===// 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 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 // 12 /// \file 13 /// 14 /// This file contains definition for AMDGPU ISA disassembler 15 // 16 //===----------------------------------------------------------------------===// 17 18 // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)? 19 20 #include "AMDGPUDisassembler.h" 21 #include "AMDGPU.h" 22 #include "AMDGPURegisterInfo.h" 23 #include "SIDefines.h" 24 #include "Utils/AMDGPUBaseInfo.h" 25 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 26 27 #include "llvm/MC/MCContext.h" 28 #include "llvm/MC/MCFixedLenDisassembler.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/MC/MCInstrDesc.h" 31 #include "llvm/MC/MCSubtargetInfo.h" 32 #include "llvm/Support/ELF.h" 33 #include "llvm/Support/Endian.h" 34 #include "llvm/Support/Debug.h" 35 #include "llvm/Support/TargetRegistry.h" 36 37 38 using namespace llvm; 39 40 #define DEBUG_TYPE "amdgpu-disassembler" 41 42 typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; 43 44 45 inline static MCDisassembler::DecodeStatus 46 addOperand(MCInst &Inst, const MCOperand& Opnd) { 47 Inst.addOperand(Opnd); 48 return Opnd.isValid() ? 49 MCDisassembler::Success : 50 MCDisassembler::SoftFail; 51 } 52 53 static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm, 54 uint64_t Addr, const void *Decoder) { 55 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 56 57 APInt SignedOffset(18, Imm * 4, true); 58 int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue(); 59 60 if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2)) 61 return MCDisassembler::Success; 62 return addOperand(Inst, MCOperand::createImm(Imm)); 63 } 64 65 #define DECODE_OPERAND(StaticDecoderName, DecoderName) \ 66 static DecodeStatus StaticDecoderName(MCInst &Inst, \ 67 unsigned Imm, \ 68 uint64_t /*Addr*/, \ 69 const void *Decoder) { \ 70 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \ 71 return addOperand(Inst, DAsm->DecoderName(Imm)); \ 72 } 73 74 #define DECODE_OPERAND_REG(RegClass) \ 75 DECODE_OPERAND(Decode##RegClass##RegisterClass, decodeOperand_##RegClass) 76 77 DECODE_OPERAND_REG(VGPR_32) 78 DECODE_OPERAND_REG(VS_32) 79 DECODE_OPERAND_REG(VS_64) 80 81 DECODE_OPERAND_REG(VReg_64) 82 DECODE_OPERAND_REG(VReg_96) 83 DECODE_OPERAND_REG(VReg_128) 84 85 DECODE_OPERAND_REG(SReg_32) 86 DECODE_OPERAND_REG(SReg_32_XM0_XEXEC) 87 DECODE_OPERAND_REG(SReg_64) 88 DECODE_OPERAND_REG(SReg_64_XEXEC) 89 DECODE_OPERAND_REG(SReg_128) 90 DECODE_OPERAND_REG(SReg_256) 91 DECODE_OPERAND_REG(SReg_512) 92 93 94 static DecodeStatus decodeOperand_VSrc16(MCInst &Inst, 95 unsigned Imm, 96 uint64_t Addr, 97 const void *Decoder) { 98 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 99 return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm)); 100 } 101 102 static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst, 103 unsigned Imm, 104 uint64_t Addr, 105 const void *Decoder) { 106 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 107 return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm)); 108 } 109 110 #define DECODE_SDWA9(DecName) \ 111 DECODE_OPERAND(decodeSDWA9##DecName, decodeSDWA9##DecName) 112 113 DECODE_SDWA9(Src32) 114 DECODE_SDWA9(Src16) 115 DECODE_SDWA9(VopcDst) 116 117 #include "AMDGPUGenDisassemblerTables.inc" 118 119 //===----------------------------------------------------------------------===// 120 // 121 //===----------------------------------------------------------------------===// 122 123 template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) { 124 assert(Bytes.size() >= sizeof(T)); 125 const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data()); 126 Bytes = Bytes.slice(sizeof(T)); 127 return Res; 128 } 129 130 DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table, 131 MCInst &MI, 132 uint64_t Inst, 133 uint64_t Address) const { 134 assert(MI.getOpcode() == 0); 135 assert(MI.getNumOperands() == 0); 136 MCInst TmpInst; 137 HasLiteral = false; 138 const auto SavedBytes = Bytes; 139 if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) { 140 MI = TmpInst; 141 return MCDisassembler::Success; 142 } 143 Bytes = SavedBytes; 144 return MCDisassembler::Fail; 145 } 146 147 DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 148 ArrayRef<uint8_t> Bytes_, 149 uint64_t Address, 150 raw_ostream &WS, 151 raw_ostream &CS) const { 152 CommentStream = &CS; 153 154 // ToDo: AMDGPUDisassembler supports only VI ISA. 155 if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding]) 156 report_fatal_error("Disassembly not yet supported for subtarget"); 157 158 const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size()); 159 Bytes = Bytes_.slice(0, MaxInstBytesNum); 160 161 DecodeStatus Res = MCDisassembler::Fail; 162 do { 163 // ToDo: better to switch encoding length using some bit predicate 164 // but it is unknown yet, so try all we can 165 166 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2 167 // encodings 168 if (Bytes.size() >= 8) { 169 const uint64_t QW = eatBytes<uint64_t>(Bytes); 170 Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address); 171 if (Res) break; 172 173 Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address); 174 if (Res) break; 175 176 Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address); 177 if (Res) break; 178 } 179 180 // Reinitialize Bytes as DPP64 could have eaten too much 181 Bytes = Bytes_.slice(0, MaxInstBytesNum); 182 183 // Try decode 32-bit instruction 184 if (Bytes.size() < 4) break; 185 const uint32_t DW = eatBytes<uint32_t>(Bytes); 186 Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address); 187 if (Res) break; 188 189 Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address); 190 if (Res) break; 191 192 if (Bytes.size() < 4) break; 193 const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW; 194 Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address); 195 if (Res) break; 196 197 Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address); 198 } while (false); 199 200 if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi || 201 MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si || 202 MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi)) { 203 // Insert dummy unused src2_modifiers. 204 int Src2ModIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 205 AMDGPU::OpName::src2_modifiers); 206 auto I = MI.begin(); 207 std::advance(I, Src2ModIdx); 208 MI.insert(I, MCOperand::createImm(0)); 209 } 210 211 Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0; 212 return Res; 213 } 214 215 const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const { 216 return getContext().getRegisterInfo()-> 217 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]); 218 } 219 220 inline 221 MCOperand AMDGPUDisassembler::errOperand(unsigned V, 222 const Twine& ErrMsg) const { 223 *CommentStream << "Error: " + ErrMsg; 224 225 // ToDo: add support for error operands to MCInst.h 226 // return MCOperand::createError(V); 227 return MCOperand(); 228 } 229 230 inline 231 MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const { 232 return MCOperand::createReg(RegId); 233 } 234 235 inline 236 MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID, 237 unsigned Val) const { 238 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID]; 239 if (Val >= RegCl.getNumRegs()) 240 return errOperand(Val, Twine(getRegClassName(RegClassID)) + 241 ": unknown register " + Twine(Val)); 242 return createRegOperand(RegCl.getRegister(Val)); 243 } 244 245 inline 246 MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID, 247 unsigned Val) const { 248 // ToDo: SI/CI have 104 SGPRs, VI - 102 249 // Valery: here we accepting as much as we can, let assembler sort it out 250 int shift = 0; 251 switch (SRegClassID) { 252 case AMDGPU::SGPR_32RegClassID: 253 case AMDGPU::TTMP_32RegClassID: 254 break; 255 case AMDGPU::SGPR_64RegClassID: 256 case AMDGPU::TTMP_64RegClassID: 257 shift = 1; 258 break; 259 case AMDGPU::SGPR_128RegClassID: 260 case AMDGPU::TTMP_128RegClassID: 261 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in 262 // this bundle? 263 case AMDGPU::SReg_256RegClassID: 264 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in 265 // this bundle? 266 case AMDGPU::SReg_512RegClassID: 267 shift = 2; 268 break; 269 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in 270 // this bundle? 271 default: 272 llvm_unreachable("unhandled register class"); 273 } 274 275 if (Val % (1 << shift)) { 276 *CommentStream << "Warning: " << getRegClassName(SRegClassID) 277 << ": scalar reg isn't aligned " << Val; 278 } 279 280 return createRegOperand(SRegClassID, Val >> shift); 281 } 282 283 MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const { 284 return decodeSrcOp(OPW32, Val); 285 } 286 287 MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const { 288 return decodeSrcOp(OPW64, Val); 289 } 290 291 MCOperand AMDGPUDisassembler::decodeOperand_VSrc16(unsigned Val) const { 292 return decodeSrcOp(OPW16, Val); 293 } 294 295 MCOperand AMDGPUDisassembler::decodeOperand_VSrcV216(unsigned Val) const { 296 return decodeSrcOp(OPWV216, Val); 297 } 298 299 MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const { 300 // Some instructions have operand restrictions beyond what the encoding 301 // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra 302 // high bit. 303 Val &= 255; 304 305 return createRegOperand(AMDGPU::VGPR_32RegClassID, Val); 306 } 307 308 MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const { 309 return createRegOperand(AMDGPU::VReg_64RegClassID, Val); 310 } 311 312 MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const { 313 return createRegOperand(AMDGPU::VReg_96RegClassID, Val); 314 } 315 316 MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const { 317 return createRegOperand(AMDGPU::VReg_128RegClassID, Val); 318 } 319 320 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const { 321 // table-gen generated disassembler doesn't care about operand types 322 // leaving only registry class so SSrc_32 operand turns into SReg_32 323 // and therefore we accept immediates and literals here as well 324 return decodeSrcOp(OPW32, Val); 325 } 326 327 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0_XEXEC( 328 unsigned Val) const { 329 // SReg_32_XM0 is SReg_32 without M0 or EXEC_LO/EXEC_HI 330 return decodeOperand_SReg_32(Val); 331 } 332 333 MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const { 334 return decodeSrcOp(OPW64, Val); 335 } 336 337 MCOperand AMDGPUDisassembler::decodeOperand_SReg_64_XEXEC(unsigned Val) const { 338 return decodeSrcOp(OPW64, Val); 339 } 340 341 MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const { 342 return decodeSrcOp(OPW128, Val); 343 } 344 345 MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const { 346 return createSRegOperand(AMDGPU::SReg_256RegClassID, Val); 347 } 348 349 MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const { 350 return createSRegOperand(AMDGPU::SReg_512RegClassID, Val); 351 } 352 353 354 MCOperand AMDGPUDisassembler::decodeLiteralConstant() const { 355 // For now all literal constants are supposed to be unsigned integer 356 // ToDo: deal with signed/unsigned 64-bit integer constants 357 // ToDo: deal with float/double constants 358 if (!HasLiteral) { 359 if (Bytes.size() < 4) { 360 return errOperand(0, "cannot read literal, inst bytes left " + 361 Twine(Bytes.size())); 362 } 363 HasLiteral = true; 364 Literal = eatBytes<uint32_t>(Bytes); 365 } 366 return MCOperand::createImm(Literal); 367 } 368 369 MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) { 370 using namespace AMDGPU::EncValues; 371 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX); 372 return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ? 373 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) : 374 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm))); 375 // Cast prevents negative overflow. 376 } 377 378 static int64_t getInlineImmVal32(unsigned Imm) { 379 switch (Imm) { 380 case 240: 381 return FloatToBits(0.5f); 382 case 241: 383 return FloatToBits(-0.5f); 384 case 242: 385 return FloatToBits(1.0f); 386 case 243: 387 return FloatToBits(-1.0f); 388 case 244: 389 return FloatToBits(2.0f); 390 case 245: 391 return FloatToBits(-2.0f); 392 case 246: 393 return FloatToBits(4.0f); 394 case 247: 395 return FloatToBits(-4.0f); 396 case 248: // 1 / (2 * PI) 397 return 0x3e22f983; 398 default: 399 llvm_unreachable("invalid fp inline imm"); 400 } 401 } 402 403 static int64_t getInlineImmVal64(unsigned Imm) { 404 switch (Imm) { 405 case 240: 406 return DoubleToBits(0.5); 407 case 241: 408 return DoubleToBits(-0.5); 409 case 242: 410 return DoubleToBits(1.0); 411 case 243: 412 return DoubleToBits(-1.0); 413 case 244: 414 return DoubleToBits(2.0); 415 case 245: 416 return DoubleToBits(-2.0); 417 case 246: 418 return DoubleToBits(4.0); 419 case 247: 420 return DoubleToBits(-4.0); 421 case 248: // 1 / (2 * PI) 422 return 0x3fc45f306dc9c882; 423 default: 424 llvm_unreachable("invalid fp inline imm"); 425 } 426 } 427 428 static int64_t getInlineImmVal16(unsigned Imm) { 429 switch (Imm) { 430 case 240: 431 return 0x3800; 432 case 241: 433 return 0xB800; 434 case 242: 435 return 0x3C00; 436 case 243: 437 return 0xBC00; 438 case 244: 439 return 0x4000; 440 case 245: 441 return 0xC000; 442 case 246: 443 return 0x4400; 444 case 247: 445 return 0xC400; 446 case 248: // 1 / (2 * PI) 447 return 0x3118; 448 default: 449 llvm_unreachable("invalid fp inline imm"); 450 } 451 } 452 453 MCOperand AMDGPUDisassembler::decodeFPImmed(OpWidthTy Width, unsigned Imm) { 454 assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN 455 && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX); 456 457 // ToDo: case 248: 1/(2*PI) - is allowed only on VI 458 switch (Width) { 459 case OPW32: 460 return MCOperand::createImm(getInlineImmVal32(Imm)); 461 case OPW64: 462 return MCOperand::createImm(getInlineImmVal64(Imm)); 463 case OPW16: 464 case OPWV216: 465 return MCOperand::createImm(getInlineImmVal16(Imm)); 466 default: 467 llvm_unreachable("implement me"); 468 } 469 } 470 471 unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const { 472 using namespace AMDGPU; 473 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 474 switch (Width) { 475 default: // fall 476 case OPW32: 477 case OPW16: 478 case OPWV216: 479 return VGPR_32RegClassID; 480 case OPW64: return VReg_64RegClassID; 481 case OPW128: return VReg_128RegClassID; 482 } 483 } 484 485 unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const { 486 using namespace AMDGPU; 487 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 488 switch (Width) { 489 default: // fall 490 case OPW32: 491 case OPW16: 492 case OPWV216: 493 return SGPR_32RegClassID; 494 case OPW64: return SGPR_64RegClassID; 495 case OPW128: return SGPR_128RegClassID; 496 } 497 } 498 499 unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const { 500 using namespace AMDGPU; 501 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 502 switch (Width) { 503 default: // fall 504 case OPW32: 505 case OPW16: 506 case OPWV216: 507 return TTMP_32RegClassID; 508 case OPW64: return TTMP_64RegClassID; 509 case OPW128: return TTMP_128RegClassID; 510 } 511 } 512 513 MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const { 514 using namespace AMDGPU::EncValues; 515 assert(Val < 512); // enum9 516 517 if (VGPR_MIN <= Val && Val <= VGPR_MAX) { 518 return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN); 519 } 520 if (Val <= SGPR_MAX) { 521 assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning. 522 return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN); 523 } 524 if (TTMP_MIN <= Val && Val <= TTMP_MAX) { 525 return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN); 526 } 527 528 assert(Width == OPW16 || Width == OPW32 || Width == OPW64); 529 530 if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) 531 return decodeIntImmed(Val); 532 533 if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) 534 return decodeFPImmed(Width, Val); 535 536 if (Val == LITERAL_CONST) 537 return decodeLiteralConstant(); 538 539 switch (Width) { 540 case OPW32: 541 case OPW16: 542 case OPWV216: 543 return decodeSpecialReg32(Val); 544 case OPW64: 545 return decodeSpecialReg64(Val); 546 default: 547 llvm_unreachable("unexpected immediate type"); 548 } 549 } 550 551 MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { 552 using namespace AMDGPU; 553 switch (Val) { 554 case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI)); 555 case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI)); 556 // ToDo: no support for xnack_mask_lo/_hi register 557 case 104: 558 case 105: break; 559 case 106: return createRegOperand(VCC_LO); 560 case 107: return createRegOperand(VCC_HI); 561 case 108: return createRegOperand(TBA_LO); 562 case 109: return createRegOperand(TBA_HI); 563 case 110: return createRegOperand(TMA_LO); 564 case 111: return createRegOperand(TMA_HI); 565 case 124: return createRegOperand(M0); 566 case 126: return createRegOperand(EXEC_LO); 567 case 127: return createRegOperand(EXEC_HI); 568 case 235: return createRegOperand(SRC_SHARED_BASE); 569 case 236: return createRegOperand(SRC_SHARED_LIMIT); 570 case 237: return createRegOperand(SRC_PRIVATE_BASE); 571 case 238: return createRegOperand(SRC_PRIVATE_LIMIT); 572 // TODO: SRC_POPS_EXITING_WAVE_ID 573 // ToDo: no support for vccz register 574 case 251: break; 575 // ToDo: no support for execz register 576 case 252: break; 577 case 253: return createRegOperand(SCC); 578 default: break; 579 } 580 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 581 } 582 583 MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const { 584 using namespace AMDGPU; 585 switch (Val) { 586 case 102: return createRegOperand(getMCReg(FLAT_SCR, STI)); 587 case 106: return createRegOperand(VCC); 588 case 108: return createRegOperand(TBA); 589 case 110: return createRegOperand(TMA); 590 case 126: return createRegOperand(EXEC); 591 default: break; 592 } 593 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 594 } 595 596 MCOperand AMDGPUDisassembler::decodeSDWA9Src(const OpWidthTy Width, 597 unsigned Val) const { 598 using namespace AMDGPU::SDWA; 599 600 if (SDWA9EncValues::SRC_VGPR_MIN <= Val && 601 Val <= SDWA9EncValues::SRC_VGPR_MAX) { 602 return createRegOperand(getVgprClassId(Width), 603 Val - SDWA9EncValues::SRC_VGPR_MIN); 604 } 605 if (SDWA9EncValues::SRC_SGPR_MIN <= Val && 606 Val <= SDWA9EncValues::SRC_SGPR_MAX) { 607 return createSRegOperand(getSgprClassId(Width), 608 Val - SDWA9EncValues::SRC_SGPR_MIN); 609 } 610 611 return decodeSpecialReg32(Val - SDWA9EncValues::SRC_SGPR_MIN); 612 } 613 614 MCOperand AMDGPUDisassembler::decodeSDWA9Src16(unsigned Val) const { 615 return decodeSDWA9Src(OPW16, Val); 616 } 617 618 MCOperand AMDGPUDisassembler::decodeSDWA9Src32(unsigned Val) const { 619 return decodeSDWA9Src(OPW32, Val); 620 } 621 622 623 MCOperand AMDGPUDisassembler::decodeSDWA9VopcDst(unsigned Val) const { 624 using namespace AMDGPU::SDWA; 625 626 if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) { 627 Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK; 628 if (Val > AMDGPU::EncValues::SGPR_MAX) { 629 return decodeSpecialReg64(Val); 630 } else { 631 return createSRegOperand(getSgprClassId(OPW64), Val); 632 } 633 } else { 634 return createRegOperand(AMDGPU::VCC); 635 } 636 } 637 638 //===----------------------------------------------------------------------===// 639 // AMDGPUSymbolizer 640 //===----------------------------------------------------------------------===// 641 642 // Try to find symbol name for specified label 643 bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst, 644 raw_ostream &/*cStream*/, int64_t Value, 645 uint64_t /*Address*/, bool IsBranch, 646 uint64_t /*Offset*/, uint64_t /*InstSize*/) { 647 typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy; 648 typedef std::vector<SymbolInfoTy> SectionSymbolsTy; 649 650 if (!IsBranch) { 651 return false; 652 } 653 654 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo); 655 auto Result = std::find_if(Symbols->begin(), Symbols->end(), 656 [Value](const SymbolInfoTy& Val) { 657 return std::get<0>(Val) == static_cast<uint64_t>(Value) 658 && std::get<2>(Val) == ELF::STT_NOTYPE; 659 }); 660 if (Result != Symbols->end()) { 661 auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result)); 662 const auto *Add = MCSymbolRefExpr::create(Sym, Ctx); 663 Inst.addOperand(MCOperand::createExpr(Add)); 664 return true; 665 } 666 return false; 667 } 668 669 void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, 670 int64_t Value, 671 uint64_t Address) { 672 llvm_unreachable("unimplemented"); 673 } 674 675 //===----------------------------------------------------------------------===// 676 // Initialization 677 //===----------------------------------------------------------------------===// 678 679 static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/, 680 LLVMOpInfoCallback /*GetOpInfo*/, 681 LLVMSymbolLookupCallback /*SymbolLookUp*/, 682 void *DisInfo, 683 MCContext *Ctx, 684 std::unique_ptr<MCRelocationInfo> &&RelInfo) { 685 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo); 686 } 687 688 static MCDisassembler *createAMDGPUDisassembler(const Target &T, 689 const MCSubtargetInfo &STI, 690 MCContext &Ctx) { 691 return new AMDGPUDisassembler(STI, Ctx); 692 } 693 694 extern "C" void LLVMInitializeAMDGPUDisassembler() { 695 TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(), 696 createAMDGPUDisassembler); 697 TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(), 698 createAMDGPUSymbolizer); 699 } 700