blob: 898f6a46876794f695260297aadabed5ab7a3a9c [file] [log] [blame]
Jan Voungb36ad9b2015-04-21 17:01:49 -07001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Andrew Scull57e12682015-09-16 11:30:19 -070011/// This file declares the InstARM32 and OperandARM32 classes and their
12/// subclasses. This represents the machine instructions and operands used for
13/// ARM32 code selection.
Andrew Scull9612d322015-07-06 14:53:25 -070014///
Jan Voungb36ad9b2015-04-21 17:01:49 -070015//===----------------------------------------------------------------------===//
16
17#ifndef SUBZERO_SRC_ICEINSTARM32_H
18#define SUBZERO_SRC_ICEINSTARM32_H
19
Jan Voung3bfd99a2015-05-22 16:35:25 -070020#include "IceConditionCodesARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070021#include "IceDefs.h"
Jan Voungb2d50842015-05-12 09:53:50 -070022#include "IceInst.h"
23#include "IceInstARM32.def"
24#include "IceOperand.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070025
26namespace Ice {
27
28class TargetARM32;
Jan Voungb2d50842015-05-12 09:53:50 -070029
Andrew Scull57e12682015-09-16 11:30:19 -070030/// OperandARM32 extends the Operand hierarchy. Its subclasses are
Andrew Scull9612d322015-07-06 14:53:25 -070031/// OperandARM32Mem and OperandARM32Flex.
Jan Voungb2d50842015-05-12 09:53:50 -070032class OperandARM32 : public Operand {
33 OperandARM32() = delete;
34 OperandARM32(const OperandARM32 &) = delete;
35 OperandARM32 &operator=(const OperandARM32 &) = delete;
36
37public:
Jan Voungb3401d22015-05-18 09:38:21 -070038 enum OperandKindARM32 {
39 k__Start = Operand::kTarget,
40 kMem,
41 kFlexStart,
42 kFlexImm = kFlexStart,
43 kFlexReg,
44 kFlexEnd = kFlexReg
45 };
Jan Voungb2d50842015-05-12 09:53:50 -070046
47 enum ShiftKind {
48 kNoShift = -1,
49#define X(enum, emit) enum,
50 ICEINSTARM32SHIFT_TABLE
51#undef X
52 };
53
54 using Operand::dump;
55 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070056 if (BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -070057 Str << "<OperandARM32>";
58 }
59
60protected:
61 OperandARM32(OperandKindARM32 Kind, Type Ty)
62 : Operand(static_cast<OperandKind>(Kind), Ty) {}
Jan Voungb2d50842015-05-12 09:53:50 -070063};
64
Andrew Scull9612d322015-07-06 14:53:25 -070065/// OperandARM32Mem represents a memory operand in any of the various ARM32
66/// addressing modes.
Jan Voungb2d50842015-05-12 09:53:50 -070067class OperandARM32Mem : public OperandARM32 {
68 OperandARM32Mem() = delete;
69 OperandARM32Mem(const OperandARM32Mem &) = delete;
70 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
71
72public:
Andrew Scull9612d322015-07-06 14:53:25 -070073 /// Memory operand addressing mode.
74 /// The enum value also carries the encoding.
Jan Voungb3401d22015-05-18 09:38:21 -070075 // TODO(jvoung): unify with the assembler.
76 enum AddrMode {
77 // bit encoding P U W
78 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base)
79 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback
80 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback
81 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base)
82 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
83 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
84 };
85
Andrew Scull9612d322015-07-06 14:53:25 -070086 /// Provide two constructors.
87 /// NOTE: The Variable-typed operands have to be registers.
88 ///
89 /// (1) Reg + Imm. The Immediate actually has a limited number of bits
Andrew Scull57e12682015-09-16 11:30:19 -070090 /// for encoding, so check canHoldOffset first. It cannot handle general
91 /// Constant operands like ConstantRelocatable, since a relocatable can
92 /// potentially take up too many bits.
Jan Voungb3401d22015-05-18 09:38:21 -070093 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
Jan Voungbefd03a2015-06-02 11:03:03 -070094 ConstantInteger32 *ImmOffset,
Jan Voungb3401d22015-05-18 09:38:21 -070095 AddrMode Mode = Offset) {
96 return new (Func->allocate<OperandARM32Mem>())
97 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
98 }
Andrew Scull57e12682015-09-16 11:30:19 -070099 /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
100 /// this mode is disallowed in the NaCl sandbox.
Jan Voungb3401d22015-05-18 09:38:21 -0700101 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
102 Variable *Index, ShiftKind ShiftOp = kNoShift,
103 uint16_t ShiftAmt = 0,
104 AddrMode Mode = Offset) {
105 return new (Func->allocate<OperandARM32Mem>())
106 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
107 }
108 Variable *getBase() const { return Base; }
109 ConstantInteger32 *getOffset() const { return ImmOffset; }
110 Variable *getIndex() const { return Index; }
111 ShiftKind getShiftOp() const { return ShiftOp; }
112 uint16_t getShiftAmt() const { return ShiftAmt; }
113 AddrMode getAddrMode() const { return Mode; }
114
115 bool isRegReg() const { return Index != nullptr; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700116 bool isNegAddrMode() const {
117 // Positive address modes have the "U" bit set, and negative modes don't.
118 static_assert((PreIndex & (4 << 21)) != 0,
119 "Positive addr modes should have U bit set.");
120 static_assert((NegPreIndex & (4 << 21)) == 0,
121 "Negative addr modes should have U bit clear.");
122 return (Mode & (4 << 21)) == 0;
123 }
Jan Voungb3401d22015-05-18 09:38:21 -0700124
125 void emit(const Cfg *Func) const override;
126 using OperandARM32::dump;
127 void dump(const Cfg *Func, Ostream &Str) const override;
128
129 static bool classof(const Operand *Operand) {
130 return Operand->getKind() == static_cast<OperandKind>(kMem);
131 }
132
Andrew Scull57e12682015-09-16 11:30:19 -0700133 /// Return true if a load/store instruction for an element of type Ty can
134 /// encode the Offset directly in the immediate field of the 32-bit ARM
135 /// instruction. For some types, if the load is Sign extending, then the range
136 /// is reduced.
Jan Voungb2d50842015-05-12 09:53:50 -0700137 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
Jan Voungb3401d22015-05-18 09:38:21 -0700138
139private:
140 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
141 ConstantInteger32 *ImmOffset, AddrMode Mode);
142 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
143 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
John Porto1bec8bc2015-06-22 10:51:13 -0700144
Jan Voungb3401d22015-05-18 09:38:21 -0700145 Variable *Base;
146 ConstantInteger32 *ImmOffset;
147 Variable *Index;
148 ShiftKind ShiftOp;
149 uint16_t ShiftAmt;
150 AddrMode Mode;
151};
152
Andrew Scull57e12682015-09-16 11:30:19 -0700153/// OperandARM32Flex represent the "flexible second operand" for data-processing
154/// instructions. It can be a rotatable 8-bit constant, or a register with an
155/// optional shift operand. The shift amount can even be a third register.
Jan Voungb3401d22015-05-18 09:38:21 -0700156class OperandARM32Flex : public OperandARM32 {
157 OperandARM32Flex() = delete;
158 OperandARM32Flex(const OperandARM32Flex &) = delete;
159 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
160
161public:
162 static bool classof(const Operand *Operand) {
163 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
164 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
165 }
166
167protected:
168 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
Jan Voungb3401d22015-05-18 09:38:21 -0700169};
170
Andrew Scull9612d322015-07-06 14:53:25 -0700171/// Rotated immediate variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700172class OperandARM32FlexImm : public OperandARM32Flex {
173 OperandARM32FlexImm() = delete;
174 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
175 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
176
177public:
Andrew Scull9612d322015-07-06 14:53:25 -0700178 /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
Jan Voungb3401d22015-05-18 09:38:21 -0700179 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
180 uint32_t RotateAmt) {
181 return new (Func->allocate<OperandARM32FlexImm>())
182 OperandARM32FlexImm(Func, Ty, Imm, RotateAmt);
183 }
184
185 void emit(const Cfg *Func) const override;
186 using OperandARM32::dump;
187 void dump(const Cfg *Func, Ostream &Str) const override;
188
189 static bool classof(const Operand *Operand) {
190 return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
191 }
192
Andrew Scull57e12682015-09-16 11:30:19 -0700193 /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
194 /// the out-params RotateAmt and Immed_8 if Immediate fits.
Jan Voungb3401d22015-05-18 09:38:21 -0700195 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
196 uint32_t *Immed_8);
197
198 uint32_t getImm() const { return Imm; }
199 uint32_t getRotateAmt() const { return RotateAmt; }
200
201private:
202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700203
204 uint32_t Imm;
205 uint32_t RotateAmt;
206};
207
Andrew Scull9612d322015-07-06 14:53:25 -0700208/// Shifted register variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700209class OperandARM32FlexReg : public OperandARM32Flex {
210 OperandARM32FlexReg() = delete;
211 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
212 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
213
214public:
Andrew Scull9612d322015-07-06 14:53:25 -0700215 /// Register with immediate/reg shift amount and shift operation.
Jan Voungb3401d22015-05-18 09:38:21 -0700216 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
217 ShiftKind ShiftOp, Operand *ShiftAmt) {
218 return new (Func->allocate<OperandARM32FlexReg>())
219 OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
220 }
221
222 void emit(const Cfg *Func) const override;
223 using OperandARM32::dump;
224 void dump(const Cfg *Func, Ostream &Str) const override;
225
226 static bool classof(const Operand *Operand) {
227 return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
228 }
229
230 Variable *getReg() const { return Reg; }
231 ShiftKind getShiftOp() const { return ShiftOp; }
Andrew Scull9612d322015-07-06 14:53:25 -0700232 /// ShiftAmt can represent an immediate or a register.
Jan Voungb3401d22015-05-18 09:38:21 -0700233 Operand *getShiftAmt() const { return ShiftAmt; }
234
235private:
236 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
237 Operand *ShiftAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700238
239 Variable *Reg;
240 ShiftKind ShiftOp;
241 Operand *ShiftAmt;
Jan Voungb2d50842015-05-12 09:53:50 -0700242};
243
Jan Voung28068ad2015-07-31 12:58:46 -0700244/// StackVariable represents a Var that isn't assigned a register (stack-only).
245/// It is assigned a stack slot, but the slot's offset may be too large to
Andrew Scull57e12682015-09-16 11:30:19 -0700246/// represent in the native addressing mode, and so it has a separate base
247/// register from SP/FP, where the offset from that base register is then in
248/// range.
Jan Voung28068ad2015-07-31 12:58:46 -0700249class StackVariable final : public Variable {
250 StackVariable() = delete;
251 StackVariable(const StackVariable &) = delete;
252 StackVariable &operator=(const StackVariable &) = delete;
253
254public:
255 static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
256 return new (Func->allocate<StackVariable>()) StackVariable(Ty, Index);
257 }
258 const static OperandKind StackVariableKind =
259 static_cast<OperandKind>(kVariable_Target);
260 static bool classof(const Operand *Operand) {
261 return Operand->getKind() == StackVariableKind;
262 }
263 void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
264 int32_t getBaseRegNum() const override { return BaseRegNum; }
265 // Inherit dump() and emit() from Variable.
266
267private:
268 StackVariable(Type Ty, SizeT Index)
269 : Variable(StackVariableKind, Ty, Index) {}
270 int32_t BaseRegNum = Variable::NoRegister;
271};
272
Andrew Scull9612d322015-07-06 14:53:25 -0700273/// Base class for ARM instructions. While most ARM instructions can be
Andrew Scull57e12682015-09-16 11:30:19 -0700274/// conditionally executed, a few of them are not predicable (halt, memory
275/// barriers, etc.).
Jan Voungb2d50842015-05-12 09:53:50 -0700276class InstARM32 : public InstTarget {
277 InstARM32() = delete;
278 InstARM32(const InstARM32 &) = delete;
279 InstARM32 &operator=(const InstARM32 &) = delete;
280
281public:
Jan Voungb3401d22015-05-18 09:38:21 -0700282 enum InstKindARM32 {
283 k__Start = Inst::Target,
Jan Voung29719972015-05-19 11:24:51 -0700284 Adc,
285 Add,
Jan Voungb0a8c242015-06-18 15:00:14 -0700286 Adjuststack,
Jan Voung29719972015-05-19 11:24:51 -0700287 And,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700288 Asr,
Jan Voung55500db2015-05-26 14:25:40 -0700289 Bic,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700290 Br,
291 Call,
292 Cmp,
Jan Voungf645d852015-07-09 10:35:09 -0700293 Clz,
John Porto16991842015-10-01 15:11:23 -0700294 Dmb,
Jan Voung29719972015-05-19 11:24:51 -0700295 Eor,
Jan Voung6ec369e2015-06-30 11:03:15 -0700296 Label,
Jan Voung29719972015-05-19 11:24:51 -0700297 Ldr,
John Porto16991842015-10-01 15:11:23 -0700298 Ldrex,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700299 Lsl,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700300 Lsr,
Jan Voung29719972015-05-19 11:24:51 -0700301 Mla,
Jan Voung6ec369e2015-06-30 11:03:15 -0700302 Mls,
Jan Voungb3401d22015-05-18 09:38:21 -0700303 Mov,
304 Movt,
305 Movw,
Jan Voung29719972015-05-19 11:24:51 -0700306 Mul,
Jan Voungb3401d22015-05-18 09:38:21 -0700307 Mvn,
Jan Voung29719972015-05-19 11:24:51 -0700308 Orr,
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700309 Pop,
310 Push,
Jan Voungf645d852015-07-09 10:35:09 -0700311 Rbit,
Jan Voungb3401d22015-05-18 09:38:21 -0700312 Ret,
Jan Voungf645d852015-07-09 10:35:09 -0700313 Rev,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700314 Rsb,
Jan Voung29719972015-05-19 11:24:51 -0700315 Sbc,
Jan Voung6ec369e2015-06-30 11:03:15 -0700316 Sdiv,
Jan Voungbefd03a2015-06-02 11:03:03 -0700317 Str,
John Porto16991842015-10-01 15:11:23 -0700318 Strex,
Jan Voung29719972015-05-19 11:24:51 -0700319 Sub,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700320 Sxt,
Jan Voung6ec369e2015-06-30 11:03:15 -0700321 Trap,
322 Tst,
323 Udiv,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700324 Umull,
Jan Voung86ebec12015-08-09 07:58:35 -0700325 Uxt,
John Portoba6a67c2015-09-25 15:19:45 -0700326 Vabs,
Jan Voung86ebec12015-08-09 07:58:35 -0700327 Vadd,
John Porto2f5534f2015-09-18 15:59:47 -0700328 Vcmp,
John Portoc31e2ed2015-09-11 05:17:08 -0700329 Vcvt,
Jan Voung86ebec12015-08-09 07:58:35 -0700330 Vdiv,
John Porto2f5534f2015-09-18 15:59:47 -0700331 Vmrs,
Jan Voung86ebec12015-08-09 07:58:35 -0700332 Vmul,
333 Vsqrt,
334 Vsub
Jan Voungb3401d22015-05-18 09:38:21 -0700335 };
Jan Voungb2d50842015-05-12 09:53:50 -0700336
337 static const char *getWidthString(Type Ty);
Jan Voung86ebec12015-08-09 07:58:35 -0700338 static const char *getVecWidthString(Type Ty);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700339 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
Jan Voungb2d50842015-05-12 09:53:50 -0700340
Jan Voung86ebec12015-08-09 07:58:35 -0700341 /// Shared emit routines for common forms of instructions.
342 static void emitThreeAddrFP(const char *Opcode, const InstARM32 *Inst,
343 const Cfg *Func);
344
Jan Voungb2d50842015-05-12 09:53:50 -0700345 void dump(const Cfg *Func) const override;
346
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700347 void emitIAS(const Cfg *Func) const override;
348
Jan Voungb2d50842015-05-12 09:53:50 -0700349protected:
350 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
351 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700352
Jan Voungb2d50842015-05-12 09:53:50 -0700353 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
354 return Inst->getKind() == static_cast<InstKind>(MyKind);
355 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700356
357 // Generates text of assembly instruction using method emit(), and then adds
358 // to the assembly buffer as a Fixup.
359 void emitUsingTextFixup(const Cfg *Func) const;
Jan Voungb2d50842015-05-12 09:53:50 -0700360};
361
Andrew Scull9612d322015-07-06 14:53:25 -0700362/// A predicable ARM instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700363class InstARM32Pred : public InstARM32 {
364 InstARM32Pred() = delete;
365 InstARM32Pred(const InstARM32Pred &) = delete;
366 InstARM32Pred &operator=(const InstARM32Pred &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700367
Jan Voung3bfd99a2015-05-22 16:35:25 -0700368public:
369 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
370 CondARM32::Cond Predicate)
371 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
372
373 CondARM32::Cond getPredicate() const { return Predicate; }
374 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
375
376 static const char *predString(CondARM32::Cond Predicate);
377 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
378
Andrew Scull9612d322015-07-06 14:53:25 -0700379 /// Shared emit routines for common forms of instructions.
Jan Voung66c3d5e2015-06-04 17:02:31 -0700380 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
Jan Voungf645d852015-07-09 10:35:09 -0700381 const Cfg *Func, bool NeedsWidthSuffix);
Jan Voung86ebec12015-08-09 07:58:35 -0700382 static void emitUnaryopFP(const char *Opcode, const InstARM32Pred *Inst,
383 const Cfg *Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700384 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
385 const Cfg *Func);
386 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
387 const Cfg *Func, bool SetFlags);
Jan Voung6ec369e2015-06-30 11:03:15 -0700388 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
389 const Cfg *Func);
390 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Inst,
391 const Cfg *Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700392
393protected:
394 CondARM32::Cond Predicate;
395};
396
397template <typename StreamType>
398inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
399 Stream << InstARM32Pred::predString(Predicate);
400 return Stream;
401}
Jan Voungb3401d22015-05-18 09:38:21 -0700402
Andrew Scull9612d322015-07-06 14:53:25 -0700403/// Instructions of the form x := op(y).
Jan Voungf645d852015-07-09 10:35:09 -0700404template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700405class InstARM32UnaryopGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700406 InstARM32UnaryopGPR() = delete;
407 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
408 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
409
410public:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700411 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
412 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700413 return new (Func->allocate<InstARM32UnaryopGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700414 InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700415 }
416 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700417 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700418 return;
Jan Voungf645d852015-07-09 10:35:09 -0700419 emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
Jan Voungb3401d22015-05-18 09:38:21 -0700420 }
Jan Voungb3401d22015-05-18 09:38:21 -0700421 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700422 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700423 return;
424 Ostream &Str = Func->getContext()->getStrDump();
425 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700426 Str << " = ";
427 dumpOpcodePred(Str, Opcode, getDest()->getType());
428 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700429 dumpSources(Func);
430 }
431 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
432
433private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700434 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
435 CondARM32::Cond Predicate)
436 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700437 addSource(Src);
438 }
John Porto1bec8bc2015-06-22 10:51:13 -0700439
Jan Voungb3401d22015-05-18 09:38:21 -0700440 static const char *Opcode;
441};
442
Jan Voung86ebec12015-08-09 07:58:35 -0700443/// Instructions of the form x := op(y), for vector/FP.
444template <InstARM32::InstKindARM32 K>
445class InstARM32UnaryopFP : public InstARM32Pred {
446 InstARM32UnaryopFP() = delete;
447 InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
448 InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
449
450public:
451 static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
452 CondARM32::Cond Predicate) {
453 return new (Func->allocate<InstARM32UnaryopFP>())
454 InstARM32UnaryopFP(Func, Dest, Src, Predicate);
455 }
456 void emit(const Cfg *Func) const override {
457 if (!BuildDefs::dump())
458 return;
459 emitUnaryopFP(Opcode, this, Func);
460 }
Jan Voung86ebec12015-08-09 07:58:35 -0700461 void dump(const Cfg *Func) const override {
462 if (!BuildDefs::dump())
463 return;
464 Ostream &Str = Func->getContext()->getStrDump();
465 dumpDest(Func);
466 Str << " = ";
467 dumpOpcodePred(Str, Opcode, getDest()->getType());
468 Str << " ";
469 dumpSources(Func);
470 }
471 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
472
473private:
474 InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
475 CondARM32::Cond Predicate)
476 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
477 addSource(Src);
478 }
479
480 static const char *Opcode;
481};
482
Andrew Scull9612d322015-07-06 14:53:25 -0700483/// Instructions of the form x := x op y.
Jan Voungb3401d22015-05-18 09:38:21 -0700484template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700485class InstARM32TwoAddrGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700486 InstARM32TwoAddrGPR() = delete;
487 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
488 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
489
490public:
Andrew Scull9612d322015-07-06 14:53:25 -0700491 /// Dest must be a register.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700492 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
493 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700494 return new (Func->allocate<InstARM32TwoAddrGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700495 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700496 }
497 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700498 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700499 return;
500 emitTwoAddr(Opcode, this, Func);
501 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700502 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700503 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700504 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700505 return;
506 Ostream &Str = Func->getContext()->getStrDump();
507 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700508 Str << " = ";
509 dumpOpcodePred(Str, Opcode, getDest()->getType());
510 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700511 dumpSources(Func);
512 }
513 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
514
515private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700516 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
517 CondARM32::Cond Predicate)
518 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700519 addSource(Dest);
520 addSource(Src);
521 }
John Porto1bec8bc2015-06-22 10:51:13 -0700522
Jan Voungb3401d22015-05-18 09:38:21 -0700523 static const char *Opcode;
524};
525
John Porto16991842015-10-01 15:11:23 -0700526/// Base class for load instructions.
Jan Voungb3401d22015-05-18 09:38:21 -0700527template <InstARM32::InstKindARM32 K>
John Porto16991842015-10-01 15:11:23 -0700528class InstARM32LoadBase : public InstARM32Pred {
529 InstARM32LoadBase() = delete;
530 InstARM32LoadBase(const InstARM32LoadBase &) = delete;
531 InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700532
533public:
John Porto16991842015-10-01 15:11:23 -0700534 static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
535 CondARM32::Cond Predicate) {
536 return new (Func->allocate<InstARM32LoadBase>())
537 InstARM32LoadBase(Func, Dest, Source, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700538 }
Jan Voungb3401d22015-05-18 09:38:21 -0700539 void emit(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700540 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700541 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700542 return;
543 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung3bfd99a2015-05-22 16:35:25 -0700544 dumpOpcodePred(Str, Opcode, getDest()->getType());
545 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700546 dumpDest(Func);
547 Str << ", ";
548 dumpSources(Func);
549 }
550 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
551
552private:
John Porto16991842015-10-01 15:11:23 -0700553 InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
554 CondARM32::Cond Predicate)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700555 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700556 addSource(Source);
557 }
Jan Voungb3401d22015-05-18 09:38:21 -0700558
559 static const char *Opcode;
560};
561
Andrew Scull9612d322015-07-06 14:53:25 -0700562/// Instructions of the form x := y op z. May have the side-effect of setting
563/// status flags.
Jan Voung29719972015-05-19 11:24:51 -0700564template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700565class InstARM32ThreeAddrGPR : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -0700566 InstARM32ThreeAddrGPR() = delete;
567 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
568 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
569
570public:
Andrew Scull57e12682015-09-16 11:30:19 -0700571 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
572 /// must be registers.
Jan Voung29719972015-05-19 11:24:51 -0700573 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
Jan Voung6ec369e2015-06-30 11:03:15 -0700574 Variable *Src0, Operand *Src1,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700575 CondARM32::Cond Predicate,
Jan Voung29719972015-05-19 11:24:51 -0700576 bool SetFlags = false) {
577 return new (Func->allocate<InstARM32ThreeAddrGPR>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700578 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
Jan Voung29719972015-05-19 11:24:51 -0700579 }
580 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700581 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700582 return;
583 emitThreeAddr(Opcode, this, Func, SetFlags);
584 }
Karl Schimpf372bdd62015-10-13 14:39:14 -0700585 void emitIAS(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -0700586 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700587 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700588 return;
589 Ostream &Str = Func->getContext()->getStrDump();
590 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700591 Str << " = ";
592 dumpOpcodePred(Str, Opcode, getDest()->getType());
593 Str << (SetFlags ? ".s " : " ");
Jan Voung29719972015-05-19 11:24:51 -0700594 dumpSources(Func);
595 }
596 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
597
598private:
Jan Voung6ec369e2015-06-30 11:03:15 -0700599 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
600 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700601 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
Jan Voung6ec369e2015-06-30 11:03:15 -0700602 addSource(Src0);
603 addSource(Src1);
604 }
605
606 static const char *Opcode;
607 bool SetFlags;
608};
609
Andrew Scull57e12682015-09-16 11:30:19 -0700610/// Instructions of the form x := y op z, for vector/FP. We leave these as
Jan Voung86ebec12015-08-09 07:58:35 -0700611/// unconditional: "ARM deprecates the conditional execution of any instruction
612/// encoding provided by the Advanced SIMD Extension that is not also provided
Andrew Scull57e12682015-09-16 11:30:19 -0700613/// by the Floating-point (VFP) extension". They do not set flags.
Jan Voung86ebec12015-08-09 07:58:35 -0700614template <InstARM32::InstKindARM32 K>
615class InstARM32ThreeAddrFP : public InstARM32 {
616 InstARM32ThreeAddrFP() = delete;
617 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
618 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
619
620public:
Andrew Scull57e12682015-09-16 11:30:19 -0700621 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
622 /// must be a register.
Jan Voung86ebec12015-08-09 07:58:35 -0700623 static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
624 Variable *Src1) {
625 return new (Func->allocate<InstARM32ThreeAddrFP>())
626 InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
627 }
628 void emit(const Cfg *Func) const override {
629 if (!BuildDefs::dump())
630 return;
631 emitThreeAddrFP(Opcode, this, Func);
632 }
Jan Voung86ebec12015-08-09 07:58:35 -0700633 void dump(const Cfg *Func) const override {
634 if (!BuildDefs::dump())
635 return;
636 Ostream &Str = Func->getContext()->getStrDump();
637 dumpDest(Func);
638 Str << " = ";
639 Str << Opcode << "." << getDest()->getType() << " ";
640 dumpSources(Func);
641 }
642 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
643
644private:
645 InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0,
646 Variable *Src1)
647 : InstARM32(Func, K, 2, Dest) {
648 addSource(Src0);
649 addSource(Src1);
650 }
651
652 static const char *Opcode;
653};
654
655/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
Jan Voung6ec369e2015-06-30 11:03:15 -0700656template <InstARM32::InstKindARM32 K>
657class InstARM32FourAddrGPR : public InstARM32Pred {
658 InstARM32FourAddrGPR() = delete;
659 InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
660 InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
661
662public:
663 // Every operand must be a register.
664 static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
665 Variable *Src1, Variable *Src2,
666 CondARM32::Cond Predicate) {
667 return new (Func->allocate<InstARM32FourAddrGPR>())
668 InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
669 }
670 void emit(const Cfg *Func) const override {
671 if (!BuildDefs::dump())
672 return;
673 emitFourAddr(Opcode, this, Func);
674 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700675 void dump(const Cfg *Func) const override {
676 if (!BuildDefs::dump())
677 return;
678 Ostream &Str = Func->getContext()->getStrDump();
679 dumpDest(Func);
680 Str << " = ";
681 dumpOpcodePred(Str, Opcode, getDest()->getType());
682 Str << " ";
683 dumpSources(Func);
684 }
685 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
686
687private:
688 InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
689 Variable *Src1, Variable *Src2,
690 CondARM32::Cond Predicate)
691 : InstARM32Pred(Func, K, 3, Dest, Predicate) {
692 addSource(Src0);
Jan Voung29719972015-05-19 11:24:51 -0700693 addSource(Src1);
694 addSource(Src2);
695 }
John Porto1bec8bc2015-06-22 10:51:13 -0700696
Jan Voung29719972015-05-19 11:24:51 -0700697 static const char *Opcode;
Jan Voung6ec369e2015-06-30 11:03:15 -0700698};
699
Jan Voung86ebec12015-08-09 07:58:35 -0700700/// Instructions of the form x cmpop y (setting flags).
Jan Voung6ec369e2015-06-30 11:03:15 -0700701template <InstARM32::InstKindARM32 K>
702class InstARM32CmpLike : public InstARM32Pred {
703 InstARM32CmpLike() = delete;
704 InstARM32CmpLike(const InstARM32CmpLike &) = delete;
705 InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
706
707public:
708 static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
709 CondARM32::Cond Predicate) {
710 return new (Func->allocate<InstARM32CmpLike>())
711 InstARM32CmpLike(Func, Src0, Src1, Predicate);
712 }
713 void emit(const Cfg *Func) const override {
714 if (!BuildDefs::dump())
715 return;
716 emitCmpLike(Opcode, this, Func);
717 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700718 void dump(const Cfg *Func) const override {
719 if (!BuildDefs::dump())
720 return;
721 Ostream &Str = Func->getContext()->getStrDump();
722 dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
723 Str << " ";
724 dumpSources(Func);
725 }
726 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
727
728private:
729 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
730 CondARM32::Cond Predicate)
731 : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
732 addSource(Src0);
733 addSource(Src1);
734 }
735
736 static const char *Opcode;
Jan Voung29719972015-05-19 11:24:51 -0700737};
738
Andrew Scull8072bae2015-09-14 16:01:26 -0700739using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
740using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
741using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
742using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
743using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
744using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
745using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
746using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
747using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
748using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
749using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
750using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
751using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
752using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
753using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
754using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
755using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
756using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
757using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
John Porto16991842015-10-01 15:11:23 -0700758using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
759using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
Andrew Scull57e12682015-09-16 11:30:19 -0700760/// MovT leaves the bottom bits alone so dest is also a source. This helps
761/// indicate that a previous MovW setting dest is not dead code.
Andrew Scull8072bae2015-09-14 16:01:26 -0700762using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
763using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
764using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
765using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
766using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
767using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
Andrew Scull57e12682015-09-16 11:30:19 -0700768// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
769// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
770// using that for now, so just model as a Unaryop.
Andrew Scull8072bae2015-09-14 16:01:26 -0700771using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
772using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
773using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
774using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
775using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
776using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
777using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
Jan Voung6ec369e2015-06-30 11:03:15 -0700778
Andrew Scull57e12682015-09-16 11:30:19 -0700779// InstARM32Label represents an intra-block label that is the target of an
780// intra-block branch. The offset between the label and the branch must be fit
781// in the instruction immediate (considered "near").
Jan Voung6ec369e2015-06-30 11:03:15 -0700782class InstARM32Label : public InstARM32 {
783 InstARM32Label() = delete;
784 InstARM32Label(const InstARM32Label &) = delete;
785 InstARM32Label &operator=(const InstARM32Label &) = delete;
786
787public:
788 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
789 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
790 }
791 uint32_t getEmitInstCount() const override { return 0; }
792 IceString getName(const Cfg *Func) const;
793 SizeT getNumber() const { return Number; }
794 void emit(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700795 void dump(const Cfg *Func) const override;
796
797private:
798 InstARM32Label(Cfg *Func, TargetARM32 *Target);
799
800 SizeT Number; // used for unique label generation.
801};
Jan Voungb3401d22015-05-18 09:38:21 -0700802
Andrew Scull9612d322015-07-06 14:53:25 -0700803/// Direct branch instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700804class InstARM32Br : public InstARM32Pred {
805 InstARM32Br() = delete;
806 InstARM32Br(const InstARM32Br &) = delete;
807 InstARM32Br &operator=(const InstARM32Br &) = delete;
808
809public:
Andrew Scull9612d322015-07-06 14:53:25 -0700810 /// Create a conditional branch to one of two nodes.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700811 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
812 CfgNode *TargetFalse, CondARM32::Cond Predicate) {
813 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -0700814 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700815 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700816 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700817 }
Andrew Scull9612d322015-07-06 14:53:25 -0700818 /// Create an unconditional branch to a node.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700819 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
Jan Voung6ec369e2015-06-30 11:03:15 -0700820 constexpr CfgNode *NoCondTarget = nullptr;
821 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700822 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700823 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700824 }
Andrew Scull57e12682015-09-16 11:30:19 -0700825 /// Create a non-terminator conditional branch to a node, with a fallthrough
826 /// to the next instruction in the current node. This is used for switch
827 /// lowering.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700828 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
829 CondARM32::Cond Predicate) {
830 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -0700831 constexpr CfgNode *NoUncondTarget = nullptr;
832 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700833 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700834 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
835 }
836 // Create a conditional intra-block branch (or unconditional, if
837 // Condition==AL) to a label in the current block.
838 static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
839 CondARM32::Cond Predicate) {
840 constexpr CfgNode *NoCondTarget = nullptr;
841 constexpr CfgNode *NoUncondTarget = nullptr;
842 return new (Func->allocate<InstARM32Br>())
843 InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700844 }
845 const CfgNode *getTargetTrue() const { return TargetTrue; }
846 const CfgNode *getTargetFalse() const { return TargetFalse; }
847 bool optimizeBranch(const CfgNode *NextNode);
848 uint32_t getEmitInstCount() const override {
849 uint32_t Sum = 0;
Jan Voung6ec369e2015-06-30 11:03:15 -0700850 if (Label)
851 ++Sum;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700852 if (getTargetTrue())
853 ++Sum;
854 if (getTargetFalse())
855 ++Sum;
856 return Sum;
857 }
858 bool isUnconditionalBranch() const override {
859 return getPredicate() == CondARM32::AL;
860 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700861 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700862 void emit(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700863 void dump(const Cfg *Func) const override;
864 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
865
866private:
867 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Jan Voung6ec369e2015-06-30 11:03:15 -0700868 const InstARM32Label *Label, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -0700869
Jan Voung3bfd99a2015-05-22 16:35:25 -0700870 const CfgNode *TargetTrue;
871 const CfgNode *TargetFalse;
Jan Voung6ec369e2015-06-30 11:03:15 -0700872 const InstARM32Label *Label; // Intra-block branch target
Jan Voung3bfd99a2015-05-22 16:35:25 -0700873};
874
Andrew Scull57e12682015-09-16 11:30:19 -0700875/// AdjustStack instruction - subtracts SP by the given amount and updates the
876/// stack offset during code emission.
Jan Voungb0a8c242015-06-18 15:00:14 -0700877class InstARM32AdjustStack : public InstARM32 {
878 InstARM32AdjustStack() = delete;
879 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
880 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
881
882public:
Andrew Scull57e12682015-09-16 11:30:19 -0700883 /// Note: We need both Amount and SrcAmount. If Amount is too large then it
884 /// needs to be copied to a register (so SrcAmount could be a register).
885 /// However, we also need the numeric Amount for bookkeeping, and it's hard to
886 /// pull that from the generic SrcAmount operand.
Jan Voungb0a8c242015-06-18 15:00:14 -0700887 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
888 Operand *SrcAmount) {
889 return new (Func->allocate<InstARM32AdjustStack>())
890 InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
891 }
892 void emit(const Cfg *Func) const override;
Jan Voungb0a8c242015-06-18 15:00:14 -0700893 void dump(const Cfg *Func) const override;
894 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
Jan Voung28068ad2015-07-31 12:58:46 -0700895 SizeT getAmount() const { return Amount; }
Jan Voungb0a8c242015-06-18 15:00:14 -0700896
897private:
898 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount,
899 Operand *SrcAmount);
900 const SizeT Amount;
901};
902
Andrew Scull57e12682015-09-16 11:30:19 -0700903/// Call instruction (bl/blx). Arguments should have already been pushed.
Andrew Scull9612d322015-07-06 14:53:25 -0700904/// Technically bl and the register form of blx can be predicated, but we'll
905/// leave that out until needed.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700906class InstARM32Call : public InstARM32 {
907 InstARM32Call() = delete;
908 InstARM32Call(const InstARM32Call &) = delete;
909 InstARM32Call &operator=(const InstARM32Call &) = delete;
910
911public:
912 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
913 return new (Func->allocate<InstARM32Call>())
914 InstARM32Call(Func, Dest, CallTarget);
915 }
916 Operand *getCallTarget() const { return getSrc(0); }
917 void emit(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700918 void dump(const Cfg *Func) const override;
919 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
920
921private:
922 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700923};
924
Andrew Scull9612d322015-07-06 14:53:25 -0700925/// Pop into a list of GPRs. Technically this can be predicated, but we don't
926/// need that functionality.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700927class InstARM32Pop : public InstARM32 {
928 InstARM32Pop() = delete;
929 InstARM32Pop(const InstARM32Pop &) = delete;
930 InstARM32Pop &operator=(const InstARM32Pop &) = delete;
931
932public:
933 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
934 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
935 }
936 void emit(const Cfg *Func) const override;
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700937 void dump(const Cfg *Func) const override;
938 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
939
940private:
941 InstARM32Pop(Cfg *Func, const VarList &Dests);
John Porto1bec8bc2015-06-22 10:51:13 -0700942
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700943 VarList Dests;
944};
945
Andrew Scull57e12682015-09-16 11:30:19 -0700946/// Push a list of GPRs. Technically this can be predicated, but we don't need
947/// that functionality.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700948class InstARM32Push : public InstARM32 {
949 InstARM32Push() = delete;
950 InstARM32Push(const InstARM32Push &) = delete;
951 InstARM32Push &operator=(const InstARM32Push &) = delete;
952
953public:
954 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
955 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
956 }
957 void emit(const Cfg *Func) const override;
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700958 void dump(const Cfg *Func) const override;
959 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
960
961private:
962 InstARM32Push(Cfg *Func, const VarList &Srcs);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700963};
964
Andrew Scull57e12682015-09-16 11:30:19 -0700965/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
966/// register operand, but epilogue lowering will search for a Ret instead of a
967/// generic "bx". This instruction also takes a Source operand (for non-void
968/// returning functions) for liveness analysis, though a FakeUse before the ret
969/// would do just as well.
Andrew Scull9612d322015-07-06 14:53:25 -0700970///
971/// NOTE: Even though "bx" can be predicated, for now leave out the predication
972/// since it's not yet known to be useful for Ret. That may complicate finding
973/// the terminator instruction if it's not guaranteed to be executed.
Jan Voungb2d50842015-05-12 09:53:50 -0700974class InstARM32Ret : public InstARM32 {
975 InstARM32Ret() = delete;
976 InstARM32Ret(const InstARM32Ret &) = delete;
977 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
978
979public:
980 static InstARM32Ret *create(Cfg *Func, Variable *LR,
981 Variable *Source = nullptr) {
982 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
983 }
984 void emit(const Cfg *Func) const override;
985 void emitIAS(const Cfg *Func) const override;
986 void dump(const Cfg *Func) const override;
987 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
988
989private:
990 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
Jan Voungb2d50842015-05-12 09:53:50 -0700991};
Jan Voungb36ad9b2015-04-21 17:01:49 -0700992
Andrew Scull57e12682015-09-16 11:30:19 -0700993/// Store instruction. It's important for liveness that there is no Dest operand
994/// (OperandARM32Mem instead of Dest Variable).
John Porto16991842015-10-01 15:11:23 -0700995class InstARM32Str final : public InstARM32Pred {
Jan Voungbefd03a2015-06-02 11:03:03 -0700996 InstARM32Str() = delete;
997 InstARM32Str(const InstARM32Str &) = delete;
998 InstARM32Str &operator=(const InstARM32Str &) = delete;
999
1000public:
Andrew Scull9612d322015-07-06 14:53:25 -07001001 /// Value must be a register.
Jan Voungbefd03a2015-06-02 11:03:03 -07001002 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1003 CondARM32::Cond Predicate) {
1004 return new (Func->allocate<InstARM32Str>())
1005 InstARM32Str(Func, Value, Mem, Predicate);
1006 }
1007 void emit(const Cfg *Func) const override;
Jan Voungbefd03a2015-06-02 11:03:03 -07001008 void dump(const Cfg *Func) const override;
1009 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
1010
1011private:
1012 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1013 CondARM32::Cond Predicate);
Jan Voungbefd03a2015-06-02 11:03:03 -07001014};
1015
John Porto16991842015-10-01 15:11:23 -07001016/// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1017/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1018/// Variable).
1019class InstARM32Strex final : public InstARM32Pred {
1020 InstARM32Strex() = delete;
1021 InstARM32Strex(const InstARM32Strex &) = delete;
1022 InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1023
1024public:
1025 /// Value must be a register.
1026 static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1027 OperandARM32Mem *Mem,
1028 CondARM32::Cond Predicate) {
1029 return new (Func->allocate<InstARM32Strex>())
1030 InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1031 }
1032 void emit(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001033 void dump(const Cfg *Func) const override;
1034 static bool classof(const Inst *Inst) { return isClassof(Inst, Strex); }
1035
1036private:
1037 InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1038 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1039};
1040
Jan Voung6ec369e2015-06-30 11:03:15 -07001041class InstARM32Trap : public InstARM32 {
1042 InstARM32Trap() = delete;
1043 InstARM32Trap(const InstARM32Trap &) = delete;
1044 InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1045
1046public:
1047 static InstARM32Trap *create(Cfg *Func) {
1048 return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1049 }
1050 void emit(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -07001051 void dump(const Cfg *Func) const override;
1052 static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); }
1053
1054private:
1055 explicit InstARM32Trap(Cfg *Func);
1056};
1057
Andrew Scull9612d322015-07-06 14:53:25 -07001058/// Unsigned Multiply Long: d.lo, d.hi := x * y
Jan Voung3bfd99a2015-05-22 16:35:25 -07001059class InstARM32Umull : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -07001060 InstARM32Umull() = delete;
1061 InstARM32Umull(const InstARM32Umull &) = delete;
1062 InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1063
1064public:
Andrew Scull9612d322015-07-06 14:53:25 -07001065 /// Everything must be a register.
Jan Voung29719972015-05-19 11:24:51 -07001066 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001067 Variable *Src0, Variable *Src1,
1068 CondARM32::Cond Predicate) {
Jan Voung29719972015-05-19 11:24:51 -07001069 return new (Func->allocate<InstARM32Umull>())
Jan Voung3bfd99a2015-05-22 16:35:25 -07001070 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
Jan Voung29719972015-05-19 11:24:51 -07001071 }
1072 void emit(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -07001073 void dump(const Cfg *Func) const override;
1074 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
1075
1076private:
1077 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001078 Variable *Src1, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -07001079
Jan Voung29719972015-05-19 11:24:51 -07001080 Variable *DestHi;
1081};
1082
John Portoc31e2ed2015-09-11 05:17:08 -07001083/// Handles fp2int, int2fp, and fp2fp conversions.
1084class InstARM32Vcvt final : public InstARM32Pred {
1085 InstARM32Vcvt() = delete;
1086 InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1087 InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1088
1089public:
1090 enum VcvtVariant { S2si, S2ui, Si2s, Ui2s, D2si, D2ui, Si2d, Ui2d, S2d, D2s };
1091 static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1092 VcvtVariant Variant, CondARM32::Cond Predicate) {
1093 return new (Func->allocate<InstARM32Vcvt>())
1094 InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1095 }
1096 void emit(const Cfg *Func) const override;
John Portoc31e2ed2015-09-11 05:17:08 -07001097 void dump(const Cfg *Func) const override;
1098 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
1099
1100private:
1101 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1102 CondARM32::Cond Predicate);
1103
1104 const VcvtVariant Variant;
1105};
1106
John Portof977f712015-09-14 16:28:33 -07001107/// Handles (some of) vmov's various formats.
John Portoba6a67c2015-09-25 15:19:45 -07001108class InstARM32Mov final : public InstARM32Pred {
1109 InstARM32Mov() = delete;
1110 InstARM32Mov(const InstARM32Mov &) = delete;
1111 InstARM32Mov &operator=(const InstARM32Mov &) = delete;
John Portof977f712015-09-14 16:28:33 -07001112
1113public:
John Portoba6a67c2015-09-25 15:19:45 -07001114 static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1115 CondARM32::Cond Predicate) {
1116 return new (Func->allocate<InstARM32Mov>())
1117 InstARM32Mov(Func, Dest, Src, Predicate);
John Portof977f712015-09-14 16:28:33 -07001118 }
1119 bool isRedundantAssign() const override {
John Portoba6a67c2015-09-25 15:19:45 -07001120 return !isMultiDest() && !isMultiSource() &&
John Portof977f712015-09-14 16:28:33 -07001121 checkForRedundantAssign(getDest(), getSrc(0));
1122 }
Jim Stichnoth28b71be2015-10-12 15:24:46 -07001123 bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
John Portof977f712015-09-14 16:28:33 -07001124 void emit(const Cfg *Func) const override;
1125 void emitIAS(const Cfg *Func) const override;
1126 void dump(const Cfg *Func) const override;
John Portoba6a67c2015-09-25 15:19:45 -07001127 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
John Portof977f712015-09-14 16:28:33 -07001128
John Portoe0b829f2015-09-28 09:50:48 -07001129 bool isMultiDest() const { return DestHi != nullptr; }
John Portof977f712015-09-14 16:28:33 -07001130
1131 bool isMultiSource() const {
John Portoe0b829f2015-09-28 09:50:48 -07001132 assert(getSrcSize() == 1 || getSrcSize() == 2);
1133 return getSrcSize() == 2;
John Portoba6a67c2015-09-25 15:19:45 -07001134 }
1135
John Portoe0b829f2015-09-28 09:50:48 -07001136 Variable *getDestHi() const { return DestHi; }
1137
John Portoba6a67c2015-09-25 15:19:45 -07001138private:
1139 InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
John Portoe0b829f2015-09-28 09:50:48 -07001140 CondARM32::Cond Predicate);
John Portof977f712015-09-14 16:28:33 -07001141
1142 void emitMultiDestSingleSource(const Cfg *Func) const;
1143 void emitSingleDestMultiSource(const Cfg *Func) const;
1144 void emitSingleDestSingleSource(const Cfg *Func) const;
John Portoe0b829f2015-09-28 09:50:48 -07001145
Karl Schimpf85342a72015-10-13 09:49:31 -07001146 void emitIASSingleDestSingleSource(const Cfg *Func) const;
1147
John Portoe0b829f2015-09-28 09:50:48 -07001148 Variable *DestHi = nullptr;
John Portof977f712015-09-14 16:28:33 -07001149};
1150
John Porto2f5534f2015-09-18 15:59:47 -07001151class InstARM32Vcmp final : public InstARM32Pred {
1152 InstARM32Vcmp() = delete;
1153 InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1154 InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1155
1156public:
1157 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1158 CondARM32::Cond Predicate) {
1159 return new (Func->allocate<InstARM32Vcmp>())
1160 InstARM32Vcmp(Func, Src0, Src1, Predicate);
1161 }
1162 void emit(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001163 void dump(const Cfg *Func) const override;
1164 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); }
1165
1166private:
1167 InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1,
1168 CondARM32::Cond Predicate);
1169};
1170
1171/// Copies the FP Status and Control Register the core flags.
1172class InstARM32Vmrs final : public InstARM32Pred {
1173 InstARM32Vmrs() = delete;
1174 InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1175 InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1176
1177public:
1178 static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1179 return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1180 }
1181 void emit(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001182 void dump(const Cfg *Func) const override;
1183 static bool classof(const Inst *Inst) { return isClassof(Inst, Vmrs); }
1184
1185private:
1186 InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1187};
1188
John Portoba6a67c2015-09-25 15:19:45 -07001189class InstARM32Vabs final : public InstARM32Pred {
1190 InstARM32Vabs() = delete;
1191 InstARM32Vabs(const InstARM32Vabs &) = delete;
1192 InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1193
1194public:
1195 static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1196 CondARM32::Cond Predicate) {
1197 return new (Func->allocate<InstARM32Vabs>())
1198 InstARM32Vabs(Func, Dest, Src, Predicate);
1199 }
1200 void emit(const Cfg *Func) const override;
John Portoba6a67c2015-09-25 15:19:45 -07001201 void dump(const Cfg *Func) const override;
1202 static bool classof(const Inst *Inst) { return isClassof(Inst, Vabs); }
1203
1204private:
1205 InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1206 CondARM32::Cond Predicate);
1207};
John Porto16991842015-10-01 15:11:23 -07001208
1209class InstARM32Dmb final : public InstARM32Pred {
1210 InstARM32Dmb() = delete;
1211 InstARM32Dmb(const InstARM32Dmb &) = delete;
1212 InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1213
1214public:
1215 static InstARM32Dmb *create(Cfg *Func) {
1216 return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1217 }
1218 void emit(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001219 void dump(const Cfg *Func) const override;
1220 static bool classof(const Inst *Inst) { return isClassof(Inst, Dmb); }
1221
1222private:
1223 explicit InstARM32Dmb(Cfg *Func);
1224};
1225
Andrew Scull57e12682015-09-16 11:30:19 -07001226// Declare partial template specializations of emit() methods that already have
1227// default implementations. Without this, there is the possibility of ODR
1228// violations and link errors.
Jan Voungb3401d22015-05-18 09:38:21 -07001229
Jan Voung86ebec12015-08-09 07:58:35 -07001230template <> void InstARM32Ldr::emit(const Cfg *Func) const;
Jan Voungb3401d22015-05-18 09:38:21 -07001231template <> void InstARM32Movw::emit(const Cfg *Func) const;
1232template <> void InstARM32Movt::emit(const Cfg *Func) const;
1233
Jan Voungb36ad9b2015-04-21 17:01:49 -07001234} // end of namespace Ice
1235
1236#endif // SUBZERO_SRC_ICEINSTARM32_H