diff options
Diffstat (limited to 'lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp')
| -rw-r--r-- | lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp | 107 | 
1 files changed, 95 insertions, 12 deletions
diff --git a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp index 47a2d3f2fdc5..f3de903f21b2 100644 --- a/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ b/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -20,7 +20,9 @@  #include "Disassembler/AMDGPUDisassembler.h"  #include "AMDGPU.h"  #include "AMDGPURegisterInfo.h" +#include "MCTargetDesc/AMDGPUMCTargetDesc.h"  #include "SIDefines.h" +#include "MCTargetDesc/AMDGPUMCTargetDesc.h"  #include "Utils/AMDGPUBaseInfo.h"  #include "llvm-c/Disassembler.h"  #include "llvm/ADT/APInt.h" @@ -198,6 +200,21 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,        Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address);        if (Res) { IsSDWA = true;  break; } + +      if (STI.getFeatureBits()[AMDGPU::FeatureUnpackedD16VMem]) { +        Res = tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address); +        if (Res) +          break; +      } + +      // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and +      // v_mad_mixhi_f16 for FMA variants. Try to decode using this special +      // table first so we print the correct name. +      if (STI.getFeatureBits()[AMDGPU::FeatureFmaMixInsts]) { +        Res = tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address); +        if (Res) +          break; +      }      }      // Reinitialize Bytes as DPP64 could have eaten too much @@ -228,7 +245,8 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,    if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||                MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si || -              MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi)) { +              MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi || +              MI.getOpcode() == AMDGPU::V_FMAC_F32_e64_vi)) {      // Insert dummy unused src2_modifiers.      insertNamedMCOperand(MI, MCOperand::createImm(0),                           AMDGPU::OpName::src2_modifiers); @@ -241,7 +259,10 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,    if (Res && IsSDWA)      Res = convertSDWAInst(MI); -  Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0; +  // if the opcode was not recognized we'll assume a Size of 4 bytes +  // (unless there are fewer bytes left) +  Size = Res ? (MaxInstBytesNum - Bytes.size()) +             : std::min((size_t)4, Bytes_.size());    return Res;  } @@ -264,26 +285,70 @@ DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {    return MCDisassembler::Success;  } +// Note that MIMG format provides no information about VADDR size. +// Consequently, decoded instructions always show address +// as if it has 1 dword, which could be not really so.  DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { + +  int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), +                                           AMDGPU::OpName::vdst); +    int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),                                              AMDGPU::OpName::vdata);    int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),                                              AMDGPU::OpName::dmask); + +  int TFEIdx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(), +                                            AMDGPU::OpName::tfe); +  int D16Idx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(), +                                            AMDGPU::OpName::d16); + +  assert(VDataIdx != -1); +  assert(DMaskIdx != -1); +  assert(TFEIdx != -1); + +  bool IsAtomic = (VDstIdx != -1); +  bool IsGather4 = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::Gather4; +    unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;    if (DMask == 0)      return MCDisassembler::Success; -  unsigned ChannelCount = countPopulation(DMask); -  if (ChannelCount == 1) +  unsigned DstSize = IsGather4 ? 4 : countPopulation(DMask); +  if (DstSize == 1)      return MCDisassembler::Success; -  int NewOpcode = AMDGPU::getMaskedMIMGOp(*MCII, MI.getOpcode(), ChannelCount); -  assert(NewOpcode != -1 && "could not find matching mimg channel instruction"); +  bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm(); +  if (D16 && AMDGPU::hasPackedD16(STI)) { +    DstSize = (DstSize + 1) / 2; +  } + +  // FIXME: Add tfe support +  if (MI.getOperand(TFEIdx).getImm()) +    return MCDisassembler::Success; + +  int NewOpcode = -1; + +  if (IsGather4) { +    if (D16 && AMDGPU::hasPackedD16(STI)) +      NewOpcode = AMDGPU::getMaskedMIMGOp(MI.getOpcode(), 2); +    else +      return MCDisassembler::Success; +  } else { +    NewOpcode = AMDGPU::getMaskedMIMGOp(MI.getOpcode(), DstSize); +    if (NewOpcode == -1) +      return MCDisassembler::Success; +  } +    auto RCID = MCII->get(NewOpcode).OpInfo[VDataIdx].RegClass; -  // Widen the register to the correct number of enabled channels. +  // Get first subregister of VData    unsigned Vdata0 = MI.getOperand(VDataIdx).getReg(); +  unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0); +  Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0; + +  // Widen the register to the correct number of enabled channels.    auto NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,                                            &MRI.getRegClass(RCID));    if (NewVdata == AMDGPU::NoRegister) { @@ -297,6 +362,12 @@ DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {    // how it is usually emitted because the number of register components is not    // in the instruction encoding.    MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata); + +  if (IsAtomic) { +    // Atomic operations have an additional operand (a copy of data) +    MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata); +  } +    return MCDisassembler::Success;  } @@ -690,9 +761,8 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {    switch (Val) {    case 102: return createRegOperand(FLAT_SCR_LO);    case 103: return createRegOperand(FLAT_SCR_HI); -    // ToDo: no support for xnack_mask_lo/_hi register -  case 104: -  case 105: break; +  case 104: return createRegOperand(XNACK_MASK_LO); +  case 105: return createRegOperand(XNACK_MASK_HI);    case 106: return createRegOperand(VCC_LO);    case 107: return createRegOperand(VCC_HI);    case 108: assert(!isGFX9()); return createRegOperand(TBA_LO); @@ -722,6 +792,7 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {    switch (Val) {    case 102: return createRegOperand(FLAT_SCR); +  case 104: return createRegOperand(XNACK_MASK);    case 106: return createRegOperand(VCC);    case 108: assert(!isGFX9()); return createRegOperand(TBA);    case 110: assert(!isGFX9()); return createRegOperand(TMA); @@ -732,8 +803,9 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {  }  MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width, -                                            unsigned Val) const { +                                            const unsigned Val) const {    using namespace AMDGPU::SDWA; +  using namespace AMDGPU::EncValues;    if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {      // XXX: static_cast<int> is needed to avoid stupid warning: @@ -754,7 +826,15 @@ MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,                                 Val - SDWA9EncValues::SRC_TTMP_MIN);      } -    return decodeSpecialReg32(Val - SDWA9EncValues::SRC_SGPR_MIN); +    const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN; + +    if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX) +      return decodeIntImmed(SVal); + +    if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX) +      return decodeFPImmed(Width, SVal); + +    return decodeSpecialReg32(SVal);    } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {      return createRegOperand(getVgprClassId(Width), Val);    } @@ -815,6 +895,9 @@ bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,    }    auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo); +  if (!Symbols) +    return false; +    auto Result = std::find_if(Symbols->begin(), Symbols->end(),                               [Value](const SymbolInfoTy& Val) {                                  return std::get<0>(Val) == static_cast<uint64_t>(Value)  | 
