//===- HexagonMCInstrInfo.cpp - Hexagon sub-class of MCInst ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This class extends MCInstrInfo to allow Hexagon specific MCInstr queries
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCChecker.h"
#include "MCTargetDesc/HexagonMCExpr.h"
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstdint>
#include <limits>

using namespace llvm;

bool HexagonMCInstrInfo::PredicateInfo::isPredicated() const {
  return Register != Hexagon::NoRegister;
}

Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
                                        MCInst const &Inst)
    : MCII(MCII), BundleCurrent(Inst.begin() +
                                HexagonMCInstrInfo::bundleInstructionsOffset),
      BundleEnd(Inst.end()), DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {}

Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
                                        MCInst const &Inst, std::nullptr_t)
    : MCII(MCII), BundleCurrent(Inst.end()), BundleEnd(Inst.end()),
      DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {}

Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() {
  if (DuplexCurrent != DuplexEnd) {
    ++DuplexCurrent;
    if (DuplexCurrent == DuplexEnd) {
      DuplexCurrent = BundleEnd;
      DuplexEnd = BundleEnd;
      ++BundleCurrent;
    }
    return *this;
  }
  ++BundleCurrent;
  if (BundleCurrent != BundleEnd) {
    MCInst const &Inst = *BundleCurrent->getInst();
    if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
      DuplexCurrent = Inst.begin();
      DuplexEnd = Inst.end();
    }
  }
  return *this;
}

MCInst const &Hexagon::PacketIterator::operator*() const {
  if (DuplexCurrent != DuplexEnd)
    return *DuplexCurrent->getInst();
  return *BundleCurrent->getInst();
}

bool Hexagon::PacketIterator::operator==(PacketIterator const &Other) const {
  return BundleCurrent == Other.BundleCurrent && BundleEnd == Other.BundleEnd &&
         DuplexCurrent == Other.DuplexCurrent && DuplexEnd == Other.DuplexEnd;
}

void HexagonMCInstrInfo::addConstant(MCInst &MI, uint64_t Value,
                                     MCContext &Context) {
  MI.addOperand(MCOperand::createExpr(MCConstantExpr::create(Value, Context)));
}

void HexagonMCInstrInfo::addConstExtender(MCContext &Context,
                                          MCInstrInfo const &MCII, MCInst &MCB,
                                          MCInst const &MCI) {
  assert(HexagonMCInstrInfo::isBundle(MCB));
  MCOperand const &exOp =
      MCI.getOperand(HexagonMCInstrInfo::getExtendableOp(MCII, MCI));

  // Create the extender.
  MCInst *XMCI =
      new (Context) MCInst(HexagonMCInstrInfo::deriveExtender(MCII, MCI, exOp));
  XMCI->setLoc(MCI.getLoc());

  MCB.addOperand(MCOperand::createInst(XMCI));
}

iterator_range<Hexagon::PacketIterator>
HexagonMCInstrInfo::bundleInstructions(MCInstrInfo const &MCII,
                                       MCInst const &MCI) {
  assert(isBundle(MCI));
  return make_range(Hexagon::PacketIterator(MCII, MCI),
                    Hexagon::PacketIterator(MCII, MCI, nullptr));
}

iterator_range<MCInst::const_iterator>
HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) {
  assert(isBundle(MCI));
  return make_range(MCI.begin() + bundleInstructionsOffset, MCI.end());
}

size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) {
  if (HexagonMCInstrInfo::isBundle(MCI))
    return (MCI.size() - bundleInstructionsOffset);
  else
    return (1);
}

bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
                                            MCSubtargetInfo const &STI,
                                            MCContext &Context, MCInst &MCB,
                                            HexagonMCChecker *Check) {
  // Check the bundle for errors.
  bool CheckOk = Check ? Check->check(false) : true;
  if (!CheckOk)
    return false;
  // Examine the packet and convert pairs of instructions to compound
  // instructions when possible.
  if (!HexagonDisableCompound)
    HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB);
  HexagonMCShuffle(Context, false, MCII, STI, MCB);
  // Examine the packet and convert pairs of instructions to duplex
  // instructions when possible.
  MCInst InstBundlePreDuplex = MCInst(MCB);
  if (STI.getFeatureBits() [Hexagon::FeatureDuplex]) {
    SmallVector<DuplexCandidate, 8> possibleDuplexes;
    possibleDuplexes =
        HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB);
    HexagonMCShuffle(Context, MCII, STI, MCB, possibleDuplexes);
  }
  // Examines packet and pad the packet, if needed, when an
  // end-loop is in the bundle.
  HexagonMCInstrInfo::padEndloop(MCB, Context);
  // If compounding and duplexing didn't reduce the size below
  // 4 or less we have a packet that is too big.
  if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE)
    return false;
  // Check the bundle for errors.
  CheckOk = Check ? Check->check(true) : true;
  if (!CheckOk)
    return false;
  HexagonMCShuffle(Context, true, MCII, STI, MCB);
  return true;
}

MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
                                          MCInst const &Inst,
                                          MCOperand const &MO) {
  assert(HexagonMCInstrInfo::isExtendable(MCII, Inst) ||
         HexagonMCInstrInfo::isExtended(MCII, Inst));

  MCInst XMI;
  XMI.setOpcode(Hexagon::A4_ext);
  if (MO.isImm())
    XMI.addOperand(MCOperand::createImm(MO.getImm() & (~0x3f)));
  else if (MO.isExpr())
    XMI.addOperand(MCOperand::createExpr(MO.getExpr()));
  else
    llvm_unreachable("invalid extendable operand");
  return XMI;
}

MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass,
                                         MCInst const &inst0,
                                         MCInst const &inst1) {
  assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf");
  MCInst *duplexInst = new (Context) MCInst;
  duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass);

  MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0));
  MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1));
  duplexInst->addOperand(MCOperand::createInst(SubInst0));
  duplexInst->addOperand(MCOperand::createInst(SubInst1));
  return duplexInst;
}

MCInst const *HexagonMCInstrInfo::extenderForIndex(MCInst const &MCB,
                                                   size_t Index) {
  assert(Index <= bundleSize(MCB));
  if (Index == 0)
    return nullptr;
  MCInst const *Inst =
      MCB.getOperand(Index + bundleInstructionsOffset - 1).getInst();
  if (isImmext(*Inst))
    return Inst;
  return nullptr;
}

void HexagonMCInstrInfo::extendIfNeeded(MCContext &Context,
                                        MCInstrInfo const &MCII, MCInst &MCB,
                                        MCInst const &MCI) {
  if (isConstExtended(MCII, MCI))
    addConstExtender(Context, MCII, MCB, MCI);
}

unsigned HexagonMCInstrInfo::getMemAccessSize(MCInstrInfo const &MCII,
      MCInst const &MCI) {
  uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  unsigned S = (F >> HexagonII::MemAccessSizePos) & HexagonII::MemAccesSizeMask;
  return HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(S));
}

unsigned HexagonMCInstrInfo::getAddrMode(MCInstrInfo const &MCII,
                                         MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return static_cast<unsigned>((F >> HexagonII::AddrModePos) &
                               HexagonII::AddrModeMask);
}

MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII,
                                               MCInst const &MCI) {
  return MCII.get(MCI.getOpcode());
}

unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) {
  using namespace Hexagon;

  switch (Reg) {
  default:
    llvm_unreachable("unknown duplex register");
  // Rs       Rss
  case R0:
  case D0:
    return 0;
  case R1:
  case D1:
    return 1;
  case R2:
  case D2:
    return 2;
  case R3:
  case D3:
    return 3;
  case R4:
  case D8:
    return 4;
  case R5:
  case D9:
    return 5;
  case R6:
  case D10:
    return 6;
  case R7:
  case D11:
    return 7;
  case R16:
    return 8;
  case R17:
    return 9;
  case R18:
    return 10;
  case R19:
    return 11;
  case R20:
    return 12;
  case R21:
    return 13;
  case R22:
    return 14;
  case R23:
    return 15;
  }
}

