LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/Disassembler - AMDGPUDisassembler.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 269 327 82.3 %
Date: 2018-10-20 13:21:21 Functions: 45 70 64.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "Disassembler/AMDGPUDisassembler.h"
      21             : #include "AMDGPU.h"
      22             : #include "AMDGPURegisterInfo.h"
      23             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      24             : #include "SIDefines.h"
      25             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      26             : #include "Utils/AMDGPUBaseInfo.h"
      27             : #include "llvm-c/Disassembler.h"
      28             : #include "llvm/ADT/APInt.h"
      29             : #include "llvm/ADT/ArrayRef.h"
      30             : #include "llvm/ADT/Twine.h"
      31             : #include "llvm/BinaryFormat/ELF.h"
      32             : #include "llvm/MC/MCContext.h"
      33             : #include "llvm/MC/MCDisassembler/MCDisassembler.h"
      34             : #include "llvm/MC/MCExpr.h"
      35             : #include "llvm/MC/MCFixedLenDisassembler.h"
      36             : #include "llvm/MC/MCInst.h"
      37             : #include "llvm/MC/MCSubtargetInfo.h"
      38             : #include "llvm/Support/Endian.h"
      39             : #include "llvm/Support/ErrorHandling.h"
      40             : #include "llvm/Support/MathExtras.h"
      41             : #include "llvm/Support/TargetRegistry.h"
      42             : #include "llvm/Support/raw_ostream.h"
      43             : #include <algorithm>
      44             : #include <cassert>
      45             : #include <cstddef>
      46             : #include <cstdint>
      47             : #include <iterator>
      48             : #include <tuple>
      49             : #include <vector>
      50             : 
      51             : using namespace llvm;
      52             : 
      53             : #define DEBUG_TYPE "amdgpu-disassembler"
      54             : 
      55             : using DecodeStatus = llvm::MCDisassembler::DecodeStatus;
      56             : 
      57             : inline static MCDisassembler::DecodeStatus
      58             : addOperand(MCInst &Inst, const MCOperand& Opnd) {
      59             :   Inst.addOperand(Opnd);
      60          53 :   return Opnd.isValid() ?
      61             :     MCDisassembler::Success :
      62             :     MCDisassembler::SoftFail;
      63             : }
      64             : 
      65        9770 : static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,
      66             :                                 uint16_t NameIdx) {
      67        9770 :   int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), NameIdx);
      68        9770 :   if (OpIdx != -1) {
      69             :     auto I = MI.begin();
      70             :     std::advance(I, OpIdx);
      71             :     MI.insert(I, Op);
      72             :   }
      73        9770 :   return OpIdx;
      74             : }
      75             : 
      76          56 : static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm,
      77             :                                        uint64_t Addr, const void *Decoder) {
      78             :   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
      79             : 
      80          56 :   APInt SignedOffset(18, Imm * 4, true);
      81         112 :   int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
      82             : 
      83          56 :   if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2))
      84             :     return MCDisassembler::Success;
      85         106 :   return addOperand(Inst, MCOperand::createImm(Imm));
      86             : }
      87             : 
      88             : #define DECODE_OPERAND(StaticDecoderName, DecoderName) \
      89             : static DecodeStatus StaticDecoderName(MCInst &Inst, \
      90             :                                        unsigned Imm, \
      91             :                                        uint64_t /*Addr*/, \
      92             :                                        const void *Decoder) { \
      93             :   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \
      94             :   return addOperand(Inst, DAsm->DecoderName(Imm)); \
      95             : }
      96             : 
      97             : #define DECODE_OPERAND_REG(RegClass) \
      98             : DECODE_OPERAND(Decode##RegClass##RegisterClass, decodeOperand_##RegClass)
      99             : 
     100           0 : DECODE_OPERAND_REG(VGPR_32)
     101           0 : DECODE_OPERAND_REG(VS_32)
     102           0 : DECODE_OPERAND_REG(VS_64)
     103           0 : DECODE_OPERAND_REG(VS_128)
     104             : 
     105           0 : DECODE_OPERAND_REG(VReg_64)
     106           0 : DECODE_OPERAND_REG(VReg_96)
     107           0 : DECODE_OPERAND_REG(VReg_128)
     108             : 
     109           0 : DECODE_OPERAND_REG(SReg_32)
     110           0 : DECODE_OPERAND_REG(SReg_32_XM0_XEXEC)
     111           0 : DECODE_OPERAND_REG(SReg_32_XEXEC_HI)
     112           0 : DECODE_OPERAND_REG(SReg_64)
     113           0 : DECODE_OPERAND_REG(SReg_64_XEXEC)
     114           0 : DECODE_OPERAND_REG(SReg_128)
     115           0 : DECODE_OPERAND_REG(SReg_256)
     116           0 : DECODE_OPERAND_REG(SReg_512)
     117             : 
     118           0 : static DecodeStatus decodeOperand_VSrc16(MCInst &Inst,
     119             :                                          unsigned Imm,
     120             :                                          uint64_t Addr,
     121             :                                          const void *Decoder) {
     122             :   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
     123           0 :   return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm));
     124             : }
     125             : 
     126           0 : static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst,
     127             :                                          unsigned Imm,
     128             :                                          uint64_t Addr,
     129             :                                          const void *Decoder) {
     130             :   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
     131           0 :   return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm));
     132             : }
     133             : 
     134             : #define DECODE_SDWA(DecName) \
     135             : DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
     136             : 
     137           0 : DECODE_SDWA(Src32)
     138           0 : DECODE_SDWA(Src16)
     139           0 : DECODE_SDWA(VopcDst)
     140             : 
     141             : #include "AMDGPUGenDisassemblerTables.inc"
     142             : 
     143             : //===----------------------------------------------------------------------===//
     144             : //
     145             : //===----------------------------------------------------------------------===//
     146             : 
     147             : template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
     148             :   assert(Bytes.size() >= sizeof(T));
     149       38518 :   const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data());
     150      178584 :   Bytes = Bytes.slice(sizeof(T));
     151             :   return Res;
     152             : }
     153             : 
     154      431209 : DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table,
     155             :                                                MCInst &MI,
     156             :                                                uint64_t Inst,
     157             :                                                uint64_t Address) const {
     158             :   assert(MI.getOpcode() == 0);
     159             :   assert(MI.getNumOperands() == 0);
     160             :   MCInst TmpInst;
     161      431209 :   HasLiteral = false;
     162      431209 :   const auto SavedBytes = Bytes;
     163      431209 :   if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
     164             :     MI = TmpInst;
     165       78695 :     return MCDisassembler::Success;
     166             :   }
     167      352514 :   Bytes = SavedBytes;
     168      352514 :   return MCDisassembler::Fail;
     169             : }
     170             : 
     171       78702 : DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
     172             :                                                 ArrayRef<uint8_t> Bytes_,
     173             :                                                 uint64_t Address,
     174             :                                                 raw_ostream &WS,
     175             :                                                 raw_ostream &CS) const {
     176       78702 :   CommentStream = &CS;
     177             :   bool IsSDWA = false;
     178             : 
     179             :   // ToDo: AMDGPUDisassembler supports only VI ISA.
     180      157404 :   if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding])
     181           1 :     report_fatal_error("Disassembly not yet supported for subtarget");
     182             : 
     183       78701 :   const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size());
     184       78701 :   Bytes = Bytes_.slice(0, MaxInstBytesNum);
     185             : 
     186             :   DecodeStatus Res = MCDisassembler::Fail;
     187             :   do {
     188             :     // ToDo: better to switch encoding length using some bit predicate
     189             :     // but it is unknown yet, so try all we can
     190             : 
     191             :     // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
     192             :     // encodings
     193       78701 :     if (Bytes.size() >= 8) {
     194             :       const uint64_t QW = eatBytes<uint64_t>(Bytes);
     195       78681 :       Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address);
     196       78681 :       if (Res) break;
     197             : 
     198       73297 :       Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address);
     199       73297 :       if (Res) { IsSDWA = true;  break; }
     200             : 
     201       68397 :       Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address);
     202       68397 :       if (Res) { IsSDWA = true;  break; }
     203             : 
     204      119042 :       if (STI.getFeatureBits()[AMDGPU::FeatureUnpackedD16VMem]) {
     205       31723 :         Res = tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address);
     206       31723 :         if (Res)
     207             :           break;
     208             :       }
     209             : 
     210             :       // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and
     211             :       // v_mad_mixhi_f16 for FMA variants. Try to decode using this special
     212             :       // table first so we print the correct name.
     213      118738 :       if (STI.getFeatureBits()[AMDGPU::FeatureFmaMixInsts]) {
     214         354 :         Res = tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address);
     215         354 :         if (Res)
     216             :           break;
     217             :       }
     218             :     }
     219             : 
     220             :     // Reinitialize Bytes as DPP64 could have eaten too much
     221       59388 :     Bytes = Bytes_.slice(0, MaxInstBytesNum);
     222             : 
     223             :     // Try decode 32-bit instruction
     224       59388 :     if (Bytes.size() < 4) break;
     225             :     const uint32_t DW = eatBytes<uint32_t>(Bytes);
     226       59387 :     Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address);
     227       59387 :     if (Res) break;
     228             : 
     229       40291 :     Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address);
     230       40291 :     if (Res) break;
     231             : 
     232       38659 :     Res = tryDecodeInst(DecoderTableGFX932, MI, DW, Address);
     233       38659 :     if (Res) break;
     234             : 
     235       38519 :     if (Bytes.size() < 4) break;
     236       38518 :     const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
     237       38518 :     Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address);
     238       38518 :     if (Res) break;
     239             : 
     240        1015 :     Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address);
     241        1015 :     if (Res) break;
     242             : 
     243         887 :     Res = tryDecodeInst(DecoderTableGFX964, MI, QW, Address);
     244             :   } while (false);
     245             : 
     246       78701 :   if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
     247       78602 :               MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
     248       78515 :               MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ||
     249             :               MI.getOpcode() == AMDGPU::V_FMAC_F32_e64_vi)) {
     250             :     // Insert dummy unused src2_modifiers.
     251         220 :     insertNamedMCOperand(MI, MCOperand::createImm(0),
     252             :                          AMDGPU::OpName::src2_modifiers);
     253             :   }
     254             : 
     255       78701 :   if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG)) {
     256         305 :     Res = convertMIMGInst(MI);
     257             :   }
     258             : 
     259       78701 :   if (Res && IsSDWA)
     260       13776 :     Res = convertSDWAInst(MI);
     261             : 
     262             :   // if the opcode was not recognized we'll assume a Size of 4 bytes
     263             :   // (unless there are fewer bytes left)
     264       78707 :   Size = Res ? (MaxInstBytesNum - Bytes.size())
     265           6 :              : std::min((size_t)4, Bytes_.size());
     266       78701 :   return Res;
     267             : }
     268             : 
     269       13776 : DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
     270       27552 :   if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
     271        8876 :     if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst) != -1)
     272             :       // VOPC - insert clamp
     273        4650 :       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);
     274        4900 :   } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
     275        4900 :     int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);
     276        4900 :     if (SDst != -1) {
     277             :       // VOPC - insert VCC register as sdst
     278        2440 :       insertNamedMCOperand(MI, createRegOperand(AMDGPU::VCC),
     279             :                            AMDGPU::OpName::sdst);
     280             :     } else {
     281             :       // VOP1/2 - insert omod if present in instruction
     282        2460 :       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);
     283             :     }
     284             :   }
     285       13776 :   return MCDisassembler::Success;
     286             : }
     287             : 
     288             : // Note that MIMG format provides no information about VADDR size.
     289             : // Consequently, decoded instructions always show address
     290             : // as if it has 1 dword, which could be not really so.
     291         305 : DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
     292             : 
     293         305 :   int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
     294             :                                            AMDGPU::OpName::vdst);
     295             : 
     296         305 :   int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
     297             :                                             AMDGPU::OpName::vdata);
     298             : 
     299         305 :   int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
     300             :                                             AMDGPU::OpName::dmask);
     301             : 
     302         305 :   int TFEIdx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
     303             :                                             AMDGPU::OpName::tfe);
     304         305 :   int D16Idx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
     305             :                                             AMDGPU::OpName::d16);
     306             : 
     307             :   assert(VDataIdx != -1);
     308             :   assert(DMaskIdx != -1);
     309             :   assert(TFEIdx != -1);
     310             : 
     311             :   bool IsAtomic = (VDstIdx != -1);
     312         305 :   bool IsGather4 = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::Gather4;
     313             : 
     314         305 :   unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;
     315         305 :   if (DMask == 0)
     316             :     return MCDisassembler::Success;
     317             : 
     318         301 :   unsigned DstSize = IsGather4 ? 4 : countPopulation(DMask);
     319         287 :   if (DstSize == 1)
     320             :     return MCDisassembler::Success;
     321             : 
     322         111 :   bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm();
     323          20 :   if (D16 && AMDGPU::hasPackedD16(STI)) {
     324          10 :     DstSize = (DstSize + 1) / 2;
     325             :   }
     326             : 
     327             :   // FIXME: Add tfe support
     328         222 :   if (MI.getOperand(TFEIdx).getImm())
     329             :     return MCDisassembler::Success;
     330             : 
     331             :   int NewOpcode = -1;
     332             : 
     333         109 :   if (IsGather4) {
     334          12 :     if (D16 && AMDGPU::hasPackedD16(STI))
     335           1 :       NewOpcode = AMDGPU::getMaskedMIMGOp(MI.getOpcode(), 2);
     336             :     else
     337          11 :       return MCDisassembler::Success;
     338             :   } else {
     339          97 :     NewOpcode = AMDGPU::getMaskedMIMGOp(MI.getOpcode(), DstSize);
     340          97 :     if (NewOpcode == -1)
     341             :       return MCDisassembler::Success;
     342             :   }
     343             : 
     344          92 :   auto RCID = MCII->get(NewOpcode).OpInfo[VDataIdx].RegClass;
     345             : 
     346             :   // Get first subregister of VData
     347          92 :   unsigned Vdata0 = MI.getOperand(VDataIdx).getReg();
     348          92 :   unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0);
     349          92 :   Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;
     350             : 
     351             :   // Widen the register to the correct number of enabled channels.
     352          92 :   auto NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,
     353          92 :                                           &MRI.getRegClass(RCID));
     354          92 :   if (NewVdata == AMDGPU::NoRegister) {
     355             :     // It's possible to encode this such that the low register + enabled
     356             :     // components exceeds the register count.
     357             :     return MCDisassembler::Success;
     358             :   }
     359             : 
     360             :   MI.setOpcode(NewOpcode);
     361             :   // vaddr will be always appear as a single VGPR. This will look different than
     362             :   // how it is usually emitted because the number of register components is not
     363             :   // in the instruction encoding.
     364          85 :   MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);
     365             : 
     366          85 :   if (IsAtomic) {
     367             :     // Atomic operations have an additional operand (a copy of data)
     368          58 :     MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata);
     369             :   }
     370             : 
     371             :   return MCDisassembler::Success;
     372             : }
     373             : 
     374           0 : const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
     375           0 :   return getContext().getRegisterInfo()->
     376           0 :     getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
     377             : }
     378             : 
     379             : inline
     380           0 : MCOperand AMDGPUDisassembler::errOperand(unsigned V,
     381             :                                          const Twine& ErrMsg) const {
     382           0 :   *CommentStream << "Error: " + ErrMsg;
     383             : 
     384             :   // ToDo: add support for error operands to MCInst.h
     385             :   // return MCOperand::createError(V);
     386           0 :   return MCOperand();
     387             : }
     388             : 
     389             : inline
     390           0 : MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
     391        2440 :   return MCOperand::createReg(AMDGPU::getMCReg(RegId, STI));
     392             : }
     393             : 
     394             : inline
     395      180726 : MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
     396             :                                                unsigned Val) const {
     397      180726 :   const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
     398      361452 :   if (Val >= RegCl.getNumRegs())
     399           0 :     return errOperand(Val, Twine(getRegClassName(RegClassID)) +
     400           0 :                            ": unknown register " + Twine(Val));
     401      361452 :   return createRegOperand(RegCl.getRegister(Val));
     402             : }
     403             : 
     404             : inline
     405       44287 : MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
     406             :                                                 unsigned Val) const {
     407             :   // ToDo: SI/CI have 104 SGPRs, VI - 102
     408             :   // Valery: here we accepting as much as we can, let assembler sort it out
     409             :   int shift = 0;
     410             :   switch (SRegClassID) {
     411             :   case AMDGPU::SGPR_32RegClassID:
     412             :   case AMDGPU::TTMP_32RegClassID:
     413             :     break;
     414             :   case AMDGPU::SGPR_64RegClassID:
     415             :   case AMDGPU::TTMP_64RegClassID:
     416             :     shift = 1;
     417             :     break;
     418             :   case AMDGPU::SGPR_128RegClassID:
     419             :   case AMDGPU::TTMP_128RegClassID:
     420             :   // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
     421             :   // this bundle?
     422             :   case AMDGPU::SGPR_256RegClassID:
     423             :   case AMDGPU::TTMP_256RegClassID:
     424             :     // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
     425             :   // this bundle?
     426             :   case AMDGPU::SGPR_512RegClassID:
     427             :   case AMDGPU::TTMP_512RegClassID:
     428             :     shift = 2;
     429             :     break;
     430             :   // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
     431             :   // this bundle?
     432           0 :   default:
     433           0 :     llvm_unreachable("unhandled register class");
     434             :   }
     435             : 
     436       44287 :   if (Val % (1 << shift)) {
     437           0 :     *CommentStream << "Warning: " << getRegClassName(SRegClassID)
     438           0 :                    << ": scalar reg isn't aligned " << Val;
     439             :   }
     440             : 
     441       44287 :   return createRegOperand(SRegClassID, Val >> shift);
     442             : }
     443             : 
     444       39854 : MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const {
     445       39854 :   return decodeSrcOp(OPW32, Val);
     446             : }
     447             : 
     448       14584 : MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const {
     449       14584 :   return decodeSrcOp(OPW64, Val);
     450             : }
     451             : 
     452          59 : MCOperand AMDGPUDisassembler::decodeOperand_VS_128(unsigned Val) const {
     453          59 :   return decodeSrcOp(OPW128, Val);
     454             : }
     455             : 
     456       24450 : MCOperand AMDGPUDisassembler::decodeOperand_VSrc16(unsigned Val) const {
     457       24450 :   return decodeSrcOp(OPW16, Val);
     458             : }
     459             : 
     460        1999 : MCOperand AMDGPUDisassembler::decodeOperand_VSrcV216(unsigned Val) const {
     461        1999 :   return decodeSrcOp(OPWV216, Val);
     462             : }
     463             : 
     464       60495 : MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const {
     465             :   // Some instructions have operand restrictions beyond what the encoding
     466             :   // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra
     467             :   // high bit.
     468       60495 :   Val &= 255;
     469             : 
     470       60495 :   return createRegOperand(AMDGPU::VGPR_32RegClassID, Val);
     471             : }
     472             : 
     473        7500 : MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const {
     474        7500 :   return createRegOperand(AMDGPU::VReg_64RegClassID, Val);
     475             : }
     476             : 
     477         256 : MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const {
     478         256 :   return createRegOperand(AMDGPU::VReg_96RegClassID, Val);
     479             : }
     480             : 
     481         460 : MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const {
     482         460 :   return createRegOperand(AMDGPU::VReg_128RegClassID, Val);
     483             : }
     484             : 
     485       17209 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const {
     486             :   // table-gen generated disassembler doesn't care about operand types
     487             :   // leaving only registry class so SSrc_32 operand turns into SReg_32
     488             :   // and therefore we accept immediates and literals here as well
     489       17209 :   return decodeSrcOp(OPW32, Val);
     490             : }
     491             : 
     492         208 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0_XEXEC(
     493             :   unsigned Val) const {
     494             :   // SReg_32_XM0 is SReg_32 without M0 or EXEC_LO/EXEC_HI
     495         208 :   return decodeOperand_SReg_32(Val);
     496             : }
     497             : 
     498         270 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XEXEC_HI(
     499             :   unsigned Val) const {
     500             :   // SReg_32_XM0 is SReg_32 without EXEC_HI
     501         270 :   return decodeOperand_SReg_32(Val);
     502             : }
     503             : 
     504       21588 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const {
     505       21588 :   return decodeSrcOp(OPW64, Val);
     506             : }
     507             : 
     508         403 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_64_XEXEC(unsigned Val) const {
     509         403 :   return decodeSrcOp(OPW64, Val);
     510             : }
     511             : 
     512        2712 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const {
     513        2712 :   return decodeSrcOp(OPW128, Val);
     514             : }
     515             : 
     516         391 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const {
     517         391 :   return decodeDstOp(OPW256, Val);
     518             : }
     519             : 
     520          76 : MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const {
     521          76 :   return decodeDstOp(OPW512, Val);
     522             : }
     523             : 
     524        1999 : MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
     525             :   // For now all literal constants are supposed to be unsigned integer
     526             :   // ToDo: deal with signed/unsigned 64-bit integer constants
     527             :   // ToDo: deal with float/double constants
     528        1999 :   if (!HasLiteral) {
     529        1998 :     if (Bytes.size() < 4) {
     530           0 :       return errOperand(0, "cannot read literal, inst bytes left " +
     531           0 :                         Twine(Bytes.size()));
     532             :     }
     533        1998 :     HasLiteral = true;
     534        1998 :     Literal = eatBytes<uint32_t>(Bytes);
     535             :   }
     536        1999 :   return MCOperand::createImm(Literal);
     537             : }
     538             : 
     539        6087 : MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
     540             :   using namespace AMDGPU::EncValues;
     541             : 
     542             :   assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
     543             :   return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
     544        3074 :     (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
     545        6087 :     (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
     546             :       // Cast prevents negative overflow.
     547             : }
     548             : 
     549             : static int64_t getInlineImmVal32(unsigned Imm) {
     550             :   switch (Imm) {
     551             :   case 240:
     552             :     return FloatToBits(0.5f);
     553             :   case 241:
     554             :     return FloatToBits(-0.5f);
     555             :   case 242:
     556             :     return FloatToBits(1.0f);
     557             :   case 243:
     558             :     return FloatToBits(-1.0f);
     559             :   case 244:
     560             :     return FloatToBits(2.0f);
     561             :   case 245:
     562             :     return FloatToBits(-2.0f);
     563             :   case 246:
     564             :     return FloatToBits(4.0f);
     565             :   case 247:
     566             :     return FloatToBits(-4.0f);
     567             :   case 248: // 1 / (2 * PI)
     568             :     return 0x3e22f983;
     569           0 :   default:
     570           0 :     llvm_unreachable("invalid fp inline imm");
     571             :   }
     572             : }
     573             : 
     574             : static int64_t getInlineImmVal64(unsigned Imm) {
     575             :   switch (Imm) {
     576             :   case 240:
     577             :     return DoubleToBits(0.5);
     578             :   case 241:
     579             :     return DoubleToBits(-0.5);
     580             :   case 242:
     581             :     return DoubleToBits(1.0);
     582             :   case 243:
     583             :     return DoubleToBits(-1.0);
     584             :   case 244:
     585             :     return DoubleToBits(2.0);
     586             :   case 245:
     587             :     return DoubleToBits(-2.0);
     588             :   case 246:
     589             :     return DoubleToBits(4.0);
     590             :   case 247:
     591             :     return DoubleToBits(-4.0);
     592             :   case 248: // 1 / (2 * PI)
     593             :     return 0x3fc45f306dc9c882;
     594           0 :   default:
     595           0 :     llvm_unreachable("invalid fp inline imm");
     596             :   }
     597             : }
     598             : 
     599             : static int64_t getInlineImmVal16(unsigned Imm) {
     600             :   switch (Imm) {
     601             :   case 240:
     602             :     return 0x3800;
     603             :   case 241:
     604             :     return 0xB800;
     605             :   case 242:
     606             :     return 0x3C00;
     607             :   case 243:
     608             :     return 0xBC00;
     609             :   case 244:
     610             :     return 0x4000;
     611             :   case 245:
     612             :     return 0xC000;
     613             :   case 246:
     614             :     return 0x4400;
     615             :   case 247:
     616             :     return 0xC400;
     617             :   case 248: // 1 / (2 * PI)
     618             :     return 0x3118;
     619           0 :   default:
     620           0 :     llvm_unreachable("invalid fp inline imm");
     621             :   }
     622             : }
     623             : 
     624        6029 : MCOperand AMDGPUDisassembler::decodeFPImmed(OpWidthTy Width, unsigned Imm) {
     625             :   assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
     626             :       && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
     627             : 
     628             :   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
     629        6029 :   switch (Width) {
     630             :   case OPW32:
     631             :     return MCOperand::createImm(getInlineImmVal32(Imm));
     632             :   case OPW64:
     633             :     return MCOperand::createImm(getInlineImmVal64(Imm));
     634             :   case OPW16:
     635             :   case OPWV216:
     636             :     return MCOperand::createImm(getInlineImmVal16(Imm));
     637           0 :   default:
     638           0 :     llvm_unreachable("implement me");
     639             :   }
     640             : }
     641             : 
     642       67728 : unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
     643             :   using namespace AMDGPU;
     644             : 
     645             :   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
     646       67728 :   switch (Width) {
     647             :   default: // fall
     648             :   case OPW32:
     649             :   case OPW16:
     650             :   case OPWV216:
     651             :     return VGPR_32RegClassID;
     652        8448 :   case OPW64: return VReg_64RegClassID;
     653          59 :   case OPW128: return VReg_128RegClassID;
     654             :   }
     655             : }
     656             : 
     657       42515 : unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
     658             :   using namespace AMDGPU;
     659             : 
     660             :   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
     661             :   switch (Width) {
     662             :   default: // fall
     663             :   case OPW32:
     664             :   case OPW16:
     665             :   case OPWV216:
     666             :     return SGPR_32RegClassID;
     667             :   case OPW64: return SGPR_64RegClassID;
     668             :   case OPW128: return SGPR_128RegClassID;
     669             :   case OPW256: return SGPR_256RegClassID;
     670             :   case OPW512: return SGPR_512RegClassID;
     671             :   }
     672             : }
     673             : 
     674        1772 : unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
     675             :   using namespace AMDGPU;
     676             : 
     677             :   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
     678             :   switch (Width) {
     679             :   default: // fall
     680             :   case OPW32:
     681             :   case OPW16:
     682             :   case OPWV216:
     683             :     return TTMP_32RegClassID;
     684             :   case OPW64: return TTMP_64RegClassID;
     685             :   case OPW128: return TTMP_128RegClassID;
     686             :   case OPW256: return TTMP_256RegClassID;
     687             :   case OPW512: return TTMP_512RegClassID;
     688             :   }
     689             : }
     690             : 
     691       43331 : int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const {
     692             :   using namespace AMDGPU::EncValues;
     693             : 
     694       43331 :   unsigned TTmpMin = isGFX9() ? TTMP_GFX9_MIN : TTMP_VI_MIN;
     695       43331 :   unsigned TTmpMax = isGFX9() ? TTMP_GFX9_MAX : TTMP_VI_MAX;
     696             : 
     697       43331 :   return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1;
     698             : }
     699             : 
     700      122858 : MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const {
     701             :   using namespace AMDGPU::EncValues;
     702             : 
     703             :   assert(Val < 512); // enum9
     704             : 
     705      122858 :   if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
     706       46816 :     return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN);
     707             :   }
     708       76042 :   if (Val <= SGPR_MAX) {
     709             :     assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
     710       37239 :     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
     711             :   }
     712             : 
     713       38803 :   int TTmpIdx = getTTmpIdx(Val);
     714       38803 :   if (TTmpIdx >= 0) {
     715        1741 :     return createSRegOperand(getTtmpClassId(Width), TTmpIdx);
     716             :   }
     717             : 
     718       37062 :   if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
     719        5598 :     return decodeIntImmed(Val);
     720             : 
     721       31464 :   if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
     722        5545 :     return decodeFPImmed(Width, Val);
     723             : 
     724       25919 :   if (Val == LITERAL_CONST)
     725        1999 :     return decodeLiteralConstant();
     726             : 
     727       23920 :   switch (Width) {
     728       19539 :   case OPW32:
     729             :   case OPW16:
     730             :   case OPWV216:
     731       19539 :     return decodeSpecialReg32(Val);
     732        4381 :   case OPW64:
     733        4381 :     return decodeSpecialReg64(Val);
     734           0 :   default:
     735           0 :     llvm_unreachable("unexpected immediate type");
     736             :   }
     737             : }
     738             : 
     739         467 : MCOperand AMDGPUDisassembler::decodeDstOp(const OpWidthTy Width, unsigned Val) const {
     740             :   using namespace AMDGPU::EncValues;
     741             : 
     742             :   assert(Val < 128);
     743             :   assert(Width == OPW256 || Width == OPW512);
     744             : 
     745         467 :   if (Val <= SGPR_MAX) {
     746             :     assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
     747         439 :     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
     748             :   }
     749             : 
     750          28 :   int TTmpIdx = getTTmpIdx(Val);
     751          28 :   if (TTmpIdx >= 0) {
     752          28 :     return createSRegOperand(getTtmpClassId(Width), TTmpIdx);
     753             :   }
     754             : 
     755           0 :   llvm_unreachable("unknown dst register");
     756             : }
     757             : 
     758       21171 : MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
     759             :   using namespace AMDGPU;
     760             : 
     761       21171 :   switch (Val) {
     762        2448 :   case 102: return createRegOperand(FLAT_SCR_LO);
     763        2446 :   case 103: return createRegOperand(FLAT_SCR_HI);
     764           1 :   case 104: return createRegOperand(XNACK_MASK_LO);
     765           2 :   case 105: return createRegOperand(XNACK_MASK_HI);
     766        2439 :   case 106: return createRegOperand(VCC_LO);
     767        2439 :   case 107: return createRegOperand(VCC_HI);
     768        1007 :   case 108: assert(!isGFX9()); return createRegOperand(TBA_LO);
     769        1007 :   case 109: assert(!isGFX9()); return createRegOperand(TBA_HI);
     770        1009 :   case 110: assert(!isGFX9()); return createRegOperand(TMA_LO);
     771        1008 :   case 111: assert(!isGFX9()); return createRegOperand(TMA_HI);
     772        2620 :   case 124: return createRegOperand(M0);
     773        2372 :   case 126: return createRegOperand(EXEC_LO);
     774        2369 :   case 127: return createRegOperand(EXEC_HI);
     775           1 :   case 235: return createRegOperand(SRC_SHARED_BASE);
     776           1 :   case 236: return createRegOperand(SRC_SHARED_LIMIT);
     777           1 :   case 237: return createRegOperand(SRC_PRIVATE_BASE);
     778           1 :   case 238: return createRegOperand(SRC_PRIVATE_LIMIT);
     779             :     // TODO: SRC_POPS_EXITING_WAVE_ID
     780             :     // ToDo: no support for vccz register
     781             :   case 251: break;
     782             :     // ToDo: no support for execz register
     783             :   case 252: break;
     784           0 :   case 253: return createRegOperand(SCC);
     785             :   default: break;
     786             :   }
     787           0 :   return errOperand(Val, "unknown operand encoding " + Twine(Val));
     788             : }
     789             : 
     790        4515 : MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
     791             :   using namespace AMDGPU;
     792             : 
     793        4515 :   switch (Val) {
     794        1266 :   case 102: return createRegOperand(FLAT_SCR);
     795           2 :   case 104: return createRegOperand(XNACK_MASK);
     796        1339 :   case 106: return createRegOperand(VCC);
     797         569 :   case 108: assert(!isGFX9()); return createRegOperand(TBA);
     798         569 :   case 110: assert(!isGFX9()); return createRegOperand(TMA);
     799         770 :   case 126: return createRegOperand(EXEC);
     800             :   default: break;
     801             :   }
     802           0 :   return errOperand(Val, "unknown operand encoding " + Twine(Val));
     803             : }
     804             : 
     805       23991 : MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
     806             :                                             const unsigned Val) const {
     807             :   using namespace AMDGPU::SDWA;
     808             :   using namespace AMDGPU::EncValues;
     809             : 
     810       47982 :   if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
     811             :     // XXX: static_cast<int> is needed to avoid stupid warning:
     812             :     // compare with unsigned is always true
     813       15327 :     if (SDWA9EncValues::SRC_VGPR_MIN <= static_cast<int>(Val) &&
     814             :         Val <= SDWA9EncValues::SRC_VGPR_MAX) {
     815             :       return createRegOperand(getVgprClassId(Width),
     816       12248 :                               Val - SDWA9EncValues::SRC_VGPR_MIN);
     817             :     }
     818        3079 :     if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
     819             :         Val <= SDWA9EncValues::SRC_SGPR_MAX) {
     820             :       return createSRegOperand(getSgprClassId(Width),
     821         472 :                                Val - SDWA9EncValues::SRC_SGPR_MIN);
     822             :     }
     823        2607 :     if (SDWA9EncValues::SRC_TTMP_MIN <= Val &&
     824             :         Val <= SDWA9EncValues::SRC_TTMP_MAX) {
     825             :       return createSRegOperand(getTtmpClassId(Width),
     826           2 :                                Val - SDWA9EncValues::SRC_TTMP_MIN);
     827             :     }
     828             : 
     829             :     const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;
     830             : 
     831        2605 :     if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX)
     832         489 :       return decodeIntImmed(SVal);
     833             : 
     834        2116 :     if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX)
     835         484 :       return decodeFPImmed(Width, SVal);
     836             : 
     837        1632 :     return decodeSpecialReg32(SVal);
     838        8664 :   } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
     839        8664 :     return createRegOperand(getVgprClassId(Width), Val);
     840             :   }
     841           0 :   llvm_unreachable("unsupported target");
     842             : }
     843             : 
     844       10668 : MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
     845       10668 :   return decodeSDWASrc(OPW16, Val);
     846             : }
     847             : 
     848       13323 : MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
     849       13323 :   return decodeSDWASrc(OPW32, Val);
     850             : }
     851             : 
     852        4650 : MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
     853             :   using namespace AMDGPU::SDWA;
     854             : 
     855             :   assert(STI.getFeatureBits()[AMDGPU::FeatureGFX9] &&
     856             :          "SDWAVopcDst should be present only on GFX9");
     857        4650 :   if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
     858        4500 :     Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
     859             : 
     860        4500 :     int TTmpIdx = getTTmpIdx(Val);
     861        4500 :     if (TTmpIdx >= 0) {
     862           1 :       return createSRegOperand(getTtmpClassId(OPW64), TTmpIdx);
     863        4499 :     } else if (Val > AMDGPU::EncValues::SGPR_MAX) {
     864         134 :       return decodeSpecialReg64(Val);
     865             :     } else {
     866        4365 :       return createSRegOperand(getSgprClassId(OPW64), Val);
     867             :     }
     868             :   } else {
     869         150 :     return createRegOperand(AMDGPU::VCC);
     870             :   }
     871             : }
     872             : 
     873           0 : bool AMDGPUDisassembler::isVI() const {
     874           0 :   return STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands];
     875             : }
     876             : 
     877       86662 : bool AMDGPUDisassembler::isGFX9() const {
     878      173324 :   return STI.getFeatureBits()[AMDGPU::FeatureGFX9];
     879             : }
     880             : 
     881             : //===----------------------------------------------------------------------===//
     882             : // AMDGPUSymbolizer
     883             : //===----------------------------------------------------------------------===//
     884             : 
     885             : // Try to find symbol name for specified label
     886           5 : bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,
     887             :                                 raw_ostream &/*cStream*/, int64_t Value,
     888             :                                 uint64_t /*Address*/, bool IsBranch,
     889             :                                 uint64_t /*Offset*/, uint64_t /*InstSize*/) {
     890             :   using SymbolInfoTy = std::tuple<uint64_t, StringRef, uint8_t>;
     891             :   using SectionSymbolsTy = std::vector<SymbolInfoTy>;
     892             : 
     893           5 :   if (!IsBranch) {
     894             :     return false;
     895             :   }
     896             : 
     897           5 :   auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
     898           5 :   if (!Symbols)
     899             :     return false;
     900             : 
     901             :   auto Result = std::find_if(Symbols->begin(), Symbols->end(),
     902             :                              [Value](const SymbolInfoTy& Val) {
     903           0 :                                 return std::get<0>(Val) == static_cast<uint64_t>(Value)
     904           0 :                                     && std::get<2>(Val) == ELF::STT_NOTYPE;
     905             :                              });
     906           5 :   if (Result != Symbols->end()) {
     907           6 :     auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result));
     908           3 :     const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
     909           3 :     Inst.addOperand(MCOperand::createExpr(Add));
     910           3 :     return true;
     911             :   }
     912             :   return false;
     913             : }
     914             : 
     915           0 : void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
     916             :                                                        int64_t Value,
     917             :                                                        uint64_t Address) {
     918           0 :   llvm_unreachable("unimplemented");
     919             : }
     920             : 
     921             : //===----------------------------------------------------------------------===//
     922             : // Initialization
     923             : //===----------------------------------------------------------------------===//
     924             : 
     925           8 : static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
     926             :                               LLVMOpInfoCallback /*GetOpInfo*/,
     927             :                               LLVMSymbolLookupCallback /*SymbolLookUp*/,
     928             :                               void *DisInfo,
     929             :                               MCContext *Ctx,
     930             :                               std::unique_ptr<MCRelocationInfo> &&RelInfo) {
     931           8 :   return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
     932             : }
     933             : 
     934          56 : static MCDisassembler *createAMDGPUDisassembler(const Target &T,
     935             :                                                 const MCSubtargetInfo &STI,
     936             :                                                 MCContext &Ctx) {
     937         112 :   return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());
     938             : }
     939             : 
     940       10844 : extern "C" void LLVMInitializeAMDGPUDisassembler() {
     941       10844 :   TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
     942             :                                          createAMDGPUDisassembler);
     943       10844 :   TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
     944             :                                        createAMDGPUSymbolizer);
     945       10844 : }

Generated by: LCOV version 1.13