//===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses.
///
/// This represents the machine instructions and operands used for ARM32 code
/// selection.
///
//===----------------------------------------------------------------------===//

#ifndef SUBZERO_SRC_ICEINSTARM32_H
#define SUBZERO_SRC_ICEINSTARM32_H

#include "IceConditionCodesARM32.h"
#include "IceDefs.h"
#include "IceInst.h"
#include "IceInstARM32.def"
#include "IceOperand.h"
#include "IceRegistersARM32.h"

namespace Ice {
namespace ARM32 {

/// Encoding of an ARM 32-bit instruction.
using IValueT = uint32_t;

/// An Offset value (+/-) used in an ARM 32-bit instruction.
using IOffsetT = int32_t;

class TargetARM32;

/// OperandARM32 extends the Operand hierarchy. Its subclasses are
/// OperandARM32Mem and OperandARM32Flex.
class OperandARM32 : public Operand {
  OperandARM32() = delete;
  OperandARM32(const OperandARM32 &) = delete;
  OperandARM32 &operator=(const OperandARM32 &) = delete;

public:
  enum OperandKindARM32 {
    k__Start = Operand::kTarget,
    kMem,
    kShAmtImm,
    kFlexStart,
    kFlexImm = kFlexStart,
    kFlexFpImm,
    kFlexFpZero,
    kFlexReg,
    kFlexEnd = kFlexReg
  };

  enum ShiftKind {
    kNoShift = -1,
#define X(enum, emit) enum,
    ICEINSTARM32SHIFT_TABLE
#undef X
  };

  using Operand::dump;
  void dump(const Cfg *, Ostream &Str) const override {
    if (BuildDefs::dump())
      Str << "<OperandARM32>";
  }

protected:
  OperandARM32(OperandKindARM32 Kind, Type Ty)
      : Operand(static_cast<OperandKind>(Kind), Ty) {}
};

/// OperandARM32Mem represents a memory operand in any of the various ARM32
/// addressing modes.
class OperandARM32Mem : public OperandARM32 {
  OperandARM32Mem() = delete;
  OperandARM32Mem(const OperandARM32Mem &) = delete;
  OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;

public:
  /// Memory operand addressing mode.
  /// The enum value also carries the encoding.
  // TODO(jvoung): unify with the assembler.
  enum AddrMode {
    // bit encoding P U 0 W
    Offset = (8 | 4 | 0) << 21,      // offset (w/o writeback to base)
    PreIndex = (8 | 4 | 1) << 21,    // pre-indexed addressing with writeback
    PostIndex = (0 | 4 | 0) << 21,   // post-indexed addressing with writeback
    NegOffset = (8 | 0 | 0) << 21,   // negative offset (w/o writeback to base)
    NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
    NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
  };

  /// Provide two constructors.
  /// NOTE: The Variable-typed operands have to be registers.
  ///
  /// (1) Reg + Imm. The Immediate actually has a limited number of bits
  /// for encoding, so check canHoldOffset first. It cannot handle general
  /// Constant operands like ConstantRelocatable, since a relocatable can
  /// potentially take up too many bits.
  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
                                 ConstantInteger32 *ImmOffset,
                                 AddrMode Mode = Offset) {
    return new (Func->allocate<OperandARM32Mem>())
        OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
  }
  /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
  /// this mode is disallowed in the NaCl sandbox.
  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
                                 Variable *Index, ShiftKind ShiftOp = kNoShift,
                                 uint16_t ShiftAmt = 0,
                                 AddrMode Mode = Offset) {
    return new (Func->allocate<OperandARM32Mem>())
        OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
  }
  Variable *getBase() const { return Base; }
  ConstantInteger32 *getOffset() const { return ImmOffset; }
  Variable *getIndex() const { return Index; }
  ShiftKind getShiftOp() const { return ShiftOp; }
  uint16_t getShiftAmt() const { return ShiftAmt; }
  AddrMode getAddrMode() const { return Mode; }

  bool isRegReg() const { return Index != nullptr; }
  bool isNegAddrMode() const {
    // Positive address modes have the "U" bit set, and negative modes don't.
    static_assert((PreIndex & (4 << 21)) != 0,
                  "Positive addr modes should have U bit set.");
    static_assert((NegPreIndex & (4 << 21)) == 0,
                  "Negative addr modes should have U bit clear.");
    return (Mode & (4 << 21)) == 0;
  }

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kMem);
  }

  /// Return true if a load/store instruction for an element of type Ty can
  /// encode the Offset directly in the immediate field of the 32-bit ARM
  /// instruction. For some types, if the load is Sign extending, then the range
  /// is reduced.
  static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);