MCExpr const &HexagonMCInstrInfo::getExpr(MCExpr const &Expr) {
  const auto &HExpr = cast<HexagonMCExpr>(Expr);
  assert(HExpr.getExpr());
  return *HExpr.getExpr();
}

unsigned short HexagonMCInstrInfo::getExtendableOp(MCInstrInfo const &MCII,
                                                   MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
}

MCOperand const &
HexagonMCInstrInfo::getExtendableOperand(MCInstrInfo const &MCII,
                                         MCInst const &MCI) {
  unsigned O = HexagonMCInstrInfo::getExtendableOp(MCII, MCI);
  MCOperand const &MO = MCI.getOperand(O);

  assert((HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
          HexagonMCInstrInfo::isExtended(MCII, MCI)) &&
         (MO.isImm() || MO.isExpr()));
  return (MO);
}

unsigned HexagonMCInstrInfo::getExtentAlignment(MCInstrInfo const &MCII,
                                                MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::ExtentAlignPos) & HexagonII::ExtentAlignMask);
}

unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII,
                                           MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
}

bool HexagonMCInstrInfo::isExtentSigned(MCInstrInfo const &MCII,
                                        MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
}

/// Return the maximum value of an extendable operand.
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
                                    MCInst const &MCI) {
  assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
         HexagonMCInstrInfo::isExtended(MCII, MCI));

  if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed
    return (1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1)) - 1;
  return (1 << HexagonMCInstrInfo::getExtentBits(MCII, MCI)) - 1;
}

/// Return the minimum value of an extendable operand.
int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII,
                                    MCInst const &MCI) {
  assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
         HexagonMCInstrInfo::isExtended(MCII, MCI));

  if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed
    return -(1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1));
  return 0;
}

StringRef HexagonMCInstrInfo::getName(MCInstrInfo const &MCII,
                                      MCInst const &MCI) {
  return MCII.getName(MCI.getOpcode());
}

unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
                                                 MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask);
}

MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII,
                                                        MCInst const &MCI) {
  if (HexagonMCInstrInfo::hasTmpDst(MCII, MCI)) {
    // VTMP doesn't actually exist in the encodings for these 184
    // 3 instructions so go ahead and create it here.
    static MCOperand MCO = MCOperand::createReg(Hexagon::VTMP);
    return (MCO);
  } else {
    unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI);
    MCOperand const &MCO = MCI.getOperand(O);

    assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
            HexagonMCInstrInfo::hasNewValue(MCII, MCI)) &&
           MCO.isReg());
    return (MCO);
  }
}

/// Return the new value or the newly produced value.
unsigned short HexagonMCInstrInfo::getNewValueOp2(MCInstrInfo const &MCII,
                                                  MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::NewValueOpPos2) & HexagonII::NewValueOpMask2);
}

MCOperand const &
HexagonMCInstrInfo::getNewValueOperand2(MCInstrInfo const &MCII,
                                        MCInst const &MCI) {
  unsigned O = HexagonMCInstrInfo::getNewValueOp2(MCII, MCI);
  MCOperand const &MCO = MCI.getOperand(O);

  assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
          HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) &&
         MCO.isReg());
  return (MCO);
}

/// Return the Hexagon ISA class for the insn.
unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
                                     MCInst const &MCI) {
  const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
  return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
}

/// Return the slots this instruction can execute out of
unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
                                      MCSubtargetInfo const &STI,
                                      MCInst const &MCI) {
  const InstrItinerary *II = STI.getSchedModel().InstrItineraries;
  int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();
  return ((II[SchedClass].FirstStage + HexagonStages)->getUnits());
}

