blob: 21505a185045fd2267d2d80ddf293bb971cbf65a [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"
Jan Voungb36ad9b2015-04-21 17:01:49 -070026
27namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080028namespace ARM32 {
Jan Voungb36ad9b2015-04-21 17:01:49 -070029
Karl Schimpfc411dbf2016-01-11 09:59:19 -080030/// Encoding of an ARM 32-bit instruction.
31using IValueT = uint32_t;
32
33/// An Offset value (+/-) used in an ARM 32-bit instruction.
34using IOffsetT = int32_t;
35
Jan Voungb36ad9b2015-04-21 17:01:49 -070036class TargetARM32;
Jan Voungb2d50842015-05-12 09:53:50 -070037
Andrew Scull57e12682015-09-16 11:30:19 -070038/// OperandARM32 extends the Operand hierarchy. Its subclasses are
Andrew Scull9612d322015-07-06 14:53:25 -070039/// OperandARM32Mem and OperandARM32Flex.
Jan Voungb2d50842015-05-12 09:53:50 -070040class OperandARM32 : public Operand {
41 OperandARM32() = delete;
42 OperandARM32(const OperandARM32 &) = delete;
43 OperandARM32 &operator=(const OperandARM32 &) = delete;
44
45public:
Jan Voungb3401d22015-05-18 09:38:21 -070046 enum OperandKindARM32 {
47 k__Start = Operand::kTarget,
48 kMem,
John Porto2758bb02015-11-17 14:31:25 -080049 kShAmtImm,
Jan Voungb3401d22015-05-18 09:38:21 -070050 kFlexStart,
51 kFlexImm = kFlexStart,
John Portoccea7932015-11-17 04:58:36 -080052 kFlexFpImm,
53 kFlexFpZero,
Jan Voungb3401d22015-05-18 09:38:21 -070054 kFlexReg,
55 kFlexEnd = kFlexReg
56 };
Jan Voungb2d50842015-05-12 09:53:50 -070057
58 enum ShiftKind {
59 kNoShift = -1,
60#define X(enum, emit) enum,
61 ICEINSTARM32SHIFT_TABLE
62#undef X
63 };
64
65 using Operand::dump;
66 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070067 if (BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -070068 Str << "<OperandARM32>";
69 }
70
71protected:
72 OperandARM32(OperandKindARM32 Kind, Type Ty)
73 : Operand(static_cast<OperandKind>(Kind), Ty) {}
Jan Voungb2d50842015-05-12 09:53:50 -070074};
75
Andrew Scull9612d322015-07-06 14:53:25 -070076/// OperandARM32Mem represents a memory operand in any of the various ARM32
77/// addressing modes.
Jan Voungb2d50842015-05-12 09:53:50 -070078class OperandARM32Mem : public OperandARM32 {
79 OperandARM32Mem() = delete;
80 OperandARM32Mem(const OperandARM32Mem &) = delete;
81 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
82
83public:
Andrew Scull9612d322015-07-06 14:53:25 -070084 /// Memory operand addressing mode.
85 /// The enum value also carries the encoding.
Jan Voungb3401d22015-05-18 09:38:21 -070086 // TODO(jvoung): unify with the assembler.
87 enum AddrMode {
Karl Schimpfcdb3ed62015-11-17 14:02:02 -080088 // bit encoding P U 0 W
Jan Voungb3401d22015-05-18 09:38:21 -070089 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base)
90 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback
91 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback
92 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base)
93 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
94 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
95 };
96
Andrew Scull9612d322015-07-06 14:53:25 -070097 /// Provide two constructors.
98 /// NOTE: The Variable-typed operands have to be registers.
99 ///
100 /// (1) Reg + Imm. The Immediate actually has a limited number of bits
Andrew Scull57e12682015-09-16 11:30:19 -0700101 /// for encoding, so check canHoldOffset first. It cannot handle general
102 /// Constant operands like ConstantRelocatable, since a relocatable can
103 /// potentially take up too many bits.
Jan Voungb3401d22015-05-18 09:38:21 -0700104 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
Jan Voungbefd03a2015-06-02 11:03:03 -0700105 ConstantInteger32 *ImmOffset,
Jan Voungb3401d22015-05-18 09:38:21 -0700106 AddrMode Mode = Offset) {
107 return new (Func->allocate<OperandARM32Mem>())
108 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
109 }
Andrew Scull57e12682015-09-16 11:30:19 -0700110 /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
111 /// this mode is disallowed in the NaCl sandbox.
Jan Voungb3401d22015-05-18 09:38:21 -0700112 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
113 Variable *Index, ShiftKind ShiftOp = kNoShift,
114 uint16_t ShiftAmt = 0,
115 AddrMode Mode = Offset) {
116 return new (Func->allocate<OperandARM32Mem>())
117 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
118 }
119 Variable *getBase() const { return Base; }
120 ConstantInteger32 *getOffset() const { return ImmOffset; }
121 Variable *getIndex() const { return Index; }
122 ShiftKind getShiftOp() const { return ShiftOp; }
123 uint16_t getShiftAmt() const { return ShiftAmt; }
124 AddrMode getAddrMode() const { return Mode; }
125
126 bool isRegReg() const { return Index != nullptr; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700127 bool isNegAddrMode() const {
128 // Positive address modes have the "U" bit set, and negative modes don't.
129 static_assert((PreIndex & (4 << 21)) != 0,
130 "Positive addr modes should have U bit set.");
131 static_assert((NegPreIndex & (4 << 21)) == 0,
132 "Negative addr modes should have U bit clear.");
133 return (Mode & (4 << 21)) == 0;
134 }
Jan Voungb3401d22015-05-18 09:38:21 -0700135
136 void emit(const Cfg *Func) const override;
137 using OperandARM32::dump;
138 void dump(const Cfg *Func, Ostream &Str) const override;
139
140 static bool classof(const Operand *Operand) {
141 return Operand->getKind() == static_cast<OperandKind>(kMem);
142 }
143
Andrew Scull57e12682015-09-16 11:30:19 -0700144 /// Return true if a load/store instruction for an element of type Ty can
145 /// encode the Offset directly in the immediate field of the 32-bit ARM
146 /// instruction. For some types, if the load is Sign extending, then the range
147 /// is reduced.
Jan Voungb2d50842015-05-12 09:53:50 -0700148 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
Jan Voungb3401d22015-05-18 09:38:21 -0700149
150private:
151 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
152 ConstantInteger32 *ImmOffset, AddrMode Mode);
153 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
154 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
John Porto1bec8bc2015-06-22 10:51:13 -0700155
Jan Voungb3401d22015-05-18 09:38:21 -0700156 Variable *Base;
157 ConstantInteger32 *ImmOffset;
158 Variable *Index;
159 ShiftKind ShiftOp;
160 uint16_t ShiftAmt;
161 AddrMode Mode;
162};
163
John Porto2758bb02015-11-17 14:31:25 -0800164/// OperandARM32ShAmtImm represents an Immediate that is used in one of the
165/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
166/// shifted registers.
167class OperandARM32ShAmtImm : public OperandARM32 {
168 OperandARM32ShAmtImm() = delete;
169 OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
170 OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;
171
172public:
173 static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
174 return new (Func->allocate<OperandARM32ShAmtImm>())
175 OperandARM32ShAmtImm(ShAmt);
176 }
177
178 static bool classof(const Operand *Operand) {
179 return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
180 }
181
182 void emit(const Cfg *Func) const override;
183 using OperandARM32::dump;
184 void dump(const Cfg *Func, Ostream &Str) const override;
185
186 uint32_t getShAmtImm() const { return ShAmt->getValue(); }
187
188private:
189 explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);
190
191 const ConstantInteger32 *const ShAmt;
192};
193
Andrew Scull57e12682015-09-16 11:30:19 -0700194/// OperandARM32Flex represent the "flexible second operand" for data-processing
195/// instructions. It can be a rotatable 8-bit constant, or a register with an
196/// optional shift operand. The shift amount can even be a third register.
Jan Voungb3401d22015-05-18 09:38:21 -0700197class OperandARM32Flex : public OperandARM32 {
198 OperandARM32Flex() = delete;
199 OperandARM32Flex(const OperandARM32Flex &) = delete;
200 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
201
202public:
203 static bool classof(const Operand *Operand) {
204 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
205 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
206 }
207
208protected:
209 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
Jan Voungb3401d22015-05-18 09:38:21 -0700210};
211
Andrew Scull9612d322015-07-06 14:53:25 -0700212/// Rotated immediate variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700213class OperandARM32FlexImm : public OperandARM32Flex {
214 OperandARM32FlexImm() = delete;
215 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
216 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
217
218public:
Andrew Scull9612d322015-07-06 14:53:25 -0700219 /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
Jan Voungb3401d22015-05-18 09:38:21 -0700220 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
Karl Schimpf67574d82015-12-08 15:37:00 -0800221 uint32_t RotateAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700222
223 void emit(const Cfg *Func) const override;
224 using OperandARM32::dump;
225 void dump(const Cfg *Func, Ostream &Str) const override;
226
227 static bool classof(const Operand *Operand) {
228 return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
229 }
230
Andrew Scull57e12682015-09-16 11:30:19 -0700231 /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
232 /// the out-params RotateAmt and Immed_8 if Immediate fits.
Jan Voungb3401d22015-05-18 09:38:21 -0700233 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
234 uint32_t *Immed_8);
235
236 uint32_t getImm() const { return Imm; }
237 uint32_t getRotateAmt() const { return RotateAmt; }
238
239private:
240 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700241
242 uint32_t Imm;
243 uint32_t RotateAmt;
244};
245
John Portoccea7932015-11-17 04:58:36 -0800246/// Modified Floating-point constant.
247class OperandARM32FlexFpImm : public OperandARM32Flex {
248 OperandARM32FlexFpImm() = delete;
249 OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete;
250 OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete;
251
252public:
253 static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty,
254 uint32_t ModifiedImm) {
255 return new (Func->allocate<OperandARM32FlexFpImm>())
256 OperandARM32FlexFpImm(Func, Ty, ModifiedImm);
257 }
258
259 void emit(const Cfg *Func) const override;
260 using OperandARM32::dump;
261 void dump(const Cfg *Func, Ostream &Str) const override;
262
263 static bool classof(const Operand *Operand) {
264 return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
265 }
266
267 static bool canHoldImm(Operand *C, uint32_t *ModifiedImm);
268
Karl Schimpfc64448f2016-01-26 11:12:29 -0800269 uint32_t getModifiedImm() const { return ModifiedImm; }
270
John Portoccea7932015-11-17 04:58:36 -0800271private:
272 OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
273
Karl Schimpfc64448f2016-01-26 11:12:29 -0800274 const uint32_t ModifiedImm;
John Portoccea7932015-11-17 04:58:36 -0800275};
276
277/// An operand for representing the 0.0 immediate in vcmp.
278class OperandARM32FlexFpZero : public OperandARM32Flex {
279 OperandARM32FlexFpZero() = delete;
280 OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete;
281 OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete;
282
283public:
284 static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) {
285 return new (Func->allocate<OperandARM32FlexFpZero>())
286 OperandARM32FlexFpZero(Func, Ty);
287 }
288
289 void emit(const Cfg *Func) const override;
290 using OperandARM32::dump;
291 void dump(const Cfg *Func, Ostream &Str) const override;
292
293 static bool classof(const Operand *Operand) {
294 return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero);
295 }
296
297private:
298 OperandARM32FlexFpZero(Cfg *Func, Type Ty);
299};
300
Andrew Scull9612d322015-07-06 14:53:25 -0700301/// Shifted register variant.
Jan Voungb3401d22015-05-18 09:38:21 -0700302class OperandARM32FlexReg : public OperandARM32Flex {
303 OperandARM32FlexReg() = delete;
304 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
305 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
306
307public:
Andrew Scull9612d322015-07-06 14:53:25 -0700308 /// Register with immediate/reg shift amount and shift operation.
Jan Voungb3401d22015-05-18 09:38:21 -0700309 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
310 ShiftKind ShiftOp, Operand *ShiftAmt) {
311 return new (Func->allocate<OperandARM32FlexReg>())
312 OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
313 }
314
315 void emit(const Cfg *Func) const override;
316 using OperandARM32::dump;
317 void dump(const Cfg *Func, Ostream &Str) const override;
318
319 static bool classof(const Operand *Operand) {
320 return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
321 }
322
323 Variable *getReg() const { return Reg; }
324 ShiftKind getShiftOp() const { return ShiftOp; }
Andrew Scull9612d322015-07-06 14:53:25 -0700325 /// ShiftAmt can represent an immediate or a register.
Jan Voungb3401d22015-05-18 09:38:21 -0700326 Operand *getShiftAmt() const { return ShiftAmt; }
327
328private:
329 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
330 Operand *ShiftAmt);
Jan Voungb3401d22015-05-18 09:38:21 -0700331
332 Variable *Reg;
333 ShiftKind ShiftOp;
334 Operand *ShiftAmt;
Jan Voungb2d50842015-05-12 09:53:50 -0700335};
336
Jan Voung28068ad2015-07-31 12:58:46 -0700337/// StackVariable represents a Var that isn't assigned a register (stack-only).
338/// It is assigned a stack slot, but the slot's offset may be too large to
Andrew Scull57e12682015-09-16 11:30:19 -0700339/// represent in the native addressing mode, and so it has a separate base
340/// register from SP/FP, where the offset from that base register is then in
341/// range.
Jan Voung28068ad2015-07-31 12:58:46 -0700342class StackVariable final : public Variable {
343 StackVariable() = delete;
344 StackVariable(const StackVariable &) = delete;
345 StackVariable &operator=(const StackVariable &) = delete;
346
347public:
348 static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
349 return new (Func->allocate<StackVariable>()) StackVariable(Ty, Index);
350 }
351 const static OperandKind StackVariableKind =
352 static_cast<OperandKind>(kVariable_Target);
353 static bool classof(const Operand *Operand) {
354 return Operand->getKind() == StackVariableKind;
355 }
356 void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
357 int32_t getBaseRegNum() const override { return BaseRegNum; }
358 // Inherit dump() and emit() from Variable.
359
360private:
361 StackVariable(Type Ty, SizeT Index)
362 : Variable(StackVariableKind, Ty, Index) {}
363 int32_t BaseRegNum = Variable::NoRegister;
364};
365
Andrew Scull9612d322015-07-06 14:53:25 -0700366/// Base class for ARM instructions. While most ARM instructions can be
Andrew Scull57e12682015-09-16 11:30:19 -0700367/// conditionally executed, a few of them are not predicable (halt, memory
368/// barriers, etc.).
Jan Voungb2d50842015-05-12 09:53:50 -0700369class InstARM32 : public InstTarget {
370 InstARM32() = delete;
371 InstARM32(const InstARM32 &) = delete;
372 InstARM32 &operator=(const InstARM32 &) = delete;
373
374public:
Karl Schimpfc411dbf2016-01-11 09:59:19 -0800375 // Defines form that assembly instruction should be synthesized.
376 enum EmitForm { Emit_Text, Emit_Binary };
377
Jan Voungb3401d22015-05-18 09:38:21 -0700378 enum InstKindARM32 {
379 k__Start = Inst::Target,
Jan Voung29719972015-05-19 11:24:51 -0700380 Adc,
381 Add,
382 And,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700383 Asr,
Jan Voung55500db2015-05-26 14:25:40 -0700384 Bic,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700385 Br,
386 Call,
Karl Schimpf19567882015-12-02 10:24:15 -0800387 Clz,
John Portoccea7932015-11-17 04:58:36 -0800388 Cmn,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700389 Cmp,
John Porto16991842015-10-01 15:11:23 -0700390 Dmb,
Jan Voung29719972015-05-19 11:24:51 -0700391 Eor,
Jan Voung6ec369e2015-06-30 11:03:15 -0700392 Label,
Jan Voung29719972015-05-19 11:24:51 -0700393 Ldr,
John Porto16991842015-10-01 15:11:23 -0700394 Ldrex,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700395 Lsl,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700396 Lsr,
Jan Voung29719972015-05-19 11:24:51 -0700397 Mla,
Jan Voung6ec369e2015-06-30 11:03:15 -0700398 Mls,
Jan Voungb3401d22015-05-18 09:38:21 -0700399 Mov,
400 Movt,
401 Movw,
Jan Voung29719972015-05-19 11:24:51 -0700402 Mul,
Jan Voungb3401d22015-05-18 09:38:21 -0700403 Mvn,
Jan Voung29719972015-05-19 11:24:51 -0700404 Orr,
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700405 Pop,
406 Push,
Jan Voungf645d852015-07-09 10:35:09 -0700407 Rbit,
Jan Voungb3401d22015-05-18 09:38:21 -0700408 Ret,
Jan Voungf645d852015-07-09 10:35:09 -0700409 Rev,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700410 Rsb,
John Portoccea7932015-11-17 04:58:36 -0800411 Rsc,
Jan Voung29719972015-05-19 11:24:51 -0700412 Sbc,
Jan Voung6ec369e2015-06-30 11:03:15 -0700413 Sdiv,
Jan Voungbefd03a2015-06-02 11:03:03 -0700414 Str,
John Porto16991842015-10-01 15:11:23 -0700415 Strex,
Jan Voung29719972015-05-19 11:24:51 -0700416 Sub,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700417 Sxt,
Jan Voung6ec369e2015-06-30 11:03:15 -0700418 Trap,
419 Tst,
420 Udiv,
Jan Voung66c3d5e2015-06-04 17:02:31 -0700421 Umull,
Jan Voung86ebec12015-08-09 07:58:35 -0700422 Uxt,
John Portoba6a67c2015-09-25 15:19:45 -0700423 Vabs,
Jan Voung86ebec12015-08-09 07:58:35 -0700424 Vadd,
Eric Holkb58170c2016-01-27 11:18:29 -0800425 Vand,
John Porto2f5534f2015-09-18 15:59:47 -0700426 Vcmp,
John Portoc31e2ed2015-09-11 05:17:08 -0700427 Vcvt,
Jan Voung86ebec12015-08-09 07:58:35 -0700428 Vdiv,
John Portoccea7932015-11-17 04:58:36 -0800429 Veor,
John Portoeb13acc2015-12-09 05:10:58 -0800430 Vmla,
431 Vmls,
John Porto2f5534f2015-09-18 15:59:47 -0700432 Vmrs,
Jan Voung86ebec12015-08-09 07:58:35 -0700433 Vmul,
Eric Holkcad0b752016-01-27 14:56:22 -0800434 Vorr,
Jan Voung86ebec12015-08-09 07:58:35 -0700435 Vsqrt,
436 Vsub
Jan Voungb3401d22015-05-18 09:38:21 -0700437 };
Jan Voungb2d50842015-05-12 09:53:50 -0700438
Karl Schimpf856734c2015-11-05 08:18:26 -0800439 static constexpr size_t InstSize = sizeof(uint32_t);
440
Jan Voungb2d50842015-05-12 09:53:50 -0700441 static const char *getWidthString(Type Ty);
Jan Voung86ebec12015-08-09 07:58:35 -0700442 static const char *getVecWidthString(Type Ty);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700443 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
Jan Voungb2d50842015-05-12 09:53:50 -0700444
Karl Schimpf856734c2015-11-05 08:18:26 -0800445 /// Called inside derived methods emit() to communicate that multiple
446 /// instructions are being generated. Used by emitIAS() methods to
447 /// generate textual fixups for instructions that are not yet
448 /// implemented.
449 void startNextInst(const Cfg *Func) const;
450
Jan Voung86ebec12015-08-09 07:58:35 -0700451 /// Shared emit routines for common forms of instructions.
452 static void emitThreeAddrFP(const char *Opcode, const InstARM32 *Inst,
453 const Cfg *Func);
John Portoeb13acc2015-12-09 05:10:58 -0800454 static void emitFourAddrFP(const char *Opcode, const InstARM32 *Inst,
455 const Cfg *Func);
Jan Voung86ebec12015-08-09 07:58:35 -0700456
Jan Voungb2d50842015-05-12 09:53:50 -0700457 void dump(const Cfg *Func) const override;
458
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700459 void emitIAS(const Cfg *Func) const override;
460
Jan Voungb2d50842015-05-12 09:53:50 -0700461protected:
462 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
463 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700464
Jan Voungb2d50842015-05-12 09:53:50 -0700465 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
466 return Inst->getKind() == static_cast<InstKind>(MyKind);
467 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700468
469 // Generates text of assembly instruction using method emit(), and then adds
470 // to the assembly buffer as a Fixup.
471 void emitUsingTextFixup(const Cfg *Func) const;
Jan Voungb2d50842015-05-12 09:53:50 -0700472};
473
Andrew Scull9612d322015-07-06 14:53:25 -0700474/// A predicable ARM instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700475class InstARM32Pred : public InstARM32 {
476 InstARM32Pred() = delete;
477 InstARM32Pred(const InstARM32Pred &) = delete;
478 InstARM32Pred &operator=(const InstARM32Pred &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700479
Jan Voung3bfd99a2015-05-22 16:35:25 -0700480public:
481 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
482 CondARM32::Cond Predicate)
483 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
484
485 CondARM32::Cond getPredicate() const { return Predicate; }
486 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
487
488 static const char *predString(CondARM32::Cond Predicate);
489 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
490
Andrew Scull9612d322015-07-06 14:53:25 -0700491 /// Shared emit routines for common forms of instructions.
Jan Voung66c3d5e2015-06-04 17:02:31 -0700492 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
Jan Voungf645d852015-07-09 10:35:09 -0700493 const Cfg *Func, bool NeedsWidthSuffix);
Jan Voung86ebec12015-08-09 07:58:35 -0700494 static void emitUnaryopFP(const char *Opcode, const InstARM32Pred *Inst,
495 const Cfg *Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700496 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
497 const Cfg *Func);
498 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
499 const Cfg *Func, bool SetFlags);
Jan Voung6ec369e2015-06-30 11:03:15 -0700500 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
501 const Cfg *Func);
502 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Inst,
503 const Cfg *Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700504
505protected:
506 CondARM32::Cond Predicate;
507};
508
509template <typename StreamType>
510inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
511 Stream << InstARM32Pred::predString(Predicate);
512 return Stream;
513}
Jan Voungb3401d22015-05-18 09:38:21 -0700514
Andrew Scull9612d322015-07-06 14:53:25 -0700515/// Instructions of the form x := op(y).
Jan Voungf645d852015-07-09 10:35:09 -0700516template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700517class InstARM32UnaryopGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700518 InstARM32UnaryopGPR() = delete;
519 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
520 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
521
522public:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700523 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
524 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700525 return new (Func->allocate<InstARM32UnaryopGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700526 InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700527 }
528 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700529 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700530 return;
Jan Voungf645d852015-07-09 10:35:09 -0700531 emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
Jan Voungb3401d22015-05-18 09:38:21 -0700532 }
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700533 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700534 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700535 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700536 return;
537 Ostream &Str = Func->getContext()->getStrDump();
538 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700539 Str << " = ";
540 dumpOpcodePred(Str, Opcode, getDest()->getType());
541 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700542 dumpSources(Func);
543 }
544 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
545
546private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700547 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
548 CondARM32::Cond Predicate)
549 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700550 addSource(Src);
551 }
John Porto1bec8bc2015-06-22 10:51:13 -0700552
Jan Voungb3401d22015-05-18 09:38:21 -0700553 static const char *Opcode;
554};
555
Jan Voung86ebec12015-08-09 07:58:35 -0700556/// Instructions of the form x := op(y), for vector/FP.
557template <InstARM32::InstKindARM32 K>
558class InstARM32UnaryopFP : public InstARM32Pred {
559 InstARM32UnaryopFP() = delete;
560 InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
561 InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
562
563public:
564 static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
565 CondARM32::Cond Predicate) {
566 return new (Func->allocate<InstARM32UnaryopFP>())
567 InstARM32UnaryopFP(Func, Dest, Src, Predicate);
568 }
569 void emit(const Cfg *Func) const override {
570 if (!BuildDefs::dump())
571 return;
572 emitUnaryopFP(Opcode, this, Func);
573 }
Karl Schimpf266c5a22016-01-29 09:54:58 -0800574 void emitIAS(const Cfg *Func) const override;
Jan Voung86ebec12015-08-09 07:58:35 -0700575 void dump(const Cfg *Func) const override {
576 if (!BuildDefs::dump())
577 return;
578 Ostream &Str = Func->getContext()->getStrDump();
579 dumpDest(Func);
580 Str << " = ";
581 dumpOpcodePred(Str, Opcode, getDest()->getType());
582 Str << " ";
583 dumpSources(Func);
584 }
585 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
586
587private:
588 InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
589 CondARM32::Cond Predicate)
590 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
591 addSource(Src);
592 }
593
594 static const char *Opcode;
595};
596
Andrew Scull9612d322015-07-06 14:53:25 -0700597/// Instructions of the form x := x op y.
Jan Voungb3401d22015-05-18 09:38:21 -0700598template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700599class InstARM32TwoAddrGPR : public InstARM32Pred {
Jan Voungb3401d22015-05-18 09:38:21 -0700600 InstARM32TwoAddrGPR() = delete;
601 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
602 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
603
604public:
Andrew Scull9612d322015-07-06 14:53:25 -0700605 /// Dest must be a register.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700606 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
607 CondARM32::Cond Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700608 return new (Func->allocate<InstARM32TwoAddrGPR>())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700609 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700610 }
611 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700612 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700613 return;
614 emitTwoAddr(Opcode, this, Func);
615 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700616 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700617 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700618 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700619 return;
620 Ostream &Str = Func->getContext()->getStrDump();
621 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700622 Str << " = ";
623 dumpOpcodePred(Str, Opcode, getDest()->getType());
624 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700625 dumpSources(Func);
626 }
627 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
628
629private:
Jan Voung3bfd99a2015-05-22 16:35:25 -0700630 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
631 CondARM32::Cond Predicate)
632 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700633 addSource(Dest);
634 addSource(Src);
635 }
John Porto1bec8bc2015-06-22 10:51:13 -0700636
Jan Voungb3401d22015-05-18 09:38:21 -0700637 static const char *Opcode;
638};
639
John Porto16991842015-10-01 15:11:23 -0700640/// Base class for load instructions.
Jan Voungb3401d22015-05-18 09:38:21 -0700641template <InstARM32::InstKindARM32 K>
John Porto16991842015-10-01 15:11:23 -0700642class InstARM32LoadBase : public InstARM32Pred {
643 InstARM32LoadBase() = delete;
644 InstARM32LoadBase(const InstARM32LoadBase &) = delete;
645 InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
Jan Voungb3401d22015-05-18 09:38:21 -0700646
647public:
John Porto16991842015-10-01 15:11:23 -0700648 static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
649 CondARM32::Cond Predicate) {
650 return new (Func->allocate<InstARM32LoadBase>())
651 InstARM32LoadBase(Func, Dest, Source, Predicate);
Jan Voungb3401d22015-05-18 09:38:21 -0700652 }
Jan Voungb3401d22015-05-18 09:38:21 -0700653 void emit(const Cfg *Func) const override;
Karl Schimpff0655b62015-10-30 07:30:14 -0700654 void emitIAS(const Cfg *Func) const override;
Jan Voungb3401d22015-05-18 09:38:21 -0700655 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700656 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700657 return;
658 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung3bfd99a2015-05-22 16:35:25 -0700659 dumpOpcodePred(Str, Opcode, getDest()->getType());
660 Str << " ";
Jan Voungb3401d22015-05-18 09:38:21 -0700661 dumpDest(Func);
662 Str << ", ";
663 dumpSources(Func);
664 }
665 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
666
667private:
John Porto16991842015-10-01 15:11:23 -0700668 InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
669 CondARM32::Cond Predicate)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700670 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
Jan Voungb3401d22015-05-18 09:38:21 -0700671 addSource(Source);
672 }
Jan Voungb3401d22015-05-18 09:38:21 -0700673
674 static const char *Opcode;
675};
676
Andrew Scull9612d322015-07-06 14:53:25 -0700677/// Instructions of the form x := y op z. May have the side-effect of setting
678/// status flags.
Jan Voung29719972015-05-19 11:24:51 -0700679template <InstARM32::InstKindARM32 K>
Jan Voung3bfd99a2015-05-22 16:35:25 -0700680class InstARM32ThreeAddrGPR : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -0700681 InstARM32ThreeAddrGPR() = delete;
682 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
683 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
684
685public:
Andrew Scull57e12682015-09-16 11:30:19 -0700686 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
687 /// must be registers.
Jan Voung29719972015-05-19 11:24:51 -0700688 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
Jan Voung6ec369e2015-06-30 11:03:15 -0700689 Variable *Src0, Operand *Src1,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700690 CondARM32::Cond Predicate,
Jan Voung29719972015-05-19 11:24:51 -0700691 bool SetFlags = false) {
692 return new (Func->allocate<InstARM32ThreeAddrGPR>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700693 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
Jan Voung29719972015-05-19 11:24:51 -0700694 }
695 void emit(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700696 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700697 return;
698 emitThreeAddr(Opcode, this, Func, SetFlags);
699 }
Karl Schimpf372bdd62015-10-13 14:39:14 -0700700 void emitIAS(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -0700701 void dump(const Cfg *Func) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700702 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700703 return;
704 Ostream &Str = Func->getContext()->getStrDump();
705 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700706 Str << " = ";
707 dumpOpcodePred(Str, Opcode, getDest()->getType());
708 Str << (SetFlags ? ".s " : " ");
Jan Voung29719972015-05-19 11:24:51 -0700709 dumpSources(Func);
710 }
711 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
712
713private:
Jan Voung6ec369e2015-06-30 11:03:15 -0700714 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
715 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700716 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
John Portoccea7932015-11-17 04:58:36 -0800717 HasSideEffects = SetFlags;
Jan Voung6ec369e2015-06-30 11:03:15 -0700718 addSource(Src0);
719 addSource(Src1);
720 }
721
722 static const char *Opcode;
723 bool SetFlags;
724};
725
Andrew Scull57e12682015-09-16 11:30:19 -0700726/// Instructions of the form x := y op z, for vector/FP. We leave these as
Jan Voung86ebec12015-08-09 07:58:35 -0700727/// unconditional: "ARM deprecates the conditional execution of any instruction
728/// encoding provided by the Advanced SIMD Extension that is not also provided
John Portoeb13acc2015-12-09 05:10:58 -0800729/// by the floating-point (VFP) extension". They do not set flags.
Jan Voung86ebec12015-08-09 07:58:35 -0700730template <InstARM32::InstKindARM32 K>
731class InstARM32ThreeAddrFP : public InstARM32 {
732 InstARM32ThreeAddrFP() = delete;
733 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
734 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
735
736public:
Andrew Scull57e12682015-09-16 11:30:19 -0700737 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
738 /// must be a register.
Jan Voung86ebec12015-08-09 07:58:35 -0700739 static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
740 Variable *Src1) {
741 return new (Func->allocate<InstARM32ThreeAddrFP>())
742 InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
743 }
744 void emit(const Cfg *Func) const override {
745 if (!BuildDefs::dump())
746 return;
747 emitThreeAddrFP(Opcode, this, Func);
748 }
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800749 void emitIAS(const Cfg *Func) const override;
Jan Voung86ebec12015-08-09 07:58:35 -0700750 void dump(const Cfg *Func) const override {
751 if (!BuildDefs::dump())
752 return;
753 Ostream &Str = Func->getContext()->getStrDump();
754 dumpDest(Func);
755 Str << " = ";
756 Str << Opcode << "." << getDest()->getType() << " ";
757 dumpSources(Func);
758 }
759 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
760
761private:
762 InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0,
763 Variable *Src1)
764 : InstARM32(Func, K, 2, Dest) {
765 addSource(Src0);
766 addSource(Src1);
767 }
768
769 static const char *Opcode;
770};
771
772/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
Jan Voung6ec369e2015-06-30 11:03:15 -0700773template <InstARM32::InstKindARM32 K>
774class InstARM32FourAddrGPR : public InstARM32Pred {
775 InstARM32FourAddrGPR() = delete;
776 InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
777 InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
778
779public:
780 // Every operand must be a register.
781 static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
782 Variable *Src1, Variable *Src2,
783 CondARM32::Cond Predicate) {
784 return new (Func->allocate<InstARM32FourAddrGPR>())
785 InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
786 }
787 void emit(const Cfg *Func) const override {
788 if (!BuildDefs::dump())
789 return;
790 emitFourAddr(Opcode, this, Func);
791 }
Karl Schimpf080b65b2015-11-05 08:27:51 -0800792 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700793 void dump(const Cfg *Func) const override {
794 if (!BuildDefs::dump())
795 return;
796 Ostream &Str = Func->getContext()->getStrDump();
797 dumpDest(Func);
798 Str << " = ";
799 dumpOpcodePred(Str, Opcode, getDest()->getType());
800 Str << " ";
801 dumpSources(Func);
802 }
803 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
804
805private:
806 InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
807 Variable *Src1, Variable *Src2,
808 CondARM32::Cond Predicate)
809 : InstARM32Pred(Func, K, 3, Dest, Predicate) {
810 addSource(Src0);
Jan Voung29719972015-05-19 11:24:51 -0700811 addSource(Src1);
812 addSource(Src2);
813 }
John Porto1bec8bc2015-06-22 10:51:13 -0700814
Jan Voung29719972015-05-19 11:24:51 -0700815 static const char *Opcode;
Jan Voung6ec369e2015-06-30 11:03:15 -0700816};
817
John Portoeb13acc2015-12-09 05:10:58 -0800818/// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
819/// We leave these as unconditional: "ARM deprecates the conditional execution
820/// of any instruction encoding provided by the Advanced SIMD Extension that is
821/// not also provided by the floating-point (VFP) extension". They do not set
822/// flags.
823template <InstARM32::InstKindARM32 K>
824class InstARM32FourAddrFP : public InstARM32 {
825 InstARM32FourAddrFP() = delete;
826 InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
827 InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
828
829public:
830 // Every operand must be a register.
831 static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
832 Variable *Src1) {
833 return new (Func->allocate<InstARM32FourAddrFP>())
834 InstARM32FourAddrFP(Func, Dest, Src0, Src1);
835 }
836 void emit(const Cfg *Func) const override {
837 if (!BuildDefs::dump())
838 return;
839 emitFourAddrFP(Opcode, this, Func);
840 }
Karl Schimpf8c5544b2016-01-26 15:29:22 -0800841 void emitIAS(const Cfg *Func) const override;
John Portoeb13acc2015-12-09 05:10:58 -0800842 void dump(const Cfg *Func) const override {
843 if (!BuildDefs::dump())
844 return;
845 Ostream &Str = Func->getContext()->getStrDump();
846 dumpDest(Func);
847 Str << " = ";
848 Str << Opcode << "." << getDest()->getType() << " ";
849 dumpDest(Func);
850 Str << ", ";
851 dumpSources(Func);
852 }
853 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
854
855private:
856 InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
857 : InstARM32(Func, K, 3, Dest) {
858 addSource(Dest);
859 addSource(Src0);
860 addSource(Src1);
861 }
862
863 static const char *Opcode;
864};
865
Jan Voung86ebec12015-08-09 07:58:35 -0700866/// Instructions of the form x cmpop y (setting flags).
Jan Voung6ec369e2015-06-30 11:03:15 -0700867template <InstARM32::InstKindARM32 K>
868class InstARM32CmpLike : public InstARM32Pred {
869 InstARM32CmpLike() = delete;
870 InstARM32CmpLike(const InstARM32CmpLike &) = delete;
871 InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
872
873public:
874 static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
875 CondARM32::Cond Predicate) {
876 return new (Func->allocate<InstARM32CmpLike>())
877 InstARM32CmpLike(Func, Src0, Src1, Predicate);
878 }
879 void emit(const Cfg *Func) const override {
880 if (!BuildDefs::dump())
881 return;
882 emitCmpLike(Opcode, this, Func);
883 }
Karl Schimpff8fc12f2015-10-30 15:06:35 -0700884 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700885 void dump(const Cfg *Func) const override {
886 if (!BuildDefs::dump())
887 return;
888 Ostream &Str = Func->getContext()->getStrDump();
889 dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
890 Str << " ";
891 dumpSources(Func);
892 }
893 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
894
895private:
896 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
897 CondARM32::Cond Predicate)
898 : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
John Portoccea7932015-11-17 04:58:36 -0800899 HasSideEffects = true;
Jan Voung6ec369e2015-06-30 11:03:15 -0700900 addSource(Src0);
901 addSource(Src1);
902 }
903
904 static const char *Opcode;
Jan Voung29719972015-05-19 11:24:51 -0700905};
906
Andrew Scull8072bae2015-09-14 16:01:26 -0700907using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
908using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
909using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
910using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
911using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
912using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
913using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
914using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
915using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
916using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
917using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
John Portoccea7932015-11-17 04:58:36 -0800918using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700919using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
920using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
921using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
922using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
923using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
Eric Holkb58170c2016-01-27 11:18:29 -0800924using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700925using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
John Portoccea7932015-11-17 04:58:36 -0800926using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
John Portoeb13acc2015-12-09 05:10:58 -0800927using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
928using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
929using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
Eric Holkcad0b752016-01-27 14:56:22 -0800930using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700931using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
John Porto16991842015-10-01 15:11:23 -0700932using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
933using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
Andrew Scull57e12682015-09-16 11:30:19 -0700934/// MovT leaves the bottom bits alone so dest is also a source. This helps
935/// indicate that a previous MovW setting dest is not dead code.
Andrew Scull8072bae2015-09-14 16:01:26 -0700936using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
937using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
938using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
939using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
940using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
941using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
Andrew Scull57e12682015-09-16 11:30:19 -0700942// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
943// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
944// using that for now, so just model as a Unaryop.
Andrew Scull8072bae2015-09-14 16:01:26 -0700945using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
946using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
947using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
948using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
949using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
John Portoccea7932015-11-17 04:58:36 -0800950using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700951using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
952using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
Jan Voung6ec369e2015-06-30 11:03:15 -0700953
Andrew Scull57e12682015-09-16 11:30:19 -0700954// InstARM32Label represents an intra-block label that is the target of an
955// intra-block branch. The offset between the label and the branch must be fit
956// in the instruction immediate (considered "near").
Jan Voung6ec369e2015-06-30 11:03:15 -0700957class InstARM32Label : public InstARM32 {
958 InstARM32Label() = delete;
959 InstARM32Label(const InstARM32Label &) = delete;
960 InstARM32Label &operator=(const InstARM32Label &) = delete;
961
962public:
963 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
964 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
965 }
966 uint32_t getEmitInstCount() const override { return 0; }
967 IceString getName(const Cfg *Func) const;
968 SizeT getNumber() const { return Number; }
969 void emit(const Cfg *Func) const override;
Karl Schimpf50a33312015-10-23 09:19:48 -0700970 void emitIAS(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -0700971 void dump(const Cfg *Func) const override;
972
973private:
974 InstARM32Label(Cfg *Func, TargetARM32 *Target);
975
976 SizeT Number; // used for unique label generation.
977};
Jan Voungb3401d22015-05-18 09:38:21 -0700978
Andrew Scull9612d322015-07-06 14:53:25 -0700979/// Direct branch instruction.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700980class InstARM32Br : public InstARM32Pred {
981 InstARM32Br() = delete;
982 InstARM32Br(const InstARM32Br &) = delete;
983 InstARM32Br &operator=(const InstARM32Br &) = delete;
984
985public:
Andrew Scull9612d322015-07-06 14:53:25 -0700986 /// Create a conditional branch to one of two nodes.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700987 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
988 CfgNode *TargetFalse, CondARM32::Cond Predicate) {
989 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -0700990 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700991 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700992 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700993 }
Andrew Scull9612d322015-07-06 14:53:25 -0700994 /// Create an unconditional branch to a node.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700995 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
Jan Voung6ec369e2015-06-30 11:03:15 -0700996 constexpr CfgNode *NoCondTarget = nullptr;
997 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700998 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -0700999 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001000 }
Andrew Scull57e12682015-09-16 11:30:19 -07001001 /// Create a non-terminator conditional branch to a node, with a fallthrough
1002 /// to the next instruction in the current node. This is used for switch
1003 /// lowering.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001004 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1005 CondARM32::Cond Predicate) {
1006 assert(Predicate != CondARM32::AL);
Jan Voung6ec369e2015-06-30 11:03:15 -07001007 constexpr CfgNode *NoUncondTarget = nullptr;
1008 constexpr InstARM32Label *NoLabel = nullptr;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001009 return new (Func->allocate<InstARM32Br>())
Jan Voung6ec369e2015-06-30 11:03:15 -07001010 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
1011 }
1012 // Create a conditional intra-block branch (or unconditional, if
1013 // Condition==AL) to a label in the current block.
1014 static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
1015 CondARM32::Cond Predicate) {
1016 constexpr CfgNode *NoCondTarget = nullptr;
1017 constexpr CfgNode *NoUncondTarget = nullptr;
1018 return new (Func->allocate<InstARM32Br>())
1019 InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001020 }
1021 const CfgNode *getTargetTrue() const { return TargetTrue; }
1022 const CfgNode *getTargetFalse() const { return TargetFalse; }
1023 bool optimizeBranch(const CfgNode *NextNode);
1024 uint32_t getEmitInstCount() const override {
1025 uint32_t Sum = 0;
Jan Voung6ec369e2015-06-30 11:03:15 -07001026 if (Label)
1027 ++Sum;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001028 if (getTargetTrue())
1029 ++Sum;
1030 if (getTargetFalse())
1031 ++Sum;
1032 return Sum;
1033 }
1034 bool isUnconditionalBranch() const override {
1035 return getPredicate() == CondARM32::AL;
1036 }
Andrew Scull87f80c12015-07-20 10:19:16 -07001037 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001038 void emit(const Cfg *Func) const override;
Karl Schimpf137e62b2015-10-27 07:28:09 -07001039 void emitIAS(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001040 void dump(const Cfg *Func) const override;
1041 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
1042
1043private:
1044 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Jan Voung6ec369e2015-06-30 11:03:15 -07001045 const InstARM32Label *Label, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -07001046
Jan Voung3bfd99a2015-05-22 16:35:25 -07001047 const CfgNode *TargetTrue;
1048 const CfgNode *TargetFalse;
Jan Voung6ec369e2015-06-30 11:03:15 -07001049 const InstARM32Label *Label; // Intra-block branch target
Jan Voung3bfd99a2015-05-22 16:35:25 -07001050};
1051
Andrew Scull57e12682015-09-16 11:30:19 -07001052/// Call instruction (bl/blx). Arguments should have already been pushed.
Andrew Scull9612d322015-07-06 14:53:25 -07001053/// Technically bl and the register form of blx can be predicated, but we'll
1054/// leave that out until needed.
Jan Voung3bfd99a2015-05-22 16:35:25 -07001055class InstARM32Call : public InstARM32 {
1056 InstARM32Call() = delete;
1057 InstARM32Call(const InstARM32Call &) = delete;
1058 InstARM32Call &operator=(const InstARM32Call &) = delete;
1059
1060public:
1061 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
1062 return new (Func->allocate<InstARM32Call>())
1063 InstARM32Call(Func, Dest, CallTarget);
1064 }
1065 Operand *getCallTarget() const { return getSrc(0); }
1066 void emit(const Cfg *Func) const override;
Karl Schimpf174531e2015-11-18 08:19:26 -08001067 void emitIAS(const Cfg *Func) const override;
Jan Voung3bfd99a2015-05-22 16:35:25 -07001068 void dump(const Cfg *Func) const override;
1069 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
1070
1071private:
1072 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
Jan Voung3bfd99a2015-05-22 16:35:25 -07001073};
1074
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001075class InstARM32RegisterStackOp : public InstARM32 {
1076 InstARM32RegisterStackOp() = delete;
1077 InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1078 InstARM32RegisterStackOp &
1079 operator=(const InstARM32RegisterStackOp &) = delete;
1080
1081public:
1082 void emit(const Cfg *Func) const override;
1083 void emitIAS(const Cfg *Func) const override;
1084 void dump(const Cfg *Func) const override;
1085
1086protected:
1087 InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1088 Variable *Dest)
1089 : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1090 void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1091 void emitGPRsAsText(const Cfg *Func) const;
1092 void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1093 SizeT Regcount) const;
1094 virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1095 virtual const char *getGPROpcode() const = 0;
1096 virtual const char *getSRegOpcode() const = 0;
1097 virtual Variable *getStackReg(SizeT Index) const = 0;
1098 virtual SizeT getNumStackRegs() const = 0;
1099 virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1100 const Variable *Reg) const = 0;
1101 virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1102 IValueT Registers) const = 0;
1103 virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1104 const Variable *BaseReg, SizeT RegCount) const = 0;
1105};
1106
John Portoeb13acc2015-12-09 05:10:58 -08001107/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1108/// regs, but not both. In any case, the list must be sorted.
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001109class InstARM32Pop : public InstARM32RegisterStackOp {
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001110 InstARM32Pop() = delete;
1111 InstARM32Pop(const InstARM32Pop &) = delete;
1112 InstARM32Pop &operator=(const InstARM32Pop &) = delete;
1113
1114public:
1115 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
1116 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
1117 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001118 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
1119
1120private:
1121 InstARM32Pop(Cfg *Func, const VarList &Dests);
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001122 virtual const char *getGPROpcode() const final;
1123 virtual const char *getSRegOpcode() const final;
1124 Variable *getStackReg(SizeT Index) const final;
1125 SizeT getNumStackRegs() const final;
1126 void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1127 const Variable *Reg) const final;
1128 void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1129 IValueT Registers) const final;
1130 void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1131 SizeT RegCount) const final;
John Porto1bec8bc2015-06-22 10:51:13 -07001132
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001133 VarList Dests;
1134};
1135
John Portoeb13acc2015-12-09 05:10:58 -08001136/// Pushes a list of registers. Just like Pop (see above), the list may be of
1137/// GPRs, or VFP "s" registers, but not both.
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001138class InstARM32Push : public InstARM32RegisterStackOp {
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001139 InstARM32Push() = delete;
1140 InstARM32Push(const InstARM32Push &) = delete;
1141 InstARM32Push &operator=(const InstARM32Push &) = delete;
1142
1143public:
1144 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
1145 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
1146 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001147 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
1148
1149private:
1150 InstARM32Push(Cfg *Func, const VarList &Srcs);
Karl Schimpfc411dbf2016-01-11 09:59:19 -08001151 const char *getGPROpcode() const final;
1152 const char *getSRegOpcode() const final;
1153 Variable *getStackReg(SizeT Index) const final;
1154 SizeT getNumStackRegs() const final;
1155 void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1156 const Variable *Reg) const final;
1157 void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1158 IValueT Registers) const final;
1159 void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1160 SizeT RegCount) const final;
Jan Voung0fa6c5a2015-06-01 11:04:04 -07001161};
1162
Andrew Scull57e12682015-09-16 11:30:19 -07001163/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1164/// register operand, but epilogue lowering will search for a Ret instead of a
1165/// generic "bx". This instruction also takes a Source operand (for non-void
1166/// returning functions) for liveness analysis, though a FakeUse before the ret
1167/// would do just as well.
Andrew Scull9612d322015-07-06 14:53:25 -07001168///
1169/// NOTE: Even though "bx" can be predicated, for now leave out the predication
1170/// since it's not yet known to be useful for Ret. That may complicate finding
1171/// the terminator instruction if it's not guaranteed to be executed.
Jan Voungb2d50842015-05-12 09:53:50 -07001172class InstARM32Ret : public InstARM32 {
1173 InstARM32Ret() = delete;
1174 InstARM32Ret(const InstARM32Ret &) = delete;
1175 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1176
1177public:
1178 static InstARM32Ret *create(Cfg *Func, Variable *LR,
1179 Variable *Source = nullptr) {
1180 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1181 }
1182 void emit(const Cfg *Func) const override;
1183 void emitIAS(const Cfg *Func) const override;
1184 void dump(const Cfg *Func) const override;
1185 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
1186
1187private:
1188 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
Jan Voungb2d50842015-05-12 09:53:50 -07001189};
Jan Voungb36ad9b2015-04-21 17:01:49 -07001190
Andrew Scull57e12682015-09-16 11:30:19 -07001191/// Store instruction. It's important for liveness that there is no Dest operand
1192/// (OperandARM32Mem instead of Dest Variable).
John Porto16991842015-10-01 15:11:23 -07001193class InstARM32Str final : public InstARM32Pred {
Jan Voungbefd03a2015-06-02 11:03:03 -07001194 InstARM32Str() = delete;
1195 InstARM32Str(const InstARM32Str &) = delete;
1196 InstARM32Str &operator=(const InstARM32Str &) = delete;
1197
1198public:
Andrew Scull9612d322015-07-06 14:53:25 -07001199 /// Value must be a register.
Jan Voungbefd03a2015-06-02 11:03:03 -07001200 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1201 CondARM32::Cond Predicate) {
1202 return new (Func->allocate<InstARM32Str>())
1203 InstARM32Str(Func, Value, Mem, Predicate);
1204 }
1205 void emit(const Cfg *Func) const override;
Karl Schimpff0655b62015-10-30 07:30:14 -07001206 void emitIAS(const Cfg *Func) const override;
Jan Voungbefd03a2015-06-02 11:03:03 -07001207 void dump(const Cfg *Func) const override;
1208 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
1209
1210private:
1211 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1212 CondARM32::Cond Predicate);
Jan Voungbefd03a2015-06-02 11:03:03 -07001213};
1214
John Porto16991842015-10-01 15:11:23 -07001215/// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1216/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1217/// Variable).
1218class InstARM32Strex final : public InstARM32Pred {
1219 InstARM32Strex() = delete;
1220 InstARM32Strex(const InstARM32Strex &) = delete;
1221 InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1222
1223public:
1224 /// Value must be a register.
1225 static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1226 OperandARM32Mem *Mem,
1227 CondARM32::Cond Predicate) {
1228 return new (Func->allocate<InstARM32Strex>())
1229 InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1230 }
1231 void emit(const Cfg *Func) const override;
Karl Schimpf4175d452015-12-17 08:06:01 -08001232 void emitIAS(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001233 void dump(const Cfg *Func) const override;
1234 static bool classof(const Inst *Inst) { return isClassof(Inst, Strex); }
1235
1236private:
1237 InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1238 OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1239};
1240
Jan Voung6ec369e2015-06-30 11:03:15 -07001241class InstARM32Trap : public InstARM32 {
1242 InstARM32Trap() = delete;
1243 InstARM32Trap(const InstARM32Trap &) = delete;
1244 InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1245
1246public:
1247 static InstARM32Trap *create(Cfg *Func) {
1248 return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1249 }
1250 void emit(const Cfg *Func) const override;
Jan Voung6ec369e2015-06-30 11:03:15 -07001251 void dump(const Cfg *Func) const override;
1252 static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); }
1253
1254private:
1255 explicit InstARM32Trap(Cfg *Func);
1256};
1257
Andrew Scull9612d322015-07-06 14:53:25 -07001258/// Unsigned Multiply Long: d.lo, d.hi := x * y
Jan Voung3bfd99a2015-05-22 16:35:25 -07001259class InstARM32Umull : public InstARM32Pred {
Jan Voung29719972015-05-19 11:24:51 -07001260 InstARM32Umull() = delete;
1261 InstARM32Umull(const InstARM32Umull &) = delete;
1262 InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1263
1264public:
Andrew Scull9612d322015-07-06 14:53:25 -07001265 /// Everything must be a register.
Jan Voung29719972015-05-19 11:24:51 -07001266 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001267 Variable *Src0, Variable *Src1,
1268 CondARM32::Cond Predicate) {
Jan Voung29719972015-05-19 11:24:51 -07001269 return new (Func->allocate<InstARM32Umull>())
Jan Voung3bfd99a2015-05-22 16:35:25 -07001270 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
Jan Voung29719972015-05-19 11:24:51 -07001271 }
1272 void emit(const Cfg *Func) const override;
Karl Schimpf430e8442015-11-09 12:16:20 -08001273 void emitIAS(const Cfg *Func) const override;
Jan Voung29719972015-05-19 11:24:51 -07001274 void dump(const Cfg *Func) const override;
1275 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
1276
1277private:
1278 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -07001279 Variable *Src1, CondARM32::Cond Predicate);
John Porto1bec8bc2015-06-22 10:51:13 -07001280
Jan Voung29719972015-05-19 11:24:51 -07001281 Variable *DestHi;
1282};
1283
John Portoc31e2ed2015-09-11 05:17:08 -07001284/// Handles fp2int, int2fp, and fp2fp conversions.
1285class InstARM32Vcvt final : public InstARM32Pred {
1286 InstARM32Vcvt() = delete;
1287 InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1288 InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1289
1290public:
1291 enum VcvtVariant { S2si, S2ui, Si2s, Ui2s, D2si, D2ui, Si2d, Ui2d, S2d, D2s };
1292 static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1293 VcvtVariant Variant, CondARM32::Cond Predicate) {
1294 return new (Func->allocate<InstARM32Vcvt>())
1295 InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1296 }
1297 void emit(const Cfg *Func) const override;
Karl Schimpf6c7181c2016-01-08 07:31:08 -08001298 void emitIAS(const Cfg *Func) const override;
John Portoc31e2ed2015-09-11 05:17:08 -07001299 void dump(const Cfg *Func) const override;
1300 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
1301
1302private:
1303 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1304 CondARM32::Cond Predicate);
1305
1306 const VcvtVariant Variant;
1307};
1308
John Portof977f712015-09-14 16:28:33 -07001309/// Handles (some of) vmov's various formats.
John Portoba6a67c2015-09-25 15:19:45 -07001310class InstARM32Mov final : public InstARM32Pred {
1311 InstARM32Mov() = delete;
1312 InstARM32Mov(const InstARM32Mov &) = delete;
1313 InstARM32Mov &operator=(const InstARM32Mov &) = delete;
John Portof977f712015-09-14 16:28:33 -07001314
1315public:
John Portoba6a67c2015-09-25 15:19:45 -07001316 static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1317 CondARM32::Cond Predicate) {
1318 return new (Func->allocate<InstARM32Mov>())
1319 InstARM32Mov(Func, Dest, Src, Predicate);
John Portof977f712015-09-14 16:28:33 -07001320 }
1321 bool isRedundantAssign() const override {
John Portoba6a67c2015-09-25 15:19:45 -07001322 return !isMultiDest() && !isMultiSource() &&
John Porto7b3d9cb2015-11-11 14:26:57 -08001323 getPredicate() == CondARM32::AL &&
John Portof977f712015-09-14 16:28:33 -07001324 checkForRedundantAssign(getDest(), getSrc(0));
1325 }
Jim Stichnoth28b71be2015-10-12 15:24:46 -07001326 bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
John Portof977f712015-09-14 16:28:33 -07001327 void emit(const Cfg *Func) const override;
1328 void emitIAS(const Cfg *Func) const override;
1329 void dump(const Cfg *Func) const override;
John Portoba6a67c2015-09-25 15:19:45 -07001330 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
John Portof977f712015-09-14 16:28:33 -07001331
John Portoe0b829f2015-09-28 09:50:48 -07001332 bool isMultiDest() const { return DestHi != nullptr; }
John Portof977f712015-09-14 16:28:33 -07001333
1334 bool isMultiSource() const {
John Portoe0b829f2015-09-28 09:50:48 -07001335 assert(getSrcSize() == 1 || getSrcSize() == 2);
1336 return getSrcSize() == 2;
John Portoba6a67c2015-09-25 15:19:45 -07001337 }
1338
John Portoe0b829f2015-09-28 09:50:48 -07001339 Variable *getDestHi() const { return DestHi; }
1340
John Portoba6a67c2015-09-25 15:19:45 -07001341private:
1342 InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
John Portoe0b829f2015-09-28 09:50:48 -07001343 CondARM32::Cond Predicate);
John Portof977f712015-09-14 16:28:33 -07001344
1345 void emitMultiDestSingleSource(const Cfg *Func) const;
1346 void emitSingleDestMultiSource(const Cfg *Func) const;
1347 void emitSingleDestSingleSource(const Cfg *Func) const;
John Portoe0b829f2015-09-28 09:50:48 -07001348
Karl Schimpf85342a72015-10-13 09:49:31 -07001349 void emitIASSingleDestSingleSource(const Cfg *Func) const;
Karl Schimpfc64448f2016-01-26 11:12:29 -08001350 void emitIASScalarVFPMove(const Cfg *Func) const;
Karl Schimpf4ff90be2016-01-22 15:15:50 -08001351 void emitIASCoreVFPMove(const Cfg *Func) const;
Karl Schimpf85342a72015-10-13 09:49:31 -07001352
John Portoe0b829f2015-09-28 09:50:48 -07001353 Variable *DestHi = nullptr;
John Portof977f712015-09-14 16:28:33 -07001354};
1355
John Porto2f5534f2015-09-18 15:59:47 -07001356class InstARM32Vcmp final : public InstARM32Pred {
1357 InstARM32Vcmp() = delete;
1358 InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1359 InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1360
1361public:
1362 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1363 CondARM32::Cond Predicate) {
1364 return new (Func->allocate<InstARM32Vcmp>())
1365 InstARM32Vcmp(Func, Src0, Src1, Predicate);
1366 }
John Portoccea7932015-11-17 04:58:36 -08001367 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1368 OperandARM32FlexFpZero *Src1,
1369 CondARM32::Cond Predicate) {
1370 return new (Func->allocate<InstARM32Vcmp>())
1371 InstARM32Vcmp(Func, Src0, Src1, Predicate);
1372 }
John Porto2f5534f2015-09-18 15:59:47 -07001373 void emit(const Cfg *Func) const override;
Karl Schimpfcd5e07e2016-01-11 10:12:20 -08001374 void emitIAS(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001375 void dump(const Cfg *Func) const override;
1376 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); }
1377
1378private:
John Portoccea7932015-11-17 04:58:36 -08001379 InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
John Porto2f5534f2015-09-18 15:59:47 -07001380 CondARM32::Cond Predicate);
1381};
1382
1383/// Copies the FP Status and Control Register the core flags.
1384class InstARM32Vmrs final : public InstARM32Pred {
1385 InstARM32Vmrs() = delete;
1386 InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1387 InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1388
1389public:
1390 static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1391 return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1392 }
1393 void emit(const Cfg *Func) const override;
Karl Schimpfee718272016-01-25 09:17:26 -08001394 void emitIAS(const Cfg *Func) const override;
John Porto2f5534f2015-09-18 15:59:47 -07001395 void dump(const Cfg *Func) const override;
1396 static bool classof(const Inst *Inst) { return isClassof(Inst, Vmrs); }
1397
1398private:
1399 InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1400};
1401
John Portoba6a67c2015-09-25 15:19:45 -07001402class InstARM32Vabs final : public InstARM32Pred {
1403 InstARM32Vabs() = delete;
1404 InstARM32Vabs(const InstARM32Vabs &) = delete;
1405 InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1406
1407public:
1408 static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1409 CondARM32::Cond Predicate) {
1410 return new (Func->allocate<InstARM32Vabs>())
1411 InstARM32Vabs(Func, Dest, Src, Predicate);
1412 }
1413 void emit(const Cfg *Func) const override;
John Portoba6a67c2015-09-25 15:19:45 -07001414 void dump(const Cfg *Func) const override;
1415 static bool classof(const Inst *Inst) { return isClassof(Inst, Vabs); }
1416
1417private:
1418 InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1419 CondARM32::Cond Predicate);
1420};
John Porto16991842015-10-01 15:11:23 -07001421
1422class InstARM32Dmb final : public InstARM32Pred {
1423 InstARM32Dmb() = delete;
1424 InstARM32Dmb(const InstARM32Dmb &) = delete;
1425 InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1426
1427public:
1428 static InstARM32Dmb *create(Cfg *Func) {
1429 return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1430 }
1431 void emit(const Cfg *Func) const override;
Karl Schimpfd3f94f72015-12-09 07:35:00 -08001432 void emitIAS(const Cfg *Func) const override;
John Porto16991842015-10-01 15:11:23 -07001433 void dump(const Cfg *Func) const override;
1434 static bool classof(const Inst *Inst) { return isClassof(Inst, Dmb); }
1435
1436private:
1437 explicit InstARM32Dmb(Cfg *Func);
1438};
1439
Andrew Scull57e12682015-09-16 11:30:19 -07001440// Declare partial template specializations of emit() methods that already have
1441// default implementations. Without this, there is the possibility of ODR
1442// violations and link errors.
Jan Voungb3401d22015-05-18 09:38:21 -07001443
Jan Voung86ebec12015-08-09 07:58:35 -07001444template <> void InstARM32Ldr::emit(const Cfg *Func) const;
Jan Voungb3401d22015-05-18 09:38:21 -07001445template <> void InstARM32Movw::emit(const Cfg *Func) const;
1446template <> void InstARM32Movt::emit(const Cfg *Func) const;
1447
John Porto4a566862016-01-04 09:33:41 -08001448} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -07001449} // end of namespace Ice
1450
1451#endif // SUBZERO_SRC_ICEINSTARM32_H