private:
  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
                  ConstantInteger32 *ImmOffset, AddrMode Mode);
  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
                  ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);

  Variable *Base;
  ConstantInteger32 *ImmOffset;
  Variable *Index;
  ShiftKind ShiftOp;
  uint16_t ShiftAmt;
  AddrMode Mode;
};

/// OperandARM32ShAmtImm represents an Immediate that is used in one of the
/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
/// shifted registers.
class OperandARM32ShAmtImm : public OperandARM32 {
  OperandARM32ShAmtImm() = delete;
  OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
  OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;

public:
  static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
    return new (Func->allocate<OperandARM32ShAmtImm>())
        OperandARM32ShAmtImm(ShAmt);
  }

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
  }

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  uint32_t getShAmtImm() const { return ShAmt->getValue(); }

private:
  explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);

  const ConstantInteger32 *const ShAmt;
};

/// OperandARM32Flex represent the "flexible second operand" for data-processing
/// instructions. It can be a rotatable 8-bit constant, or a register with an
/// optional shift operand. The shift amount can even be a third register.
class OperandARM32Flex : public OperandARM32 {
  OperandARM32Flex() = delete;
  OperandARM32Flex(const OperandARM32Flex &) = delete;
  OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;

public:
  static bool classof(const Operand *Operand) {
    return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
           Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
  }

protected:
  OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
};

/// Rotated immediate variant.
class OperandARM32FlexImm : public OperandARM32Flex {
  OperandARM32FlexImm() = delete;
  OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
  OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;

public:
  /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
  static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
                                     uint32_t RotateAmt);

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
  }

  /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
  /// the out-params RotateAmt and Immed_8 if Immediate fits.
  static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
                         uint32_t *Immed_8);

  uint32_t getImm() const { return Imm; }
  uint32_t getRotateAmt() const { return RotateAmt; }

private:
  OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);

  uint32_t Imm;
  uint32_t RotateAmt;
};

/// Modified Floating-point constant.
class OperandARM32FlexFpImm : public OperandARM32Flex {
  OperandARM32FlexFpImm() = delete;
  OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete;
  OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete;

public:
  static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty,
                                       uint32_t ModifiedImm) {
    return new (Func->allocate<OperandARM32FlexFpImm>())
        OperandARM32FlexFpImm(Func, Ty, ModifiedImm);
  }

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
  }

  static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm);

  uint32_t getModifiedImm() const { return ModifiedImm; }

private:
  OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);

  const uint32_t ModifiedImm;
};

/// An operand for representing the 0.0 immediate in vcmp.
class OperandARM32FlexFpZero : public OperandARM32Flex {
  OperandARM32FlexFpZero() = delete;
  OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete;
  OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete;

public:
  static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) {
    return new (Func->allocate<OperandARM32FlexFpZero>())
        OperandARM32FlexFpZero(Func, Ty);
  }

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero);
  }

private:
  OperandARM32FlexFpZero(Cfg *Func, Type Ty);
};

/// Shifted register variant.
class OperandARM32FlexReg : public OperandARM32Flex {
  OperandARM32FlexReg() = delete;
  OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
  OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;

public:
  /// Register with immediate/reg shift amount and shift operation.
  static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
                                     ShiftKind ShiftOp, Operand *ShiftAmt) {
    return new (Func->allocate<OperandARM32FlexReg>())
        OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
  }

  void emit(const Cfg *Func) const override;
  using OperandARM32::dump;
  void dump(const Cfg *Func, Ostream &Str) const override;

  static bool classof(const Operand *Operand) {
    return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
  }

  Variable *getReg() const { return Reg; }
  ShiftKind getShiftOp() const { return ShiftOp; }
  /// ShiftAmt can represent an immediate or a register.
  Operand *getShiftAmt() const { return ShiftAmt; }

private:
  OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
                      Operand *ShiftAmt);

  Variable *Reg;
  ShiftKind ShiftOp;
  Operand *ShiftAmt;
};

/// StackVariable represents a Var that isn't assigned a register (stack-only).
/// It is assigned a stack slot, but the slot's offset may be too large to
/// represent in the native addressing mode, and so it has a separate base
/// register from SP/FP, where the offset from that base register is then in
/// range.
class StackVariable final : public Variable {
  StackVariable() = delete;
  StackVariable(const StackVariable &) = delete;
  StackVariable &operator=(const StackVariable &) = delete;

public:
  static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
    return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index);
  }
  constexpr static auto StackVariableKind =
      static_cast<OperandKind>(kVariable_Target);
  static bool classof(const Operand *Operand) {
    return Operand->getKind() == StackVariableKind;
  }
  void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
  RegNumT getBaseRegNum() const override { return BaseRegNum; }
  // Inherit dump() and emit() from Variable.