/// Return the slots this instruction consumes in addition to
/// the slot(s) it can execute out of

unsigned HexagonMCInstrInfo::getOtherReservedSlots(MCInstrInfo const &MCII,
                                                   MCSubtargetInfo const &STI,
                                                   MCInst const &MCI) {
  const InstrItinerary *II = STI.getSchedModel().InstrItineraries;
  int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();
  unsigned Slots = 0;

  // FirstStage are slots that this instruction can execute in.
  // FirstStage+1 are slots that are also consumed by this instruction.
  // For example: vmemu can only execute in slot 0 but also consumes slot 1.
  for (unsigned Stage = II[SchedClass].FirstStage + 1;
       Stage < II[SchedClass].LastStage; ++Stage) {
    unsigned Units = (Stage + HexagonStages)->getUnits();
    if (Units > HexagonGetLastSlot())
      break;
    // fyi: getUnits() will return 0x1, 0x2, 0x4 or 0x8
    Slots |= Units;
  }

  // if 0 is returned, then no additional slots are consumed by this inst.
  return Slots;
}

bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
  if (!HexagonMCInstrInfo::isBundle(MCI))
    return false;

  for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
    if (HexagonMCInstrInfo::isDuplex(MCII, *I.getInst()))
      return true;
  }

  return false;
}

bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
  return extenderForIndex(MCB, Index) != nullptr;
}

bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
  if (!HexagonMCInstrInfo::isBundle(MCI))
    return false;

  for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
    if (isImmext(*I.getInst()))
      return true;
  }

  return false;
}

/// Return whether the insn produces a value.
bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
                                     MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask);
}

/// Return whether the insn produces a second value.
bool HexagonMCInstrInfo::hasNewValue2(MCInstrInfo const &MCII,
                                      MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::hasNewValuePos2) & HexagonII::hasNewValueMask2);
}

MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) {
  assert(isBundle(MCB));
  assert(Index < HEXAGON_PACKET_SIZE);
  return *MCB.getOperand(bundleInstructionsOffset + Index).getInst();
}

/// Return where the instruction is an accumulator.
bool HexagonMCInstrInfo::isAccumulator(MCInstrInfo const &MCII,
                                       MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask);
}

bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) {
  auto Result = Hexagon::BUNDLE == MCI.getOpcode();
  assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm()));
  return Result;
}

bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
                                         MCInst const &MCI) {
  if (HexagonMCInstrInfo::isExtended(MCII, MCI))
    return true;
  if (!HexagonMCInstrInfo::isExtendable(MCII, MCI))
    return false;
  MCOperand const &MO = HexagonMCInstrInfo::getExtendableOperand(MCII, MCI);
  if (isa<HexagonMCExpr>(MO.getExpr()) &&
      HexagonMCInstrInfo::mustExtend(*MO.getExpr()))
    return true;
  // Branch insns are handled as necessary by relaxation.
  if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeJ) ||
      (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCJ &&
       HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()) ||
      (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ &&
       HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()))
    return false;
  // Otherwise loop instructions and other CR insts are handled by relaxation
  else if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCR) &&
           (MCI.getOpcode() != Hexagon::C4_addipc))
    return false;

  assert(!MO.isImm());
  if (isa<HexagonMCExpr>(MO.getExpr()) &&
      HexagonMCInstrInfo::mustNotExtend(*MO.getExpr()))
    return false;
  int64_t Value;
  if (!MO.getExpr()->evaluateAsAbsolute(Value))
    return true;
  int MinValue = HexagonMCInstrInfo::getMinValue(MCII, MCI);
  int MaxValue = HexagonMCInstrInfo::getMaxValue(MCII, MCI);
  return (MinValue > Value || Value > MaxValue);
}

bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
  return !HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
         !HexagonMCInstrInfo::isPrefix(MCII, MCI);
}

bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
}

bool HexagonMCInstrInfo::isCofRelax1(MCInstrInfo const &MCII,
                                     MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::CofRelax1Pos) & HexagonII::CofRelax1Mask);
}

bool HexagonMCInstrInfo::isCofRelax2(MCInstrInfo const &MCII,
                                     MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::CofRelax2Pos) & HexagonII::CofRelax2Mask);
}

bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
                                    MCInst const &MCI) {
  return (getType(MCII, MCI) == HexagonII::TypeCJ);
}

bool HexagonMCInstrInfo::isCVINew(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::CVINewPos) & HexagonII::CVINewMask);
}

bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) {
  return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) ||
          (Reg >= Hexagon::D8 && Reg <= Hexagon::D11));
}

bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
  return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI);
}

bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII,
                                      MCInst const &MCI) {
  uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
}

bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII,
                                    MCInst const &MCI) {
  uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
}

bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::FPPos) & HexagonII::FPMask);
}

bool HexagonMCInstrInfo::isHVX(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t V = getType(MCII, MCI);
  return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST;
}

bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) {
  return MCI.getOpcode() == Hexagon::A4_ext;
}

bool HexagonMCInstrInfo::isInnerLoop(MCInst const &MCI) {
  assert(isBundle(MCI));
  int64_t Flags = MCI.getOperand(0).getImm();
  return (Flags & innerLoopMask) != 0;
}

bool HexagonMCInstrInfo::isIntReg(unsigned Reg) {
  return (Reg >= Hexagon::R0 && Reg <= Hexagon::R31);
}

bool HexagonMCInstrInfo::isIntRegForSubInst(unsigned Reg) {
  return ((Reg >= Hexagon::R0 && Reg <= Hexagon::R7) ||
          (Reg >= Hexagon::R16 && Reg <= Hexagon::R23));
}

/// Return whether the insn expects newly produced value.
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
                                    MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask);
}

/// Return whether the operand is extendable.
bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII,
                                        MCInst const &MCI, unsigned short O) {
  return (O == HexagonMCInstrInfo::getExtendableOp(MCII, MCI));
}

bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) {
  assert(isBundle(MCI));
  int64_t Flags = MCI.getOperand(0).getImm();
  return (Flags & outerLoopMask) != 0;
}

bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII,
                                      MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask);
}

bool HexagonMCInstrInfo::isPrefix(MCInstrInfo const &MCII, MCInst const &MCI) {
  return HexagonII::TypeEXTENDER == HexagonMCInstrInfo::getType(MCII, MCI);
}

bool HexagonMCInstrInfo::isPredicateLate(MCInstrInfo const &MCII,
                                         MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::PredicateLatePos & HexagonII::PredicateLateMask);
}

/// Return whether the insn is newly predicated.
bool HexagonMCInstrInfo::isPredicatedNew(MCInstrInfo const &MCII,
                                         MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask);
}

bool HexagonMCInstrInfo::isPredicatedTrue(MCInstrInfo const &MCII,
                                          MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (
      !((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask));
}

bool HexagonMCInstrInfo::isPredReg(unsigned Reg) {
  return (Reg >= Hexagon::P0 && Reg <= Hexagon::P3_0);
}

/// Return whether the insn can be packaged only with A and X-type insns.
bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
}

/// Return whether the insn can be packaged only with an A-type insn in slot #1.
bool HexagonMCInstrInfo::isRestrictSlot1AOK(MCInstrInfo const &MCII,
                                            MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::RestrictSlot1AOKPos) &
          HexagonII::RestrictSlot1AOKMask);
}

bool HexagonMCInstrInfo::isRestrictNoSlot1Store(MCInstrInfo const &MCII,
                                                MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return ((F >> HexagonII::RestrictNoSlot1StorePos) &
          HexagonII::RestrictNoSlot1StoreMask);
}

