Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: src/IceInstARM32.h

Issue 1216963007: Doxygenize the documentation comments (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file declares the InstARM32 and OperandARM32 classes and 10 // This file declares the InstARM32 and OperandARM32 classes and
11 // their subclasses. This represents the machine instructions and 11 // their subclasses. This represents the machine instructions and
12 // operands used for ARM32 code selection. 12 // operands used for ARM32 code selection.
13 // 13 //
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #ifndef SUBZERO_SRC_ICEINSTARM32_H 16 #ifndef SUBZERO_SRC_ICEINSTARM32_H
17 #define SUBZERO_SRC_ICEINSTARM32_H 17 #define SUBZERO_SRC_ICEINSTARM32_H
18 18
19 #include "IceConditionCodesARM32.h" 19 #include "IceConditionCodesARM32.h"
20 #include "IceDefs.h" 20 #include "IceDefs.h"
21 #include "IceInst.h" 21 #include "IceInst.h"
22 #include "IceInstARM32.def" 22 #include "IceInstARM32.def"
23 #include "IceOperand.h" 23 #include "IceOperand.h"
24 24
25 namespace Ice { 25 namespace Ice {
26 26
27 class TargetARM32; 27 class TargetARM32;
28 28
29 // OperandARM32 extends the Operand hierarchy. Its subclasses are 29 /// OperandARM32 extends the Operand hierarchy. Its subclasses are
30 // OperandARM32Mem and OperandARM32Flex. 30 /// OperandARM32Mem and OperandARM32Flex.
31 class OperandARM32 : public Operand { 31 class OperandARM32 : public Operand {
32 OperandARM32() = delete; 32 OperandARM32() = delete;
33 OperandARM32(const OperandARM32 &) = delete; 33 OperandARM32(const OperandARM32 &) = delete;
34 OperandARM32 &operator=(const OperandARM32 &) = delete; 34 OperandARM32 &operator=(const OperandARM32 &) = delete;
35 35
36 public: 36 public:
37 enum OperandKindARM32 { 37 enum OperandKindARM32 {
38 k__Start = Operand::kTarget, 38 k__Start = Operand::kTarget,
39 kMem, 39 kMem,
40 kFlexStart, 40 kFlexStart,
(...skipping 13 matching lines...) Expand all
54 void dump(const Cfg *, Ostream &Str) const override { 54 void dump(const Cfg *, Ostream &Str) const override {
55 if (BuildDefs::dump()) 55 if (BuildDefs::dump())
56 Str << "<OperandARM32>"; 56 Str << "<OperandARM32>";
57 } 57 }
58 58
59 protected: 59 protected:
60 OperandARM32(OperandKindARM32 Kind, Type Ty) 60 OperandARM32(OperandKindARM32 Kind, Type Ty)
61 : Operand(static_cast<OperandKind>(Kind), Ty) {} 61 : Operand(static_cast<OperandKind>(Kind), Ty) {}
62 }; 62 };
63 63
64 // OperandARM32Mem represents a memory operand in any of the various ARM32 64 /// OperandARM32Mem represents a memory operand in any of the various ARM32
65 // addressing modes. 65 /// addressing modes.
66 class OperandARM32Mem : public OperandARM32 { 66 class OperandARM32Mem : public OperandARM32 {
67 OperandARM32Mem() = delete; 67 OperandARM32Mem() = delete;
68 OperandARM32Mem(const OperandARM32Mem &) = delete; 68 OperandARM32Mem(const OperandARM32Mem &) = delete;
69 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete; 69 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
70 70
71 public: 71 public:
72 // Memory operand addressing mode. 72 /// Memory operand addressing mode.
73 // The enum value also carries the encoding. 73 /// The enum value also carries the encoding.
74 // TODO(jvoung): unify with the assembler. 74 // TODO(jvoung): unify with the assembler.
75 enum AddrMode { 75 enum AddrMode {
76 // bit encoding P U W 76 // bit encoding P U W
77 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base) 77 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base)
78 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback 78 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback
79 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback 79 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback
80 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base) 80 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base)
81 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback 81 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
82 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback 82 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
83 }; 83 };
84 84
85 // Provide two constructors. 85 /// Provide two constructors.
86 // NOTE: The Variable-typed operands have to be registers. 86 /// NOTE: The Variable-typed operands have to be registers.
87 // 87 ///
88 // (1) Reg + Imm. The Immediate actually has a limited number of bits 88 /// (1) Reg + Imm. The Immediate actually has a limited number of bits
89 // for encoding, so check canHoldOffset first. It cannot handle 89 /// for encoding, so check canHoldOffset first. It cannot handle
90 // general Constant operands like ConstantRelocatable, since a relocatable 90 /// general Constant operands like ConstantRelocatable, since a relocatable
91 // can potentially take up too many bits. 91 /// can potentially take up too many bits.
92 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 92 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
93 ConstantInteger32 *ImmOffset, 93 ConstantInteger32 *ImmOffset,
94 AddrMode Mode = Offset) { 94 AddrMode Mode = Offset) {
95 return new (Func->allocate<OperandARM32Mem>()) 95 return new (Func->allocate<OperandARM32Mem>())
96 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode); 96 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
97 } 97 }
98 // (2) Reg +/- Reg with an optional shift of some kind and amount. 98 /// (2) Reg +/- Reg with an optional shift of some kind and amount.
99 // Note that this mode is disallowed in the NaCl sandbox. 99 /// Note that this mode is disallowed in the NaCl sandbox.
100 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 100 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
101 Variable *Index, ShiftKind ShiftOp = kNoShift, 101 Variable *Index, ShiftKind ShiftOp = kNoShift,
102 uint16_t ShiftAmt = 0, 102 uint16_t ShiftAmt = 0,
103 AddrMode Mode = Offset) { 103 AddrMode Mode = Offset) {
104 return new (Func->allocate<OperandARM32Mem>()) 104 return new (Func->allocate<OperandARM32Mem>())
105 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode); 105 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
106 } 106 }
107 Variable *getBase() const { return Base; } 107 Variable *getBase() const { return Base; }
108 ConstantInteger32 *getOffset() const { return ImmOffset; } 108 ConstantInteger32 *getOffset() const { return ImmOffset; }
109 Variable *getIndex() const { return Index; } 109 Variable *getIndex() const { return Index; }
(...skipping 12 matching lines...) Expand all
122 } 122 }
123 123
124 void emit(const Cfg *Func) const override; 124 void emit(const Cfg *Func) const override;
125 using OperandARM32::dump; 125 using OperandARM32::dump;
126 void dump(const Cfg *Func, Ostream &Str) const override; 126 void dump(const Cfg *Func, Ostream &Str) const override;
127 127
128 static bool classof(const Operand *Operand) { 128 static bool classof(const Operand *Operand) {
129 return Operand->getKind() == static_cast<OperandKind>(kMem); 129 return Operand->getKind() == static_cast<OperandKind>(kMem);
130 } 130 }
131 131
132 // Return true if a load/store instruction for an element of type Ty 132 /// Return true if a load/store instruction for an element of type Ty
133 // can encode the Offset directly in the immediate field of the 32-bit 133 /// can encode the Offset directly in the immediate field of the 32-bit
134 // ARM instruction. For some types, if the load is Sign extending, then 134 /// ARM instruction. For some types, if the load is Sign extending, then
135 // the range is reduced. 135 /// the range is reduced.
136 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); 136 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
137 137
138 private: 138 private:
139 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, 139 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
140 ConstantInteger32 *ImmOffset, AddrMode Mode); 140 ConstantInteger32 *ImmOffset, AddrMode Mode);
141 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, 141 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
142 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); 142 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
143 143
144 Variable *Base; 144 Variable *Base;
145 ConstantInteger32 *ImmOffset; 145 ConstantInteger32 *ImmOffset;
146 Variable *Index; 146 Variable *Index;
147 ShiftKind ShiftOp; 147 ShiftKind ShiftOp;
148 uint16_t ShiftAmt; 148 uint16_t ShiftAmt;
149 AddrMode Mode; 149 AddrMode Mode;
150 }; 150 };
151 151
152 // OperandARM32Flex represent the "flexible second operand" for 152 /// OperandARM32Flex represent the "flexible second operand" for
153 // data-processing instructions. It can be a rotatable 8-bit constant, or 153 /// data-processing instructions. It can be a rotatable 8-bit constant, or
154 // a register with an optional shift operand. The shift amount can even be 154 /// a register with an optional shift operand. The shift amount can even be
155 // a third register. 155 /// a third register.
156 class OperandARM32Flex : public OperandARM32 { 156 class OperandARM32Flex : public OperandARM32 {
157 OperandARM32Flex() = delete; 157 OperandARM32Flex() = delete;
158 OperandARM32Flex(const OperandARM32Flex &) = delete; 158 OperandARM32Flex(const OperandARM32Flex &) = delete;
159 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete; 159 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
160 160
161 public: 161 public:
162 static bool classof(const Operand *Operand) { 162 static bool classof(const Operand *Operand) {
163 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() && 163 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
164 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd); 164 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
165 } 165 }
166 166
167 protected: 167 protected:
168 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {} 168 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
169 }; 169 };
170 170
171 // Rotated immediate variant. 171 /// Rotated immediate variant.
172 class OperandARM32FlexImm : public OperandARM32Flex { 172 class OperandARM32FlexImm : public OperandARM32Flex {
173 OperandARM32FlexImm() = delete; 173 OperandARM32FlexImm() = delete;
174 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete; 174 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
175 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete; 175 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
176 176
177 public: 177 public:
178 // Immed_8 rotated by an even number of bits (2 * RotateAmt). 178 /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
179 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm, 179 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
180 uint32_t RotateAmt) { 180 uint32_t RotateAmt) {
181 return new (Func->allocate<OperandARM32FlexImm>()) 181 return new (Func->allocate<OperandARM32FlexImm>())
182 OperandARM32FlexImm(Func, Ty, Imm, RotateAmt); 182 OperandARM32FlexImm(Func, Ty, Imm, RotateAmt);
183 } 183 }
184 184
185 void emit(const Cfg *Func) const override; 185 void emit(const Cfg *Func) const override;
186 using OperandARM32::dump; 186 using OperandARM32::dump;
187 void dump(const Cfg *Func, Ostream &Str) const override; 187 void dump(const Cfg *Func, Ostream &Str) const override;
188 188
189 static bool classof(const Operand *Operand) { 189 static bool classof(const Operand *Operand) {
190 return Operand->getKind() == static_cast<OperandKind>(kFlexImm); 190 return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
191 } 191 }
192 192
193 // Return true if the Immediate can fit in the ARM flexible operand. 193 /// Return true if the Immediate can fit in the ARM flexible operand.
194 // Fills in the out-params RotateAmt and Immed_8 if Immediate fits. 194 /// Fills in the out-params RotateAmt and Immed_8 if Immediate fits.
195 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, 195 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
196 uint32_t *Immed_8); 196 uint32_t *Immed_8);
197 197
198 uint32_t getImm() const { return Imm; } 198 uint32_t getImm() const { return Imm; }
199 uint32_t getRotateAmt() const { return RotateAmt; } 199 uint32_t getRotateAmt() const { return RotateAmt; }
200 200
201 private: 201 private:
202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); 202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
203 203
204 uint32_t Imm; 204 uint32_t Imm;
205 uint32_t RotateAmt; 205 uint32_t RotateAmt;
206 }; 206 };
207 207
208 // Shifted register variant. 208 /// Shifted register variant.
209 class OperandARM32FlexReg : public OperandARM32Flex { 209 class OperandARM32FlexReg : public OperandARM32Flex {
210 OperandARM32FlexReg() = delete; 210 OperandARM32FlexReg() = delete;
211 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; 211 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
212 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; 212 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
213 213
214 public: 214 public:
215 // Register with immediate/reg shift amount and shift operation. 215 /// Register with immediate/reg shift amount and shift operation.
216 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg, 216 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
217 ShiftKind ShiftOp, Operand *ShiftAmt) { 217 ShiftKind ShiftOp, Operand *ShiftAmt) {
218 return new (Func->allocate<OperandARM32FlexReg>()) 218 return new (Func->allocate<OperandARM32FlexReg>())
219 OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt); 219 OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
220 } 220 }
221 221
222 void emit(const Cfg *Func) const override; 222 void emit(const Cfg *Func) const override;
223 using OperandARM32::dump; 223 using OperandARM32::dump;
224 void dump(const Cfg *Func, Ostream &Str) const override; 224 void dump(const Cfg *Func, Ostream &Str) const override;
225 225
226 static bool classof(const Operand *Operand) { 226 static bool classof(const Operand *Operand) {
227 return Operand->getKind() == static_cast<OperandKind>(kFlexReg); 227 return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
228 } 228 }
229 229
230 Variable *getReg() const { return Reg; } 230 Variable *getReg() const { return Reg; }
231 ShiftKind getShiftOp() const { return ShiftOp; } 231 ShiftKind getShiftOp() const { return ShiftOp; }
232 // ShiftAmt can represent an immediate or a register. 232 /// ShiftAmt can represent an immediate or a register.
233 Operand *getShiftAmt() const { return ShiftAmt; } 233 Operand *getShiftAmt() const { return ShiftAmt; }
234 234
235 private: 235 private:
236 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, 236 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
237 Operand *ShiftAmt); 237 Operand *ShiftAmt);
238 238
239 Variable *Reg; 239 Variable *Reg;
240 ShiftKind ShiftOp; 240 ShiftKind ShiftOp;
241 Operand *ShiftAmt; 241 Operand *ShiftAmt;
242 }; 242 };
243 243
244 // Base class for ARM instructions. While most ARM instructions can be 244 /// Base class for ARM instructions. While most ARM instructions can be
245 // conditionally executed, a few of them are not predicable (halt, 245 /// conditionally executed, a few of them are not predicable (halt,
246 // memory barriers, etc.). 246 /// memory barriers, etc.).
247 class InstARM32 : public InstTarget { 247 class InstARM32 : public InstTarget {
248 InstARM32() = delete; 248 InstARM32() = delete;
249 InstARM32(const InstARM32 &) = delete; 249 InstARM32(const InstARM32 &) = delete;
250 InstARM32 &operator=(const InstARM32 &) = delete; 250 InstARM32 &operator=(const InstARM32 &) = delete;
251 251
252 public: 252 public:
253 enum InstKindARM32 { 253 enum InstKindARM32 {
254 k__Start = Inst::Target, 254 k__Start = Inst::Target,
255 Adc, 255 Adc,
256 Add, 256 Add,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 291
292 protected: 292 protected:
293 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) 293 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
294 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 294 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
295 295
296 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { 296 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
297 return Inst->getKind() == static_cast<InstKind>(MyKind); 297 return Inst->getKind() == static_cast<InstKind>(MyKind);
298 } 298 }
299 }; 299 };
300 300
301 // A predicable ARM instruction. 301 /// A predicable ARM instruction.
302 class InstARM32Pred : public InstARM32 { 302 class InstARM32Pred : public InstARM32 {
303 InstARM32Pred() = delete; 303 InstARM32Pred() = delete;
304 InstARM32Pred(const InstARM32Pred &) = delete; 304 InstARM32Pred(const InstARM32Pred &) = delete;
305 InstARM32Pred &operator=(const InstARM32Pred &) = delete; 305 InstARM32Pred &operator=(const InstARM32Pred &) = delete;
306 306
307 public: 307 public:
308 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, 308 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
309 CondARM32::Cond Predicate) 309 CondARM32::Cond Predicate)
310 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} 310 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
311 311
312 CondARM32::Cond getPredicate() const { return Predicate; } 312 CondARM32::Cond getPredicate() const { return Predicate; }
313 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } 313 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
314 314
315 static const char *predString(CondARM32::Cond Predicate); 315 static const char *predString(CondARM32::Cond Predicate);
316 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; 316 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
317 317
318 // Shared emit routines for common forms of instructions. 318 /// Shared emit routines for common forms of instructions.
319 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst, 319 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
320 const Cfg *Func); 320 const Cfg *Func);
321 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, 321 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
322 const Cfg *Func); 322 const Cfg *Func);
323 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, 323 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
324 const Cfg *Func, bool SetFlags); 324 const Cfg *Func, bool SetFlags);
325 325
326 protected: 326 protected:
327 CondARM32::Cond Predicate; 327 CondARM32::Cond Predicate;
328 }; 328 };
329 329
330 template <typename StreamType> 330 template <typename StreamType>
331 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { 331 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
332 Stream << InstARM32Pred::predString(Predicate); 332 Stream << InstARM32Pred::predString(Predicate);
333 return Stream; 333 return Stream;
334 } 334 }
335 335
336 // Instructions of the form x := op(y). 336 /// Instructions of the form x := op(y).
337 template <InstARM32::InstKindARM32 K> 337 template <InstARM32::InstKindARM32 K>
338 class InstARM32UnaryopGPR : public InstARM32Pred { 338 class InstARM32UnaryopGPR : public InstARM32Pred {
339 InstARM32UnaryopGPR() = delete; 339 InstARM32UnaryopGPR() = delete;
340 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; 340 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
341 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; 341 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
342 342
343 public: 343 public:
344 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 344 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
345 CondARM32::Cond Predicate) { 345 CondARM32::Cond Predicate) {
346 return new (Func->allocate<InstARM32UnaryopGPR>()) 346 return new (Func->allocate<InstARM32UnaryopGPR>())
(...skipping 23 matching lines...) Expand all
370 private: 370 private:
371 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, 371 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
372 CondARM32::Cond Predicate) 372 CondARM32::Cond Predicate)
373 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 373 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
374 addSource(Src); 374 addSource(Src);
375 } 375 }
376 376
377 static const char *Opcode; 377 static const char *Opcode;
378 }; 378 };
379 379
380 // Instructions of the form x := x op y. 380 /// Instructions of the form x := x op y.
381 template <InstARM32::InstKindARM32 K> 381 template <InstARM32::InstKindARM32 K>
382 class InstARM32TwoAddrGPR : public InstARM32Pred { 382 class InstARM32TwoAddrGPR : public InstARM32Pred {
383 InstARM32TwoAddrGPR() = delete; 383 InstARM32TwoAddrGPR() = delete;
384 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; 384 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
385 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; 385 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
386 386
387 public: 387 public:
388 // Dest must be a register. 388 /// Dest must be a register.
389 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 389 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
390 CondARM32::Cond Predicate) { 390 CondARM32::Cond Predicate) {
391 return new (Func->allocate<InstARM32TwoAddrGPR>()) 391 return new (Func->allocate<InstARM32TwoAddrGPR>())
392 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); 392 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
393 } 393 }
394 void emit(const Cfg *Func) const override { 394 void emit(const Cfg *Func) const override {
395 if (!BuildDefs::dump()) 395 if (!BuildDefs::dump())
396 return; 396 return;
397 emitTwoAddr(Opcode, this, Func); 397 emitTwoAddr(Opcode, this, Func);
398 } 398 }
(...skipping 17 matching lines...) Expand all
416 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, 416 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
417 CondARM32::Cond Predicate) 417 CondARM32::Cond Predicate)
418 : InstARM32Pred(Func, K, 2, Dest, Predicate) { 418 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
419 addSource(Dest); 419 addSource(Dest);
420 addSource(Src); 420 addSource(Src);
421 } 421 }
422 422
423 static const char *Opcode; 423 static const char *Opcode;
424 }; 424 };
425 425
426 // Base class for assignment instructions. 426 /// Base class for assignment instructions.
427 // These can be tested for redundancy (and elided if redundant). 427 /// These can be tested for redundancy (and elided if redundant).
428 template <InstARM32::InstKindARM32 K> 428 template <InstARM32::InstKindARM32 K>
429 class InstARM32Movlike : public InstARM32Pred { 429 class InstARM32Movlike : public InstARM32Pred {
430 InstARM32Movlike() = delete; 430 InstARM32Movlike() = delete;
431 InstARM32Movlike(const InstARM32Movlike &) = delete; 431 InstARM32Movlike(const InstARM32Movlike &) = delete;
432 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; 432 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete;
433 433
434 public: 434 public:
435 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source, 435 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source,
436 CondARM32::Cond Predicate) { 436 CondARM32::Cond Predicate) {
437 return new (Func->allocate<InstARM32Movlike>()) 437 return new (Func->allocate<InstARM32Movlike>())
(...skipping 20 matching lines...) Expand all
458 private: 458 private:
459 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, 459 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source,
460 CondARM32::Cond Predicate) 460 CondARM32::Cond Predicate)
461 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 461 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
462 addSource(Source); 462 addSource(Source);
463 } 463 }
464 464
465 static const char *Opcode; 465 static const char *Opcode;
466 }; 466 };
467 467
468 // Instructions of the form x := y op z. May have the side-effect of setting 468 /// Instructions of the form x := y op z. May have the side-effect of setting
469 // status flags. 469 /// status flags.
470 template <InstARM32::InstKindARM32 K> 470 template <InstARM32::InstKindARM32 K>
471 class InstARM32ThreeAddrGPR : public InstARM32Pred { 471 class InstARM32ThreeAddrGPR : public InstARM32Pred {
472 InstARM32ThreeAddrGPR() = delete; 472 InstARM32ThreeAddrGPR() = delete;
473 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; 473 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
474 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; 474 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
475 475
476 public: 476 public:
477 // Create an ordinary binary-op instruction like add, and sub. 477 /// Create an ordinary binary-op instruction like add, and sub.
478 // Dest and Src1 must be registers. 478 /// Dest and Src1 must be registers.
479 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 479 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
480 Variable *Src1, Operand *Src2, 480 Variable *Src1, Operand *Src2,
481 CondARM32::Cond Predicate, 481 CondARM32::Cond Predicate,
482 bool SetFlags = false) { 482 bool SetFlags = false) {
483 return new (Func->allocate<InstARM32ThreeAddrGPR>()) 483 return new (Func->allocate<InstARM32ThreeAddrGPR>())
484 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, Predicate, SetFlags); 484 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, Predicate, SetFlags);
485 } 485 }
486 void emit(const Cfg *Func) const override { 486 void emit(const Cfg *Func) const override {
487 if (!BuildDefs::dump()) 487 if (!BuildDefs::dump())
488 return; 488 return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr; 522 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr;
523 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic; 523 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic;
524 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; 524 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor;
525 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; 525 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl;
526 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr; 526 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr;
527 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; 527 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul;
528 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; 528 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr;
529 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb; 529 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb;
530 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; 530 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc;
531 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; 531 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub;
532 // Move instruction (variable <- flex). This is more of a pseudo-inst. 532 /// Move instruction (variable <- flex). This is more of a pseudo-inst.
533 // If var is a register, then we use "mov". If var is stack, then we use 533 /// If var is a register, then we use "mov". If var is stack, then we use
534 // "str" to store to the stack. 534 /// "str" to store to the stack.
535 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; 535 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov;
536 // MovT leaves the bottom bits alone so dest is also a source. 536 /// MovT leaves the bottom bits alone so dest is also a source.
537 // This helps indicate that a previous MovW setting dest is not dead code. 537 /// This helps indicate that a previous MovW setting dest is not dead code.
538 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; 538 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt;
539 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; 539 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw;
540 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; 540 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn;
541 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation 541 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation
542 // operand as well (rotate source by 8, 16, 24 bits prior to extending), 542 // operand as well (rotate source by 8, 16, 24 bits prior to extending),
543 // but we aren't using that for now, so just model as a Unaryop. 543 // but we aren't using that for now, so just model as a Unaryop.
544 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt; 544 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt;
545 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt; 545 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt;
546 546
547 // Direct branch instruction. 547 /// Direct branch instruction.
548 class InstARM32Br : public InstARM32Pred { 548 class InstARM32Br : public InstARM32Pred {
549 InstARM32Br() = delete; 549 InstARM32Br() = delete;
550 InstARM32Br(const InstARM32Br &) = delete; 550 InstARM32Br(const InstARM32Br &) = delete;
551 InstARM32Br &operator=(const InstARM32Br &) = delete; 551 InstARM32Br &operator=(const InstARM32Br &) = delete;
552 552
553 public: 553 public:
554 // Create a conditional branch to one of two nodes. 554 /// Create a conditional branch to one of two nodes.
555 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, 555 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
556 CfgNode *TargetFalse, CondARM32::Cond Predicate) { 556 CfgNode *TargetFalse, CondARM32::Cond Predicate) {
557 assert(Predicate != CondARM32::AL); 557 assert(Predicate != CondARM32::AL);
558 return new (Func->allocate<InstARM32Br>()) 558 return new (Func->allocate<InstARM32Br>())
559 InstARM32Br(Func, TargetTrue, TargetFalse, Predicate); 559 InstARM32Br(Func, TargetTrue, TargetFalse, Predicate);
560 } 560 }
561 // Create an unconditional branch to a node. 561 /// Create an unconditional branch to a node.
562 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 562 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
563 const CfgNode *NoCondTarget = nullptr; 563 const CfgNode *NoCondTarget = nullptr;
564 return new (Func->allocate<InstARM32Br>()) 564 return new (Func->allocate<InstARM32Br>())
565 InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL); 565 InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL);
566 } 566 }
567 // Create a non-terminator conditional branch to a node, with a 567 /// Create a non-terminator conditional branch to a node, with a
568 // fallthrough to the next instruction in the current node. This is 568 /// fallthrough to the next instruction in the current node. This is
569 // used for switch lowering. 569 /// used for switch lowering.
570 static InstARM32Br *create(Cfg *Func, CfgNode *Target, 570 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
571 CondARM32::Cond Predicate) { 571 CondARM32::Cond Predicate) {
572 assert(Predicate != CondARM32::AL); 572 assert(Predicate != CondARM32::AL);
573 const CfgNode *NoUncondTarget = nullptr; 573 const CfgNode *NoUncondTarget = nullptr;
574 return new (Func->allocate<InstARM32Br>()) 574 return new (Func->allocate<InstARM32Br>())
575 InstARM32Br(Func, Target, NoUncondTarget, Predicate); 575 InstARM32Br(Func, Target, NoUncondTarget, Predicate);
576 } 576 }
577 const CfgNode *getTargetTrue() const { return TargetTrue; } 577 const CfgNode *getTargetTrue() const { return TargetTrue; }
578 const CfgNode *getTargetFalse() const { return TargetFalse; } 578 const CfgNode *getTargetFalse() const { return TargetFalse; }
579 bool optimizeBranch(const CfgNode *NextNode); 579 bool optimizeBranch(const CfgNode *NextNode);
(...skipping 15 matching lines...) Expand all
595 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } 595 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
596 596
597 private: 597 private:
598 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 598 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
599 CondARM32::Cond Predicate); 599 CondARM32::Cond Predicate);
600 600
601 const CfgNode *TargetTrue; 601 const CfgNode *TargetTrue;
602 const CfgNode *TargetFalse; 602 const CfgNode *TargetFalse;
603 }; 603 };
604 604
605 // AdjustStack instruction - subtracts SP by the given amount and 605 /// AdjustStack instruction - subtracts SP by the given amount and
606 // updates the stack offset during code emission. 606 /// updates the stack offset during code emission.
607 class InstARM32AdjustStack : public InstARM32 { 607 class InstARM32AdjustStack : public InstARM32 {
608 InstARM32AdjustStack() = delete; 608 InstARM32AdjustStack() = delete;
609 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; 609 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
610 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; 610 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
611 611
612 public: 612 public:
613 // Note: We need both Amount and SrcAmount. If Amount is too large then 613 /// Note: We need both Amount and SrcAmount. If Amount is too large then
614 // it needs to be copied to a register (so SrcAmount could be a register). 614 /// it needs to be copied to a register (so SrcAmount could be a register).
615 // However, we also need the numeric Amount for bookkeeping, and it's 615 /// However, we also need the numeric Amount for bookkeeping, and it's
616 // hard to pull that from the generic SrcAmount operand. 616 /// hard to pull that from the generic SrcAmount operand.
617 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount, 617 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
618 Operand *SrcAmount) { 618 Operand *SrcAmount) {
619 return new (Func->allocate<InstARM32AdjustStack>()) 619 return new (Func->allocate<InstARM32AdjustStack>())
620 InstARM32AdjustStack(Func, SP, Amount, SrcAmount); 620 InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
621 } 621 }
622 void emit(const Cfg *Func) const override; 622 void emit(const Cfg *Func) const override;
623 void emitIAS(const Cfg *Func) const override; 623 void emitIAS(const Cfg *Func) const override;
624 void dump(const Cfg *Func) const override; 624 void dump(const Cfg *Func) const override;
625 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } 625 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
626 626
627 private: 627 private:
628 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount, 628 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount,
629 Operand *SrcAmount); 629 Operand *SrcAmount);
630 const SizeT Amount; 630 const SizeT Amount;
631 }; 631 };
632 632
633 // Call instruction (bl/blx). Arguments should have already been pushed. 633 /// Call instruction (bl/blx). Arguments should have already been pushed.
634 // Technically bl and the register form of blx can be predicated, but we'll 634 /// Technically bl and the register form of blx can be predicated, but we'll
635 // leave that out until needed. 635 /// leave that out until needed.
636 class InstARM32Call : public InstARM32 { 636 class InstARM32Call : public InstARM32 {
637 InstARM32Call() = delete; 637 InstARM32Call() = delete;
638 InstARM32Call(const InstARM32Call &) = delete; 638 InstARM32Call(const InstARM32Call &) = delete;
639 InstARM32Call &operator=(const InstARM32Call &) = delete; 639 InstARM32Call &operator=(const InstARM32Call &) = delete;
640 640
641 public: 641 public:
642 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 642 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
643 return new (Func->allocate<InstARM32Call>()) 643 return new (Func->allocate<InstARM32Call>())
644 InstARM32Call(Func, Dest, CallTarget); 644 InstARM32Call(Func, Dest, CallTarget);
645 } 645 }
646 Operand *getCallTarget() const { return getSrc(0); } 646 Operand *getCallTarget() const { return getSrc(0); }
647 void emit(const Cfg *Func) const override; 647 void emit(const Cfg *Func) const override;
648 void emitIAS(const Cfg *Func) const override; 648 void emitIAS(const Cfg *Func) const override;
649 void dump(const Cfg *Func) const override; 649 void dump(const Cfg *Func) const override;
650 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } 650 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
651 651
652 private: 652 private:
653 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 653 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
654 }; 654 };
655 655
656 // Integer compare instruction. 656 /// Integer compare instruction.
657 class InstARM32Cmp : public InstARM32Pred { 657 class InstARM32Cmp : public InstARM32Pred {
658 InstARM32Cmp() = delete; 658 InstARM32Cmp() = delete;
659 InstARM32Cmp(const InstARM32Cmp &) = delete; 659 InstARM32Cmp(const InstARM32Cmp &) = delete;
660 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; 660 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete;
661 661
662 public: 662 public:
663 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, 663 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2,
664 CondARM32::Cond Predicate) { 664 CondARM32::Cond Predicate) {
665 return new (Func->allocate<InstARM32Cmp>()) 665 return new (Func->allocate<InstARM32Cmp>())
666 InstARM32Cmp(Func, Src1, Src2, Predicate); 666 InstARM32Cmp(Func, Src1, Src2, Predicate);
667 } 667 }
668 void emit(const Cfg *Func) const override; 668 void emit(const Cfg *Func) const override;
669 void emitIAS(const Cfg *Func) const override; 669 void emitIAS(const Cfg *Func) const override;
670 void dump(const Cfg *Func) const override; 670 void dump(const Cfg *Func) const override;
671 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } 671 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); }
672 672
673 private: 673 private:
674 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, 674 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2,
675 CondARM32::Cond Predicate); 675 CondARM32::Cond Predicate);
676 }; 676 };
677 677
678 // Load instruction. 678 /// Load instruction.
679 class InstARM32Ldr : public InstARM32Pred { 679 class InstARM32Ldr : public InstARM32Pred {
680 InstARM32Ldr() = delete; 680 InstARM32Ldr() = delete;
681 InstARM32Ldr(const InstARM32Ldr &) = delete; 681 InstARM32Ldr(const InstARM32Ldr &) = delete;
682 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; 682 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete;
683 683
684 public: 684 public:
685 // Dest must be a register. 685 /// Dest must be a register.
686 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, 686 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
687 CondARM32::Cond Predicate) { 687 CondARM32::Cond Predicate) {
688 return new (Func->allocate<InstARM32Ldr>()) 688 return new (Func->allocate<InstARM32Ldr>())
689 InstARM32Ldr(Func, Dest, Mem, Predicate); 689 InstARM32Ldr(Func, Dest, Mem, Predicate);
690 } 690 }
691 void emit(const Cfg *Func) const override; 691 void emit(const Cfg *Func) const override;
692 void emitIAS(const Cfg *Func) const override; 692 void emitIAS(const Cfg *Func) const override;
693 void dump(const Cfg *Func) const override; 693 void dump(const Cfg *Func) const override;
694 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } 694 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); }
695 695
696 private: 696 private:
697 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, 697 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
698 CondARM32::Cond Predicate); 698 CondARM32::Cond Predicate);
699 }; 699 };
700 700
701 // Multiply Accumulate: d := x * y + a 701 /// Multiply Accumulate: d := x * y + a
702 class InstARM32Mla : public InstARM32Pred { 702 class InstARM32Mla : public InstARM32Pred {
703 InstARM32Mla() = delete; 703 InstARM32Mla() = delete;
704 InstARM32Mla(const InstARM32Mla &) = delete; 704 InstARM32Mla(const InstARM32Mla &) = delete;
705 InstARM32Mla &operator=(const InstARM32Mla &) = delete; 705 InstARM32Mla &operator=(const InstARM32Mla &) = delete;
706 706
707 public: 707 public:
708 // Everything must be a register. 708 /// Everything must be a register.
709 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, 709 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0,
710 Variable *Src1, Variable *Acc, 710 Variable *Src1, Variable *Acc,
711 CondARM32::Cond Predicate) { 711 CondARM32::Cond Predicate) {
712 return new (Func->allocate<InstARM32Mla>()) 712 return new (Func->allocate<InstARM32Mla>())
713 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); 713 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate);
714 } 714 }
715 void emit(const Cfg *Func) const override; 715 void emit(const Cfg *Func) const override;
716 void emitIAS(const Cfg *Func) const override; 716 void emitIAS(const Cfg *Func) const override;
717 void dump(const Cfg *Func) const override; 717 void dump(const Cfg *Func) const override;
718 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } 718 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); }
719 719
720 private: 720 private:
721 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, 721 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1,
722 Variable *Acc, CondARM32::Cond Predicate); 722 Variable *Acc, CondARM32::Cond Predicate);
723 }; 723 };
724 724
725 // Pop into a list of GPRs. Technically this can be predicated, but we don't 725 /// Pop into a list of GPRs. Technically this can be predicated, but we don't
726 // need that functionality. 726 /// need that functionality.
727 class InstARM32Pop : public InstARM32 { 727 class InstARM32Pop : public InstARM32 {
728 InstARM32Pop() = delete; 728 InstARM32Pop() = delete;
729 InstARM32Pop(const InstARM32Pop &) = delete; 729 InstARM32Pop(const InstARM32Pop &) = delete;
730 InstARM32Pop &operator=(const InstARM32Pop &) = delete; 730 InstARM32Pop &operator=(const InstARM32Pop &) = delete;
731 731
732 public: 732 public:
733 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { 733 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
734 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); 734 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
735 } 735 }
736 void emit(const Cfg *Func) const override; 736 void emit(const Cfg *Func) const override;
737 void emitIAS(const Cfg *Func) const override; 737 void emitIAS(const Cfg *Func) const override;
738 void dump(const Cfg *Func) const override; 738 void dump(const Cfg *Func) const override;
739 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } 739 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
740 740
741 private: 741 private:
742 InstARM32Pop(Cfg *Func, const VarList &Dests); 742 InstARM32Pop(Cfg *Func, const VarList &Dests);
743 743
744 VarList Dests; 744 VarList Dests;
745 }; 745 };
746 746
747 // Push a list of GPRs. Technically this can be predicated, but we don't 747 /// Push a list of GPRs. Technically this can be predicated, but we don't
748 // need that functionality. 748 /// need that functionality.
749 class InstARM32Push : public InstARM32 { 749 class InstARM32Push : public InstARM32 {
750 InstARM32Push() = delete; 750 InstARM32Push() = delete;
751 InstARM32Push(const InstARM32Push &) = delete; 751 InstARM32Push(const InstARM32Push &) = delete;
752 InstARM32Push &operator=(const InstARM32Push &) = delete; 752 InstARM32Push &operator=(const InstARM32Push &) = delete;
753 753
754 public: 754 public:
755 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 755 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
756 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 756 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
757 } 757 }
758 void emit(const Cfg *Func) const override; 758 void emit(const Cfg *Func) const override;
759 void emitIAS(const Cfg *Func) const override; 759 void emitIAS(const Cfg *Func) const override;
760 void dump(const Cfg *Func) const override; 760 void dump(const Cfg *Func) const override;
761 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } 761 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
762 762
763 private: 763 private:
764 InstARM32Push(Cfg *Func, const VarList &Srcs); 764 InstARM32Push(Cfg *Func, const VarList &Srcs);
765 }; 765 };
766 766
767 // Ret pseudo-instruction. This is actually a "bx" instruction with 767 /// Ret pseudo-instruction. This is actually a "bx" instruction with
768 // an "lr" register operand, but epilogue lowering will search for a Ret 768 /// an "lr" register operand, but epilogue lowering will search for a Ret
769 // instead of a generic "bx". This instruction also takes a Source 769 /// instead of a generic "bx". This instruction also takes a Source
770 // operand (for non-void returning functions) for liveness analysis, though 770 /// operand (for non-void returning functions) for liveness analysis, though
771 // a FakeUse before the ret would do just as well. 771 /// a FakeUse before the ret would do just as well.
772 // 772 ///
773 // NOTE: Even though "bx" can be predicated, for now leave out the predication 773 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
774 // since it's not yet known to be useful for Ret. That may complicate finding 774 /// since it's not yet known to be useful for Ret. That may complicate finding
775 // the terminator instruction if it's not guaranteed to be executed. 775 /// the terminator instruction if it's not guaranteed to be executed.
776 class InstARM32Ret : public InstARM32 { 776 class InstARM32Ret : public InstARM32 {
777 InstARM32Ret() = delete; 777 InstARM32Ret() = delete;
778 InstARM32Ret(const InstARM32Ret &) = delete; 778 InstARM32Ret(const InstARM32Ret &) = delete;
779 InstARM32Ret &operator=(const InstARM32Ret &) = delete; 779 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
780 780
781 public: 781 public:
782 static InstARM32Ret *create(Cfg *Func, Variable *LR, 782 static InstARM32Ret *create(Cfg *Func, Variable *LR,
783 Variable *Source = nullptr) { 783 Variable *Source = nullptr) {
784 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 784 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
785 } 785 }
786 void emit(const Cfg *Func) const override; 786 void emit(const Cfg *Func) const override;
787 void emitIAS(const Cfg *Func) const override; 787 void emitIAS(const Cfg *Func) const override;
788 void dump(const Cfg *Func) const override; 788 void dump(const Cfg *Func) const override;
789 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } 789 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
790 790
791 private: 791 private:
792 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 792 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
793 }; 793 };
794 794
795 // Store instruction. It's important for liveness that there is no Dest 795 /// Store instruction. It's important for liveness that there is no Dest
796 // operand (OperandARM32Mem instead of Dest Variable). 796 /// operand (OperandARM32Mem instead of Dest Variable).
797 class InstARM32Str : public InstARM32Pred { 797 class InstARM32Str : public InstARM32Pred {
798 InstARM32Str() = delete; 798 InstARM32Str() = delete;
799 InstARM32Str(const InstARM32Str &) = delete; 799 InstARM32Str(const InstARM32Str &) = delete;
800 InstARM32Str &operator=(const InstARM32Str &) = delete; 800 InstARM32Str &operator=(const InstARM32Str &) = delete;
801 801
802 public: 802 public:
803 // Value must be a register. 803 /// Value must be a register.
804 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 804 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
805 CondARM32::Cond Predicate) { 805 CondARM32::Cond Predicate) {
806 return new (Func->allocate<InstARM32Str>()) 806 return new (Func->allocate<InstARM32Str>())
807 InstARM32Str(Func, Value, Mem, Predicate); 807 InstARM32Str(Func, Value, Mem, Predicate);
808 } 808 }
809 void emit(const Cfg *Func) const override; 809 void emit(const Cfg *Func) const override;
810 void emitIAS(const Cfg *Func) const override; 810 void emitIAS(const Cfg *Func) const override;
811 void dump(const Cfg *Func) const override; 811 void dump(const Cfg *Func) const override;
812 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } 812 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
813 813
814 private: 814 private:
815 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 815 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
816 CondARM32::Cond Predicate); 816 CondARM32::Cond Predicate);
817 }; 817 };
818 818
819 // Unsigned Multiply Long: d.lo, d.hi := x * y 819 /// Unsigned Multiply Long: d.lo, d.hi := x * y
820 class InstARM32Umull : public InstARM32Pred { 820 class InstARM32Umull : public InstARM32Pred {
821 InstARM32Umull() = delete; 821 InstARM32Umull() = delete;
822 InstARM32Umull(const InstARM32Umull &) = delete; 822 InstARM32Umull(const InstARM32Umull &) = delete;
823 InstARM32Umull &operator=(const InstARM32Umull &) = delete; 823 InstARM32Umull &operator=(const InstARM32Umull &) = delete;
824 824
825 public: 825 public:
826 // Everything must be a register. 826 /// Everything must be a register.
827 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, 827 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
828 Variable *Src0, Variable *Src1, 828 Variable *Src0, Variable *Src1,
829 CondARM32::Cond Predicate) { 829 CondARM32::Cond Predicate) {
830 return new (Func->allocate<InstARM32Umull>()) 830 return new (Func->allocate<InstARM32Umull>())
831 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); 831 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
832 } 832 }
833 void emit(const Cfg *Func) const override; 833 void emit(const Cfg *Func) const override;
834 void emitIAS(const Cfg *Func) const override; 834 void emitIAS(const Cfg *Func) const override;
835 void dump(const Cfg *Func) const override; 835 void dump(const Cfg *Func) const override;
836 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } 836 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
837 837
838 private: 838 private:
839 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, 839 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
840 Variable *Src1, CondARM32::Cond Predicate); 840 Variable *Src1, CondARM32::Cond Predicate);
841 841
842 Variable *DestHi; 842 Variable *DestHi;
843 }; 843 };
844 844
845 // Declare partial template specializations of emit() methods that 845 // Declare partial template specializations of emit() methods that
846 // already have default implementations. Without this, there is the 846 // already have default implementations. Without this, there is the
847 // possibility of ODR violations and link errors. 847 // possibility of ODR violations and link errors.
848 848
849 template <> void InstARM32Movw::emit(const Cfg *Func) const; 849 template <> void InstARM32Movw::emit(const Cfg *Func) const;
850 template <> void InstARM32Movt::emit(const Cfg *Func) const; 850 template <> void InstARM32Movt::emit(const Cfg *Func) const;
851 851
852 } // end of namespace Ice 852 } // end of namespace Ice
853 853
854 #endif // SUBZERO_SRC_ICEINSTARM32_H 854 #endif // SUBZERO_SRC_ICEINSTARM32_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698