private:
  StackVariable(const Cfg *Func, Type Ty, SizeT Index)
      : Variable(Func, StackVariableKind, Ty, Index) {}
  RegNumT BaseRegNum;
};

/// Base class for ARM instructions. While most ARM instructions can be
/// conditionally executed, a few of them are not predicable (halt, memory
/// barriers, etc.).
class InstARM32 : public InstTarget {
  InstARM32() = delete;
  InstARM32(const InstARM32 &) = delete;
  InstARM32 &operator=(const InstARM32 &) = delete;

public:
  // Defines form that assembly instruction should be synthesized.
  enum EmitForm { Emit_Text, Emit_Binary };

  enum InstKindARM32 {
    k__Start = Inst::Target,
    Adc,
    Add,
    And,
    Asr,
    Bic,
    Br,
    Call,
    Clz,
    Cmn,
    Cmp,
    Dmb,
    Eor,
    Extract,
    Insert,
    Label,
    Ldr,
    Ldrex,
    Lsl,
    Lsr,
    Nop,
    Mla,
    Mls,
    Mov,
    Movt,
    Movw,
    Mul,
    Mvn,
    Orr,
    Pop,
    Push,
    Rbit,
    Ret,
    Rev,
    Rsb,
    Rsc,
    Sbc,
    Sdiv,
    Str,
    Strex,
    Sub,
    Sxt,
    Trap,
    Tst,
    Udiv,
    Umull,
    Uxt,
    Vabs,
    Vadd,
    Vand,
    Vbsl,
    Vceq,
    Vcge,
    Vcgt,
    Vcmp,
    Vcvt,
    Vdiv,
    Veor,
    Vmla,
    Vmls,
    Vmrs,
    Vmul,
    Vmvn,
    Vneg,
    Vorr,
    Vshl,
    Vshr,
    Vsqrt,
    Vsub
  };

  static constexpr size_t InstSize = sizeof(uint32_t);

  static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);

  /// Called inside derived methods emit() to communicate that multiple
  /// instructions are being generated. Used by emitIAS() methods to
  /// generate textual fixups for instructions that are not yet
  /// implemented.
  void startNextInst(const Cfg *Func) const;

  /// FPSign is used for certain vector instructions (particularly, right
  /// shifts) that require an operand sign specification.
  enum FPSign {
    FS_None,
    FS_Signed,
    FS_Unsigned,
  };
  /// Shared emit routines for common forms of instructions.
  /// @{
  static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
                              const InstARM32 *Instr, const Cfg *Func,
                              Type OpType);
  static void emitFourAddrFP(const char *Opcode, FPSign Sign,
                             const InstARM32 *Instr, const Cfg *Func);
  /// @}

  void dump(const Cfg *Func) const override;

  void emitIAS(const Cfg *Func) const override;

protected:
  InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
      : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}

  static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
    return Instr->getKind() == static_cast<InstKind>(MyKind);
  }

  // Generates text of assembly instruction using method emit(), and then adds
  // to the assembly buffer as a Fixup.
  void emitUsingTextFixup(const Cfg *Func) const;
};

/// A predicable ARM instruction.
class InstARM32Pred : public InstARM32 {
  InstARM32Pred() = delete;
  InstARM32Pred(const InstARM32Pred &) = delete;
  InstARM32Pred &operator=(const InstARM32Pred &) = delete;

public:
  InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
                CondARM32::Cond Predicate)
      : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}

  CondARM32::Cond getPredicate() const { return Predicate; }
  void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }

  static const char *predString(CondARM32::Cond Predicate);
  void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;

  /// Shared emit routines for common forms of instructions.
  static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
                             const Cfg *Func, bool NeedsWidthSuffix);
  static void emitUnaryopFP(const char *Opcode, FPSign Sign,
                            const InstARM32Pred *Instr, const Cfg *Func);
  static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
                          const Cfg *Func);
  static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
                            const Cfg *Func, bool SetFlags);
  static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
                           const Cfg *Func);
  static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
                          const Cfg *Func);

protected:
  CondARM32::Cond Predicate;
};

template <typename StreamType>
inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
  Stream << InstARM32Pred::predString(Predicate);
  return Stream;
}

