blob: e31aabc416e88cb59417cb4844c2c905efa6825b [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \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.
Andrew Scull9612d322015-07-06 14:53:25 -070015///
Jan Voungb36ad9b2015-04-21 17:01:49 -070016//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEINSTARM32_H
19#define SUBZERO_SRC_ICEINSTARM32_H
20
Jan Voung3bfd99a2015-05-22 16:35:25 -070021#include "IceConditionCodesARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070022#include "IceDefs.h"
Jan Voungb2d50842015-05-12 09:53:50 -070023#include "IceInst.h"
24#include "IceInstARM32.def"
25#include "IceOperand.h"
Eric Holk658bae22016-02-08 15:22:18 -080026#include "IceRegistersARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070027
28namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080029namespace ARM32 {
Jan Voungb36ad9b2015-04-21 17:01:49 -070030
Karl Schimpfc411dbf2016-01-11 09:59:19 -080031/// 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
Jan Voungb36ad9b2015-04-21 17:01:49 -070037class TargetARM32;
Jan Voungb2d50842015-05-12 09:53:50 -070038
Andrew Scull57e12682015-09-16 11:30:19 -070039/// OperandARM32 extends the Operand hierarchy. Its subclasses are
Andrew Scull9612d322015-07-06 14:53:25 -070040/// OperandARM32Mem and OperandARM32Flex.
Jan Voungb2d50842015-05-12 09:53:50 -070041class OperandARM32 : public Operand {
42 OperandARM32() = delete;
43 OperandARM32(const OperandARM32 &) = delete;
44 OperandARM32 &operator=(const OperandARM32 &) = delete;
45
46public:
Jan Voungb3401d22015-05-18 09:38:21 -070047 enum OperandKindARM32 {
48 k__Start = Operand::kTarget,
49 kMem,
John Porto2758bb02015-11-17 14:31:25 -080050 kShAmtImm,
Jan Voungb3401d22015-05-18 09:38:21 -070051 kFlexStart,
52 kFlexImm = kFlexStart,
John Portoccea7932015-11-17 04:58:36 -080053 kFlexFpImm,
54 kFlexFpZero,
Jan Voungb3401d22015-05-18 09:38:21 -070055 kFlexReg,
56 kFlexEnd = kFlexReg
57 };
Jan Voungb2d50842015-05-12 09:53:50 -070058
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 {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070068 if (BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -070069 Str << "<OperandARM32>";
70 }
71
72protected:
73 OperandARM32(OperandKindARM32 Kind, Type Ty)
74 : Operand(static_cast<OperandKind>(Kind), Ty) {}
Jan Voungb2d50842015-05-12 09:53:50 -070075};
76
Andrew Scull9612d322015-07-06 14:53:25 -070077/// OperandARM32Mem represents a memory operand in any of the various ARM32
78/// addressing modes.
Jan Voungb2d50842015-05-12 09:53:50 -070079class OperandARM32Mem : public OperandARM32 {
80 OperandARM32Mem() = delete;
81 OperandARM32Mem(const OperandARM32Mem &) = delete;
82 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
83
84public:
Andrew Scull9612d322015-07-06 14:53:25 -070085 /// Memory operand addressing mode.
86 /// The enum value also carries the encoding.
Jan Voungb3401d22015-05-18 09:38:21 -070087 // TODO(jvoung): unify with the assembler.
88 enum AddrMode {
Karl Schimpfcdb3ed62015-11-17 14:02:02 -080089 // bit encoding P U 0 W
Jan Voungb3401d22015-05-18 09:38:21 -070090 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
Andrew Scull9612d322015-07-06 14:53:25 -070098 /// 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
Andrew Scull57e12682015-09-16 11:30:19 -0700102 /// 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.
Jan Voungb3401d22015-05-18 09:38:21 -0700105 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
Jan Voungbefd03a2015-06-02 11:03:03 -0700106 ConstantInteger32 *ImmOffset,
Jan Voungb3401d22015-05-18 09:38:21 -0700107 AddrMode Mode = Offset) {
108 return new (Func->allocate<OperandARM32Mem>())
109 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
110 }
Andrew Scull57e12682015-09-16 11:30:19 -0700111 /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
112 /// this mode is disallowed in the NaCl sandbox.
Jan Voungb3401d22015-05-18 09:38:21 -0700113 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; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700128 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 }
Jan Voungb3401d22015-05-18 09:38:21 -0700136
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
Andrew Scull57e12682015-09-16 11:30:19 -0700145 /// 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.
Jan Voungb2d50842015-05-12 09:53:50 -0700149 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
Jan Voungb3401d22015-05-18 09:38:21 -0700150
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);
John Porto1bec8bc2015-06-22 10:51:13 -0700156
Jan Voungb3401d22015-05-18 09:38:21 -0700157 Variable *Base;
158 ConstantInteger32 *ImmOffset;
159 Variable *Index;
160 ShiftKind ShiftOp;
161 uint16_t ShiftAmt;
162 AddrMode Mode;
163};
164
John Porto2758bb02015-11-17 14:31:25 -0800165/// 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
Andrew Scull57e12682015-09-16 11:30:19 -0700195/// 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.
Jan Voungb3401d22015-05-18 09:38:21 -0700198class 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) {}
Jan Voungb3401d22015-05-18 09:38:21 -0700211};
212
Andrew Scull9612d322015-07-06 14:53:25 -0700213/// Rotated immediate variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700214class OperandARM32FlexImm : public OperandARM32Flex {
215 OperandARM32FlexImm() = delete;
216 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
217 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
218
219public:
Andrew Scull9612d322015-07-06 14:53:25 -0700220 /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
Jan Voungb3401d22015-05-18 09:38:21 -0700221 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
Karl Schimpf67574d82015-12-08 15:37:00 -0800222 uint32_t RotateAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700223
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
Andrew Scull57e12682015-09-16 11:30:19 -0700232 /// 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.
Jan Voungb3401d22015-05-18 09:38:21 -0700234 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);
Jan Voungb3401d22015-05-18 09:38:21 -0700242
243 uint32_t Imm;
244 uint32_t RotateAmt;
245};
246
John Portoccea7932015-11-17 04:58:36 -0800247/// 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
John Portodc619252016-02-10 15:57:16 -0800268 static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm);
John Portoccea7932015-11-17 04:58:36 -0800269
Karl Schimpfc64448f2016-01-26 11:12:29 -0800270 uint32_t getModifiedImm() const { return ModifiedImm; }
271
John Portoccea7932015-11-17 04:58:36 -0800272private:
273 OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
274
Karl Schimpfc64448f2016-01-26 11:12:29 -0800275 const uint32_t ModifiedImm;
John Portoccea7932015-11-17 04:58:36 -0800276};
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
Andrew Scull9612d322015-07-06 14:53:25 -0700302/// Shifted register variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700303class OperandARM32FlexReg : public OperandARM32Flex {
304 OperandARM32FlexReg() = delete;
305 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
306 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
307
308public:
Andrew Scull9612d322015-07-06 14:53:25 -0700309 /// Register with immediate/reg shift amount and shift operation.
Jan Voungb3401d22015-05-18 09:38:21 -0700310 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; }
Andrew Scull9612d322015-07-06 14:53:25 -0700326 /// ShiftAmt can represent an immediate or a register.
Jan Voungb3401d22015-05-18 09:38:21 -0700327 Operand *getShiftAmt() const { return ShiftAmt; }
328
329private:
330 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
331 Operand *ShiftAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700332
333 Variable *Reg;
334 ShiftKind ShiftOp;
335 Operand *ShiftAmt;
Jan Voungb2d50842015-05-12 09:53:50 -0700336};
337
Jan Voung28068ad2015-07-31 12:58:46 -0700338/// 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
Andrew Scull57e12682015-09-16 11:30:19 -0700340/// 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.
Jan Voung28068ad2015-07-31 12:58:46 -0700343class 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) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700350 return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index);
Jan Voung28068ad2015-07-31 12:58:46 -0700351 }
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800352 constexpr static auto StackVariableKind =
Jan Voung28068ad2015-07-31 12:58:46 -0700353 static_cast<OperandKind>(kVariable_Target);
354 static bool classof(const Operand *Operand) {
355 return Operand->getKind() == StackVariableKind;
356 }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800357 void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
358 RegNumT getBaseRegNum() const override { return BaseRegNum; }
Jan Voung28068ad2015-07-31 12:58:46 -0700359 // Inherit dump() and emit() from Variable.
360
361private:
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700362 StackVariable(const Cfg *Func, Type Ty, SizeT Index)
363 : Variable(Func, StackVariableKind, Ty, Index) {}
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800364 RegNumT BaseRegNum;
Jan Voung28068ad2015-07-31 12:58:46 -0700365};
366
Andrew Scull9612d322015-07-06 14:53:25 -0700367/// Base class for ARM instructions. While most ARM instructions can be
Andrew Scull57e12682015-09-16 11:30:19 -0700368/// conditionally executed, a few of them are not predicable (halt, memory
369/// barriers, etc.).
Jan Voungb2d50842015-05-12 09:53:50 -0700370class InstARM32 : public InstTarget {
371 InstARM32() = delete;
372 InstARM32(const InstARM32 &) = delete;
373 InstARM32 &operator=(const InstARM32 &) = delete;
374
375public:
Karl Schimpfc411dbf2016-01-11 09:59:19 -0800376 // Defines form that assembly instruction should be synthesized.
377 enum EmitForm { Emit_Text, Emit_Binary };
378
Jan Voungb3401d22015-05-18 09:38:21 -0700379 enum InstKindARM32 {
380 k__Start = Inst::Target,
Jan Voung29719972015-05-19 11:24:51 -0700381 Adc,
382 Add,
383 And,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700384 Asr,
Jan Voung55500db2015-05-26 14:25:40 -0700385 Bic,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700386 Br,
387 Call,
Karl Schimpf19567882015-12-02 10:24:15 -0800388 Clz,
John Portoccea7932015-11-17 04:58:36 -0800389 Cmn,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700390 Cmp,
John Porto16991842015-10-01 15:11:23 -0700391 Dmb,
Jan Voung29719972015-05-19 11:24:51 -0700392 Eor,
Eric Holk658bae22016-02-08 15:22:18 -0800393 Extract,
394 Insert,
Jan Voung6ec369e2015-06-30 11:03:15 -0700395 Label,
Jan Voung29719972015-05-19 11:24:51 -0700396 Ldr,
John Porto16991842015-10-01 15:11:23 -0700397 Ldrex,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700398 Lsl,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700399 Lsr,
Karl Schimpff084a572016-02-09 13:09:23 -0800400 Nop,
Jan Voung29719972015-05-19 11:24:51 -0700401 Mla,
Jan Voung6ec369e2015-06-30 11:03:15 -0700402 Mls,
Jan Voungb3401d22015-05-18 09:38:21 -0700403 Mov,
404 Movt,
405 Movw,
Jan Voung29719972015-05-19 11:24:51 -0700406 Mul,
Jan Voungb3401d22015-05-18 09:38:21 -0700407 Mvn,
Jan Voung29719972015-05-19 11:24:51 -0700408 Orr,
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700409 Pop,
410 Push,
Jan Voungf645d852015-07-09 10:35:09 -0700411 Rbit,
Jan Voungb3401d22015-05-18 09:38:21 -0700412 Ret,
Jan Voungf645d852015-07-09 10:35:09 -0700413 Rev,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700414 Rsb,
John Portoccea7932015-11-17 04:58:36 -0800415 Rsc,
Jan Voung29719972015-05-19 11:24:51 -0700416 Sbc,
Jan Voung6ec369e2015-06-30 11:03:15 -0700417 Sdiv,
Jan Voungbefd03a2015-06-02 11:03:03 -0700418 Str,
John Porto16991842015-10-01 15:11:23 -0700419 Strex,
Jan Voung29719972015-05-19 11:24:51 -0700420 Sub,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700421 Sxt,
Jan Voung6ec369e2015-06-30 11:03:15 -0700422 Trap,
423 Tst,
424 Udiv,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700425 Umull,
Jan Voung86ebec12015-08-09 07:58:35 -0700426 Uxt,
John Portoba6a67c2015-09-25 15:19:45 -0700427 Vabs,
Jan Voung86ebec12015-08-09 07:58:35 -0700428 Vadd,
Eric Holkb58170c2016-01-27 11:18:29 -0800429 Vand,
John Porto397f6022016-04-15 06:26:58 -0700430 Vbsl,
John Portoa4d100a2016-04-18 15:32:27 -0700431 Vceq,
432 Vcge,
433 Vcgt,
John Porto2f5534f2015-09-18 15:59:47 -0700434 Vcmp,
John Portoc31e2ed2015-09-11 05:17:08 -0700435 Vcvt,
Jan Voung86ebec12015-08-09 07:58:35 -0700436 Vdiv,
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400437 Vdup,
John Portoccea7932015-11-17 04:58:36 -0800438 Veor,
Nicolas Capens675e15b2017-09-27 15:06:35 -0400439 Vldr1d,
440 Vldr1q,
John Portoeb13acc2015-12-09 05:10:58 -0800441 Vmla,
Nicolas Capens675e15b2017-09-27 15:06:35 -0400442 Vmlap,
John Portoeb13acc2015-12-09 05:10:58 -0800443 Vmls,
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400444 Vmovl,
445 Vmovh,
446 Vmovhl,
447 Vmovlh,
John Porto2f5534f2015-09-18 15:59:47 -0700448 Vmrs,
Jan Voung86ebec12015-08-09 07:58:35 -0700449 Vmul,
Nicolas Capens675e15b2017-09-27 15:06:35 -0400450 Vmulh,
John Portoa4d100a2016-04-18 15:32:27 -0700451 Vmvn,
John Porto15e77d42016-04-13 12:57:14 -0700452 Vneg,
Eric Holkcad0b752016-01-27 14:56:22 -0800453 Vorr,
Casey Dahlinb40560b2017-06-28 13:58:58 -0700454 Vqadd,
Nicolas Capens675e15b2017-09-27 15:06:35 -0400455 Vqmovn2,
Casey Dahlinb40560b2017-06-28 13:58:58 -0700456 Vqsub,
John Porto15e77d42016-04-13 12:57:14 -0700457 Vshl,
John Portoe88c7de2016-04-14 11:51:38 -0700458 Vshr,
Jan Voung86ebec12015-08-09 07:58:35 -0700459 Vsqrt,
Nicolas Capens675e15b2017-09-27 15:06:35 -0400460 Vstr1,
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400461 Vsub,
462 Vzip
Jan Voungb3401d22015-05-18 09:38:21 -0700463 };
Jan Voungb2d50842015-05-12 09:53:50 -0700464
Karl Schimpf856734c2015-11-05 08:18:26 -0800465 static constexpr size_t InstSize = sizeof(uint32_t);
466
Jan Voung3bfd99a2015-05-22 16:35:25 -0700467 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
Jan Voungb2d50842015-05-12 09:53:50 -0700468
Karl Schimpf856734c2015-11-05 08:18:26 -0800469 /// 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
John Porto15e77d42016-04-13 12:57:14 -0700475 /// 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 };
Jan Voung86ebec12015-08-09 07:58:35 -0700482 /// Shared emit routines for common forms of instructions.
John Porto15e77d42016-04-13 12:57:14 -0700483 /// @{
484 static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
John Portoa4d100a2016-04-18 15:32:27 -0700485 const InstARM32 *Instr, const Cfg *Func,
486 Type OpType);
John Porto15e77d42016-04-13 12:57:14 -0700487 static void emitFourAddrFP(const char *Opcode, FPSign Sign,
488 const InstARM32 *Instr, const Cfg *Func);
489 /// @}
Jan Voung86ebec12015-08-09 07:58:35 -0700490
Jan Voungb2d50842015-05-12 09:53:50 -0700491 void dump(const Cfg *Func) const override;
492
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700493 void emitIAS(const Cfg *Func) const override;
494
Jan Voungb2d50842015-05-12 09:53:50 -0700495protected:
496 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
497 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700498
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800499 static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
500 return Instr->getKind() == static_cast<InstKind>(MyKind);
Jan Voungb2d50842015-05-12 09:53:50 -0700501 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700502
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;
Jan Voungb2d50842015-05-12 09:53:50 -0700506};
507
Andrew Scull9612d322015-07-06 14:53:25 -0700508/// A predicable ARM instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700509class InstARM32Pred : public InstARM32 {
510 InstARM32Pred() = delete;
511 InstARM32Pred(const InstARM32Pred &) = delete;
512 InstARM32Pred &operator=(const InstARM32Pred &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700513
Jan Voung3bfd99a2015-05-22 16:35:25 -0700514public:
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
Andrew Scull9612d322015-07-06 14:53:25 -0700525 /// Shared emit routines for common forms of instructions.
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800526 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
Jan Voungf645d852015-07-09 10:35:09 -0700527 const Cfg *Func, bool NeedsWidthSuffix);
John Porto15e77d42016-04-13 12:57:14 -0700528 static void emitUnaryopFP(const char *Opcode, FPSign Sign,
529 const InstARM32Pred *Instr, const Cfg *Func);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800530 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700531 const Cfg *Func);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800532 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700533 const Cfg *Func, bool SetFlags);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800534 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
Jan Voung6ec369e2015-06-30 11:03:15 -0700535 const Cfg *Func);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800536 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
Jan Voung6ec369e2015-06-30 11:03:15 -0700537 const Cfg *Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700538
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}
Jan Voungb3401d22015-05-18 09:38:21 -0700548
Andrew Scull9612d322015-07-06 14:53:25 -0700549/// Instructions of the form x := op(y).
Jan Voungf645d852015-07-09 10:35:09 -0700550template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700551class InstARM32UnaryopGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700552 InstARM32UnaryopGPR() = delete;
553 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
554 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
555
556public:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700557 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
558 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700559 return new (Func->allocate<InstARM32UnaryopGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700560 InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700561 }
562 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700563 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700564 return;
Jan Voungf645d852015-07-09 10:35:09 -0700565 emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
Jan Voungb3401d22015-05-18 09:38:21 -0700566 }
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700567 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700568 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700569 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700570 return;
571 Ostream &Str = Func->getContext()->getStrDump();
572 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700573 Str << " = ";
574 dumpOpcodePred(Str, Opcode, getDest()->getType());
575 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700576 dumpSources(Func);
577 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800578 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voungb3401d22015-05-18 09:38:21 -0700579
580private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700581 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
582 CondARM32::Cond Predicate)
583 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700584 addSource(Src);
585 }
John Porto1bec8bc2015-06-22 10:51:13 -0700586
Jan Voungb3401d22015-05-18 09:38:21 -0700587 static const char *Opcode;
588};
589
Jan Voung86ebec12015-08-09 07:58:35 -0700590/// 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;
John Porto15e77d42016-04-13 12:57:14 -0700606 emitUnaryopFP(Opcode, Sign, this, Func);
Jan Voung86ebec12015-08-09 07:58:35 -0700607 }
Karl Schimpf266c5a22016-01-29 09:54:58 -0800608 void emitIAS(const Cfg *Func) const override;
Jan Voung86ebec12015-08-09 07:58:35 -0700609 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800619 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voung86ebec12015-08-09 07:58:35 -0700620
John Porto15e77d42016-04-13 12:57:14 -0700621protected:
Jan Voung86ebec12015-08-09 07:58:35 -0700622 InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
623 CondARM32::Cond Predicate)
624 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
625 addSource(Src);
626 }
627
John Porto15e77d42016-04-13 12:57:14 -0700628 FPSign Sign = FS_None;
Jan Voung86ebec12015-08-09 07:58:35 -0700629 static const char *Opcode;
630};
631
John Porto15e77d42016-04-13 12:57:14 -0700632template <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
Andrew Scull9612d322015-07-06 14:53:25 -0700654/// Instructions of the form x := x op y.
Jan Voungb3401d22015-05-18 09:38:21 -0700655template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700656class InstARM32TwoAddrGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700657 InstARM32TwoAddrGPR() = delete;
658 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
659 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
660
661public:
Andrew Scull9612d322015-07-06 14:53:25 -0700662 /// Dest must be a register.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700663 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
664 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700665 return new (Func->allocate<InstARM32TwoAddrGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700666 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700667 }
668 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700669 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700670 return;
671 emitTwoAddr(Opcode, this, Func);
672 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700673 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700674 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700675 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700676 return;
677 Ostream &Str = Func->getContext()->getStrDump();
678 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700679 Str << " = ";
680 dumpOpcodePred(Str, Opcode, getDest()->getType());
681 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700682 dumpSources(Func);
683 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800684 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voungb3401d22015-05-18 09:38:21 -0700685
686private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700687 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
688 CondARM32::Cond Predicate)
689 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700690 addSource(Dest);
691 addSource(Src);
692 }
John Porto1bec8bc2015-06-22 10:51:13 -0700693
Jan Voungb3401d22015-05-18 09:38:21 -0700694 static const char *Opcode;
695};
696
John Porto16991842015-10-01 15:11:23 -0700697/// Base class for load instructions.
Jan Voungb3401d22015-05-18 09:38:21 -0700698template <InstARM32::InstKindARM32 K>
John Porto16991842015-10-01 15:11:23 -0700699class InstARM32LoadBase : public InstARM32Pred {
700 InstARM32LoadBase() = delete;
701 InstARM32LoadBase(const InstARM32LoadBase &) = delete;
702 InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700703
704public:
John Porto16991842015-10-01 15:11:23 -0700705 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);
Jan Voungb3401d22015-05-18 09:38:21 -0700709 }
Jan Voungb3401d22015-05-18 09:38:21 -0700710 void emit(const Cfg *Func) const override;
Karl Schimpff0655b62015-10-30 07:30:14 -0700711 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700712 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700713 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700714 return;
715 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung3bfd99a2015-05-22 16:35:25 -0700716 dumpOpcodePred(Str, Opcode, getDest()->getType());
717 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700718 dumpDest(Func);
719 Str << ", ";
720 dumpSources(Func);
721 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800722 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voungb3401d22015-05-18 09:38:21 -0700723
724private:
John Porto16991842015-10-01 15:11:23 -0700725 InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
726 CondARM32::Cond Predicate)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700727 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700728 addSource(Source);
729 }
Jan Voungb3401d22015-05-18 09:38:21 -0700730
731 static const char *Opcode;
732};
733
Andrew Scull9612d322015-07-06 14:53:25 -0700734/// Instructions of the form x := y op z. May have the side-effect of setting
735/// status flags.
Jan Voung29719972015-05-19 11:24:51 -0700736template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700737class InstARM32ThreeAddrGPR : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -0700738 InstARM32ThreeAddrGPR() = delete;
739 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
740 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
741
742public:
Andrew Scull57e12682015-09-16 11:30:19 -0700743 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
744 /// must be registers.
Jan Voung29719972015-05-19 11:24:51 -0700745 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
Jan Voung6ec369e2015-06-30 11:03:15 -0700746 Variable *Src0, Operand *Src1,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700747 CondARM32::Cond Predicate,
Jan Voung29719972015-05-19 11:24:51 -0700748 bool SetFlags = false) {
749 return new (Func->allocate<InstARM32ThreeAddrGPR>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700750 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
Jan Voung29719972015-05-19 11:24:51 -0700751 }
752 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700753 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700754 return;
755 emitThreeAddr(Opcode, this, Func, SetFlags);
756 }
Karl Schimpf372bdd62015-10-13 14:39:14 -0700757 void emitIAS(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -0700758 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700759 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700760 return;
761 Ostream &Str = Func->getContext()->getStrDump();
762 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700763 Str << " = ";
764 dumpOpcodePred(Str, Opcode, getDest()->getType());
765 Str << (SetFlags ? ".s " : " ");
Jan Voung29719972015-05-19 11:24:51 -0700766 dumpSources(Func);
767 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800768 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voung29719972015-05-19 11:24:51 -0700769
770private:
Jan Voung6ec369e2015-06-30 11:03:15 -0700771 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
772 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700773 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
John Portoccea7932015-11-17 04:58:36 -0800774 HasSideEffects = SetFlags;
Jan Voung6ec369e2015-06-30 11:03:15 -0700775 addSource(Src0);
776 addSource(Src1);
777 }
778
779 static const char *Opcode;
780 bool SetFlags;
781};
782
Andrew Scull57e12682015-09-16 11:30:19 -0700783/// Instructions of the form x := y op z, for vector/FP. We leave these as
Jan Voung86ebec12015-08-09 07:58:35 -0700784/// unconditional: "ARM deprecates the conditional execution of any instruction
785/// encoding provided by the Advanced SIMD Extension that is not also provided
John Portoeb13acc2015-12-09 05:10:58 -0800786/// by the floating-point (VFP) extension". They do not set flags.
Jan Voung86ebec12015-08-09 07:58:35 -0700787template <InstARM32::InstKindARM32 K>
788class InstARM32ThreeAddrFP : public InstARM32 {
789 InstARM32ThreeAddrFP() = delete;
790 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
791 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
792
793public:
Andrew Scull57e12682015-09-16 11:30:19 -0700794 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
795 /// must be a register.
Jan Voung86ebec12015-08-09 07:58:35 -0700796 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;
John Portoa4d100a2016-04-18 15:32:27 -0700804 const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
805 emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
Jan Voung86ebec12015-08-09 07:58:35 -0700806 }
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800807 void emitIAS(const Cfg *Func) const override;
Jan Voung86ebec12015-08-09 07:58:35 -0700808 void dump(const Cfg *Func) const override {
809 if (!BuildDefs::dump())
810 return;
811 Ostream &Str = Func->getContext()->getStrDump();
812 dumpDest(Func);
John Portoa4d100a2016-04-18 15:32:27 -0700813 const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
814 Str << " = " << Opcode << "." << OpType << " ";
Jan Voung86ebec12015-08-09 07:58:35 -0700815 dumpSources(Func);
816 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800817 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voung86ebec12015-08-09 07:58:35 -0700818
John Porto15e77d42016-04-13 12:57:14 -0700819protected:
820 FPSign Sign = FS_None;
821
822 InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
Jan Voung86ebec12015-08-09 07:58:35 -0700823 : InstARM32(Func, K, 2, Dest) {
824 addSource(Src0);
825 addSource(Src1);
826 }
827
828 static const char *Opcode;
John Portoa4d100a2016-04-18 15:32:27 -0700829
830private:
831 static constexpr bool isVectorCompare() {
832 return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
833 }
Jan Voung86ebec12015-08-09 07:58:35 -0700834};
835
John Porto15e77d42016-04-13 12:57:14 -0700836template <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
John Portoe88c7de2016-04-14 11:51:38 -0700852 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
John Porto15e77d42016-04-13 12:57:14 -0700858 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,
John Portoe88c7de2016-04-14 11:51:38 -0700863 Operand *Src1)
John Porto15e77d42016-04-13 12:57:14 -0700864 : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
865};
866
Jan Voung86ebec12015-08-09 07:58:35 -0700867/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
Jan Voung6ec369e2015-06-30 11:03:15 -0700868template <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 }
Karl Schimpf080b65b2015-11-05 08:27:51 -0800887 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700888 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800898 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voung6ec369e2015-06-30 11:03:15 -0700899
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);
Jan Voung29719972015-05-19 11:24:51 -0700906 addSource(Src1);
907 addSource(Src2);
908 }
John Porto1bec8bc2015-06-22 10:51:13 -0700909
Jan Voung29719972015-05-19 11:24:51 -0700910 static const char *Opcode;
Jan Voung6ec369e2015-06-30 11:03:15 -0700911};
912
John Portoeb13acc2015-12-09 05:10:58 -0800913/// 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;
John Porto15e77d42016-04-13 12:57:14 -0700934 emitFourAddrFP(Opcode, Sign, this, Func);
John Portoeb13acc2015-12-09 05:10:58 -0800935 }
Karl Schimpf8c5544b2016-01-26 15:29:22 -0800936 void emitIAS(const Cfg *Func) const override;
John Portoeb13acc2015-12-09 05:10:58 -0800937 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800948 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
John Portoeb13acc2015-12-09 05:10:58 -0800949
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
John Porto15e77d42016-04-13 12:57:14 -0700958 FPSign Sign = FS_None;
John Portoeb13acc2015-12-09 05:10:58 -0800959 static const char *Opcode;
960};
961
Jan Voung86ebec12015-08-09 07:58:35 -0700962/// Instructions of the form x cmpop y (setting flags).
Jan Voung6ec369e2015-06-30 11:03:15 -0700963template <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 }
Karl Schimpff8fc12f2015-10-30 15:06:35 -0700980 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700981 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800989 static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
Jan Voung6ec369e2015-06-30 11:03:15 -0700990
991private:
992 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
993 CondARM32::Cond Predicate)
994 : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
John Portoccea7932015-11-17 04:58:36 -0800995 HasSideEffects = true;
Jan Voung6ec369e2015-06-30 11:03:15 -0700996 addSource(Src0);
997 addSource(Src1);
998 }
999
1000 static const char *Opcode;
Jan Voung29719972015-05-19 11:24:51 -07001001};
1002
Andrew Scull8072bae2015-09-14 16:01:26 -07001003using 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>;
John Portoccea7932015-11-17 04:58:36 -08001014using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
Andrew Scull8072bae2015-09-14 16:01:26 -07001015using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
1016using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
1017using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
1018using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
1019using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
Eric Holkb58170c2016-01-27 11:18:29 -08001020using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
John Porto397f6022016-04-15 06:26:58 -07001021using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
John Portoa4d100a2016-04-18 15:32:27 -07001022using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
1023using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
1024using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
Andrew Scull8072bae2015-09-14 16:01:26 -07001025using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
John Portoccea7932015-11-17 04:58:36 -08001026using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
John Portoeb13acc2015-12-09 05:10:58 -08001027using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
1028using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001029using InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>;
1030using InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>;
1031using InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>;
1032using InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>;
John Portoeb13acc2015-12-09 05:10:58 -08001033using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
John Portoa4d100a2016-04-18 15:32:27 -07001034using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
John Porto15e77d42016-04-13 12:57:14 -07001035using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
Eric Holkcad0b752016-01-27 14:56:22 -08001036using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
Casey Dahlinb40560b2017-06-28 13:58:58 -07001037using InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
1038using InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
Nicolas Capens675e15b2017-09-27 15:06:35 -04001039using InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
1040using InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
1041using InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>;
John Porto15e77d42016-04-13 12:57:14 -07001042using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
John Portoe88c7de2016-04-14 11:51:38 -07001043using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
Andrew Scull8072bae2015-09-14 16:01:26 -07001044using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
John Porto16991842015-10-01 15:11:23 -07001045using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
1046using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
Nicolas Capens675e15b2017-09-27 15:06:35 -04001047using InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>;
1048using InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>;
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001049using InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>;
Andrew Scull57e12682015-09-16 11:30:19 -07001050/// 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.
Andrew Scull8072bae2015-09-14 16:01:26 -07001052using 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>;
Andrew Scull57e12682015-09-16 11:30:19 -07001058// 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.
Andrew Scull8072bae2015-09-14 16:01:26 -07001061using 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>;
John Portoccea7932015-11-17 04:58:36 -08001066using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
Andrew Scull8072bae2015-09-14 16:01:26 -07001067using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
1068using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
Jan Voung6ec369e2015-06-30 11:03:15 -07001069
Andrew Scull57e12682015-09-16 11:30:19 -07001070// 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").
Jan Voung6ec369e2015-06-30 11:03:15 -07001073class 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; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001083 GlobalString getLabelName() const { return Name; }
Jan Voung6ec369e2015-06-30 11:03:15 -07001084 SizeT getNumber() const { return Number; }
1085 void emit(const Cfg *Func) const override;
Karl Schimpf50a33312015-10-23 09:19:48 -07001086 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -07001087 void dump(const Cfg *Func) const override;
John Portodc619252016-02-10 15:57:16 -08001088 void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }
Jan Voung6ec369e2015-06-30 11:03:15 -07001089
1090private:
1091 InstARM32Label(Cfg *Func, TargetARM32 *Target);
1092
John Portodc619252016-02-10 15:57:16 -08001093 RelocOffset *OffsetReloc = nullptr;
Jan Voung6ec369e2015-06-30 11:03:15 -07001094 SizeT Number; // used for unique label generation.
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001095 GlobalString Name;
Jan Voung6ec369e2015-06-30 11:03:15 -07001096};
Jan Voungb3401d22015-05-18 09:38:21 -07001097
Andrew Scull9612d322015-07-06 14:53:25 -07001098/// Direct branch instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001099class InstARM32Br : public InstARM32Pred {
1100 InstARM32Br() = delete;
1101 InstARM32Br(const InstARM32Br &) = delete;
1102 InstARM32Br &operator=(const InstARM32Br &) = delete;
1103
1104public:
Andrew Scull9612d322015-07-06 14:53:25 -07001105 /// Create a conditional branch to one of two nodes.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001106 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
1107 CfgNode *TargetFalse, CondARM32::Cond Predicate) {
1108 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -07001109 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001110 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -07001111 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001112 }
Andrew Scull9612d322015-07-06 14:53:25 -07001113 /// Create an unconditional branch to a node.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001114 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
Jan Voung6ec369e2015-06-30 11:03:15 -07001115 constexpr CfgNode *NoCondTarget = nullptr;
1116 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001117 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -07001118 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001119 }
Andrew Scull57e12682015-09-16 11:30:19 -07001120 /// 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.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001123 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1124 CondARM32::Cond Predicate) {
1125 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -07001126 constexpr CfgNode *NoUncondTarget = nullptr;
1127 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001128 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -07001129 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);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001139 }
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;
Jan Voung6ec369e2015-06-30 11:03:15 -07001145 if (Label)
1146 ++Sum;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001147 if (getTargetTrue())
1148 ++Sum;
1149 if (getTargetFalse())
1150 ++Sum;
1151 return Sum;
1152 }
1153 bool isUnconditionalBranch() const override {
1154 return getPredicate() == CondARM32::AL;
1155 }
Andrew Scull87f80c12015-07-20 10:19:16 -07001156 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001157 void emit(const Cfg *Func) const override;
Karl Schimpf137e62b2015-10-27 07:28:09 -07001158 void emitIAS(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001159 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001160 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
Jan Voung3bfd99a2015-05-22 16:35:25 -07001161
1162private:
1163 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Jan Voung6ec369e2015-06-30 11:03:15 -07001164 const InstARM32Label *Label, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -07001165
Jan Voung3bfd99a2015-05-22 16:35:25 -07001166 const CfgNode *TargetTrue;
1167 const CfgNode *TargetFalse;
Jan Voung6ec369e2015-06-30 11:03:15 -07001168 const InstARM32Label *Label; // Intra-block branch target
Jan Voung3bfd99a2015-05-22 16:35:25 -07001169};
1170
Andrew Scull57e12682015-09-16 11:30:19 -07001171/// Call instruction (bl/blx). Arguments should have already been pushed.
Andrew Scull9612d322015-07-06 14:53:25 -07001172/// Technically bl and the register form of blx can be predicated, but we'll
1173/// leave that out until needed.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001174class 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;
Karl Schimpf174531e2015-11-18 08:19:26 -08001186 void emitIAS(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001187 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001188 static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
Jan Voung3bfd99a2015-05-22 16:35:25 -07001189
1190private:
1191 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001192};
1193
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001194class 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;
Karl Schimpf00c30382016-02-09 12:23:55 -08001213 void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
1214 SizeT RegCount, SizeT InstIndex) const;
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001215 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
John Portoeb13acc2015-12-09 05:10:58 -08001228/// 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.
Karl Schimpf00c30382016-02-09 12:23:55 -08001230class InstARM32Pop final : public InstARM32RegisterStackOp {
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001231 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001239 static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001240
1241private:
1242 InstARM32Pop(Cfg *Func, const VarList &Dests);
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001243 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;
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001253 VarList Dests;
1254};
1255
John Portoeb13acc2015-12-09 05:10:58 -08001256/// Pushes a list of registers. Just like Pop (see above), the list may be of
1257/// GPRs, or VFP "s" registers, but not both.
Karl Schimpf00c30382016-02-09 12:23:55 -08001258class InstARM32Push final : public InstARM32RegisterStackOp {
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001259 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 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001267 static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001268
1269private:
1270 InstARM32Push(Cfg *Func, const VarList &Srcs);
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001271 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;
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001281};
1282
Andrew Scull57e12682015-09-16 11:30:19 -07001283/// 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.
Andrew Scull9612d322015-07-06 14:53:25 -07001288///
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.
Jan Voungb2d50842015-05-12 09:53:50 -07001292class 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;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001305 static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
Jan Voungb2d50842015-05-12 09:53:50 -07001306
1307private:
1308 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
Jan Voungb2d50842015-05-12 09:53:50 -07001309};
Jan Voungb36ad9b2015-04-21 17:01:49 -07001310
Andrew Scull57e12682015-09-16 11:30:19 -07001311/// Store instruction. It's important for liveness that there is no Dest operand
1312/// (OperandARM32Mem instead of Dest Variable).
John Porto16991842015-10-01 15:11:23 -07001313class InstARM32Str final : public InstARM32Pred {
Jan Voungbefd03a2015-06-02 11:03:03 -07001314 InstARM32Str() = delete;
1315 InstARM32Str(const InstARM32Str &) = delete;
1316 InstARM32Str &operator=(const InstARM32Str &) = delete;
1317
1318public:
Andrew Scull9612d322015-07-06 14:53:25 -07001319 /// Value must be a register.
Jan Voungbefd03a2015-06-02 11:03:03 -07001320 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;
Karl Schimpff0655b62015-10-30 07:30:14 -07001326 void emitIAS(const Cfg *Func) const override;
Jan Voungbefd03a2015-06-02 11:03:03 -07001327 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001328 static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }
Jan Voungbefd03a2015-06-02 11:03:03 -07001329
1330private:
1331 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1332 CondARM32::Cond Predicate);
Jan Voungbefd03a2015-06-02 11:03:03 -07001333};
1334
John Porto16991842015-10-01 15:11:23 -07001335/// 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;
Karl Schimpf4175d452015-12-17 08:06:01 -08001352 void emitIAS(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001353 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001354 static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
John Porto16991842015-10-01 15:11:23 -07001355
1356private:
1357 InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1358 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1359};
1360
Nicolas Capens675e15b2017-09-27 15:06:35 -04001361/// 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
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001388/// 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
Jan Voung6ec369e2015-06-30 11:03:15 -07001412class 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;
Karl Schimpf6ddabc12016-01-29 12:24:01 -08001422 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -07001423 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001424 static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
Jan Voung6ec369e2015-06-30 11:03:15 -07001425
1426private:
1427 explicit InstARM32Trap(Cfg *Func);
1428};
1429
Andrew Scull9612d322015-07-06 14:53:25 -07001430/// Unsigned Multiply Long: d.lo, d.hi := x * y
Jan Voung3bfd99a2015-05-22 16:35:25 -07001431class InstARM32Umull : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -07001432 InstARM32Umull() = delete;
1433 InstARM32Umull(const InstARM32Umull &) = delete;
1434 InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1435
1436public:
Andrew Scull9612d322015-07-06 14:53:25 -07001437 /// Everything must be a register.
Jan Voung29719972015-05-19 11:24:51 -07001438 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001439 Variable *Src0, Variable *Src1,
1440 CondARM32::Cond Predicate) {
Jan Voung29719972015-05-19 11:24:51 -07001441 return new (Func->allocate<InstARM32Umull>())
Jan Voung3bfd99a2015-05-22 16:35:25 -07001442 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
Jan Voung29719972015-05-19 11:24:51 -07001443 }
1444 void emit(const Cfg *Func) const override;
Karl Schimpf430e8442015-11-09 12:16:20 -08001445 void emitIAS(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -07001446 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001447 static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
Jan Voung29719972015-05-19 11:24:51 -07001448
1449private:
1450 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001451 Variable *Src1, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -07001452
Jan Voung29719972015-05-19 11:24:51 -07001453 Variable *DestHi;
1454};
1455
John Portoc31e2ed2015-09-11 05:17:08 -07001456/// 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:
John Portoe88c7de2016-04-14 11:51:38 -07001463 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 };
John Portoc31e2ed2015-09-11 05:17:08 -07001479 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;
Karl Schimpf6c7181c2016-01-08 07:31:08 -08001485 void emitIAS(const Cfg *Func) const override;
John Portoc31e2ed2015-09-11 05:17:08 -07001486 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001487 static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
John Portoc31e2ed2015-09-11 05:17:08 -07001488
1489private:
1490 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1491 CondARM32::Cond Predicate);
1492
1493 const VcvtVariant Variant;
1494};
1495
John Portof977f712015-09-14 16:28:33 -07001496/// Handles (some of) vmov's various formats.
John Portoba6a67c2015-09-25 15:19:45 -07001497class InstARM32Mov final : public InstARM32Pred {
1498 InstARM32Mov() = delete;
1499 InstARM32Mov(const InstARM32Mov &) = delete;
1500 InstARM32Mov &operator=(const InstARM32Mov &) = delete;
John Portof977f712015-09-14 16:28:33 -07001501
1502public:
John Portoba6a67c2015-09-25 15:19:45 -07001503 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);
John Portof977f712015-09-14 16:28:33 -07001507 }
1508 bool isRedundantAssign() const override {
John Portoba6a67c2015-09-25 15:19:45 -07001509 return !isMultiDest() && !isMultiSource() &&
John Porto7b3d9cb2015-11-11 14:26:57 -08001510 getPredicate() == CondARM32::AL &&
John Portof977f712015-09-14 16:28:33 -07001511 checkForRedundantAssign(getDest(), getSrc(0));
1512 }
Jim Stichnoth28b71be2015-10-12 15:24:46 -07001513 bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
John Portof977f712015-09-14 16:28:33 -07001514 void emit(const Cfg *Func) const override;
1515 void emitIAS(const Cfg *Func) const override;
1516 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001517 static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
John Portof977f712015-09-14 16:28:33 -07001518
John Portoe0b829f2015-09-28 09:50:48 -07001519 bool isMultiDest() const { return DestHi != nullptr; }
John Portof977f712015-09-14 16:28:33 -07001520
1521 bool isMultiSource() const {
John Portoe0b829f2015-09-28 09:50:48 -07001522 assert(getSrcSize() == 1 || getSrcSize() == 2);
1523 return getSrcSize() == 2;
John Portoba6a67c2015-09-25 15:19:45 -07001524 }
1525
John Portoe0b829f2015-09-28 09:50:48 -07001526 Variable *getDestHi() const { return DestHi; }
1527
John Portoba6a67c2015-09-25 15:19:45 -07001528private:
1529 InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
John Portoe0b829f2015-09-28 09:50:48 -07001530 CondARM32::Cond Predicate);
John Portof977f712015-09-14 16:28:33 -07001531 void emitMultiDestSingleSource(const Cfg *Func) const;
1532 void emitSingleDestMultiSource(const Cfg *Func) const;
1533 void emitSingleDestSingleSource(const Cfg *Func) const;
John Portoe0b829f2015-09-28 09:50:48 -07001534
1535 Variable *DestHi = nullptr;
John Portof977f712015-09-14 16:28:33 -07001536};
1537
Eric Holk658bae22016-02-08 15:22:18 -08001538/// 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;
Karl Schimpf6de32b22016-02-10 13:30:48 -08001552 void emitIAS(const Cfg *Func) const override;
Eric Holk658bae22016-02-08 15:22:18 -08001553 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;
Karl Schimpf6de32b22016-02-10 13:30:48 -08001581 void emitIAS(const Cfg *Func) const override;
Eric Holk658bae22016-02-08 15:22:18 -08001582 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
John Porto2f5534f2015-09-18 15:59:47 -07001596class 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 }
John Portoccea7932015-11-17 04:58:36 -08001607 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 }
John Porto2f5534f2015-09-18 15:59:47 -07001613 void emit(const Cfg *Func) const override;
Karl Schimpfcd5e07e2016-01-11 10:12:20 -08001614 void emitIAS(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001615 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001616 static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }
John Porto2f5534f2015-09-18 15:59:47 -07001617
1618private:
John Portoccea7932015-11-17 04:58:36 -08001619 InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
John Porto2f5534f2015-09-18 15:59:47 -07001620 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;
Karl Schimpfee718272016-01-25 09:17:26 -08001634 void emitIAS(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001635 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001636 static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
John Porto2f5534f2015-09-18 15:59:47 -07001637
1638private:
1639 InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1640};
1641
John Portoba6a67c2015-09-25 15:19:45 -07001642class 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;
Karl Schimpfbd4356d2016-02-02 13:35:45 -08001654 void emitIAS(const Cfg *Func) const override;
John Portoba6a67c2015-09-25 15:19:45 -07001655 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001656 static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
John Portoba6a67c2015-09-25 15:19:45 -07001657
1658private:
1659 InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1660 CondARM32::Cond Predicate);
1661};
John Porto16991842015-10-01 15:11:23 -07001662
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;
Karl Schimpfd3f94f72015-12-09 07:35:00 -08001673 void emitIAS(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001674 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001675 static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
John Porto16991842015-10-01 15:11:23 -07001676
1677private:
1678 explicit InstARM32Dmb(Cfg *Func);
1679};
1680
Karl Schimpff084a572016-02-09 13:09:23 -08001681class 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
Andrew Scull57e12682015-09-16 11:30:19 -07001699// 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.
Jan Voungb3401d22015-05-18 09:38:21 -07001702
Jan Voung86ebec12015-08-09 07:58:35 -07001703template <> void InstARM32Ldr::emit(const Cfg *Func) const;
Jan Voungb3401d22015-05-18 09:38:21 -07001704template <> void InstARM32Movw::emit(const Cfg *Func) const;
1705template <> void InstARM32Movt::emit(const Cfg *Func) const;
Nicolas Capens675e15b2017-09-27 15:06:35 -04001706template <> void InstARM32Vldr1d::emit(const Cfg *Func) const;
1707template <> void InstARM32Vldr1q::emit(const Cfg *Func) const;
Jan Voungb3401d22015-05-18 09:38:21 -07001708
John Porto4a566862016-01-04 09:33:41 -08001709} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -07001710} // end of namespace Ice
1711
1712#endif // SUBZERO_SRC_ICEINSTARM32_H