1//===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===//
2//
3//                        The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses.
12///
13/// This represents the machine instructions and operands used for ARM32 code
14/// selection.
15///
16//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEINSTARM32_H
19#define SUBZERO_SRC_ICEINSTARM32_H
20
21#include "IceConditionCodesARM32.h"
22#include "IceDefs.h"
23#include "IceInst.h"
24#include "IceInstARM32.def"
25#include "IceOperand.h"
26#include "IceRegistersARM32.h"
27
28namespace Ice {
29namespace ARM32 {
30
31/// Encoding of an ARM 32-bit instruction.
32using IValueT = uint32_t;
33
34/// An Offset value (+/-) used in an ARM 32-bit instruction.
35using IOffsetT = int32_t;
36
37class TargetARM32;
38
39/// OperandARM32 extends the Operand hierarchy. Its subclasses are
40/// OperandARM32Mem and OperandARM32Flex.
41class OperandARM32 : public Operand {
42  OperandARM32() = delete;
43  OperandARM32(const OperandARM32 &) = delete;
44  OperandARM32 &operator=(const OperandARM32 &) = delete;
45
46public:
47  enum OperandKindARM32 {
48    k__Start = Operand::kTarget,
49    kMem,
50    kShAmtImm,
51    kFlexStart,
52    kFlexImm = kFlexStart,
53    kFlexFpImm,
54    kFlexFpZero,
55    kFlexReg,
56    kFlexEnd = kFlexReg
57  };
58
59  enum ShiftKind {
60    kNoShift = -1,
61#define X(enum, emit) enum,
62    ICEINSTARM32SHIFT_TABLE
63#undef X
64  };
65
66  using Operand::dump;
67  void dump(const Cfg *, Ostream &Str) const override {
68    if (BuildDefs::dump())
69      Str << "<OperandARM32>";
70  }
71
72protected:
73  OperandARM32(OperandKindARM32 Kind, Type Ty)
74      : Operand(static_cast<OperandKind>(Kind), Ty) {}
75};
76
77/// OperandARM32Mem represents a memory operand in any of the various ARM32
78/// addressing modes.
79class OperandARM32Mem : public OperandARM32 {
80  OperandARM32Mem() = delete;
81  OperandARM32Mem(const OperandARM32Mem &) = delete;
82  OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
83
84public:
85  /// Memory operand addressing mode.
86  /// The enum value also carries the encoding.
87  // TODO(jvoung): unify with the assembler.
88  enum AddrMode {
89    // bit encoding P U 0 W
90    Offset = (8 | 4 | 0) << 21,      // offset (w/o writeback to base)
91    PreIndex = (8 | 4 | 1) << 21,    // pre-indexed addressing with writeback
92    PostIndex = (0 | 4 | 0) << 21,   // post-indexed addressing with writeback
93    NegOffset = (8 | 0 | 0) << 21,   // negative offset (w/o writeback to base)
94    NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
95    NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
96  };
97
98  /// Provide two constructors.
99  /// NOTE: The Variable-typed operands have to be registers.
100  ///
101  /// (1) Reg + Imm. The Immediate actually has a limited number of bits
102  /// for encoding, so check canHoldOffset first. It cannot handle general
103  /// Constant operands like ConstantRelocatable, since a relocatable can
104  /// potentially take up too many bits.
105  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
106                                 ConstantInteger32 *ImmOffset,
107                                 AddrMode Mode = Offset) {
108    return new (Func->allocate<OperandARM32Mem>())
109        OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
110  }
111  /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
112  /// this mode is disallowed in the NaCl sandbox.
113  static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
114                                 Variable *Index, ShiftKind ShiftOp = kNoShift,
115                                 uint16_t ShiftAmt = 0,
116                                 AddrMode Mode = Offset) {
117    return new (Func->allocate<OperandARM32Mem>())
118        OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
119  }
120  Variable *getBase() const { return Base; }
121  ConstantInteger32 *getOffset() const { return ImmOffset; }
122  Variable *getIndex() const { return Index; }
123  ShiftKind getShiftOp() const { return ShiftOp; }
124  uint16_t getShiftAmt() const { return ShiftAmt; }
125  AddrMode getAddrMode() const { return Mode; }
126
127  bool isRegReg() const { return Index != nullptr; }
128  bool isNegAddrMode() const {
129    // Positive address modes have the "U" bit set, and negative modes don't.
130    static_assert((PreIndex & (4 << 21)) != 0,
131                  "Positive addr modes should have U bit set.");
132    static_assert((NegPreIndex & (4 << 21)) == 0,
133                  "Negative addr modes should have U bit clear.");
134    return (Mode & (4 << 21)) == 0;
135  }
136
137  void emit(const Cfg *Func) const override;
138  using OperandARM32::dump;
139  void dump(const Cfg *Func, Ostream &Str) const override;
140
141  static bool classof(const Operand *Operand) {
142    return Operand->getKind() == static_cast<OperandKind>(kMem);
143  }
144
145  /// Return true if a load/store instruction for an element of type Ty can
146  /// encode the Offset directly in the immediate field of the 32-bit ARM
147  /// instruction. For some types, if the load is Sign extending, then the range
148  /// is reduced.
149  static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
150
151private:
152  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
153                  ConstantInteger32 *ImmOffset, AddrMode Mode);
154  OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
155                  ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
156
157  Variable *Base;
158  ConstantInteger32 *ImmOffset;
159  Variable *Index;
160  ShiftKind ShiftOp;
161  uint16_t ShiftAmt;
162  AddrMode Mode;
163};
164
165/// OperandARM32ShAmtImm represents an Immediate that is used in one of the
166/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
167/// shifted registers.
168class OperandARM32ShAmtImm : public OperandARM32 {
169  OperandARM32ShAmtImm() = delete;
170  OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
171  OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;
172
173public:
174  static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
175    return new (Func->allocate<OperandARM32ShAmtImm>())
176        OperandARM32ShAmtImm(ShAmt);
177  }
178
179  static bool classof(const Operand *Operand) {
180    return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
181  }
182
183  void emit(const Cfg *Func) const override;
184  using OperandARM32::dump;
185  void dump(const Cfg *Func, Ostream &Str) const override;
186
187  uint32_t getShAmtImm() const { return ShAmt->getValue(); }
188
189private:
190  explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);
191
192  const ConstantInteger32 *const ShAmt;
193};
194
195/// OperandARM32Flex represent the "flexible second operand" for data-processing
196/// instructions. It can be a rotatable 8-bit constant, or a register with an
197/// optional shift operand. The shift amount can even be a third register.
198class OperandARM32Flex : public OperandARM32 {
199  OperandARM32Flex() = delete;
200  OperandARM32Flex(const OperandARM32Flex &) = delete;
201  OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
202
203public:
204  static bool classof(const Operand *Operand) {
205    return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
206           Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
207  }
208
209protected:
210  OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
211};
212
213/// Rotated immediate variant.
214class OperandARM32FlexImm : public OperandARM32Flex {
215  OperandARM32FlexImm() = delete;
216  OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
217  OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
218
219public:
220  /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
221  static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
222                                     uint32_t RotateAmt);
223
224  void emit(const Cfg *Func) const override;
225  using OperandARM32::dump;
226  void dump(const Cfg *Func, Ostream &Str) const override;
227
228  static bool classof(const Operand *Operand) {
229    return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
230  }
231
232  /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
233  /// the out-params RotateAmt and Immed_8 if Immediate fits.
234  static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
235                         uint32_t *Immed_8);
236
237  uint32_t getImm() const { return Imm; }
238  uint32_t getRotateAmt() const { return RotateAmt; }
239
240private:
241  OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
242
243  uint32_t Imm;
244  uint32_t RotateAmt;
245};
246
247/// Modified Floating-point constant.
248class OperandARM32FlexFpImm : public OperandARM32Flex {
249  OperandARM32FlexFpImm() = delete;
250  OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete;
251  OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete;
252
253public:
254  static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty,
255                                       uint32_t ModifiedImm) {
256    return new (Func->allocate<OperandARM32FlexFpImm>())
257        OperandARM32FlexFpImm(Func, Ty, ModifiedImm);
258  }
259
260  void emit(const Cfg *Func) const override;
261  using OperandARM32::dump;
262  void dump(const Cfg *Func, Ostream &Str) const override;
263
264  static bool classof(const Operand *Operand) {
265    return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
266  }
267
268  static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm);
269
270  uint32_t getModifiedImm() const { return ModifiedImm; }
271
272private:
273  OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
274
275  const uint32_t ModifiedImm;
276};
277
278/// An operand for representing the 0.0 immediate in vcmp.
279class OperandARM32FlexFpZero : public OperandARM32Flex {
280  OperandARM32FlexFpZero() = delete;
281  OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete;
282  OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete;
283
284public:
285  static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) {
286    return new (Func->allocate<OperandARM32FlexFpZero>())
287        OperandARM32FlexFpZero(Func, Ty);
288  }
289
290  void emit(const Cfg *Func) const override;
291  using OperandARM32::dump;
292  void dump(const Cfg *Func, Ostream &Str) const override;
293
294  static bool classof(const Operand *Operand) {
295    return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero);
296  }
297
298private:
299  OperandARM32FlexFpZero(Cfg *Func, Type Ty);
300};
301
302/// Shifted register variant.
303class OperandARM32FlexReg : public OperandARM32Flex {
304  OperandARM32FlexReg() = delete;
305  OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
306  OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
307
308public:
309  /// Register with immediate/reg shift amount and shift operation.
310  static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
311                                     ShiftKind ShiftOp, Operand *ShiftAmt) {
312    return new (Func->allocate<OperandARM32FlexReg>())
313        OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
314  }
315
316  void emit(const Cfg *Func) const override;
317  using OperandARM32::dump;
318  void dump(const Cfg *Func, Ostream &Str) const override;
319
320  static bool classof(const Operand *Operand) {
321    return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
322  }
323
324  Variable *getReg() const { return Reg; }
325  ShiftKind getShiftOp() const { return ShiftOp; }
326  /// ShiftAmt can represent an immediate or a register.
327  Operand *getShiftAmt() const { return ShiftAmt; }
328
329private:
330  OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
331                      Operand *ShiftAmt);
332
333  Variable *Reg;
334  ShiftKind ShiftOp;
335  Operand *ShiftAmt;
336};
337
338/// StackVariable represents a Var that isn't assigned a register (stack-only).
339/// It is assigned a stack slot, but the slot's offset may be too large to
340/// represent in the native addressing mode, and so it has a separate base
341/// register from SP/FP, where the offset from that base register is then in
342/// range.
343class StackVariable final : public Variable {
344  StackVariable() = delete;
345  StackVariable(const StackVariable &) = delete;
346  StackVariable &operator=(const StackVariable &) = delete;
347
348public:
349  static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
350    return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index);
351  }
352  constexpr static auto StackVariableKind =
353      static_cast<OperandKind>(kVariable_Target);
354  static bool classof(const Operand *Operand) {
355    return Operand->getKind() == StackVariableKind;
356  }
357  void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
358  RegNumT getBaseRegNum() const override { return BaseRegNum; }
359  // Inherit dump() and emit() from Variable.
360
361private:
362  StackVariable(const Cfg *Func, Type Ty, SizeT Index)
363      : Variable(Func, StackVariableKind, Ty, Index) {}
364  RegNumT BaseRegNum;
365};
366
367/// Base class for ARM instructions. While most ARM instructions can be
368/// conditionally executed, a few of them are not predicable (halt, memory
369/// barriers, etc.).
370class InstARM32 : public InstTarget {
371  InstARM32() = delete;
372  InstARM32(const InstARM32 &) = delete;
373  InstARM32 &operator=(const InstARM32 &) = delete;
374
375public:
376  // Defines form that assembly instruction should be synthesized.
377  enum EmitForm { Emit_Text, Emit_Binary };
378
379  enum InstKindARM32 {
380    k__Start = Inst::Target,
381    Adc,
382    Add,
383    And,
384    Asr,
385    Bic,
386    Br,
387    Call,
388    Clz,
389    Cmn,
390    Cmp,
391    Dmb,
392    Eor,
393    Extract,
394    Insert,
395    Label,
396    Ldr,
397    Ldrex,
398    Lsl,
399    Lsr,
400    Nop,
401    Mla,
402    Mls,
403    Mov,
404    Movt,
405    Movw,
406    Mul,
407    Mvn,
408    Orr,
409    Pop,
410    Push,
411    Rbit,
412    Ret,
413    Rev,
414    Rsb,
415    Rsc,
416    Sbc,
417    Sdiv,
418    Str,
419    Strex,
420    Sub,
421    Sxt,
422    Trap,
423    Tst,
424    Udiv,
425    Umull,
426    Uxt,
427    Vabs,
428    Vadd,
429    Vand,
430    Vbsl,
431    Vceq,
432    Vcge,
433    Vcgt,
434    Vcmp,
435    Vcvt,
436    Vdiv,
437    Vdup,
438    Veor,
439    Vldr1d,
440    Vldr1q,
441    Vmla,
442    Vmlap,
443    Vmls,
444    Vmovl,
445    Vmovh,
446    Vmovhl,
447    Vmovlh,
448    Vmrs,
449    Vmul,
450    Vmulh,
451    Vmvn,
452    Vneg,
453    Vorr,
454    Vqadd,
455    Vqmovn2,
456    Vqsub,
457    Vshl,
458    Vshr,
459    Vsqrt,
460    Vstr1,
461    Vsub,
462    Vzip
463  };
464
465  static constexpr size_t InstSize = sizeof(uint32_t);
466
467  static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
468
469  /// Called inside derived methods emit() to communicate that multiple
470  /// instructions are being generated. Used by emitIAS() methods to
471  /// generate textual fixups for instructions that are not yet
472  /// implemented.
473  void startNextInst(const Cfg *Func) const;
474
475  /// FPSign is used for certain vector instructions (particularly, right
476  /// shifts) that require an operand sign specification.
477  enum FPSign {
478    FS_None,
479    FS_Signed,
480    FS_Unsigned,
481  };
482  /// Shared emit routines for common forms of instructions.
483  /// @{
484  static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
485                              const InstARM32 *Instr, const Cfg *Func,
486                              Type OpType);
487  static void emitFourAddrFP(const char *Opcode, FPSign Sign,
488                             const InstARM32 *Instr, const Cfg *Func);
489  /// @}
490
491  void dump(const Cfg *Func) const override;
492
493  void emitIAS(const Cfg *Func) const override;
494
495protected:
496  InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
497      : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
498
499  static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
500    return Instr->getKind() == static_cast<InstKind>(MyKind);
501  }
502
503  // Generates text of assembly instruction using method emit(), and then adds
504  // to the assembly buffer as a Fixup.
505  void emitUsingTextFixup(const Cfg *Func) const;
506};
507
508/// A predicable ARM instruction.
509class InstARM32Pred : public InstARM32 {
510  InstARM32Pred() = delete;
511  InstARM32Pred(const InstARM32Pred &) = delete;
512  InstARM32Pred &operator=(const InstARM32Pred &) = delete;
513
514public:
515  InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
516                CondARM32::Cond Predicate)
517      : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
518
519  CondARM32::Cond getPredicate() const { return Predicate; }
520  void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
521
522  static const char *predString(CondARM32::Cond Predicate);
523  void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
524
525  /// Shared emit routines for common forms of instructions.
526  static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
527                             const Cfg *Func, bool NeedsWidthSuffix);
528  static void emitUnaryopFP(const char *Opcode, FPSign Sign,
529                            const InstARM32Pred *Instr, const Cfg *Func);
530  static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
531                          const Cfg *Func);
532  static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
533                            const Cfg *Func, bool SetFlags);
534  static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
535                           const Cfg *Func);
536  static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
537                          const Cfg *Func);
538
539protected:
540  CondARM32::Cond Predicate;
541};
542
543template <typename StreamType>
544inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
545  Stream << InstARM32Pred::predString(Predicate);
546  return Stream;
547}
548
549/// Instructions of the form x := op(y).
550template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
551class InstARM32UnaryopGPR : public InstARM32Pred {
552  InstARM32UnaryopGPR() = delete;
553  InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
554  InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
555
556public:
557  static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
558                                     CondARM32::Cond Predicate) {
559    return new (Func->allocate<InstARM32UnaryopGPR>())
560        InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
561  }
562  void emit(const Cfg *Func) const override {
563    if (!BuildDefs::dump())
564      return;
565    emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
566  }
567  void emitIAS(const Cfg *Func) const override;
568  void dump(const Cfg *Func) const override {
569    if (!BuildDefs::dump())
570      return;
571    Ostream &Str = Func->getContext()->getStrDump();
572    dumpDest(Func);
573    Str << " = ";
574    dumpOpcodePred(Str, Opcode, getDest()->getType());
575    Str << " ";
576    dumpSources(Func);
577  }
578  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
579
580private:
581  InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
582                      CondARM32::Cond Predicate)
583      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
584    addSource(Src);
585  }
586
587  static const char *Opcode;
588};
589
590/// Instructions of the form x := op(y), for vector/FP.
591template <InstARM32::InstKindARM32 K>
592class InstARM32UnaryopFP : public InstARM32Pred {
593  InstARM32UnaryopFP() = delete;
594  InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
595  InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
596
597public:
598  static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
599                                    CondARM32::Cond Predicate) {
600    return new (Func->allocate<InstARM32UnaryopFP>())
601        InstARM32UnaryopFP(Func, Dest, Src, Predicate);
602  }
603  void emit(const Cfg *Func) const override {
604    if (!BuildDefs::dump())
605      return;
606    emitUnaryopFP(Opcode, Sign, this, Func);
607  }
608  void emitIAS(const Cfg *Func) const override;
609  void dump(const Cfg *Func) const override {
610    if (!BuildDefs::dump())
611      return;
612    Ostream &Str = Func->getContext()->getStrDump();
613    dumpDest(Func);
614    Str << " = ";
615    dumpOpcodePred(Str, Opcode, getDest()->getType());
616    Str << " ";
617    dumpSources(Func);
618  }
619  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
620
621protected:
622  InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
623                     CondARM32::Cond Predicate)
624      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
625    addSource(Src);
626  }
627
628  FPSign Sign = FS_None;
629  static const char *Opcode;
630};
631
632template <InstARM32::InstKindARM32 K>
633class InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> {
634  InstARM32UnaryopSignAwareFP() = delete;
635  InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete;
636  InstARM32UnaryopSignAwareFP &
637  operator=(const InstARM32UnaryopSignAwareFP &) = delete;
638
639public:
640  static InstARM32UnaryopSignAwareFP *
641  create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) {
642    return new (Func->allocate<InstARM32UnaryopSignAwareFP>())
643        InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate);
644  }
645  void emitIAS(const Cfg *Func) const override;
646  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
647
648private:
649  InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src,
650                              CondARM32::Cond Predicate)
651      : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {}
652};
653
654/// Instructions of the form x := x op y.
655template <InstARM32::InstKindARM32 K>
656class InstARM32TwoAddrGPR : public InstARM32Pred {
657  InstARM32TwoAddrGPR() = delete;
658  InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
659  InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
660
661public:
662  /// Dest must be a register.
663  static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
664                                     CondARM32::Cond Predicate) {
665    return new (Func->allocate<InstARM32TwoAddrGPR>())
666        InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
667  }
668  void emit(const Cfg *Func) const override {
669    if (!BuildDefs::dump())
670      return;
671    emitTwoAddr(Opcode, this, Func);
672  }
673  void emitIAS(const Cfg *Func) const override;
674  void dump(const Cfg *Func) const override {
675    if (!BuildDefs::dump())
676      return;
677    Ostream &Str = Func->getContext()->getStrDump();
678    dumpDest(Func);
679    Str << " = ";
680    dumpOpcodePred(Str, Opcode, getDest()->getType());
681    Str << " ";
682    dumpSources(Func);
683  }
684  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
685
686private:
687  InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
688                      CondARM32::Cond Predicate)
689      : InstARM32Pred(Func, K, 2, Dest, Predicate) {
690    addSource(Dest);
691    addSource(Src);
692  }
693
694  static const char *Opcode;
695};
696
697/// Base class for load instructions.
698template <InstARM32::InstKindARM32 K>
699class InstARM32LoadBase : public InstARM32Pred {
700  InstARM32LoadBase() = delete;
701  InstARM32LoadBase(const InstARM32LoadBase &) = delete;
702  InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
703
704public:
705  static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
706                                   CondARM32::Cond Predicate) {
707    return new (Func->allocate<InstARM32LoadBase>())
708        InstARM32LoadBase(Func, Dest, Source, Predicate);
709  }
710  void emit(const Cfg *Func) const override;
711  void emitIAS(const Cfg *Func) const override;
712  void dump(const Cfg *Func) const override {
713    if (!BuildDefs::dump())
714      return;
715    Ostream &Str = Func->getContext()->getStrDump();
716    dumpOpcodePred(Str, Opcode, getDest()->getType());
717    Str << " ";
718    dumpDest(Func);
719    Str << ", ";
720    dumpSources(Func);
721  }
722  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
723
724private:
725  InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
726                    CondARM32::Cond Predicate)
727      : InstARM32Pred(Func, K, 1, Dest, Predicate) {
728    addSource(Source);
729  }
730
731  static const char *Opcode;
732};
733
734/// Instructions of the form x := y op z. May have the side-effect of setting
735/// status flags.
736template <InstARM32::InstKindARM32 K>
737class InstARM32ThreeAddrGPR : public InstARM32Pred {
738  InstARM32ThreeAddrGPR() = delete;
739  InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
740  InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
741
742public:
743  /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
744  /// must be registers.
745  static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
746                                       Variable *Src0, Operand *Src1,
747                                       CondARM32::Cond Predicate,
748                                       bool SetFlags = false) {
749    return new (Func->allocate<InstARM32ThreeAddrGPR>())
750        InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
751  }
752  void emit(const Cfg *Func) const override {
753    if (!BuildDefs::dump())
754      return;
755    emitThreeAddr(Opcode, this, Func, SetFlags);
756  }
757  void emitIAS(const Cfg *Func) const override;
758  void dump(const Cfg *Func) const override {
759    if (!BuildDefs::dump())
760      return;
761    Ostream &Str = Func->getContext()->getStrDump();
762    dumpDest(Func);
763    Str << " = ";
764    dumpOpcodePred(Str, Opcode, getDest()->getType());
765    Str << (SetFlags ? ".s " : " ");
766    dumpSources(Func);
767  }
768  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
769
770private:
771  InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
772                        Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
773      : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
774    HasSideEffects = SetFlags;
775    addSource(Src0);
776    addSource(Src1);
777  }
778
779  static const char *Opcode;
780  bool SetFlags;
781};
782
783/// Instructions of the form x := y op z, for vector/FP. We leave these as
784/// unconditional: "ARM deprecates the conditional execution of any instruction
785/// encoding provided by the Advanced SIMD Extension that is not also provided
786/// by the floating-point (VFP) extension". They do not set flags.
787template <InstARM32::InstKindARM32 K>
788class InstARM32ThreeAddrFP : public InstARM32 {
789  InstARM32ThreeAddrFP() = delete;
790  InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
791  InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
792
793public:
794  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
795  /// must be a register.
796  static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
797                                      Variable *Src1) {
798    return new (Func->allocate<InstARM32ThreeAddrFP>())
799        InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
800  }
801  void emit(const Cfg *Func) const override {
802    if (!BuildDefs::dump())
803      return;
804    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
805    emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
806  }
807  void emitIAS(const Cfg *Func) const override;
808  void dump(const Cfg *Func) const override {
809    if (!BuildDefs::dump())
810      return;
811    Ostream &Str = Func->getContext()->getStrDump();
812    dumpDest(Func);
813    const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
814    Str << " = " << Opcode << "." << OpType << " ";
815    dumpSources(Func);
816  }
817  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
818
819protected:
820  FPSign Sign = FS_None;
821
822  InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
823      : InstARM32(Func, K, 2, Dest) {
824    addSource(Src0);
825    addSource(Src1);
826  }
827
828  static const char *Opcode;
829
830private:
831  static constexpr bool isVectorCompare() {
832    return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
833  }
834};
835
836template <InstARM32::InstKindARM32 K>
837class InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> {
838  InstARM32ThreeAddrSignAwareFP() = delete;
839  InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete;
840  InstARM32ThreeAddrSignAwareFP &
841  operator=(const InstARM32ThreeAddrSignAwareFP &) = delete;
842
843public:
844  /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
845  /// must be a register.
846  static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest,
847                                               Variable *Src0, Variable *Src1) {
848    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
849        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
850  }
851
852  static InstARM32ThreeAddrSignAwareFP *
853  create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
854    return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
855        InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
856  }
857
858  void emitIAS(const Cfg *Func) const override;
859  void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
860
861private:
862  InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0,
863                                Operand *Src1)
864      : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
865};
866
867/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
868template <InstARM32::InstKindARM32 K>
869class InstARM32FourAddrGPR : public InstARM32Pred {
870  InstARM32FourAddrGPR() = delete;
871  InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
872  InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
873
874public:
875  // Every operand must be a register.
876  static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
877                                      Variable *Src1, Variable *Src2,
878                                      CondARM32::Cond Predicate) {
879    return new (Func->allocate<InstARM32FourAddrGPR>())
880        InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
881  }
882  void emit(const Cfg *Func) const override {
883    if (!BuildDefs::dump())
884      return;
885    emitFourAddr(Opcode, this, Func);
886  }
887  void emitIAS(const Cfg *Func) const override;
888  void dump(const Cfg *Func) const override {
889    if (!BuildDefs::dump())
890      return;
891    Ostream &Str = Func->getContext()->getStrDump();
892    dumpDest(Func);
893    Str << " = ";
894    dumpOpcodePred(Str, Opcode, getDest()->getType());
895    Str << " ";
896    dumpSources(Func);
897  }
898  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
899
900private:
901  InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
902                       Variable *Src1, Variable *Src2,
903                       CondARM32::Cond Predicate)
904      : InstARM32Pred(Func, K, 3, Dest, Predicate) {
905    addSource(Src0);
906    addSource(Src1);
907    addSource(Src2);
908  }
909
910  static const char *Opcode;
911};
912
913/// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
914/// We leave these as unconditional: "ARM deprecates the conditional execution
915/// of any instruction encoding provided by the Advanced SIMD Extension that is
916/// not also provided by the floating-point (VFP) extension". They do not set
917/// flags.
918template <InstARM32::InstKindARM32 K>
919class InstARM32FourAddrFP : public InstARM32 {
920  InstARM32FourAddrFP() = delete;
921  InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
922  InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
923
924public:
925  // Every operand must be a register.
926  static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
927                                     Variable *Src1) {
928    return new (Func->allocate<InstARM32FourAddrFP>())
929        InstARM32FourAddrFP(Func, Dest, Src0, Src1);
930  }
931  void emit(const Cfg *Func) const override {
932    if (!BuildDefs::dump())
933      return;
934    emitFourAddrFP(Opcode, Sign, this, Func);
935  }
936  void emitIAS(const Cfg *Func) const override;
937  void dump(const Cfg *Func) const override {
938    if (!BuildDefs::dump())
939      return;
940    Ostream &Str = Func->getContext()->getStrDump();
941    dumpDest(Func);
942    Str << " = ";
943    Str << Opcode << "." << getDest()->getType() << " ";
944    dumpDest(Func);
945    Str << ", ";
946    dumpSources(Func);
947  }
948  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
949
950private:
951  InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
952      : InstARM32(Func, K, 3, Dest) {
953    addSource(Dest);
954    addSource(Src0);
955    addSource(Src1);
956  }
957
958  FPSign Sign = FS_None;
959  static const char *Opcode;
960};
961
962/// Instructions of the form x cmpop y (setting flags).
963template <InstARM32::InstKindARM32 K>
964class InstARM32CmpLike : public InstARM32Pred {
965  InstARM32CmpLike() = delete;
966  InstARM32CmpLike(const InstARM32CmpLike &) = delete;
967  InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
968
969public:
970  static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
971                                  CondARM32::Cond Predicate) {
972    return new (Func->allocate<InstARM32CmpLike>())
973        InstARM32CmpLike(Func, Src0, Src1, Predicate);
974  }
975  void emit(const Cfg *Func) const override {
976    if (!BuildDefs::dump())
977      return;
978    emitCmpLike(Opcode, this, Func);
979  }
980  void emitIAS(const Cfg *Func) const override;
981  void dump(const Cfg *Func) const override {
982    if (!BuildDefs::dump())
983      return;
984    Ostream &Str = Func->getContext()->getStrDump();
985    dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
986    Str << " ";
987    dumpSources(Func);
988  }
989  static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
990
991private:
992  InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
993                   CondARM32::Cond Predicate)
994      : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
995    HasSideEffects = true;
996    addSource(Src0);
997    addSource(Src1);
998  }
999
1000  static const char *Opcode;
1001};
1002
1003using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
1004using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
1005using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
1006using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
1007using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
1008using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
1009using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
1010using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
1011using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
1012using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
1013using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
1014using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
1015using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
1016using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
1017using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
1018using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
1019using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
1020using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
1021using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
1022using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
1023using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
1024using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
1025using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
1026using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
1027using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
1028using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
1029using InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>;
1030using InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>;
1031using InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>;
1032using InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>;
1033using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
1034using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
1035using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
1036using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
1037using InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
1038using InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
1039using InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
1040using InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
1041using InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>;
1042using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
1043using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
1044using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
1045using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
1046using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
1047using InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>;
1048using InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>;
1049using InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>;
1050/// MovT leaves the bottom bits alone so dest is also a source. This helps
1051/// indicate that a previous MovW setting dest is not dead code.
1052using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
1053using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
1054using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
1055using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
1056using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
1057using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
1058// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
1059// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
1060// using that for now, so just model as a Unaryop.
1061using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
1062using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
1063using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
1064using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
1065using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
1066using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
1067using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
1068using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
1069
1070// InstARM32Label represents an intra-block label that is the target of an
1071// intra-block branch. The offset between the label and the branch must be fit
1072// in the instruction immediate (considered "near").
1073class InstARM32Label : public InstARM32 {
1074  InstARM32Label() = delete;
1075  InstARM32Label(const InstARM32Label &) = delete;
1076  InstARM32Label &operator=(const InstARM32Label &) = delete;
1077
1078public:
1079  static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
1080    return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
1081  }
1082  uint32_t getEmitInstCount() const override { return 0; }
1083  GlobalString getLabelName() const { return Name; }
1084  SizeT getNumber() const { return Number; }
1085  void emit(const Cfg *Func) const override;
1086  void emitIAS(const Cfg *Func) const override;
1087  void dump(const Cfg *Func) const override;
1088  void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }
1089
1090private:
1091  InstARM32Label(Cfg *Func, TargetARM32 *Target);
1092
1093  RelocOffset *OffsetReloc = nullptr;
1094  SizeT Number; // used for unique label generation.
1095  GlobalString Name;
1096};
1097
1098/// Direct branch instruction.
1099class InstARM32Br : public InstARM32Pred {
1100  InstARM32Br() = delete;
1101  InstARM32Br(const InstARM32Br &) = delete;
1102  InstARM32Br &operator=(const InstARM32Br &) = delete;
1103
1104public:
1105  /// Create a conditional branch to one of two nodes.
1106  static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
1107                             CfgNode *TargetFalse, CondARM32::Cond Predicate) {
1108    assert(Predicate != CondARM32::AL);
1109    constexpr InstARM32Label *NoLabel = nullptr;
1110    return new (Func->allocate<InstARM32Br>())
1111        InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
1112  }
1113  /// Create an unconditional branch to a node.
1114  static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
1115    constexpr CfgNode *NoCondTarget = nullptr;
1116    constexpr InstARM32Label *NoLabel = nullptr;
1117    return new (Func->allocate<InstARM32Br>())
1118        InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
1119  }
1120  /// Create a non-terminator conditional branch to a node, with a fallthrough
1121  /// to the next instruction in the current node. This is used for switch
1122  /// lowering.
1123  static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1124                             CondARM32::Cond Predicate) {
1125    assert(Predicate != CondARM32::AL);
1126    constexpr CfgNode *NoUncondTarget = nullptr;
1127    constexpr InstARM32Label *NoLabel = nullptr;
1128    return new (Func->allocate<InstARM32Br>())
1129        InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
1130  }
1131  // Create a conditional intra-block branch (or unconditional, if
1132  // Condition==AL) to a label in the current block.
1133  static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
1134                             CondARM32::Cond Predicate) {
1135    constexpr CfgNode *NoCondTarget = nullptr;
1136    constexpr CfgNode *NoUncondTarget = nullptr;
1137    return new (Func->allocate<InstARM32Br>())
1138        InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
1139  }
1140  const CfgNode *getTargetTrue() const { return TargetTrue; }
1141  const CfgNode *getTargetFalse() const { return TargetFalse; }
1142  bool optimizeBranch(const CfgNode *NextNode);
1143  uint32_t getEmitInstCount() const override {
1144    uint32_t Sum = 0;
1145    if (Label)
1146      ++Sum;
1147    if (getTargetTrue())
1148      ++Sum;
1149    if (getTargetFalse())
1150      ++Sum;
1151    return Sum;
1152  }
1153  bool isUnconditionalBranch() const override {
1154    return getPredicate() == CondARM32::AL;
1155  }
1156  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
1157  void emit(const Cfg *Func) const override;
1158  void emitIAS(const Cfg *Func) const override;
1159  void dump(const Cfg *Func) const override;
1160  static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
1161
1162private:
1163  InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
1164              const InstARM32Label *Label, CondARM32::Cond Predicate);
1165
1166  const CfgNode *TargetTrue;
1167  const CfgNode *TargetFalse;
1168  const InstARM32Label *Label; // Intra-block branch target
1169};
1170
1171/// Call instruction (bl/blx). Arguments should have already been pushed.
1172/// Technically bl and the register form of blx can be predicated, but we'll
1173/// leave that out until needed.
1174class InstARM32Call : public InstARM32 {
1175  InstARM32Call() = delete;
1176  InstARM32Call(const InstARM32Call &) = delete;
1177  InstARM32Call &operator=(const InstARM32Call &) = delete;
1178
1179public:
1180  static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
1181    return new (Func->allocate<InstARM32Call>())
1182        InstARM32Call(Func, Dest, CallTarget);
1183  }
1184  Operand *getCallTarget() const { return getSrc(0); }
1185  void emit(const Cfg *Func) const override;
1186  void emitIAS(const Cfg *Func) const override;
1187  void dump(const Cfg *Func) const override;
1188  static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
1189
1190private:
1191  InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
1192};
1193
1194class InstARM32RegisterStackOp : public InstARM32 {
1195  InstARM32RegisterStackOp() = delete;
1196  InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1197  InstARM32RegisterStackOp &
1198  operator=(const InstARM32RegisterStackOp &) = delete;
1199
1200public:
1201  void emit(const Cfg *Func) const override;
1202  void emitIAS(const Cfg *Func) const override;
1203  void dump(const Cfg *Func) const override;
1204
1205protected:
1206  InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1207                           Variable *Dest)
1208      : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1209  void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1210  void emitGPRsAsText(const Cfg *Func) const;
1211  void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1212                       SizeT Regcount) const;
1213  void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
1214                   SizeT RegCount, SizeT InstIndex) const;
1215  virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1216  virtual const char *getGPROpcode() const = 0;
1217  virtual const char *getSRegOpcode() const = 0;
1218  virtual Variable *getStackReg(SizeT Index) const = 0;
1219  virtual SizeT getNumStackRegs() const = 0;
1220  virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1221                             const Variable *Reg) const = 0;
1222  virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1223                                IValueT Registers) const = 0;
1224  virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1225                         const Variable *BaseReg, SizeT RegCount) const = 0;
1226};
1227
1228/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1229/// regs, but not both. In any case, the list must be sorted.
1230class InstARM32Pop final : public InstARM32RegisterStackOp {
1231  InstARM32Pop() = delete;
1232  InstARM32Pop(const InstARM32Pop &) = delete;
1233  InstARM32Pop &operator=(const InstARM32Pop &) = delete;
1234
1235public:
1236  static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
1237    return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
1238  }
1239  static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
1240
1241private:
1242  InstARM32Pop(Cfg *Func, const VarList &Dests);
1243  virtual const char *getGPROpcode() const final;
1244  virtual const char *getSRegOpcode() const final;
1245  Variable *getStackReg(SizeT Index) const final;
1246  SizeT getNumStackRegs() const final;
1247  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1248                     const Variable *Reg) const final;
1249  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1250                        IValueT Registers) const final;
1251  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1252                 SizeT RegCount) const final;
1253  VarList Dests;
1254};
1255
1256/// Pushes a list of registers. Just like Pop (see above), the list may be of
1257/// GPRs, or VFP "s" registers, but not both.
1258class InstARM32Push final : public InstARM32RegisterStackOp {
1259  InstARM32Push() = delete;
1260  InstARM32Push(const InstARM32Push &) = delete;
1261  InstARM32Push &operator=(const InstARM32Push &) = delete;
1262
1263public:
1264  static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
1265    return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
1266  }
1267  static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
1268
1269private:
1270  InstARM32Push(Cfg *Func, const VarList &Srcs);
1271  const char *getGPROpcode() const final;
1272  const char *getSRegOpcode() const final;
1273  Variable *getStackReg(SizeT Index) const final;
1274  SizeT getNumStackRegs() const final;
1275  void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1276                     const Variable *Reg) const final;
1277  void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1278                        IValueT Registers) const final;
1279  void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1280                 SizeT RegCount) const final;
1281};
1282
1283/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1284/// register operand, but epilogue lowering will search for a Ret instead of a
1285/// generic "bx". This instruction also takes a Source operand (for non-void
1286/// returning functions) for liveness analysis, though a FakeUse before the ret
1287/// would do just as well.
1288///
1289/// NOTE: Even though "bx" can be predicated, for now leave out the predication
1290/// since it's not yet known to be useful for Ret. That may complicate finding
1291/// the terminator instruction if it's not guaranteed to be executed.
1292class InstARM32Ret : public InstARM32 {
1293  InstARM32Ret() = delete;
1294  InstARM32Ret(const InstARM32Ret &) = delete;
1295  InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1296
1297public:
1298  static InstARM32Ret *create(Cfg *Func, Variable *LR,
1299                              Variable *Source = nullptr) {
1300    return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1301  }
1302  void emit(const Cfg *Func) const override;
1303  void emitIAS(const Cfg *Func) const override;
1304  void dump(const Cfg *Func) const override;
1305  static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
1306
1307private:
1308  InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1309};
1310
1311/// Store instruction. It's important for liveness that there is no Dest operand
1312/// (OperandARM32Mem instead of Dest Variable).
1313class InstARM32Str final : public InstARM32Pred {
1314  InstARM32Str() = delete;
1315  InstARM32Str(const InstARM32Str &) = delete;
1316  InstARM32Str &operator=(const InstARM32Str &) = delete;
1317
1318public:
1319  /// Value must be a register.
1320  static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1321                              CondARM32::Cond Predicate) {
1322    return new (Func->allocate<InstARM32Str>())
1323        InstARM32Str(Func, Value, Mem, Predicate);
1324  }
1325  void emit(const Cfg *Func) const override;
1326  void emitIAS(const Cfg *Func) const override;
1327  void dump(const Cfg *Func) const override;
1328  static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }
1329
1330private:
1331  InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1332               CondARM32::Cond Predicate);
1333};
1334
1335/// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1336/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1337/// Variable).
1338class InstARM32Strex final : public InstARM32Pred {
1339  InstARM32Strex() = delete;
1340  InstARM32Strex(const InstARM32Strex &) = delete;
1341  InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1342
1343public:
1344  /// Value must be a register.
1345  static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1346                                OperandARM32Mem *Mem,
1347                                CondARM32::Cond Predicate) {
1348    return new (Func->allocate<InstARM32Strex>())
1349        InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1350  }
1351  void emit(const Cfg *Func) const override;
1352  void emitIAS(const Cfg *Func) const override;
1353  void dump(const Cfg *Func) const override;
1354  static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
1355
1356private:
1357  InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1358                 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1359};
1360
1361/// Sub-vector store instruction. It's important for liveness that there is no
1362///  Dest operand (OperandARM32Mem instead of Dest Variable).
1363class InstARM32Vstr1 final : public InstARM32Pred {
1364  InstARM32Vstr1() = delete;
1365  InstARM32Vstr1(const InstARM32Vstr1 &) = delete;
1366  InstARM32Vstr1 &operator=(const InstARM32Vstr1 &) = delete;
1367
1368public:
1369  /// Value must be a register.
1370  static InstARM32Vstr1 *create(Cfg *Func, Variable *Value,
1371                                OperandARM32Mem *Mem, CondARM32::Cond Predicate,
1372                                SizeT Size) {
1373    return new (Func->allocate<InstARM32Vstr1>())
1374        InstARM32Vstr1(Func, Value, Mem, Predicate, Size);
1375  }
1376  void emit(const Cfg *Func) const override;
1377  void emitIAS(const Cfg *Func) const override;
1378  void dump(const Cfg *Func) const override;
1379  static bool classof(const Inst *Instr) { return isClassof(Instr, Vstr1); }
1380
1381private:
1382  InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1383                 CondARM32::Cond Predicate, SizeT Size);
1384
1385  SizeT Size;
1386};
1387
1388/// Vector element duplication/replication instruction.
1389class InstARM32Vdup final : public InstARM32Pred {
1390  InstARM32Vdup() = delete;
1391  InstARM32Vdup(const InstARM32Vdup &) = delete;
1392  InstARM32Vdup &operator=(const InstARM32Vdup &) = delete;
1393
1394public:
1395  /// Value must be a register.
1396  static InstARM32Vdup *create(Cfg *Func, Variable *Dest, Variable *Src,
1397                               IValueT Idx) {
1398    return new (Func->allocate<InstARM32Vdup>())
1399        InstARM32Vdup(Func, Dest, Src, Idx);
1400  }
1401  void emit(const Cfg *Func) const override;
1402  void emitIAS(const Cfg *Func) const override;
1403  void dump(const Cfg *Func) const override;
1404  static bool classof(const Inst *Instr) { return isClassof(Instr, Vdup); }
1405
1406private:
1407  InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src, IValueT Idx);
1408
1409  const IValueT Idx;
1410};
1411
1412class InstARM32Trap : public InstARM32 {
1413  InstARM32Trap() = delete;
1414  InstARM32Trap(const InstARM32Trap &) = delete;
1415  InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1416
1417public:
1418  static InstARM32Trap *create(Cfg *Func) {
1419    return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1420  }
1421  void emit(const Cfg *Func) const override;
1422  void emitIAS(const Cfg *Func) const override;
1423  void dump(const Cfg *Func) const override;
1424  static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
1425
1426private:
1427  explicit InstARM32Trap(Cfg *Func);
1428};
1429
1430/// Unsigned Multiply Long: d.lo, d.hi := x * y
1431class InstARM32Umull : public InstARM32Pred {
1432  InstARM32Umull() = delete;
1433  InstARM32Umull(const InstARM32Umull &) = delete;
1434  InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1435
1436public:
1437  /// Everything must be a register.
1438  static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
1439                                Variable *Src0, Variable *Src1,
1440                                CondARM32::Cond Predicate) {
1441    return new (Func->allocate<InstARM32Umull>())
1442        InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
1443  }
1444  void emit(const Cfg *Func) const override;
1445  void emitIAS(const Cfg *Func) const override;
1446  void dump(const Cfg *Func) const override;
1447  static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
1448
1449private:
1450  InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
1451                 Variable *Src1, CondARM32::Cond Predicate);
1452
1453  Variable *DestHi;
1454};
1455
1456/// Handles fp2int, int2fp, and fp2fp conversions.
1457class InstARM32Vcvt final : public InstARM32Pred {
1458  InstARM32Vcvt() = delete;
1459  InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1460  InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1461
1462public:
1463  enum VcvtVariant {
1464    S2si,
1465    S2ui,
1466    Si2s,
1467    Ui2s,
1468    D2si,
1469    D2ui,
1470    Si2d,
1471    Ui2d,
1472    S2d,
1473    D2s,
1474    Vs2si,
1475    Vs2ui,
1476    Vsi2s,
1477    Vui2s,
1478  };
1479  static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1480                               VcvtVariant Variant, CondARM32::Cond Predicate) {
1481    return new (Func->allocate<InstARM32Vcvt>())
1482        InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1483  }
1484  void emit(const Cfg *Func) const override;
1485  void emitIAS(const Cfg *Func) const override;
1486  void dump(const Cfg *Func) const override;
1487  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
1488
1489private:
1490  InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1491                CondARM32::Cond Predicate);
1492
1493  const VcvtVariant Variant;
1494};
1495
1496/// Handles (some of) vmov's various formats.
1497class InstARM32Mov final : public InstARM32Pred {
1498  InstARM32Mov() = delete;
1499  InstARM32Mov(const InstARM32Mov &) = delete;
1500  InstARM32Mov &operator=(const InstARM32Mov &) = delete;
1501
1502public:
1503  static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1504                              CondARM32::Cond Predicate) {
1505    return new (Func->allocate<InstARM32Mov>())
1506        InstARM32Mov(Func, Dest, Src, Predicate);
1507  }
1508  bool isRedundantAssign() const override {
1509    return !isMultiDest() && !isMultiSource() &&
1510           getPredicate() == CondARM32::AL &&
1511           checkForRedundantAssign(getDest(), getSrc(0));
1512  }
1513  bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
1514  void emit(const Cfg *Func) const override;
1515  void emitIAS(const Cfg *Func) const override;
1516  void dump(const Cfg *Func) const override;
1517  static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
1518
1519  bool isMultiDest() const { return DestHi != nullptr; }
1520
1521  bool isMultiSource() const {
1522    assert(getSrcSize() == 1 || getSrcSize() == 2);
1523    return getSrcSize() == 2;
1524  }
1525
1526  Variable *getDestHi() const { return DestHi; }
1527
1528private:
1529  InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1530               CondARM32::Cond Predicate);
1531  void emitMultiDestSingleSource(const Cfg *Func) const;
1532  void emitSingleDestMultiSource(const Cfg *Func) const;
1533  void emitSingleDestSingleSource(const Cfg *Func) const;
1534
1535  Variable *DestHi = nullptr;
1536};
1537
1538/// Generates vmov Rd, Dn[x] instructions, and their related floating point
1539/// versions.
1540class InstARM32Extract final : public InstARM32Pred {
1541  InstARM32Extract() = delete;
1542  InstARM32Extract(const InstARM32Extract &) = delete;
1543  InstARM32Extract &operator=(const InstARM32Extract &) = delete;
1544
1545public:
1546  static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0,
1547                                  uint32_t Index, CondARM32::Cond Predicate) {
1548    return new (Func->allocate<InstARM32Extract>())
1549        InstARM32Extract(Func, Dest, Src0, Index, Predicate);
1550  }
1551  void emit(const Cfg *Func) const override;
1552  void emitIAS(const Cfg *Func) const override;
1553  static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); }
1554
1555private:
1556  InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1557                   CondARM32::Cond Predicate)
1558      : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate),
1559        Index(Index) {
1560    assert(Index < typeNumElements(Src0->getType()));
1561    addSource(Src0);
1562  }
1563
1564  const uint32_t Index;
1565};
1566
1567/// Generates vmov Dn[x], Rd instructions, and their related floating point
1568/// versions.
1569class InstARM32Insert final : public InstARM32Pred {
1570  InstARM32Insert() = delete;
1571  InstARM32Insert(const InstARM32Insert &) = delete;
1572  InstARM32Insert &operator=(const InstARM32Insert &) = delete;
1573
1574public:
1575  static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0,
1576                                 uint32_t Index, CondARM32::Cond Predicate) {
1577    return new (Func->allocate<InstARM32Insert>())
1578        InstARM32Insert(Func, Dest, Src0, Index, Predicate);
1579  }
1580  void emit(const Cfg *Func) const override;
1581  void emitIAS(const Cfg *Func) const override;
1582  static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); }
1583
1584private:
1585  InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1586                  CondARM32::Cond Predicate)
1587      : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate),
1588        Index(Index) {
1589    assert(Index < typeNumElements(Dest->getType()));
1590    addSource(Src0);
1591  }
1592
1593  const uint32_t Index;
1594};
1595
1596class InstARM32Vcmp final : public InstARM32Pred {
1597  InstARM32Vcmp() = delete;
1598  InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1599  InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1600
1601public:
1602  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1603                               CondARM32::Cond Predicate) {
1604    return new (Func->allocate<InstARM32Vcmp>())
1605        InstARM32Vcmp(Func, Src0, Src1, Predicate);
1606  }
1607  static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1608                               OperandARM32FlexFpZero *Src1,
1609                               CondARM32::Cond Predicate) {
1610    return new (Func->allocate<InstARM32Vcmp>())
1611        InstARM32Vcmp(Func, Src0, Src1, Predicate);
1612  }
1613  void emit(const Cfg *Func) const override;
1614  void emitIAS(const Cfg *Func) const override;
1615  void dump(const Cfg *Func) const override;
1616  static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }
1617
1618private:
1619  InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1620                CondARM32::Cond Predicate);
1621};
1622
1623/// Copies the FP Status and Control Register the core flags.
1624class InstARM32Vmrs final : public InstARM32Pred {
1625  InstARM32Vmrs() = delete;
1626  InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1627  InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1628
1629public:
1630  static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1631    return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1632  }
1633  void emit(const Cfg *Func) const override;
1634  void emitIAS(const Cfg *Func) const override;
1635  void dump(const Cfg *Func) const override;
1636  static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
1637
1638private:
1639  InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1640};
1641
1642class InstARM32Vabs final : public InstARM32Pred {
1643  InstARM32Vabs() = delete;
1644  InstARM32Vabs(const InstARM32Vabs &) = delete;
1645  InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1646
1647public:
1648  static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1649                               CondARM32::Cond Predicate) {
1650    return new (Func->allocate<InstARM32Vabs>())
1651        InstARM32Vabs(Func, Dest, Src, Predicate);
1652  }
1653  void emit(const Cfg *Func) const override;
1654  void emitIAS(const Cfg *Func) const override;
1655  void dump(const Cfg *Func) const override;
1656  static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
1657
1658private:
1659  InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1660                CondARM32::Cond Predicate);
1661};
1662
1663class InstARM32Dmb final : public InstARM32Pred {
1664  InstARM32Dmb() = delete;
1665  InstARM32Dmb(const InstARM32Dmb &) = delete;
1666  InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1667
1668public:
1669  static InstARM32Dmb *create(Cfg *Func) {
1670    return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1671  }
1672  void emit(const Cfg *Func) const override;
1673  void emitIAS(const Cfg *Func) const override;
1674  void dump(const Cfg *Func) const override;
1675  static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
1676
1677private:
1678  explicit InstARM32Dmb(Cfg *Func);
1679};
1680
1681class InstARM32Nop final : public InstARM32Pred {
1682  InstARM32Nop() = delete;
1683  InstARM32Nop(const InstARM32Nop &) = delete;
1684  InstARM32Nop &operator=(const InstARM32Nop &) = delete;
1685
1686public:
1687  static InstARM32Nop *create(Cfg *Func) {
1688    return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func);
1689  }
1690  void emit(const Cfg *Func) const override;
1691  void emitIAS(const Cfg *Func) const override;
1692  void dump(const Cfg *Func) const override;
1693  static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); }
1694
1695private:
1696  explicit InstARM32Nop(Cfg *Func);
1697};
1698
1699// Declare partial template specializations of emit() methods that already have
1700// default implementations. Without this, there is the possibility of ODR
1701// violations and link errors.
1702
1703template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1704template <> void InstARM32Movw::emit(const Cfg *Func) const;
1705template <> void InstARM32Movt::emit(const Cfg *Func) const;
1706template <> void InstARM32Vldr1d::emit(const Cfg *Func) const;
1707template <> void InstARM32Vldr1q::emit(const Cfg *Func) const;
1708
1709} // end of namespace ARM32
1710} // end of namespace Ice
1711
1712#endif // SUBZERO_SRC_ICEINSTARM32_H
1713