/// Instructions of the form x := op(y).
template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
class InstARM32UnaryopGPR : public InstARM32Pred {
  InstARM32UnaryopGPR() = delete;
  InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
  InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;

public:
  static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
                                     CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32UnaryopGPR>())
        InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
                      CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
    addSource(Src);
  }

  static const char *Opcode;
};

/// Instructions of the form x := op(y), for vector/FP.
template <InstARM32::InstKindARM32 K>
class InstARM32UnaryopFP : public InstARM32Pred {
  InstARM32UnaryopFP() = delete;
  InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
  InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;

public:
  static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
                                    CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32UnaryopFP>())
        InstARM32UnaryopFP(Func, Dest, Src, Predicate);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitUnaryopFP(Opcode, Sign, this, Func);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

protected:
  InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
                     CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
    addSource(Src);
  }

  FPSign Sign = FS_None;
  static const char *Opcode;
};

template <InstARM32::InstKindARM32 K>
class InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> {
  InstARM32UnaryopSignAwareFP() = delete;
  InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete;
  InstARM32UnaryopSignAwareFP &
  operator=(const InstARM32UnaryopSignAwareFP &) = delete;

public:
  static InstARM32UnaryopSignAwareFP *
  create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32UnaryopSignAwareFP>())
        InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate);
  }
  void emitIAS(const Cfg *Func) const override;
  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }

private:
  InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src,
                              CondARM32::Cond Predicate)
      : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {}
};

/// Instructions of the form x := x op y.
template <InstARM32::InstKindARM32 K>
class InstARM32TwoAddrGPR : public InstARM32Pred {
  InstARM32TwoAddrGPR() = delete;
  InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
  InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;

public:
  /// Dest must be a register.
  static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
                                     CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32TwoAddrGPR>())
        InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitTwoAddr(Opcode, this, Func);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
                      CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 2, Dest, Predicate) {
    addSource(Dest);
    addSource(Src);
  }

  static const char *Opcode;
};

/// Base class for load instructions.
template <InstARM32::InstKindARM32 K>
class InstARM32LoadBase : public InstARM32Pred {
  InstARM32LoadBase() = delete;
  InstARM32LoadBase(const InstARM32LoadBase &) = delete;
  InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;

public:
  static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
                                   CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32LoadBase>())
        InstARM32LoadBase(Func, Dest, Source, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << " ";
    dumpDest(Func);
    Str << ", ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
                    CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
    addSource(Source);
  }

  static const char *Opcode;
};

/// Instructions of the form x := y op z. May have the side-effect of setting
/// status flags.
template <InstARM32::InstKindARM32 K>
class InstARM32ThreeAddrGPR : public InstARM32Pred {
  InstARM32ThreeAddrGPR() = delete;
  InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
  InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;

public:
  /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
  /// must be registers.
  static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
                                       Variable *Src0, Operand *Src1,
                                       CondARM32::Cond Predicate,
                                       bool SetFlags = false) {
    return new (Func->allocate<InstARM32ThreeAddrGPR>())
        InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitThreeAddr(Opcode, this, Func, SetFlags);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << (SetFlags ? ".s " : " ");
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
                        Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
      : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
    HasSideEffects = SetFlags;
    addSource(Src0);
    addSource(Src1);
  }

  static const char *Opcode;
  bool SetFlags;
};

/// Instructions of the form x := y op z, for vector/FP. We leave these as
/// unconditional: "ARM deprecates the conditional execution of any instruction
/// encoding provided by the Advanced SIMD Extension that is not also provided
/// by the floating-point (VFP) extension". They do not set flags.
template <InstARM32::InstKindARM32 K>
class InstARM32ThreeAddrFP : public InstARM32 {
  InstARM32ThreeAddrFP() = delete;
  InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
  InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;

public:
  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
  /// must be a register.
  static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
                                      Variable *Src1) {
    return new (Func->allocate<InstARM32ThreeAddrFP>())
        InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
    emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
    Str << " = " << Opcode << "." << OpType << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

protected:
  FPSign Sign = FS_None;

  InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
      : InstARM32(Func, K, 2, Dest) {
    addSource(Src0);
    addSource(Src1);
  }

  static const char *Opcode;

private:
  static constexpr bool isVectorCompare() {
    return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
  }
};

template <InstARM32::InstKindARM32 K>
class InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> {
  InstARM32ThreeAddrSignAwareFP() = delete;
  InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete;
  InstARM32ThreeAddrSignAwareFP &
  operator=(const InstARM32ThreeAddrSignAwareFP &) = delete;

public:
  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
  /// must be a register.
  static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest,
                                               Variable *Src0, Variable *Src1) {
    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
  }

  static InstARM32ThreeAddrSignAwareFP *
  create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
  }

  void emitIAS(const Cfg *Func) const override;
  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }

private:
  InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0,
                                Operand *Src1)
      : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
};

/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
template <InstARM32::InstKindARM32 K>
class InstARM32FourAddrGPR : public InstARM32Pred {
  InstARM32FourAddrGPR() = delete;
  InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
  InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;

public:
  // Every operand must be a register.
  static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
                                      Variable *Src1, Variable *Src2,
                                      CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32FourAddrGPR>())
        InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitFourAddr(Opcode, this, Func);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    dumpOpcodePred(Str, Opcode, getDest()->getType());
    Str << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
                       Variable *Src1, Variable *Src2,
                       CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 3, Dest, Predicate) {
    addSource(Src0);
    addSource(Src1);
    addSource(Src2);
  }

  static const char *Opcode;
};

/// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
/// We leave these as unconditional: "ARM deprecates the conditional execution
/// of any instruction encoding provided by the Advanced SIMD Extension that is
/// not also provided by the floating-point (VFP) extension". They do not set
/// flags.
template <InstARM32::InstKindARM32 K>
class InstARM32FourAddrFP : public InstARM32 {
  InstARM32FourAddrFP() = delete;
  InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
  InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;

public:
  // Every operand must be a register.
  static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
                                     Variable *Src1) {
    return new (Func->allocate<InstARM32FourAddrFP>())
        InstARM32FourAddrFP(Func, Dest, Src0, Src1);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitFourAddrFP(Opcode, Sign, this, Func);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpDest(Func);
    Str << " = ";
    Str << Opcode << "." << getDest()->getType() << " ";
    dumpDest(Func);
    Str << ", ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
      : InstARM32(Func, K, 3, Dest) {
    addSource(Dest);
    addSource(Src0);
    addSource(Src1);
  }

  FPSign Sign = FS_None;
  static const char *Opcode;
};

/// Instructions of the form x cmpop y (setting flags).
template <InstARM32::InstKindARM32 K>
class InstARM32CmpLike : public InstARM32Pred {
  InstARM32CmpLike() = delete;
  InstARM32CmpLike(const InstARM32CmpLike &) = delete;
  InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;

public:
  static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
                                  CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32CmpLike>())
        InstARM32CmpLike(Func, Src0, Src1, Predicate);
  }
  void emit(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    emitCmpLike(Opcode, this, Func);
  }
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override {
    if (!BuildDefs::dump())
      return;
    Ostream &Str = Func->getContext()->getStrDump();
    dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
    Str << " ";
    dumpSources(Func);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }

private:
  InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
                   CondARM32::Cond Predicate)
      : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
    HasSideEffects = true;
    addSource(Src0);
    addSource(Src1);
  }

  static const char *Opcode;
};

using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
/// MovT leaves the bottom bits alone so dest is also a source. This helps
/// indicate that a previous MovW setting dest is not dead code.
using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
// using that for now, so just model as a Unaryop.
using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;

// InstARM32Label represents an intra-block label that is the target of an
// intra-block branch. The offset between the label and the branch must be fit
// in the instruction immediate (considered "near").
class InstARM32Label : public InstARM32 {
  InstARM32Label() = delete;
  InstARM32Label(const InstARM32Label &) = delete;
  InstARM32Label &operator=(const InstARM32Label &) = delete;

public:
  static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
    return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
  }
  uint32_t getEmitInstCount() const override { return 0; }
  GlobalString getLabelName() const { return Name; }
  SizeT getNumber() const { return Number; }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }

private:
  InstARM32Label(Cfg *Func, TargetARM32 *Target);

  RelocOffset *OffsetReloc = nullptr;
  SizeT Number; // used for unique label generation.
  GlobalString Name;
};