/// Return whether the insn is solo, i.e., cannot be in a packet.
bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
  return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
}

bool HexagonMCInstrInfo::isMemReorderDisabled(MCInst const &MCI) {
  assert(isBundle(MCI));
  auto Flags = MCI.getOperand(0).getImm();
  return (Flags & memReorderDisabledMask) != 0;
}

bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) {
  switch (MCI.getOpcode()) {
  default:
    return false;
  case Hexagon::SA1_addi:
  case Hexagon::SA1_addrx:
  case Hexagon::SA1_addsp:
  case Hexagon::SA1_and1:
  case Hexagon::SA1_clrf:
  case Hexagon::SA1_clrfnew:
  case Hexagon::SA1_clrt:
  case Hexagon::SA1_clrtnew:
  case Hexagon::SA1_cmpeqi:
  case Hexagon::SA1_combine0i:
  case Hexagon::SA1_combine1i:
  case Hexagon::SA1_combine2i:
  case Hexagon::SA1_combine3i:
  case Hexagon::SA1_combinerz:
  case Hexagon::SA1_combinezr:
  case Hexagon::SA1_dec:
  case Hexagon::SA1_inc:
  case Hexagon::SA1_seti:
  case Hexagon::SA1_setin1:
  case Hexagon::SA1_sxtb:
  case Hexagon::SA1_sxth:
  case Hexagon::SA1_tfr:
  case Hexagon::SA1_zxtb:
  case Hexagon::SA1_zxth:
  case Hexagon::SL1_loadri_io:
  case Hexagon::SL1_loadrub_io:
  case Hexagon::SL2_deallocframe:
  case Hexagon::SL2_jumpr31:
  case Hexagon::SL2_jumpr31_f:
  case Hexagon::SL2_jumpr31_fnew:
  case Hexagon::SL2_jumpr31_t:
  case Hexagon::SL2_jumpr31_tnew:
  case Hexagon::SL2_loadrb_io:
  case Hexagon::SL2_loadrd_sp:
  case Hexagon::SL2_loadrh_io:
  case Hexagon::SL2_loadri_sp:
  case Hexagon::SL2_loadruh_io:
  case Hexagon::SL2_return:
  case Hexagon::SL2_return_f:
  case Hexagon::SL2_return_fnew:
  case Hexagon::SL2_return_t:
  case Hexagon::SL2_return_tnew:
  case Hexagon::SS1_storeb_io:
  case Hexagon::SS1_storew_io:
  case Hexagon::SS2_allocframe:
  case Hexagon::SS2_storebi0:
  case Hexagon::SS2_storebi1:
  case Hexagon::SS2_stored_sp:
  case Hexagon::SS2_storeh_io:
  case Hexagon::SS2_storew_sp:
  case Hexagon::SS2_storewi0:
  case Hexagon::SS2_storewi1:
    return true;
  }
}

bool HexagonMCInstrInfo::isVector(MCInstrInfo const &MCII, MCInst const &MCI) {
  if ((getType(MCII, MCI) <= HexagonII::TypeCVI_LAST) &&
      (getType(MCII, MCI) >= HexagonII::TypeCVI_FIRST))
    return true;
  return false;
}

int64_t HexagonMCInstrInfo::minConstant(MCInst const &MCI, size_t Index) {
  auto Sentinal = static_cast<int64_t>(std::numeric_limits<uint32_t>::max())
                  << 8;
  if (MCI.size() <= Index)
    return Sentinal;
  MCOperand const &MCO = MCI.getOperand(Index);
  if (!MCO.isExpr())
    return Sentinal;
  int64_t Value;
  if (!MCO.getExpr()->evaluateAsAbsolute(Value))
    return Sentinal;
  return Value;
}

void HexagonMCInstrInfo::setMustExtend(MCExpr const &Expr, bool Val) {
  HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
  HExpr.setMustExtend(Val);
}

