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

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

Powered by Google App Engine
This is Rietveld 408576698