/// Direct branch instruction.
class InstARM32Br : public InstARM32Pred {
  InstARM32Br() = delete;
  InstARM32Br(const InstARM32Br &) = delete;
  InstARM32Br &operator=(const InstARM32Br &) = delete;

public:
  /// Create a conditional branch to one of two nodes.
  static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
                             CfgNode *TargetFalse, CondARM32::Cond Predicate) {
    assert(Predicate != CondARM32::AL);
    constexpr InstARM32Label *NoLabel = nullptr;
    return new (Func->allocate<InstARM32Br>())
        InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
  }
  /// Create an unconditional branch to a node.
  static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
    constexpr CfgNode *NoCondTarget = nullptr;
    constexpr InstARM32Label *NoLabel = nullptr;
    return new (Func->allocate<InstARM32Br>())
        InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
  }
  /// Create a non-terminator conditional branch to a node, with a fallthrough
  /// to the next instruction in the current node. This is used for switch
  /// lowering.
  static InstARM32Br *create(Cfg *Func, CfgNode *Target,
                             CondARM32::Cond Predicate) {
    assert(Predicate != CondARM32::AL);
    constexpr CfgNode *NoUncondTarget = nullptr;
    constexpr InstARM32Label *NoLabel = nullptr;
    return new (Func->allocate<InstARM32Br>())
        InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
  }
  // Create a conditional intra-block branch (or unconditional, if
  // Condition==AL) to a label in the current block.
  static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
                             CondARM32::Cond Predicate) {
    constexpr CfgNode *NoCondTarget = nullptr;
    constexpr CfgNode *NoUncondTarget = nullptr;
    return new (Func->allocate<InstARM32Br>())
        InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
  }
  const CfgNode *getTargetTrue() const { return TargetTrue; }
  const CfgNode *getTargetFalse() const { return TargetFalse; }
  bool optimizeBranch(const CfgNode *NextNode);
  uint32_t getEmitInstCount() const override {
    uint32_t Sum = 0;
    if (Label)
      ++Sum;
    if (getTargetTrue())
      ++Sum;
    if (getTargetFalse())
      ++Sum;
    return Sum;
  }
  bool isUnconditionalBranch() const override {
    return getPredicate() == CondARM32::AL;
  }
  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }

private:
  InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
              const InstARM32Label *Label, CondARM32::Cond Predicate);

  const CfgNode *TargetTrue;
  const CfgNode *TargetFalse;
  const InstARM32Label *Label; // Intra-block branch target
};

/// Call instruction (bl/blx). Arguments should have already been pushed.
/// Technically bl and the register form of blx can be predicated, but we'll
/// leave that out until needed.
class InstARM32Call : public InstARM32 {
  InstARM32Call() = delete;
  InstARM32Call(const InstARM32Call &) = delete;
  InstARM32Call &operator=(const InstARM32Call &) = delete;

public:
  static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
    return new (Func->allocate<InstARM32Call>())
        InstARM32Call(Func, Dest, CallTarget);
  }
  Operand *getCallTarget() const { return getSrc(0); }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }

private:
  InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
};

class InstARM32RegisterStackOp : public InstARM32 {
  InstARM32RegisterStackOp() = delete;
  InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
  InstARM32RegisterStackOp &
  operator=(const InstARM32RegisterStackOp &) = delete;

public:
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;

protected:
  InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
                           Variable *Dest)
      : InstARM32(Func, Kind, Maxsrcs, Dest) {}
  void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
  void emitGPRsAsText(const Cfg *Func) const;
  void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
                       SizeT Regcount) const;
  void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
                   SizeT RegCount, SizeT InstIndex) const;
  virtual const char *getDumpOpcode() const { return getGPROpcode(); }
  virtual const char *getGPROpcode() const = 0;
  virtual const char *getSRegOpcode() const = 0;
  virtual Variable *getStackReg(SizeT Index) const = 0;
  virtual SizeT getNumStackRegs() const = 0;
  virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
                             const Variable *Reg) const = 0;
  virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
                                IValueT Registers) const = 0;
  virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
                         const Variable *BaseReg, SizeT RegCount) const = 0;
};

/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
/// regs, but not both. In any case, the list must be sorted.
class InstARM32Pop final : public InstARM32RegisterStackOp {
  InstARM32Pop() = delete;
  InstARM32Pop(const InstARM32Pop &) = delete;
  InstARM32Pop &operator=(const InstARM32Pop &) = delete;

public:
  static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
    return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }

private:
  InstARM32Pop(Cfg *Func, const VarList &Dests);
  virtual const char *getGPROpcode() const final;
  virtual const char *getSRegOpcode() const final;
  Variable *getStackReg(SizeT Index) const final;
  SizeT getNumStackRegs() const final;
  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
                     const Variable *Reg) const final;
  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
                        IValueT Registers) const final;
  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
                 SizeT RegCount) const final;
  VarList Dests;
};

/// Pushes a list of registers. Just like Pop (see above), the list may be of
/// GPRs, or VFP "s" registers, but not both.
class InstARM32Push final : public InstARM32RegisterStackOp {
  InstARM32Push() = delete;
  InstARM32Push(const InstARM32Push &) = delete;
  InstARM32Push &operator=(const InstARM32Push &) = delete;

public:
  static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
    return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
  }
  static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }

private:
  InstARM32Push(Cfg *Func, const VarList &Srcs);
  const char *getGPROpcode() const final;
  const char *getSRegOpcode() const final;
  Variable *getStackReg(SizeT Index) const final;
  SizeT getNumStackRegs() const final;
  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
                     const Variable *Reg) const final;
  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
                        IValueT Registers) const final;
  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
                 SizeT RegCount) const final;
};

/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
/// register operand, but epilogue lowering will search for a Ret instead of a
/// generic "bx". This instruction also takes a Source operand (for non-void
/// returning functions) for liveness analysis, though a FakeUse before the ret
/// would do just as well.
///
/// NOTE: Even though "bx" can be predicated, for now leave out the predication
/// since it's not yet known to be useful for Ret. That may complicate finding
/// the terminator instruction if it's not guaranteed to be executed.
class InstARM32Ret : public InstARM32 {
  InstARM32Ret() = delete;
  InstARM32Ret(const InstARM32Ret &) = delete;
  InstARM32Ret &operator=(const InstARM32Ret &) = delete;

public:
  static InstARM32Ret *create(Cfg *Func, Variable *LR,
                              Variable *Source = nullptr) {
    return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }

private:
  InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
};

/// Store instruction. It's important for liveness that there is no Dest operand
/// (OperandARM32Mem instead of Dest Variable).
class InstARM32Str final : public InstARM32Pred {
  InstARM32Str() = delete;
  InstARM32Str(const InstARM32Str &) = delete;
  InstARM32Str &operator=(const InstARM32Str &) = delete;

public:
  /// Value must be a register.
  static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
                              CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Str>())
        InstARM32Str(Func, Value, Mem, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }

private:
  InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
               CondARM32::Cond Predicate);
};

/// Exclusive Store instruction. Like its non-exclusive sibling, it's important
/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
/// Variable).
class InstARM32Strex final : public InstARM32Pred {
  InstARM32Strex() = delete;
  InstARM32Strex(const InstARM32Strex &) = delete;
  InstARM32Strex &operator=(const InstARM32Strex &) = delete;

public:
  /// Value must be a register.
  static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
                                OperandARM32Mem *Mem,
                                CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Strex>())
        InstARM32Strex(Func, Dest, Value, Mem, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }

private:
  InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
                 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
};

class InstARM32Trap : public InstARM32 {
  InstARM32Trap() = delete;
  InstARM32Trap(const InstARM32Trap &) = delete;
  InstARM32Trap &operator=(const InstARM32Trap &) = delete;

public:
  static InstARM32Trap *create(Cfg *Func) {
    return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }

private:
  explicit InstARM32Trap(Cfg *Func);
};

/// Unsigned Multiply Long: d.lo, d.hi := x * y
class InstARM32Umull : public InstARM32Pred {
  InstARM32Umull() = delete;
  InstARM32Umull(const InstARM32Umull &) = delete;
  InstARM32Umull &operator=(const InstARM32Umull &) = delete;

public:
  /// Everything must be a register.
  static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
                                Variable *Src0, Variable *Src1,
                                CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Umull>())
        InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }

private:
  InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
                 Variable *Src1, CondARM32::Cond Predicate);

  Variable *DestHi;
};

/// Handles fp2int, int2fp, and fp2fp conversions.
class InstARM32Vcvt final : public InstARM32Pred {
  InstARM32Vcvt() = delete;
  InstARM32Vcvt(const InstARM32Vcvt &) = delete;
  InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;

public:
  enum VcvtVariant {
    S2si,
    S2ui,
    Si2s,
    Ui2s,
    D2si,
    D2ui,
    Si2d,
    Ui2d,
    S2d,
    D2s,
    Vs2si,
    Vs2ui,
    Vsi2s,
    Vui2s,
  };
  static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
                               VcvtVariant Variant, CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Vcvt>())
        InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }

private:
  InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
                CondARM32::Cond Predicate);

  const VcvtVariant Variant;
};

/// Handles (some of) vmov's various formats.
class InstARM32Mov final : public InstARM32Pred {
  InstARM32Mov() = delete;
  InstARM32Mov(const InstARM32Mov &) = delete;
  InstARM32Mov &operator=(const InstARM32Mov &) = delete;

public:
  static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
                              CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Mov>())
        InstARM32Mov(Func, Dest, Src, Predicate);
  }
  bool isRedundantAssign() const override {
    return !isMultiDest() && !isMultiSource() &&
           getPredicate() == CondARM32::AL &&
           checkForRedundantAssign(getDest(), getSrc(0));
  }
  bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }

  bool isMultiDest() const { return DestHi != nullptr; }

  bool isMultiSource() const {
    assert(getSrcSize() == 1 || getSrcSize() == 2);
    return getSrcSize() == 2;
  }

  Variable *getDestHi() const { return DestHi; }

