1b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===//
2b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//
3b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//                        The Subzero Code Generator
4b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//
5b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// This file is distributed under the University of Illinois Open Source
6b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// License. See LICENSE.TXT for details.
7b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//
8b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses.
1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth///
1392a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// This represents the machine instructions and operands used for ARM32 code
1492a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// selection.
159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
16b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===//
17b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
18b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#ifndef SUBZERO_SRC_ICEINSTARM32_H
19b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#define SUBZERO_SRC_ICEINSTARM32_H
20b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
213bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung#include "IceConditionCodesARM32.h"
22b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#include "IceDefs.h"
23b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceInst.h"
24b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceInstARM32.def"
25b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceOperand.h"
26658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk#include "IceRegistersARM32.h"
27b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
28b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungnamespace Ice {
294a56686b5b56db6803f90ad53514bf2fa190d9f7John Portonamespace ARM32 {
30b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
31c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf/// Encoding of an ARM 32-bit instruction.
32c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfusing IValueT = uint32_t;
33c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
34c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf/// An Offset value (+/-) used in an ARM 32-bit instruction.
35c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfusing IOffsetT = int32_t;
36c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
37b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungclass TargetARM32;
38b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
3957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// OperandARM32 extends the Operand hierarchy. Its subclasses are
409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// OperandARM32Mem and OperandARM32Flex.
41b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass OperandARM32 : public Operand {
42b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32() = delete;
43b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32(const OperandARM32 &) = delete;
44b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32 &operator=(const OperandARM32 &) = delete;
45b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
46b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic:
47b3401d27a236b81393092b4d571df473b5bba64bJan Voung  enum OperandKindARM32 {
48b3401d27a236b81393092b4d571df473b5bba64bJan Voung    k__Start = Operand::kTarget,
49b3401d27a236b81393092b4d571df473b5bba64bJan Voung    kMem,
502758bb077495d7a88b3d66368b3d760de61cedc7John Porto    kShAmtImm,
51b3401d27a236b81393092b4d571df473b5bba64bJan Voung    kFlexStart,
52b3401d27a236b81393092b4d571df473b5bba64bJan Voung    kFlexImm = kFlexStart,
53ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    kFlexFpImm,
54ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    kFlexFpZero,
55b3401d27a236b81393092b4d571df473b5bba64bJan Voung    kFlexReg,
56b3401d27a236b81393092b4d571df473b5bba64bJan Voung    kFlexEnd = kFlexReg
57b3401d27a236b81393092b4d571df473b5bba64bJan Voung  };
58b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
59b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  enum ShiftKind {
60b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung    kNoShift = -1,
61b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#define X(enum, emit) enum,
62b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung    ICEINSTARM32SHIFT_TABLE
63b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#undef X
64b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  };
65b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
66b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  using Operand::dump;
67b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  void dump(const Cfg *, Ostream &Str) const override {
6820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (BuildDefs::dump())
69b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung      Str << "<OperandARM32>";
70b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  }
71b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
72b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprotected:
73b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32(OperandKindARM32 Kind, Type Ty)
74b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung      : Operand(static_cast<OperandKind>(Kind), Ty) {}
75b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung};
76b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
779612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// OperandARM32Mem represents a memory operand in any of the various ARM32
789612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// addressing modes.
79b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass OperandARM32Mem : public OperandARM32 {
80b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32Mem() = delete;
81b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32Mem(const OperandARM32Mem &) = delete;
82b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
83b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
84b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic:
859612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Memory operand addressing mode.
869612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// The enum value also carries the encoding.
87b3401d27a236b81393092b4d571df473b5bba64bJan Voung  // TODO(jvoung): unify with the assembler.
88b3401d27a236b81393092b4d571df473b5bba64bJan Voung  enum AddrMode {
89cdb3ed6870ef03215a8d6ed977d8ed0e4bc328a5Karl Schimpf    // bit encoding P U 0 W
90b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Offset = (8 | 4 | 0) << 21,      // offset (w/o writeback to base)
91b3401d27a236b81393092b4d571df473b5bba64bJan Voung    PreIndex = (8 | 4 | 1) << 21,    // pre-indexed addressing with writeback
92b3401d27a236b81393092b4d571df473b5bba64bJan Voung    PostIndex = (0 | 4 | 0) << 21,   // post-indexed addressing with writeback
93b3401d27a236b81393092b4d571df473b5bba64bJan Voung    NegOffset = (8 | 0 | 0) << 21,   // negative offset (w/o writeback to base)
94b3401d27a236b81393092b4d571df473b5bba64bJan Voung    NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
95b3401d27a236b81393092b4d571df473b5bba64bJan Voung    NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
96b3401d27a236b81393092b4d571df473b5bba64bJan Voung  };
97b3401d27a236b81393092b4d571df473b5bba64bJan Voung
989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Provide two constructors.
999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// NOTE: The Variable-typed operands have to be registers.
1009612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  ///
1019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// (1) Reg + Imm. The Immediate actually has a limited number of bits
10257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for encoding, so check canHoldOffset first. It cannot handle general
10357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Constant operands like ConstantRelocatable, since a relocatable can
10457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// potentially take up too many bits.
105b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
106befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung                                 ConstantInteger32 *ImmOffset,
107b3401d27a236b81393092b4d571df473b5bba64bJan Voung                                 AddrMode Mode = Offset) {
108b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return new (Func->allocate<OperandARM32Mem>())
109b3401d27a236b81393092b4d571df473b5bba64bJan Voung        OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
110b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
11157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
11257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// this mode is disallowed in the NaCl sandbox.
113b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
114b3401d27a236b81393092b4d571df473b5bba64bJan Voung                                 Variable *Index, ShiftKind ShiftOp = kNoShift,
115b3401d27a236b81393092b4d571df473b5bba64bJan Voung                                 uint16_t ShiftAmt = 0,
116b3401d27a236b81393092b4d571df473b5bba64bJan Voung                                 AddrMode Mode = Offset) {
117b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return new (Func->allocate<OperandARM32Mem>())
118b3401d27a236b81393092b4d571df473b5bba64bJan Voung        OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
119b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
120b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *getBase() const { return Base; }
121b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ConstantInteger32 *getOffset() const { return ImmOffset; }
122b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *getIndex() const { return Index; }
123b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ShiftKind getShiftOp() const { return ShiftOp; }
124b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint16_t getShiftAmt() const { return ShiftAmt; }
125b3401d27a236b81393092b4d571df473b5bba64bJan Voung  AddrMode getAddrMode() const { return Mode; }
126b3401d27a236b81393092b4d571df473b5bba64bJan Voung
127b3401d27a236b81393092b4d571df473b5bba64bJan Voung  bool isRegReg() const { return Index != nullptr; }
1280fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  bool isNegAddrMode() const {
1290fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    // Positive address modes have the "U" bit set, and negative modes don't.
1300fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    static_assert((PreIndex & (4 << 21)) != 0,
1310fa6c5a062f465360448a672abed3b916b413ca8Jan Voung                  "Positive addr modes should have U bit set.");
1320fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    static_assert((NegPreIndex & (4 << 21)) == 0,
1330fa6c5a062f465360448a672abed3b916b413ca8Jan Voung                  "Negative addr modes should have U bit clear.");
1340fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    return (Mode & (4 << 21)) == 0;
1350fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  }
136b3401d27a236b81393092b4d571df473b5bba64bJan Voung
137b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override;
138b3401d27a236b81393092b4d571df473b5bba64bJan Voung  using OperandARM32::dump;
139b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func, Ostream &Str) const override;
140b3401d27a236b81393092b4d571df473b5bba64bJan Voung
141b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static bool classof(const Operand *Operand) {
142b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return Operand->getKind() == static_cast<OperandKind>(kMem);
143b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
144b3401d27a236b81393092b4d571df473b5bba64bJan Voung
14557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Return true if a load/store instruction for an element of type Ty can
14657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// encode the Offset directly in the immediate field of the 32-bit ARM
14757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. For some types, if the load is Sign extending, then the range
14857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is reduced.
149b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
150b3401d27a236b81393092b4d571df473b5bba64bJan Voung
151b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
152b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
153b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  ConstantInteger32 *ImmOffset, AddrMode Mode);
154b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
155b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
1561bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
157b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *Base;
158b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ConstantInteger32 *ImmOffset;
159b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *Index;
160b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ShiftKind ShiftOp;
161b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint16_t ShiftAmt;
162b3401d27a236b81393092b4d571df473b5bba64bJan Voung  AddrMode Mode;
163b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
164b3401d27a236b81393092b4d571df473b5bba64bJan Voung
1652758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// OperandARM32ShAmtImm represents an Immediate that is used in one of the
1662758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
1672758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// shifted registers.
1682758bb077495d7a88b3d66368b3d760de61cedc7John Portoclass OperandARM32ShAmtImm : public OperandARM32 {
1692758bb077495d7a88b3d66368b3d760de61cedc7John Porto  OperandARM32ShAmtImm() = delete;
1702758bb077495d7a88b3d66368b3d760de61cedc7John Porto  OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
1712758bb077495d7a88b3d66368b3d760de61cedc7John Porto  OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;
1722758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1732758bb077495d7a88b3d66368b3d760de61cedc7John Portopublic:
1742758bb077495d7a88b3d66368b3d760de61cedc7John Porto  static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
1752758bb077495d7a88b3d66368b3d760de61cedc7John Porto    return new (Func->allocate<OperandARM32ShAmtImm>())
1762758bb077495d7a88b3d66368b3d760de61cedc7John Porto        OperandARM32ShAmtImm(ShAmt);
1772758bb077495d7a88b3d66368b3d760de61cedc7John Porto  }
1782758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1792758bb077495d7a88b3d66368b3d760de61cedc7John Porto  static bool classof(const Operand *Operand) {
1802758bb077495d7a88b3d66368b3d760de61cedc7John Porto    return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
1812758bb077495d7a88b3d66368b3d760de61cedc7John Porto  }
1822758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1832758bb077495d7a88b3d66368b3d760de61cedc7John Porto  void emit(const Cfg *Func) const override;
1842758bb077495d7a88b3d66368b3d760de61cedc7John Porto  using OperandARM32::dump;
1852758bb077495d7a88b3d66368b3d760de61cedc7John Porto  void dump(const Cfg *Func, Ostream &Str) const override;
1862758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1872758bb077495d7a88b3d66368b3d760de61cedc7John Porto  uint32_t getShAmtImm() const { return ShAmt->getValue(); }
1882758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1892758bb077495d7a88b3d66368b3d760de61cedc7John Portoprivate:
1902758bb077495d7a88b3d66368b3d760de61cedc7John Porto  explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);
1912758bb077495d7a88b3d66368b3d760de61cedc7John Porto
1922758bb077495d7a88b3d66368b3d760de61cedc7John Porto  const ConstantInteger32 *const ShAmt;
1932758bb077495d7a88b3d66368b3d760de61cedc7John Porto};
1942758bb077495d7a88b3d66368b3d760de61cedc7John Porto
19557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// OperandARM32Flex represent the "flexible second operand" for data-processing
19657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. It can be a rotatable 8-bit constant, or a register with an
19757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// optional shift operand. The shift amount can even be a third register.
198b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32Flex : public OperandARM32 {
199b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Flex() = delete;
200b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Flex(const OperandARM32Flex &) = delete;
201b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
202b3401d27a236b81393092b4d571df473b5bba64bJan Voung
203b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
204b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static bool classof(const Operand *Operand) {
205b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
206b3401d27a236b81393092b4d571df473b5bba64bJan Voung           Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
207b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
208b3401d27a236b81393092b4d571df473b5bba64bJan Voung
209b3401d27a236b81393092b4d571df473b5bba64bJan Voungprotected:
210b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
211b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
212b3401d27a236b81393092b4d571df473b5bba64bJan Voung
2139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Rotated immediate variant.
214b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32FlexImm : public OperandARM32Flex {
215b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexImm() = delete;
216b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
217b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
218b3401d27a236b81393092b4d571df473b5bba64bJan Voung
219b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
2209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
221b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
22267574d83d05f5bde748843a73adcab6247736601Karl Schimpf                                     uint32_t RotateAmt);
223b3401d27a236b81393092b4d571df473b5bba64bJan Voung
224b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override;
225b3401d27a236b81393092b4d571df473b5bba64bJan Voung  using OperandARM32::dump;
226b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func, Ostream &Str) const override;
227b3401d27a236b81393092b4d571df473b5bba64bJan Voung
228b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static bool classof(const Operand *Operand) {
229b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
230b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
231b3401d27a236b81393092b4d571df473b5bba64bJan Voung
23257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
23357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the out-params RotateAmt and Immed_8 if Immediate fits.
234b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
235b3401d27a236b81393092b4d571df473b5bba64bJan Voung                         uint32_t *Immed_8);
236b3401d27a236b81393092b4d571df473b5bba64bJan Voung
237b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint32_t getImm() const { return Imm; }
238b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint32_t getRotateAmt() const { return RotateAmt; }
239b3401d27a236b81393092b4d571df473b5bba64bJan Voung
240b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
241b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
242b3401d27a236b81393092b4d571df473b5bba64bJan Voung
243b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint32_t Imm;
244b3401d27a236b81393092b4d571df473b5bba64bJan Voung  uint32_t RotateAmt;
245b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
246b3401d27a236b81393092b4d571df473b5bba64bJan Voung
247ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto/// Modified Floating-point constant.
248ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoclass OperandARM32FlexFpImm : public OperandARM32Flex {
249ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpImm() = delete;
250ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete;
251ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete;
252ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
253ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portopublic:
254ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty,
255ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto                                       uint32_t ModifiedImm) {
256ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    return new (Func->allocate<OperandARM32FlexFpImm>())
257ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto        OperandARM32FlexFpImm(Func, Ty, ModifiedImm);
258ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  }
259ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
260ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  void emit(const Cfg *Func) const override;
261ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  using OperandARM32::dump;
262ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  void dump(const Cfg *Func, Ostream &Str) const override;
263ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
264ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  static bool classof(const Operand *Operand) {
265ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
266ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  }
267ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
268dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto  static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm);
269ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
270c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf  uint32_t getModifiedImm() const { return ModifiedImm; }
271c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf
272ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoprivate:
273ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
274ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
275c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf  const uint32_t ModifiedImm;
276ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto};
277ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
278ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto/// An operand for representing the 0.0 immediate in vcmp.
279ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoclass OperandARM32FlexFpZero : public OperandARM32Flex {
280ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpZero() = delete;
281ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete;
282ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete;
283ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
284ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portopublic:
285ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) {
286ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    return new (Func->allocate<OperandARM32FlexFpZero>())
287ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto        OperandARM32FlexFpZero(Func, Ty);
288ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  }
289ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
290ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  void emit(const Cfg *Func) const override;
291ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  using OperandARM32::dump;
292ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  void dump(const Cfg *Func, Ostream &Str) const override;
293ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
294ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  static bool classof(const Operand *Operand) {
295ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero);
296ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  }
297ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
298ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoprivate:
299ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  OperandARM32FlexFpZero(Cfg *Func, Type Ty);
300ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto};
301ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto
3029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Shifted register variant.
303b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32FlexReg : public OperandARM32Flex {
304b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexReg() = delete;
305b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
306b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
307b3401d27a236b81393092b4d571df473b5bba64bJan Voung
308b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
3099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Register with immediate/reg shift amount and shift operation.
310b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
311b3401d27a236b81393092b4d571df473b5bba64bJan Voung                                     ShiftKind ShiftOp, Operand *ShiftAmt) {
312b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return new (Func->allocate<OperandARM32FlexReg>())
313b3401d27a236b81393092b4d571df473b5bba64bJan Voung        OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
314b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
315b3401d27a236b81393092b4d571df473b5bba64bJan Voung
316b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override;
317b3401d27a236b81393092b4d571df473b5bba64bJan Voung  using OperandARM32::dump;
318b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func, Ostream &Str) const override;
319b3401d27a236b81393092b4d571df473b5bba64bJan Voung
320b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static bool classof(const Operand *Operand) {
321b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
322b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
323b3401d27a236b81393092b4d571df473b5bba64bJan Voung
324b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *getReg() const { return Reg; }
325b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ShiftKind getShiftOp() const { return ShiftOp; }
3269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// ShiftAmt can represent an immediate or a register.
327b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Operand *getShiftAmt() const { return ShiftAmt; }
328b3401d27a236b81393092b4d571df473b5bba64bJan Voung
329b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
330b3401d27a236b81393092b4d571df473b5bba64bJan Voung  OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
331b3401d27a236b81393092b4d571df473b5bba64bJan Voung                      Operand *ShiftAmt);
332b3401d27a236b81393092b4d571df473b5bba64bJan Voung
333b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Variable *Reg;
334b3401d27a236b81393092b4d571df473b5bba64bJan Voung  ShiftKind ShiftOp;
335b3401d27a236b81393092b4d571df473b5bba64bJan Voung  Operand *ShiftAmt;
336b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung};
337b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
33828068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung/// StackVariable represents a Var that isn't assigned a register (stack-only).
33928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung/// It is assigned a stack slot, but the slot's offset may be too large to
34057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// represent in the native addressing mode, and so it has a separate base
34157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register from SP/FP, where the offset from that base register is then in
34257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range.
34328068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungclass StackVariable final : public Variable {
34428068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  StackVariable() = delete;
34528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  StackVariable(const StackVariable &) = delete;
34628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  StackVariable &operator=(const StackVariable &) = delete;
34728068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung
34828068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungpublic:
34928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
350467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth    return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index);
35128068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  }
3522d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth  constexpr static auto StackVariableKind =
35328068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung      static_cast<OperandKind>(kVariable_Target);
35428068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  static bool classof(const Operand *Operand) {
35528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung    return Operand->getKind() == StackVariableKind;
35628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  }
3578aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
3588aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  RegNumT getBaseRegNum() const override { return BaseRegNum; }
35928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung  // Inherit dump() and emit() from Variable.
36028068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung
36128068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungprivate:
362467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  StackVariable(const Cfg *Func, Type Ty, SizeT Index)
363467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth      : Variable(Func, StackVariableKind, Ty, Index) {}
3645fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler  RegNumT BaseRegNum;
36528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung};
36628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung
3679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Base class for ARM instructions. While most ARM instructions can be
36857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// conditionally executed, a few of them are not predicable (halt, memory
36957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// barriers, etc.).
370b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass InstARM32 : public InstTarget {
371b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32() = delete;
372b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32(const InstARM32 &) = delete;
373b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32 &operator=(const InstARM32 &) = delete;
374b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
375b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic:
376c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  // Defines form that assembly instruction should be synthesized.
377c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  enum EmitForm { Emit_Text, Emit_Binary };
378c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
379b3401d27a236b81393092b4d571df473b5bba64bJan Voung  enum InstKindARM32 {
380b3401d27a236b81393092b4d571df473b5bba64bJan Voung    k__Start = Inst::Target,
3812971997a96b7484165cfedead111c7cafb3073aeJan Voung    Adc,
3822971997a96b7484165cfedead111c7cafb3073aeJan Voung    Add,
3832971997a96b7484165cfedead111c7cafb3073aeJan Voung    And,
38466c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung    Asr,
38555500dbceb14d4223533701158389e89c1f93a5eJan Voung    Bic,
3863bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Br,
3873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Call,
3881956788f4459e0fedf91c10e8c266ca72a5d5fa1Karl Schimpf    Clz,
389ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    Cmn,
3903bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Cmp,
39116991847500a48932426d979c4f2d4adffaf3649John Porto    Dmb,
3922971997a96b7484165cfedead111c7cafb3073aeJan Voung    Eor,
393658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    Extract,
394658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    Insert,
3956ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Label,
3962971997a96b7484165cfedead111c7cafb3073aeJan Voung    Ldr,
39716991847500a48932426d979c4f2d4adffaf3649John Porto    Ldrex,
3983bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Lsl,
39966c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung    Lsr,
400f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf    Nop,
4012971997a96b7484165cfedead111c7cafb3073aeJan Voung    Mla,
4026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Mls,
403b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Mov,
404b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Movt,
405b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Movw,
4062971997a96b7484165cfedead111c7cafb3073aeJan Voung    Mul,
407b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Mvn,
4082971997a96b7484165cfedead111c7cafb3073aeJan Voung    Orr,
4090fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    Pop,
4100fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    Push,
411f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung    Rbit,
412b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Ret,
413f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung    Rev,
41466c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung    Rsb,
415ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    Rsc,
4162971997a96b7484165cfedead111c7cafb3073aeJan Voung    Sbc,
4176ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Sdiv,
418befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung    Str,
41916991847500a48932426d979c4f2d4adffaf3649John Porto    Strex,
4202971997a96b7484165cfedead111c7cafb3073aeJan Voung    Sub,
42166c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung    Sxt,
4226ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Trap,
4236ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Tst,
4246ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Udiv,
42566c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung    Umull,
42686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Uxt,
427ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto    Vabs,
42886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Vadd,
429b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holk    Vand,
430397f602c4e4e5697806bf74e37a651ab78680628John Porto    Vbsl,
431a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    Vceq,
432a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    Vcge,
433a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    Vcgt,
4342f5534f1c523eb022880360864f60ce42fb30ee0John Porto    Vcmp,
435c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto    Vcvt,
43686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Vdiv,
437f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vdup,
438ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    Veor,
439675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vldr1d,
440675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vldr1q,
441eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Vmla,
442675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vmlap,
443eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Vmls,
444f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vmovl,
445f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vmovh,
446f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vmovhl,
447f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vmovlh,
4482f5534f1c523eb022880360864f60ce42fb30ee0John Porto    Vmrs,
44986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Vmul,
450675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vmulh,
451a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    Vmvn,
45215e77d4698df65dfce5072b59df18500ff56daa3John Porto    Vneg,
453cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holk    Vorr,
454b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin    Vqadd,
455675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vqmovn2,
456b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin    Vqsub,
45715e77d4698df65dfce5072b59df18500ff56daa3John Porto    Vshl,
458e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Vshr,
45986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Vsqrt,
460675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    Vstr1,
461f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vsub,
462f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    Vzip
463b3401d27a236b81393092b4d571df473b5bba64bJan Voung  };
464b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
465856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  static constexpr size_t InstSize = sizeof(uint32_t);
466856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf
4673bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
468b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
469856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  /// Called inside derived methods emit() to communicate that multiple
470856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  /// instructions are being generated. Used by emitIAS() methods to
471856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  /// generate textual fixups for instructions that are not yet
472856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  /// implemented.
473856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf  void startNextInst(const Cfg *Func) const;
474856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf
47515e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// FPSign is used for certain vector instructions (particularly, right
47615e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// shifts) that require an operand sign specification.
47715e77d4698df65dfce5072b59df18500ff56daa3John Porto  enum FPSign {
47815e77d4698df65dfce5072b59df18500ff56daa3John Porto    FS_None,
47915e77d4698df65dfce5072b59df18500ff56daa3John Porto    FS_Signed,
48015e77d4698df65dfce5072b59df18500ff56daa3John Porto    FS_Unsigned,
48115e77d4698df65dfce5072b59df18500ff56daa3John Porto  };
48286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  /// Shared emit routines for common forms of instructions.
48315e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// @{
48415e77d4698df65dfce5072b59df18500ff56daa3John Porto  static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
485a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto                              const InstARM32 *Instr, const Cfg *Func,
486a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto                              Type OpType);
48715e77d4698df65dfce5072b59df18500ff56daa3John Porto  static void emitFourAddrFP(const char *Opcode, FPSign Sign,
48815e77d4698df65dfce5072b59df18500ff56daa3John Porto                             const InstARM32 *Instr, const Cfg *Func);
48915e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// @}
49086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
491b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  void dump(const Cfg *Func) const override;
492b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
4932fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf  void emitIAS(const Cfg *Func) const override;
4942fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf
495b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprotected:
496b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
497b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung      : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
4981bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
4998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
5008cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == static_cast<InstKind>(MyKind);
501b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  }
5022fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf
5032fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf  // Generates text of assembly instruction using method emit(), and then adds
5042fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf  // to the assembly buffer as a Fixup.
5052fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf  void emitUsingTextFixup(const Cfg *Func) const;
506b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung};
507b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
5089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// A predicable ARM instruction.
5093bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Pred : public InstARM32 {
5103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Pred() = delete;
5113bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Pred(const InstARM32Pred &) = delete;
5123bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Pred &operator=(const InstARM32Pred &) = delete;
513b3401d27a236b81393092b4d571df473b5bba64bJan Voung
5143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic:
5153bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
5163bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                CondARM32::Cond Predicate)
5173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
5183bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
5193bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  CondARM32::Cond getPredicate() const { return Predicate; }
5203bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
5213bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
5223bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static const char *predString(CondARM32::Cond Predicate);
5233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
5243bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
5259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Shared emit routines for common forms of instructions.
5268cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
527f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung                             const Cfg *Func, bool NeedsWidthSuffix);
52815e77d4698df65dfce5072b59df18500ff56daa3John Porto  static void emitUnaryopFP(const char *Opcode, FPSign Sign,
52915e77d4698df65dfce5072b59df18500ff56daa3John Porto                            const InstARM32Pred *Instr, const Cfg *Func);
5308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
5313bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                          const Cfg *Func);
5328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
5333bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                            const Cfg *Func, bool SetFlags);
5348cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
5356ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                           const Cfg *Func);
5368cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
5376ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                          const Cfg *Func);
5383bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
5393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprotected:
5403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  CondARM32::Cond Predicate;
5413bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung};
5423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
5433bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungtemplate <typename StreamType>
5443bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Vounginline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
5453bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  Stream << InstARM32Pred::predString(Predicate);
5463bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  return Stream;
5473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung}
548b3401d27a236b81393092b4d571df473b5bba64bJan Voung
5499612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := op(y).
550f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voungtemplate <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
5513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32UnaryopGPR : public InstARM32Pred {
552b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32UnaryopGPR() = delete;
553b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
554b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
555b3401d27a236b81393092b4d571df473b5bba64bJan Voung
556b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
5573bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
5583bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                                     CondARM32::Cond Predicate) {
559b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return new (Func->allocate<InstARM32UnaryopGPR>())
5603bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung        InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
561b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
562b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override {
56320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
564b3401d27a236b81393092b4d571df473b5bba64bJan Voung      return;
565f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung    emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
566b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
5677cb2db327e386372003cdb45e2c3acef774fb902Karl Schimpf  void emitIAS(const Cfg *Func) const override;
568b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func) const override {
56920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
570b3401d27a236b81393092b4d571df473b5bba64bJan Voung      return;
571b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Ostream &Str = Func->getContext()->getStrDump();
572b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpDest(Func);
5733bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " = ";
5743bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
5753bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " ";
576b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpSources(Func);
577b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
5788cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
579b3401d27a236b81393092b4d571df473b5bba64bJan Voung
580b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
5813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
5823bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                      CondARM32::Cond Predicate)
5833bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
584b3401d27a236b81393092b4d571df473b5bba64bJan Voung    addSource(Src);
585b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
5861bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
587b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static const char *Opcode;
588b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
589b3401d27a236b81393092b4d571df473b5bba64bJan Voung
59086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x := op(y), for vector/FP.
59186ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <InstARM32::InstKindARM32 K>
59286ebec12680b5268fcb7082f770a26394e8b8080Jan Voungclass InstARM32UnaryopFP : public InstARM32Pred {
59386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32UnaryopFP() = delete;
59486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
59586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
59686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
59786ebec12680b5268fcb7082f770a26394e8b8080Jan Voungpublic:
59886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
59986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung                                    CondARM32::Cond Predicate) {
60086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    return new (Func->allocate<InstARM32UnaryopFP>())
60186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung        InstARM32UnaryopFP(Func, Dest, Src, Predicate);
60286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
60386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  void emit(const Cfg *Func) const override {
60486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    if (!BuildDefs::dump())
60586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      return;
60615e77d4698df65dfce5072b59df18500ff56daa3John Porto    emitUnaryopFP(Opcode, Sign, this, Func);
60786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
608266c5a25bb8c07b691aa6396ccef6f8d37df9cd0Karl Schimpf  void emitIAS(const Cfg *Func) const override;
60986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  void dump(const Cfg *Func) const override {
61086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    if (!BuildDefs::dump())
61186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      return;
61286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Ostream &Str = Func->getContext()->getStrDump();
61386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    dumpDest(Func);
61486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Str << " = ";
61586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
61686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Str << " ";
61786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    dumpSources(Func);
61886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
6198cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
62086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
62115e77d4698df65dfce5072b59df18500ff56daa3John Portoprotected:
62286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
62386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung                     CondARM32::Cond Predicate)
62486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
62586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    addSource(Src);
62686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
62786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
62815e77d4698df65dfce5072b59df18500ff56daa3John Porto  FPSign Sign = FS_None;
62986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  static const char *Opcode;
63086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung};
63186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
63215e77d4698df65dfce5072b59df18500ff56daa3John Portotemplate <InstARM32::InstKindARM32 K>
63315e77d4698df65dfce5072b59df18500ff56daa3John Portoclass InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> {
63415e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32UnaryopSignAwareFP() = delete;
63515e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete;
63615e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32UnaryopSignAwareFP &
63715e77d4698df65dfce5072b59df18500ff56daa3John Porto  operator=(const InstARM32UnaryopSignAwareFP &) = delete;
63815e77d4698df65dfce5072b59df18500ff56daa3John Porto
63915e77d4698df65dfce5072b59df18500ff56daa3John Portopublic:
64015e77d4698df65dfce5072b59df18500ff56daa3John Porto  static InstARM32UnaryopSignAwareFP *
64115e77d4698df65dfce5072b59df18500ff56daa3John Porto  create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) {
64215e77d4698df65dfce5072b59df18500ff56daa3John Porto    return new (Func->allocate<InstARM32UnaryopSignAwareFP>())
64315e77d4698df65dfce5072b59df18500ff56daa3John Porto        InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate);
64415e77d4698df65dfce5072b59df18500ff56daa3John Porto  }
64515e77d4698df65dfce5072b59df18500ff56daa3John Porto  void emitIAS(const Cfg *Func) const override;
64615e77d4698df65dfce5072b59df18500ff56daa3John Porto  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
64715e77d4698df65dfce5072b59df18500ff56daa3John Porto
64815e77d4698df65dfce5072b59df18500ff56daa3John Portoprivate:
64915e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src,
65015e77d4698df65dfce5072b59df18500ff56daa3John Porto                              CondARM32::Cond Predicate)
65115e77d4698df65dfce5072b59df18500ff56daa3John Porto      : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {}
65215e77d4698df65dfce5072b59df18500ff56daa3John Porto};
65315e77d4698df65dfce5072b59df18500ff56daa3John Porto
6549612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := x op y.
655b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <InstARM32::InstKindARM32 K>
6563bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32TwoAddrGPR : public InstARM32Pred {
657b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32TwoAddrGPR() = delete;
658b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
659b3401d27a236b81393092b4d571df473b5bba64bJan Voung  InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
660b3401d27a236b81393092b4d571df473b5bba64bJan Voung
661b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
6629612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Dest must be a register.
6633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
6643bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                                     CondARM32::Cond Predicate) {
665b3401d27a236b81393092b4d571df473b5bba64bJan Voung    return new (Func->allocate<InstARM32TwoAddrGPR>())
6663bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung        InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
667b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
668b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override {
66920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
670b3401d27a236b81393092b4d571df473b5bba64bJan Voung      return;
671b3401d27a236b81393092b4d571df473b5bba64bJan Voung    emitTwoAddr(Opcode, this, Func);
672b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
6732fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf  void emitIAS(const Cfg *Func) const override;
674b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func) const override {
67520b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
676b3401d27a236b81393092b4d571df473b5bba64bJan Voung      return;
677b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Ostream &Str = Func->getContext()->getStrDump();
678b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpDest(Func);
6793bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " = ";
6803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
6813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " ";
682b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpSources(Func);
683b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
6848cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
685b3401d27a236b81393092b4d571df473b5bba64bJan Voung
686b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
6873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
6883bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                      CondARM32::Cond Predicate)
6893bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      : InstARM32Pred(Func, K, 2, Dest, Predicate) {
690b3401d27a236b81393092b4d571df473b5bba64bJan Voung    addSource(Dest);
691b3401d27a236b81393092b4d571df473b5bba64bJan Voung    addSource(Src);
692b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
6931bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
694b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static const char *Opcode;
695b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
696b3401d27a236b81393092b4d571df473b5bba64bJan Voung
69716991847500a48932426d979c4f2d4adffaf3649John Porto/// Base class for load instructions.
698b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <InstARM32::InstKindARM32 K>
69916991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32LoadBase : public InstARM32Pred {
70016991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32LoadBase() = delete;
70116991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32LoadBase(const InstARM32LoadBase &) = delete;
70216991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
703b3401d27a236b81393092b4d571df473b5bba64bJan Voung
704b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic:
70516991847500a48932426d979c4f2d4adffaf3649John Porto  static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
70616991847500a48932426d979c4f2d4adffaf3649John Porto                                   CondARM32::Cond Predicate) {
70716991847500a48932426d979c4f2d4adffaf3649John Porto    return new (Func->allocate<InstARM32LoadBase>())
70816991847500a48932426d979c4f2d4adffaf3649John Porto        InstARM32LoadBase(Func, Dest, Source, Predicate);
709b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
710b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void emit(const Cfg *Func) const override;
711f0655b6cebd64b393bdd4a51706c5ee3f229ce82Karl Schimpf  void emitIAS(const Cfg *Func) const override;
712b3401d27a236b81393092b4d571df473b5bba64bJan Voung  void dump(const Cfg *Func) const override {
71320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
714b3401d27a236b81393092b4d571df473b5bba64bJan Voung      return;
715b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Ostream &Str = Func->getContext()->getStrDump();
7163bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
7173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " ";
718b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpDest(Func);
719b3401d27a236b81393092b4d571df473b5bba64bJan Voung    Str << ", ";
720b3401d27a236b81393092b4d571df473b5bba64bJan Voung    dumpSources(Func);
721b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
7228cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
723b3401d27a236b81393092b4d571df473b5bba64bJan Voung
724b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate:
72516991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
72616991847500a48932426d979c4f2d4adffaf3649John Porto                    CondARM32::Cond Predicate)
7273bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
728b3401d27a236b81393092b4d571df473b5bba64bJan Voung    addSource(Source);
729b3401d27a236b81393092b4d571df473b5bba64bJan Voung  }
730b3401d27a236b81393092b4d571df473b5bba64bJan Voung
731b3401d27a236b81393092b4d571df473b5bba64bJan Voung  static const char *Opcode;
732b3401d27a236b81393092b4d571df473b5bba64bJan Voung};
733b3401d27a236b81393092b4d571df473b5bba64bJan Voung
7349612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := y op z. May have the side-effect of setting
7359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// status flags.
7362971997a96b7484165cfedead111c7cafb3073aeJan Voungtemplate <InstARM32::InstKindARM32 K>
7373bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32ThreeAddrGPR : public InstARM32Pred {
7382971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32ThreeAddrGPR() = delete;
7392971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
7402971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
7412971997a96b7484165cfedead111c7cafb3073aeJan Voung
7422971997a96b7484165cfedead111c7cafb3073aeJan Voungpublic:
74357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
74457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// must be registers.
7452971997a96b7484165cfedead111c7cafb3073aeJan Voung  static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
7466ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                                       Variable *Src0, Operand *Src1,
7473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                                       CondARM32::Cond Predicate,
7482971997a96b7484165cfedead111c7cafb3073aeJan Voung                                       bool SetFlags = false) {
7492971997a96b7484165cfedead111c7cafb3073aeJan Voung    return new (Func->allocate<InstARM32ThreeAddrGPR>())
7506ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
7512971997a96b7484165cfedead111c7cafb3073aeJan Voung  }
7522971997a96b7484165cfedead111c7cafb3073aeJan Voung  void emit(const Cfg *Func) const override {
75320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
7542971997a96b7484165cfedead111c7cafb3073aeJan Voung      return;
7552971997a96b7484165cfedead111c7cafb3073aeJan Voung    emitThreeAddr(Opcode, this, Func, SetFlags);
7562971997a96b7484165cfedead111c7cafb3073aeJan Voung  }
757372bdd6e84a14b6bcc00b4e9ed24a1838bd0c4d7Karl Schimpf  void emitIAS(const Cfg *Func) const override;
7582971997a96b7484165cfedead111c7cafb3073aeJan Voung  void dump(const Cfg *Func) const override {
75920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    if (!BuildDefs::dump())
7602971997a96b7484165cfedead111c7cafb3073aeJan Voung      return;
7612971997a96b7484165cfedead111c7cafb3073aeJan Voung    Ostream &Str = Func->getContext()->getStrDump();
7622971997a96b7484165cfedead111c7cafb3073aeJan Voung    dumpDest(Func);
7633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << " = ";
7643bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
7653bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    Str << (SetFlags ? ".s " : " ");
7662971997a96b7484165cfedead111c7cafb3073aeJan Voung    dumpSources(Func);
7672971997a96b7484165cfedead111c7cafb3073aeJan Voung  }
7688cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
7692971997a96b7484165cfedead111c7cafb3073aeJan Voung
7702971997a96b7484165cfedead111c7cafb3073aeJan Voungprivate:
7716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
7726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                        Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
7733bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
774ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    HasSideEffects = SetFlags;
7756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src0);
7762971997a96b7484165cfedead111c7cafb3073aeJan Voung    addSource(Src1);
7772971997a96b7484165cfedead111c7cafb3073aeJan Voung  }
7781bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
7792971997a96b7484165cfedead111c7cafb3073aeJan Voung  static const char *Opcode;
7802971997a96b7484165cfedead111c7cafb3073aeJan Voung  bool SetFlags;
7812971997a96b7484165cfedead111c7cafb3073aeJan Voung};
7822971997a96b7484165cfedead111c7cafb3073aeJan Voung
78357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Instructions of the form x := y op z, for vector/FP. We leave these as
78486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// unconditional: "ARM deprecates the conditional execution of any instruction
78586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// encoding provided by the Advanced SIMD Extension that is not also provided
786eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// by the floating-point (VFP) extension". They do not set flags.
78786ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <InstARM32::InstKindARM32 K>
78886ebec12680b5268fcb7082f770a26394e8b8080Jan Voungclass InstARM32ThreeAddrFP : public InstARM32 {
78986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32ThreeAddrFP() = delete;
79086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
79186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
79286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
79386ebec12680b5268fcb7082f770a26394e8b8080Jan Voungpublic:
79457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
79557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// must be a register.
79686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
79786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung                                      Variable *Src1) {
79886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    return new (Func->allocate<InstARM32ThreeAddrFP>())
79986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung        InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
80086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
80186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  void emit(const Cfg *Func) const override {
80286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    if (!BuildDefs::dump())
80386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      return;
804a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
805a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
80686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
8074acf11ac13716f5998b56cb65c1c72341276cc5fKarl Schimpf  void emitIAS(const Cfg *Func) const override;
80886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  void dump(const Cfg *Func) const override {
80986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    if (!BuildDefs::dump())
81086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      return;
81186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    Ostream &Str = Func->getContext()->getStrDump();
81286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    dumpDest(Func);
813a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
814a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    Str << " = " << Opcode << "." << OpType << " ";
81586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    dumpSources(Func);
81686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
8178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
81886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
81915e77d4698df65dfce5072b59df18500ff56daa3John Portoprotected:
82015e77d4698df65dfce5072b59df18500ff56daa3John Porto  FPSign Sign = FS_None;
82115e77d4698df65dfce5072b59df18500ff56daa3John Porto
82215e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
82386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung      : InstARM32(Func, K, 2, Dest) {
82486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    addSource(Src0);
82586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung    addSource(Src1);
82686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  }
82786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
82886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung  static const char *Opcode;
829a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto
830a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portoprivate:
831a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto  static constexpr bool isVectorCompare() {
832a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto    return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
833a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto  }
83486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung};
83586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung
83615e77d4698df65dfce5072b59df18500ff56daa3John Portotemplate <InstARM32::InstKindARM32 K>
83715e77d4698df65dfce5072b59df18500ff56daa3John Portoclass InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> {
83815e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32ThreeAddrSignAwareFP() = delete;
83915e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete;
84015e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32ThreeAddrSignAwareFP &
84115e77d4698df65dfce5072b59df18500ff56daa3John Porto  operator=(const InstARM32ThreeAddrSignAwareFP &) = delete;
84215e77d4698df65dfce5072b59df18500ff56daa3John Porto
84315e77d4698df65dfce5072b59df18500ff56daa3John Portopublic:
84415e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
84515e77d4698df65dfce5072b59df18500ff56daa3John Porto  /// must be a register.
84615e77d4698df65dfce5072b59df18500ff56daa3John Porto  static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest,
84715e77d4698df65dfce5072b59df18500ff56daa3John Porto                                               Variable *Src0, Variable *Src1) {
84815e77d4698df65dfce5072b59df18500ff56daa3John Porto    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
84915e77d4698df65dfce5072b59df18500ff56daa3John Porto        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
85015e77d4698df65dfce5072b59df18500ff56daa3John Porto  }
85115e77d4698df65dfce5072b59df18500ff56daa3John Porto
852e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto  static InstARM32ThreeAddrSignAwareFP *
853e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto  create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
854e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
855e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
856e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto  }
857e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto
85815e77d4698df65dfce5072b59df18500ff56daa3John Porto  void emitIAS(const Cfg *Func) const override;
85915e77d4698df65dfce5072b59df18500ff56daa3John Porto  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
86015e77d4698df65dfce5072b59df18500ff56daa3John Porto
86115e77d4698df65dfce5072b59df18500ff56daa3John Portoprivate:
86215e77d4698df65dfce5072b59df18500ff56daa3John Porto  InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0,
863e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto                                Operand *Src1)
86415e77d4698df65dfce5072b59df18500ff56daa3John Porto      : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
86515e77d4698df65dfce5072b59df18500ff56daa3John Porto};
86615e77d4698df65dfce5072b59df18500ff56daa3John Porto
86786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
8686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungtemplate <InstARM32::InstKindARM32 K>
8696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32FourAddrGPR : public InstARM32Pred {
8706ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32FourAddrGPR() = delete;
8716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
8726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
8736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
8746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic:
8756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  // Every operand must be a register.
8766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
8776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                                      Variable *Src1, Variable *Src2,
8786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                                      CondARM32::Cond Predicate) {
8796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    return new (Func->allocate<InstARM32FourAddrGPR>())
8806ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
8816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
8826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void emit(const Cfg *Func) const override {
8836ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    if (!BuildDefs::dump())
8846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      return;
8856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    emitFourAddr(Opcode, this, Func);
8866ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
887080b65b5e73b17d39d1f08b84af3c075b3e46e77Karl Schimpf  void emitIAS(const Cfg *Func) const override;
8886ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void dump(const Cfg *Func) const override {
8896ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    if (!BuildDefs::dump())
8906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      return;
8916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Ostream &Str = Func->getContext()->getStrDump();
8926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    dumpDest(Func);
8936ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Str << " = ";
8946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    dumpOpcodePred(Str, Opcode, getDest()->getType());
8956ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Str << " ";
8966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    dumpSources(Func);
8976ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
8988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
8996ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
9006ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate:
9016ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
9026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                       Variable *Src1, Variable *Src2,
9036ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                       CondARM32::Cond Predicate)
9046ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      : InstARM32Pred(Func, K, 3, Dest, Predicate) {
9056ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src0);
9066ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src1);
9076ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src2);
9086ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
9096ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
9106ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static const char *Opcode;
9116ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung};
9126ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
913eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
914eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// We leave these as unconditional: "ARM deprecates the conditional execution
915eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// of any instruction encoding provided by the Advanced SIMD Extension that is
916eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// not also provided by the floating-point (VFP) extension". They do not set
917eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// flags.
918eb13acc6221f60642d17473b6329a82b02ae557aJohn Portotemplate <InstARM32::InstKindARM32 K>
919eb13acc6221f60642d17473b6329a82b02ae557aJohn Portoclass InstARM32FourAddrFP : public InstARM32 {
920eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  InstARM32FourAddrFP() = delete;
921eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
922eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
923eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto
924eb13acc6221f60642d17473b6329a82b02ae557aJohn Portopublic:
925eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  // Every operand must be a register.
926eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
927eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto                                     Variable *Src1) {
928eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    return new (Func->allocate<InstARM32FourAddrFP>())
929eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto        InstARM32FourAddrFP(Func, Dest, Src0, Src1);
930eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  }
931eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  void emit(const Cfg *Func) const override {
932eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    if (!BuildDefs::dump())
933eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto      return;
93415e77d4698df65dfce5072b59df18500ff56daa3John Porto    emitFourAddrFP(Opcode, Sign, this, Func);
935eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  }
9368c5544b529f63c81e72dc4c70930dd07e5739d85Karl Schimpf  void emitIAS(const Cfg *Func) const override;
937eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  void dump(const Cfg *Func) const override {
938eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    if (!BuildDefs::dump())
939eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto      return;
940eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Ostream &Str = Func->getContext()->getStrDump();
941eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    dumpDest(Func);
942eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Str << " = ";
943eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Str << Opcode << "." << getDest()->getType() << " ";
944eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    dumpDest(Func);
945eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    Str << ", ";
946eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    dumpSources(Func);
947eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  }
9488cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
949eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto
950eb13acc6221f60642d17473b6329a82b02ae557aJohn Portoprivate:
951eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
952eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto      : InstARM32(Func, K, 3, Dest) {
953eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    addSource(Dest);
954eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    addSource(Src0);
955eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto    addSource(Src1);
956eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  }
957eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto
95815e77d4698df65dfce5072b59df18500ff56daa3John Porto  FPSign Sign = FS_None;
959eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto  static const char *Opcode;
960eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto};
961eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto
96286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x cmpop y (setting flags).
9636ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungtemplate <InstARM32::InstKindARM32 K>
9646ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32CmpLike : public InstARM32Pred {
9656ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32CmpLike() = delete;
9666ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32CmpLike(const InstARM32CmpLike &) = delete;
9676ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
9686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
9696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic:
9706ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
9716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                                  CondARM32::Cond Predicate) {
9726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    return new (Func->allocate<InstARM32CmpLike>())
9736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32CmpLike(Func, Src0, Src1, Predicate);
9746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
9756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void emit(const Cfg *Func) const override {
9766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    if (!BuildDefs::dump())
9776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      return;
9786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    emitCmpLike(Opcode, this, Func);
9796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
980f8fc12f741cdbffaf82005d4f1324dc316d9d6dfKarl Schimpf  void emitIAS(const Cfg *Func) const override;
9816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void dump(const Cfg *Func) const override {
9826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    if (!BuildDefs::dump())
9836ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      return;
9846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Ostream &Str = Func->getContext()->getStrDump();
9856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
9866ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    Str << " ";
9876ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    dumpSources(Func);
9886ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
9898cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
9906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
9916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate:
9926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
9936ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                   CondARM32::Cond Predicate)
9946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
995ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    HasSideEffects = true;
9966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src0);
9976ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    addSource(Src1);
9986ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
9996ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
10006ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static const char *Opcode;
10016ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung};
10026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
10038072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
10048072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
10058072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
10068072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
10078072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
10088072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
10098072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
10108072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
10118072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
10128072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
10138072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
1014ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
10158072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
10168072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
10178072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
10188072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
10198072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
1020b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holkusing InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
1021397f602c4e4e5697806bf74e37a651ab78680628John Portousing InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
1022a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
1023a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
1024a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
10258072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
1026ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
1027eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
1028eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
1029f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>;
1030f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>;
1031f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>;
1032f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>;
1033eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
1034a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
103515e77d4698df65dfce5072b59df18500ff56daa3John Portousing InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
1036cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holkusing InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
1037b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlinusing InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
1038b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlinusing InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
1039675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
1040675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
1041675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>;
104215e77d4698df65dfce5072b59df18500ff56daa3John Portousing InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
1043e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Portousing InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
10448072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
104516991847500a48932426d979c4f2d4adffaf3649John Portousing InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
104616991847500a48932426d979c4f2d4adffaf3649John Portousing InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
1047675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>;
1048675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>;
1049f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>;
105057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// MovT leaves the bottom bits alone so dest is also a source. This helps
105157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// indicate that a previous MovW setting dest is not dead code.
10528072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
10538072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
10548072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
10558072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
10568072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
10578072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
105857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
105957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
106057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// using that for now, so just model as a Unaryop.
10618072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
10628072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
10638072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
10648072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
10658072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
1066ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
10678072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
10688072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
10696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
107057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// InstARM32Label represents an intra-block label that is the target of an
107157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// intra-block branch. The offset between the label and the branch must be fit
107257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// in the instruction immediate (considered "near").
10736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32Label : public InstARM32 {
10746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Label() = delete;
10756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Label(const InstARM32Label &) = delete;
10766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Label &operator=(const InstARM32Label &) = delete;
10776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
10786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic:
10796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
10806ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
10816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
10826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  uint32_t getEmitInstCount() const override { return 0; }
1083467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  GlobalString getLabelName() const { return Name; }
10846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  SizeT getNumber() const { return Number; }
10856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void emit(const Cfg *Func) const override;
108650a3331c517ea0945987b616f4c5cf607aa81b9bKarl Schimpf  void emitIAS(const Cfg *Func) const override;
10876ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void dump(const Cfg *Func) const override;
1088dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto  void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }
10896ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
10906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate:
10916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Label(Cfg *Func, TargetARM32 *Target);
10926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
1093dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto  RelocOffset *OffsetReloc = nullptr;
10946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  SizeT Number; // used for unique label generation.
1095467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  GlobalString Name;
10966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung};
1097b3401d27a236b81393092b4d571df473b5bba64bJan Voung
10989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Direct branch instruction.
10993bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Br : public InstARM32Pred {
11003bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Br() = delete;
11013bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Br(const InstARM32Br &) = delete;
11023bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Br &operator=(const InstARM32Br &) = delete;
11033bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
11043bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic:
11059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create a conditional branch to one of two nodes.
11063bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
11073bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                             CfgNode *TargetFalse, CondARM32::Cond Predicate) {
11083bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    assert(Predicate != CondARM32::AL);
11096ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr InstARM32Label *NoLabel = nullptr;
11103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return new (Func->allocate<InstARM32Br>())
11116ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
11123bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
11139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch to a node.
11143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
11156ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr CfgNode *NoCondTarget = nullptr;
11166ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr InstARM32Label *NoLabel = nullptr;
11173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return new (Func->allocate<InstARM32Br>())
11186ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
11193bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
112057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a non-terminator conditional branch to a node, with a fallthrough
112157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to the next instruction in the current node. This is used for switch
112257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering.
11233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32Br *create(Cfg *Func, CfgNode *Target,
11243bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                             CondARM32::Cond Predicate) {
11253bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    assert(Predicate != CondARM32::AL);
11266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr CfgNode *NoUncondTarget = nullptr;
11276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr InstARM32Label *NoLabel = nullptr;
11286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    return new (Func->allocate<InstARM32Br>())
11296ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
11306ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
11316ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  // Create a conditional intra-block branch (or unconditional, if
11326ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  // Condition==AL) to a label in the current block.
11336ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
11346ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung                             CondARM32::Cond Predicate) {
11356ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr CfgNode *NoCondTarget = nullptr;
11366ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    constexpr CfgNode *NoUncondTarget = nullptr;
11373bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return new (Func->allocate<InstARM32Br>())
11386ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung        InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
11393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
11403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  const CfgNode *getTargetTrue() const { return TargetTrue; }
11413bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  const CfgNode *getTargetFalse() const { return TargetFalse; }
11423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  bool optimizeBranch(const CfgNode *NextNode);
11433bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  uint32_t getEmitInstCount() const override {
11443bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    uint32_t Sum = 0;
11456ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    if (Label)
11466ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung      ++Sum;
11473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    if (getTargetTrue())
11483bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      ++Sum;
11493bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    if (getTargetFalse())
11503bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung      ++Sum;
11513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return Sum;
11523bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
11533bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  bool isUnconditionalBranch() const override {
11543bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return getPredicate() == CondARM32::AL;
11553bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
115687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
11573bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void emit(const Cfg *Func) const override;
1158137e62bd843313d4b8697621989e0e6f5c2e7f81Karl Schimpf  void emitIAS(const Cfg *Func) const override;
11593bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void dump(const Cfg *Func) const override;
11608cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
11613bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
11623bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprivate:
11633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
11646ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung              const InstARM32Label *Label, CondARM32::Cond Predicate);
11651bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
11663bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  const CfgNode *TargetTrue;
11673bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  const CfgNode *TargetFalse;
11686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  const InstARM32Label *Label; // Intra-block branch target
11693bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung};
11703bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
117157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction (bl/blx). Arguments should have already been pushed.
11729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Technically bl and the register form of blx can be predicated, but we'll
11739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// leave that out until needed.
11743bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Call : public InstARM32 {
11753bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Call() = delete;
11763bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Call(const InstARM32Call &) = delete;
11773bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Call &operator=(const InstARM32Call &) = delete;
11783bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
11793bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic:
11803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
11813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung    return new (Func->allocate<InstARM32Call>())
11823bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung        InstARM32Call(Func, Dest, CallTarget);
11833bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  }
11843bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  Operand *getCallTarget() const { return getSrc(0); }
11853bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void emit(const Cfg *Func) const override;
1186174531ec83bf9d51b2dc669b3f73f1fb637fbcceKarl Schimpf  void emitIAS(const Cfg *Func) const override;
11873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  void dump(const Cfg *Func) const override;
11888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
11893bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
11903bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprivate:
11913bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung  InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
11923bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung};
11933bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung
1194c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfclass InstARM32RegisterStackOp : public InstARM32 {
1195c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  InstARM32RegisterStackOp() = delete;
1196c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1197c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  InstARM32RegisterStackOp &
1198c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  operator=(const InstARM32RegisterStackOp &) = delete;
1199c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
1200c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfpublic:
1201c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emit(const Cfg *Func) const override;
1202c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitIAS(const Cfg *Func) const override;
1203c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void dump(const Cfg *Func) const override;
1204c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
1205c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfprotected:
1206c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1207c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                           Variable *Dest)
1208c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf      : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1209c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1210c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitGPRsAsText(const Cfg *Func) const;
1211c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1212c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                       SizeT Regcount) const;
121300c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpf  void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
121400c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpf                   SizeT RegCount, SizeT InstIndex) const;
1215c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1216c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual const char *getGPROpcode() const = 0;
1217c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual const char *getSRegOpcode() const = 0;
1218c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual Variable *getStackReg(SizeT Index) const = 0;
1219c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual SizeT getNumStackRegs() const = 0;
1220c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1221c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                             const Variable *Reg) const = 0;
1222c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1223c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                                IValueT Registers) const = 0;
1224c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1225c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                         const Variable *BaseReg, SizeT RegCount) const = 0;
1226c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf};
1227c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf
1228eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1229eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// regs, but not both. In any case, the list must be sorted.
123000c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpfclass InstARM32Pop final : public InstARM32RegisterStackOp {
12310fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Pop() = delete;
12320fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Pop(const InstARM32Pop &) = delete;
12330fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Pop &operator=(const InstARM32Pop &) = delete;
12340fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
12350fa6c5a062f465360448a672abed3b916b413ca8Jan Voungpublic:
12360fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
12370fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
12380fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  }
12398cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
12400fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
12410fa6c5a062f465360448a672abed3b916b413ca8Jan Voungprivate:
12420fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Pop(Cfg *Func, const VarList &Dests);
1243c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual const char *getGPROpcode() const final;
1244c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  virtual const char *getSRegOpcode() const final;
1245c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  Variable *getStackReg(SizeT Index) const final;
1246c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  SizeT getNumStackRegs() const final;
1247c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1248c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                     const Variable *Reg) const final;
1249c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1250c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                        IValueT Registers) const final;
1251c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1252c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                 SizeT RegCount) const final;
12530fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  VarList Dests;
12540fa6c5a062f465360448a672abed3b916b413ca8Jan Voung};
12550fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
1256eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Pushes a list of registers. Just like Pop (see above), the list may be of
1257eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// GPRs, or VFP "s" registers, but not both.
125800c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpfclass InstARM32Push final : public InstARM32RegisterStackOp {
12590fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Push() = delete;
12600fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Push(const InstARM32Push &) = delete;
12610fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Push &operator=(const InstARM32Push &) = delete;
12620fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
12630fa6c5a062f465360448a672abed3b916b413ca8Jan Voungpublic:
12640fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
12650fa6c5a062f465360448a672abed3b916b413ca8Jan Voung    return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
12660fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  }
12678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
12680fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
12690fa6c5a062f465360448a672abed3b916b413ca8Jan Voungprivate:
12700fa6c5a062f465360448a672abed3b916b413ca8Jan Voung  InstARM32Push(Cfg *Func, const VarList &Srcs);
1271c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  const char *getGPROpcode() const final;
1272c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  const char *getSRegOpcode() const final;
1273c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  Variable *getStackReg(SizeT Index) const final;
1274c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  SizeT getNumStackRegs() const final;
1275c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1276c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                     const Variable *Reg) const final;
1277c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1278c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                        IValueT Registers) const final;
1279c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1280c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf                 SizeT RegCount) const final;
12810fa6c5a062f465360448a672abed3b916b413ca8Jan Voung};
12820fa6c5a062f465360448a672abed3b916b413ca8Jan Voung
128357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
128457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register operand, but epilogue lowering will search for a Ret instead of a
128557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// generic "bx". This instruction also takes a Source operand (for non-void
128657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// returning functions) for liveness analysis, though a FakeUse before the ret
128757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// would do just as well.
12889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
12899612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// NOTE: Even though "bx" can be predicated, for now leave out the predication
12909612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// since it's not yet known to be useful for Ret. That may complicate finding
12919612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// the terminator instruction if it's not guaranteed to be executed.
1292b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass InstARM32Ret : public InstARM32 {
1293b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32Ret() = delete;
1294b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32Ret(const InstARM32Ret &) = delete;
1295b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1296b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
1297b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic:
1298b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  static InstARM32Ret *create(Cfg *Func, Variable *LR,
1299b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung                              Variable *Source = nullptr) {
1300b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung    return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1301b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  }
1302b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  void emit(const Cfg *Func) const override;
1303b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  void emitIAS(const Cfg *Func) const override;
1304b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  void dump(const Cfg *Func) const override;
13058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
1306b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung
1307b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprivate:
1308b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1309b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung};
1310b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
131157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. It's important for liveness that there is no Dest operand
131257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// (OperandARM32Mem instead of Dest Variable).
131316991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Str final : public InstARM32Pred {
1314befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  InstARM32Str() = delete;
1315befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  InstARM32Str(const InstARM32Str &) = delete;
1316befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  InstARM32Str &operator=(const InstARM32Str &) = delete;
1317befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung
1318befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voungpublic:
13199612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Value must be a register.
1320befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1321befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung                              CondARM32::Cond Predicate) {
1322befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung    return new (Func->allocate<InstARM32Str>())
1323befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung        InstARM32Str(Func, Value, Mem, Predicate);
1324befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  }
1325befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  void emit(const Cfg *Func) const override;
1326f0655b6cebd64b393bdd4a51706c5ee3f229ce82Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1327befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  void dump(const Cfg *Func) const override;
13288cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }
1329befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung
1330befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voungprivate:
1331befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung  InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1332befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung               CondARM32::Cond Predicate);
1333befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung};
1334befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung
133516991847500a48932426d979c4f2d4adffaf3649John Porto/// Exclusive Store instruction. Like its non-exclusive sibling, it's important
133616991847500a48932426d979c4f2d4adffaf3649John Porto/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
133716991847500a48932426d979c4f2d4adffaf3649John Porto/// Variable).
133816991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Strex final : public InstARM32Pred {
133916991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Strex() = delete;
134016991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Strex(const InstARM32Strex &) = delete;
134116991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Strex &operator=(const InstARM32Strex &) = delete;
134216991847500a48932426d979c4f2d4adffaf3649John Porto
134316991847500a48932426d979c4f2d4adffaf3649John Portopublic:
134416991847500a48932426d979c4f2d4adffaf3649John Porto  /// Value must be a register.
134516991847500a48932426d979c4f2d4adffaf3649John Porto  static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
134616991847500a48932426d979c4f2d4adffaf3649John Porto                                OperandARM32Mem *Mem,
134716991847500a48932426d979c4f2d4adffaf3649John Porto                                CondARM32::Cond Predicate) {
134816991847500a48932426d979c4f2d4adffaf3649John Porto    return new (Func->allocate<InstARM32Strex>())
134916991847500a48932426d979c4f2d4adffaf3649John Porto        InstARM32Strex(Func, Dest, Value, Mem, Predicate);
135016991847500a48932426d979c4f2d4adffaf3649John Porto  }
135116991847500a48932426d979c4f2d4adffaf3649John Porto  void emit(const Cfg *Func) const override;
13524175d45e14cf1eb0af11e0458a873e601dc395deKarl Schimpf  void emitIAS(const Cfg *Func) const override;
135316991847500a48932426d979c4f2d4adffaf3649John Porto  void dump(const Cfg *Func) const override;
13548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
135516991847500a48932426d979c4f2d4adffaf3649John Porto
135616991847500a48932426d979c4f2d4adffaf3649John Portoprivate:
135716991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
135816991847500a48932426d979c4f2d4adffaf3649John Porto                 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
135916991847500a48932426d979c4f2d4adffaf3649John Porto};
136016991847500a48932426d979c4f2d4adffaf3649John Porto
1361675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens/// Sub-vector store instruction. It's important for liveness that there is no
1362675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens///  Dest operand (OperandARM32Mem instead of Dest Variable).
1363675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensclass InstARM32Vstr1 final : public InstARM32Pred {
1364675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  InstARM32Vstr1() = delete;
1365675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  InstARM32Vstr1(const InstARM32Vstr1 &) = delete;
1366675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  InstARM32Vstr1 &operator=(const InstARM32Vstr1 &) = delete;
1367675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens
1368675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenspublic:
1369675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  /// Value must be a register.
1370675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  static InstARM32Vstr1 *create(Cfg *Func, Variable *Value,
1371675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens                                OperandARM32Mem *Mem, CondARM32::Cond Predicate,
1372675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens                                SizeT Size) {
1373675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens    return new (Func->allocate<InstARM32Vstr1>())
1374675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens        InstARM32Vstr1(Func, Value, Mem, Predicate, Size);
1375675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  }
1376675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  void emit(const Cfg *Func) const override;
1377675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  void emitIAS(const Cfg *Func) const override;
1378675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  void dump(const Cfg *Func) const override;
1379675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  static bool classof(const Inst *Instr) { return isClassof(Instr, Vstr1); }
1380675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens
1381675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensprivate:
1382675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1383675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens                 CondARM32::Cond Predicate, SizeT Size);
1384675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens
1385675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens  SizeT Size;
1386675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens};
1387675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens
1388f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens/// Vector element duplication/replication instruction.
1389f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensclass InstARM32Vdup final : public InstARM32Pred {
1390f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  InstARM32Vdup() = delete;
1391f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  InstARM32Vdup(const InstARM32Vdup &) = delete;
1392f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  InstARM32Vdup &operator=(const InstARM32Vdup &) = delete;
1393f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens
1394f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capenspublic:
1395f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  /// Value must be a register.
1396f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  static InstARM32Vdup *create(Cfg *Func, Variable *Dest, Variable *Src,
1397f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens                               IValueT Idx) {
1398f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens    return new (Func->allocate<InstARM32Vdup>())
1399f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens        InstARM32Vdup(Func, Dest, Src, Idx);
1400f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  }
1401f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  void emit(const Cfg *Func) const override;
1402f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  void emitIAS(const Cfg *Func) const override;
1403f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  void dump(const Cfg *Func) const override;
1404f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  static bool classof(const Inst *Instr) { return isClassof(Instr, Vdup); }
1405f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens
1406f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensprivate:
1407f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src, IValueT Idx);
1408f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens
1409f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens  const IValueT Idx;
1410f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens};
1411f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens
14126ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32Trap : public InstARM32 {
14136ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Trap() = delete;
14146ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Trap(const InstARM32Trap &) = delete;
14156ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  InstARM32Trap &operator=(const InstARM32Trap &) = delete;
14166ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
14176ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic:
14186ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  static InstARM32Trap *create(Cfg *Func) {
14196ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung    return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
14206ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  }
14216ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void emit(const Cfg *Func) const override;
14226ddabc17eb7f79e9f6c63174a65380c8fa69c630Karl Schimpf  void emitIAS(const Cfg *Func) const override;
14236ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  void dump(const Cfg *Func) const override;
14248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
14256ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
14266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate:
14276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung  explicit InstARM32Trap(Cfg *Func);
14286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung};
14296ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung
14309612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Unsigned Multiply Long: d.lo, d.hi := x * y
14313bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Umull : public InstARM32Pred {
14322971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32Umull() = delete;
14332971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32Umull(const InstARM32Umull &) = delete;
14342971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32Umull &operator=(const InstARM32Umull &) = delete;
14352971997a96b7484165cfedead111c7cafb3073aeJan Voung
14362971997a96b7484165cfedead111c7cafb3073aeJan Voungpublic:
14379612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Everything must be a register.
14382971997a96b7484165cfedead111c7cafb3073aeJan Voung  static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
14393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                                Variable *Src0, Variable *Src1,
14403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                                CondARM32::Cond Predicate) {
14412971997a96b7484165cfedead111c7cafb3073aeJan Voung    return new (Func->allocate<InstARM32Umull>())
14423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung        InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
14432971997a96b7484165cfedead111c7cafb3073aeJan Voung  }
14442971997a96b7484165cfedead111c7cafb3073aeJan Voung  void emit(const Cfg *Func) const override;
1445430e84471a54f6e5a1727054be28680e489cf28dKarl Schimpf  void emitIAS(const Cfg *Func) const override;
14462971997a96b7484165cfedead111c7cafb3073aeJan Voung  void dump(const Cfg *Func) const override;
14478cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
14482971997a96b7484165cfedead111c7cafb3073aeJan Voung
14492971997a96b7484165cfedead111c7cafb3073aeJan Voungprivate:
14502971997a96b7484165cfedead111c7cafb3073aeJan Voung  InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
14513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung                 Variable *Src1, CondARM32::Cond Predicate);
14521bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
14532971997a96b7484165cfedead111c7cafb3073aeJan Voung  Variable *DestHi;
14542971997a96b7484165cfedead111c7cafb3073aeJan Voung};
14552971997a96b7484165cfedead111c7cafb3073aeJan Voung
1456c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto/// Handles fp2int, int2fp, and fp2fp conversions.
1457c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portoclass InstARM32Vcvt final : public InstARM32Pred {
1458c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  InstARM32Vcvt() = delete;
1459c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1460c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1461c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto
1462c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portopublic:
1463e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto  enum VcvtVariant {
1464e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    S2si,
1465e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    S2ui,
1466e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Si2s,
1467e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Ui2s,
1468e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    D2si,
1469e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    D2ui,
1470e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Si2d,
1471e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Ui2d,
1472e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    S2d,
1473e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    D2s,
1474e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Vs2si,
1475e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Vs2ui,
1476e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Vsi2s,
1477e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto    Vui2s,
1478e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto  };
1479c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1480c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto                               VcvtVariant Variant, CondARM32::Cond Predicate) {
1481c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto    return new (Func->allocate<InstARM32Vcvt>())
1482c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto        InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1483c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  }
1484c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  void emit(const Cfg *Func) const override;
14856c7181c5d3f082cbc04b58dd4745253139ad51e0Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1486c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  void dump(const Cfg *Func) const override;
14878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
1488c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto
1489c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portoprivate:
1490c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1491c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto                CondARM32::Cond Predicate);
1492c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto
1493c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto  const VcvtVariant Variant;
1494c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto};
1495c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto
1496f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto/// Handles (some of) vmov's various formats.
1497ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoclass InstARM32Mov final : public InstARM32Pred {
1498ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Mov() = delete;
1499ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Mov(const InstARM32Mov &) = delete;
1500ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Mov &operator=(const InstARM32Mov &) = delete;
1501f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto
1502f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Portopublic:
1503ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1504ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto                              CondARM32::Cond Predicate) {
1505ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto    return new (Func->allocate<InstARM32Mov>())
1506ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto        InstARM32Mov(Func, Dest, Src, Predicate);
1507f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  }
1508f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  bool isRedundantAssign() const override {
1509ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto    return !isMultiDest() && !isMultiSource() &&
15107b3d9cbb1c1697e03c616162382d945f35c37347John Porto           getPredicate() == CondARM32::AL &&
1511f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto           checkForRedundantAssign(getDest(), getSrc(0));
1512f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  }
151328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
1514f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void emit(const Cfg *Func) const override;
1515f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void emitIAS(const Cfg *Func) const override;
1516f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void dump(const Cfg *Func) const override;
15178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
1518f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto
1519e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto  bool isMultiDest() const { return DestHi != nullptr; }
1520f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto
1521f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  bool isMultiSource() const {
1522e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto    assert(getSrcSize() == 1 || getSrcSize() == 2);
1523e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto    return getSrcSize() == 2;
1524ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  }
1525ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto
1526e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto  Variable *getDestHi() const { return DestHi; }
1527e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto
1528ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoprivate:
1529ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1530e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto               CondARM32::Cond Predicate);
1531f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void emitMultiDestSingleSource(const Cfg *Func) const;
1532f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void emitSingleDestMultiSource(const Cfg *Func) const;
1533f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto  void emitSingleDestSingleSource(const Cfg *Func) const;
1534e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto
1535e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto  Variable *DestHi = nullptr;
1536f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto};
1537f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto
1538658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// Generates vmov Rd, Dn[x] instructions, and their related floating point
1539658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// versions.
1540658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkclass InstARM32Extract final : public InstARM32Pred {
1541658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Extract() = delete;
1542658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Extract(const InstARM32Extract &) = delete;
1543658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Extract &operator=(const InstARM32Extract &) = delete;
1544658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1545658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkpublic:
1546658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0,
1547658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk                                  uint32_t Index, CondARM32::Cond Predicate) {
1548658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    return new (Func->allocate<InstARM32Extract>())
1549658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk        InstARM32Extract(Func, Dest, Src0, Index, Predicate);
1550658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  }
1551658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  void emit(const Cfg *Func) const override;
15526de32b2199915462a4216399ff0f3af31ec88015Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1553658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); }
1554658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1555658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkprivate:
1556658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1557658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk                   CondARM32::Cond Predicate)
1558658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk      : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate),
1559658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk        Index(Index) {
1560658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    assert(Index < typeNumElements(Src0->getType()));
1561658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    addSource(Src0);
1562658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  }
1563658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1564658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  const uint32_t Index;
1565658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk};
1566658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1567658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// Generates vmov Dn[x], Rd instructions, and their related floating point
1568658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// versions.
1569658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkclass InstARM32Insert final : public InstARM32Pred {
1570658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Insert() = delete;
1571658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Insert(const InstARM32Insert &) = delete;
1572658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Insert &operator=(const InstARM32Insert &) = delete;
1573658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1574658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkpublic:
1575658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0,
1576658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk                                 uint32_t Index, CondARM32::Cond Predicate) {
1577658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    return new (Func->allocate<InstARM32Insert>())
1578658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk        InstARM32Insert(Func, Dest, Src0, Index, Predicate);
1579658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  }
1580658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  void emit(const Cfg *Func) const override;
15816de32b2199915462a4216399ff0f3af31ec88015Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1582658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); }
1583658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1584658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkprivate:
1585658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1586658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk                  CondARM32::Cond Predicate)
1587658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk      : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate),
1588658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk        Index(Index) {
1589658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    assert(Index < typeNumElements(Dest->getType()));
1590658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk    addSource(Src0);
1591658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  }
1592658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
1593658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk  const uint32_t Index;
1594658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk};
1595658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk
15962f5534f1c523eb022880360864f60ce42fb30ee0John Portoclass InstARM32Vcmp final : public InstARM32Pred {
15972f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vcmp() = delete;
15982f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vcmp(const InstARM32Vcmp &) = delete;
15992f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
16002f5534f1c523eb022880360864f60ce42fb30ee0John Porto
16012f5534f1c523eb022880360864f60ce42fb30ee0John Portopublic:
16022f5534f1c523eb022880360864f60ce42fb30ee0John Porto  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
16032f5534f1c523eb022880360864f60ce42fb30ee0John Porto                               CondARM32::Cond Predicate) {
16042f5534f1c523eb022880360864f60ce42fb30ee0John Porto    return new (Func->allocate<InstARM32Vcmp>())
16052f5534f1c523eb022880360864f60ce42fb30ee0John Porto        InstARM32Vcmp(Func, Src0, Src1, Predicate);
16062f5534f1c523eb022880360864f60ce42fb30ee0John Porto  }
1607ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1608ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto                               OperandARM32FlexFpZero *Src1,
1609ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto                               CondARM32::Cond Predicate) {
1610ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto    return new (Func->allocate<InstARM32Vcmp>())
1611ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto        InstARM32Vcmp(Func, Src0, Src1, Predicate);
1612ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  }
16132f5534f1c523eb022880360864f60ce42fb30ee0John Porto  void emit(const Cfg *Func) const override;
1614cd5e07ec935e179d4d087379afb480c3897d8316Karl Schimpf  void emitIAS(const Cfg *Func) const override;
16152f5534f1c523eb022880360864f60ce42fb30ee0John Porto  void dump(const Cfg *Func) const override;
16168cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }
16172f5534f1c523eb022880360864f60ce42fb30ee0John Porto
16182f5534f1c523eb022880360864f60ce42fb30ee0John Portoprivate:
1619ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto  InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
16202f5534f1c523eb022880360864f60ce42fb30ee0John Porto                CondARM32::Cond Predicate);
16212f5534f1c523eb022880360864f60ce42fb30ee0John Porto};
16222f5534f1c523eb022880360864f60ce42fb30ee0John Porto
16232f5534f1c523eb022880360864f60ce42fb30ee0John Porto/// Copies the FP Status and Control Register the core flags.
16242f5534f1c523eb022880360864f60ce42fb30ee0John Portoclass InstARM32Vmrs final : public InstARM32Pred {
16252f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vmrs() = delete;
16262f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vmrs(const InstARM32Vmrs &) = delete;
16272f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
16282f5534f1c523eb022880360864f60ce42fb30ee0John Porto
16292f5534f1c523eb022880360864f60ce42fb30ee0John Portopublic:
16302f5534f1c523eb022880360864f60ce42fb30ee0John Porto  static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
16312f5534f1c523eb022880360864f60ce42fb30ee0John Porto    return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
16322f5534f1c523eb022880360864f60ce42fb30ee0John Porto  }
16332f5534f1c523eb022880360864f60ce42fb30ee0John Porto  void emit(const Cfg *Func) const override;
1634ee7182759bc8e9acc9a8622e73ac315c4d2dd601Karl Schimpf  void emitIAS(const Cfg *Func) const override;
16352f5534f1c523eb022880360864f60ce42fb30ee0John Porto  void dump(const Cfg *Func) const override;
16368cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
16372f5534f1c523eb022880360864f60ce42fb30ee0John Porto
16382f5534f1c523eb022880360864f60ce42fb30ee0John Portoprivate:
16392f5534f1c523eb022880360864f60ce42fb30ee0John Porto  InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
16402f5534f1c523eb022880360864f60ce42fb30ee0John Porto};
16412f5534f1c523eb022880360864f60ce42fb30ee0John Porto
1642ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoclass InstARM32Vabs final : public InstARM32Pred {
1643ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Vabs() = delete;
1644ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Vabs(const InstARM32Vabs &) = delete;
1645ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1646ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto
1647ba6a67c960a126d85b94a87c8ea7358bec0da048John Portopublic:
1648ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1649ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto                               CondARM32::Cond Predicate) {
1650ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto    return new (Func->allocate<InstARM32Vabs>())
1651ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto        InstARM32Vabs(Func, Dest, Src, Predicate);
1652ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  }
1653ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  void emit(const Cfg *Func) const override;
1654bd4356d59ef318d8c82f3ef0c879dce147bb3146Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1655ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  void dump(const Cfg *Func) const override;
16568cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
1657ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto
1658ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoprivate:
1659ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto  InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1660ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto                CondARM32::Cond Predicate);
1661ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto};
166216991847500a48932426d979c4f2d4adffaf3649John Porto
166316991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Dmb final : public InstARM32Pred {
166416991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Dmb() = delete;
166516991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Dmb(const InstARM32Dmb &) = delete;
166616991847500a48932426d979c4f2d4adffaf3649John Porto  InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
166716991847500a48932426d979c4f2d4adffaf3649John Porto
166816991847500a48932426d979c4f2d4adffaf3649John Portopublic:
166916991847500a48932426d979c4f2d4adffaf3649John Porto  static InstARM32Dmb *create(Cfg *Func) {
167016991847500a48932426d979c4f2d4adffaf3649John Porto    return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
167116991847500a48932426d979c4f2d4adffaf3649John Porto  }
167216991847500a48932426d979c4f2d4adffaf3649John Porto  void emit(const Cfg *Func) const override;
1673d3f94f7ef3e6999a7a31641096b70536af46f3f5Karl Schimpf  void emitIAS(const Cfg *Func) const override;
167416991847500a48932426d979c4f2d4adffaf3649John Porto  void dump(const Cfg *Func) const override;
16758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
167616991847500a48932426d979c4f2d4adffaf3649John Porto
167716991847500a48932426d979c4f2d4adffaf3649John Portoprivate:
167816991847500a48932426d979c4f2d4adffaf3649John Porto  explicit InstARM32Dmb(Cfg *Func);
167916991847500a48932426d979c4f2d4adffaf3649John Porto};
168016991847500a48932426d979c4f2d4adffaf3649John Porto
1681f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfclass InstARM32Nop final : public InstARM32Pred {
1682f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  InstARM32Nop() = delete;
1683f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  InstARM32Nop(const InstARM32Nop &) = delete;
1684f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  InstARM32Nop &operator=(const InstARM32Nop &) = delete;
1685f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf
1686f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfpublic:
1687f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  static InstARM32Nop *create(Cfg *Func) {
1688f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf    return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func);
1689f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  }
1690f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  void emit(const Cfg *Func) const override;
1691f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  void emitIAS(const Cfg *Func) const override;
1692f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  void dump(const Cfg *Func) const override;
1693f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); }
1694f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf
1695f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfprivate:
1696f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf  explicit InstARM32Nop(Cfg *Func);
1697f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf};
1698f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf
169957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Declare partial template specializations of emit() methods that already have
170057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// default implementations. Without this, there is the possibility of ODR
170157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// violations and link errors.
1702b3401d27a236b81393092b4d571df473b5bba64bJan Voung
170386ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <> void InstARM32Ldr::emit(const Cfg *Func) const;
1704b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <> void InstARM32Movw::emit(const Cfg *Func) const;
1705b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <> void InstARM32Movt::emit(const Cfg *Func) const;
1706675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenstemplate <> void InstARM32Vldr1d::emit(const Cfg *Func) const;
1707675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenstemplate <> void InstARM32Vldr1q::emit(const Cfg *Func) const;
1708b3401d27a236b81393092b4d571df473b5bba64bJan Voung
17094a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto} // end of namespace ARM32
1710b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung} // end of namespace Ice
1711b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung
1712b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#endif // SUBZERO_SRC_ICEINSTARM32_H
1713