bool HexagonMCInstrInfo::mustExtend(MCExpr const &Expr) {
  HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr);
  return HExpr.mustExtend();
}
void HexagonMCInstrInfo::setMustNotExtend(MCExpr const &Expr, bool Val) {
  HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
  HExpr.setMustNotExtend(Val);
}
bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) {
  HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr);
  return HExpr.mustNotExtend();
}
void HexagonMCInstrInfo::setS27_2_reloc(MCExpr const &Expr, bool Val) {
  HexagonMCExpr &HExpr =
      const_cast<HexagonMCExpr &>(*cast<HexagonMCExpr>(&Expr));
  HExpr.setS27_2_reloc(Val);
}
bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) {
  HexagonMCExpr const *HExpr = dyn_cast<HexagonMCExpr>(&Expr);
  if (!HExpr)
    return false;
  return HExpr->s27_2_reloc();
}

void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) {
  MCInst Nop;
  Nop.setOpcode(Hexagon::A2_nop);
  assert(isBundle(MCB));
  while ((HexagonMCInstrInfo::isInnerLoop(MCB) &&
          (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) ||
         ((HexagonMCInstrInfo::isOuterLoop(MCB) &&
           (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE))))
    MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop)));
}

HexagonMCInstrInfo::PredicateInfo
HexagonMCInstrInfo::predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI) {
  if (!isPredicated(MCII, MCI))
    return {0, 0, false};
  MCInstrDesc const &Desc = getDesc(MCII, MCI);
  for (auto I = Desc.getNumDefs(), N = Desc.getNumOperands(); I != N; ++I)
    if (Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID)
      return {MCI.getOperand(I).getReg(), I, isPredicatedTrue(MCII, MCI)};
  return {0, 0, false};
}

bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,
                                      MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::PrefersSlot3Pos) & HexagonII::PrefersSlot3Mask;
}

/// return true if instruction has hasTmpDst attribute.
bool HexagonMCInstrInfo::hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI) {
  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
  return (F >> HexagonII::HasTmpDstPos) & HexagonII::HasTmpDstMask;
}

void HexagonMCInstrInfo::replaceDuplex(MCContext &Context, MCInst &MCB,
                                       DuplexCandidate Candidate) {
  assert(Candidate.packetIndexI < MCB.size());
  assert(Candidate.packetIndexJ < MCB.size());
  assert(isBundle(MCB));
  MCInst *Duplex =
      deriveDuplex(Context, Candidate.iClass,
                   *MCB.getOperand(Candidate.packetIndexJ).getInst(),
                   *MCB.getOperand(Candidate.packetIndexI).getInst());
  assert(Duplex != nullptr);
  MCB.getOperand(Candidate.packetIndexI).setInst(Duplex);
  MCB.erase(MCB.begin() + Candidate.packetIndexJ);
}

void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) {
  assert(isBundle(MCI));
  MCOperand &Operand = MCI.getOperand(0);
  Operand.setImm(Operand.getImm() | innerLoopMask);
}

void HexagonMCInstrInfo::setMemReorderDisabled(MCInst &MCI) {
  assert(isBundle(MCI));
  MCOperand &Operand = MCI.getOperand(0);
  Operand.setImm(Operand.getImm() | memReorderDisabledMask);
  assert(isMemReorderDisabled(MCI));
}

void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
  assert(isBundle(MCI));
  MCOperand &Operand = MCI.getOperand(0);
  Operand.setImm(Operand.getImm() | outerLoopMask);
}

unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer,
                                            unsigned Producer,
                                            unsigned Producer2) {
  // If we're a single vector consumer of a double producer, set subreg bit
  // based on if we're accessing the lower or upper register component
  if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15)
    if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31)
      return (Consumer - Hexagon::V0) & 0x1;
  if (Producer2 != Hexagon::NoRegister)
    return Consumer == Producer;
  return 0;
}