private:
  InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
               CondARM32::Cond Predicate);
  void emitMultiDestSingleSource(const Cfg *Func) const;
  void emitSingleDestMultiSource(const Cfg *Func) const;
  void emitSingleDestSingleSource(const Cfg *Func) const;

  Variable *DestHi = nullptr;
};

/// Generates vmov Rd, Dn[x] instructions, and their related floating point
/// versions.
class InstARM32Extract final : public InstARM32Pred {
  InstARM32Extract() = delete;
  InstARM32Extract(const InstARM32Extract &) = delete;
  InstARM32Extract &operator=(const InstARM32Extract &) = delete;

public:
  static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0,
                                  uint32_t Index, CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Extract>())
        InstARM32Extract(Func, Dest, Src0, Index, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); }

private:
  InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
                   CondARM32::Cond Predicate)
      : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate),
        Index(Index) {
    assert(Index < typeNumElements(Src0->getType()));
    addSource(Src0);
  }

  const uint32_t Index;
};

/// Generates vmov Dn[x], Rd instructions, and their related floating point
/// versions.
class InstARM32Insert final : public InstARM32Pred {
  InstARM32Insert() = delete;
  InstARM32Insert(const InstARM32Insert &) = delete;
  InstARM32Insert &operator=(const InstARM32Insert &) = delete;

public:
  static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0,
                                 uint32_t Index, CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Insert>())
        InstARM32Insert(Func, Dest, Src0, Index, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); }

private:
  InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
                  CondARM32::Cond Predicate)
      : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate),
        Index(Index) {
    assert(Index < typeNumElements(Dest->getType()));
    addSource(Src0);
  }

  const uint32_t Index;
};

class InstARM32Vcmp final : public InstARM32Pred {
  InstARM32Vcmp() = delete;
  InstARM32Vcmp(const InstARM32Vcmp &) = delete;
  InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;

public:
  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
                               CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Vcmp>())
        InstARM32Vcmp(Func, Src0, Src1, Predicate);
  }
  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
                               OperandARM32FlexFpZero *Src1,
                               CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Vcmp>())
        InstARM32Vcmp(Func, Src0, Src1, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }

private:
  InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
                CondARM32::Cond Predicate);
};

/// Copies the FP Status and Control Register the core flags.
class InstARM32Vmrs final : public InstARM32Pred {
  InstARM32Vmrs() = delete;
  InstARM32Vmrs(const InstARM32Vmrs &) = delete;
  InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;

public:
  static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }

private:
  InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
};

class InstARM32Vabs final : public InstARM32Pred {
  InstARM32Vabs() = delete;
  InstARM32Vabs(const InstARM32Vabs &) = delete;
  InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;

public:
  static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
                               CondARM32::Cond Predicate) {
    return new (Func->allocate<InstARM32Vabs>())
        InstARM32Vabs(Func, Dest, Src, Predicate);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }

private:
  InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
                CondARM32::Cond Predicate);
};

class InstARM32Dmb final : public InstARM32Pred {
  InstARM32Dmb() = delete;
  InstARM32Dmb(const InstARM32Dmb &) = delete;
  InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;

public:
  static InstARM32Dmb *create(Cfg *Func) {
    return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }

private:
  explicit InstARM32Dmb(Cfg *Func);
};

class InstARM32Nop final : public InstARM32Pred {
  InstARM32Nop() = delete;
  InstARM32Nop(const InstARM32Nop &) = delete;
  InstARM32Nop &operator=(const InstARM32Nop &) = delete;

public:
  static InstARM32Nop *create(Cfg *Func) {
    return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg *Func) const override;
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); }

private:
  explicit InstARM32Nop(Cfg *Func);
};

// Declare partial template specializations of emit() methods that already have
// default implementations. Without this, there is the possibility of ODR
// violations and link errors.

template <> void InstARM32Ldr::emit(const Cfg *Func) const;
template <> void InstARM32Movw::emit(const Cfg *Func) const;
template <> void InstARM32Movt::emit(const Cfg *Func) const;

} // end of namespace ARM32
} // end of namespace Ice

#endif // SUBZERO_SRC_ICEINSTARM32_H
