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

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: Rebase to master 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
« no previous file with comments | « src/IceInst.cpp ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 298
298 protected: 299 protected:
299 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) 300 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
300 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 301 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
301 302
302 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { 303 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
303 return Inst->getKind() == static_cast<InstKind>(MyKind); 304 return Inst->getKind() == static_cast<InstKind>(MyKind);
304 } 305 }
305 }; 306 };
306 307
307 // A predicable ARM instruction. 308 /// A predicable ARM instruction.
308 class InstARM32Pred : public InstARM32 { 309 class InstARM32Pred : public InstARM32 {
309 InstARM32Pred() = delete; 310 InstARM32Pred() = delete;
310 InstARM32Pred(const InstARM32Pred &) = delete; 311 InstARM32Pred(const InstARM32Pred &) = delete;
311 InstARM32Pred &operator=(const InstARM32Pred &) = delete; 312 InstARM32Pred &operator=(const InstARM32Pred &) = delete;
312 313
313 public: 314 public:
314 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, 315 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
315 CondARM32::Cond Predicate) 316 CondARM32::Cond Predicate)
316 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} 317 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
317 318
318 CondARM32::Cond getPredicate() const { return Predicate; } 319 CondARM32::Cond getPredicate() const { return Predicate; }
319 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } 320 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
320 321
321 static const char *predString(CondARM32::Cond Predicate); 322 static const char *predString(CondARM32::Cond Predicate);
322 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; 323 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
323 324
324 // Shared emit routines for common forms of instructions. 325 /// Shared emit routines for common forms of instructions.
325 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst, 326 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst,
326 const Cfg *Func); 327 const Cfg *Func);
327 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, 328 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
328 const Cfg *Func); 329 const Cfg *Func);
329 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, 330 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
330 const Cfg *Func, bool SetFlags); 331 const Cfg *Func, bool SetFlags);
331 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst, 332 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
332 const Cfg *Func); 333 const Cfg *Func);
333 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Inst, 334 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Inst,
334 const Cfg *Func); 335 const Cfg *Func);
335 336
336 protected: 337 protected:
337 CondARM32::Cond Predicate; 338 CondARM32::Cond Predicate;
338 }; 339 };
339 340
340 template <typename StreamType> 341 template <typename StreamType>
341 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { 342 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
342 Stream << InstARM32Pred::predString(Predicate); 343 Stream << InstARM32Pred::predString(Predicate);
343 return Stream; 344 return Stream;
344 } 345 }
345 346
346 // Instructions of the form x := op(y). 347 /// Instructions of the form x := op(y).
347 template <InstARM32::InstKindARM32 K> 348 template <InstARM32::InstKindARM32 K>
348 class InstARM32UnaryopGPR : public InstARM32Pred { 349 class InstARM32UnaryopGPR : public InstARM32Pred {
349 InstARM32UnaryopGPR() = delete; 350 InstARM32UnaryopGPR() = delete;
350 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; 351 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
351 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; 352 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
352 353
353 public: 354 public:
354 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 355 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
355 CondARM32::Cond Predicate) { 356 CondARM32::Cond Predicate) {
356 return new (Func->allocate<InstARM32UnaryopGPR>()) 357 return new (Func->allocate<InstARM32UnaryopGPR>())
(...skipping 23 matching lines...) Expand all
380 private: 381 private:
381 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, 382 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
382 CondARM32::Cond Predicate) 383 CondARM32::Cond Predicate)
383 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 384 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
384 addSource(Src); 385 addSource(Src);
385 } 386 }
386 387
387 static const char *Opcode; 388 static const char *Opcode;
388 }; 389 };
389 390
390 // Instructions of the form x := x op y. 391 /// Instructions of the form x := x op y.
391 template <InstARM32::InstKindARM32 K> 392 template <InstARM32::InstKindARM32 K>
392 class InstARM32TwoAddrGPR : public InstARM32Pred { 393 class InstARM32TwoAddrGPR : public InstARM32Pred {
393 InstARM32TwoAddrGPR() = delete; 394 InstARM32TwoAddrGPR() = delete;
394 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; 395 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
395 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; 396 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
396 397
397 public: 398 public:
398 // Dest must be a register. 399 /// Dest must be a register.
399 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 400 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
400 CondARM32::Cond Predicate) { 401 CondARM32::Cond Predicate) {
401 return new (Func->allocate<InstARM32TwoAddrGPR>()) 402 return new (Func->allocate<InstARM32TwoAddrGPR>())
402 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); 403 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
403 } 404 }
404 void emit(const Cfg *Func) const override { 405 void emit(const Cfg *Func) const override {
405 if (!BuildDefs::dump()) 406 if (!BuildDefs::dump())
406 return; 407 return;
407 emitTwoAddr(Opcode, this, Func); 408 emitTwoAddr(Opcode, this, Func);
408 } 409 }
(...skipping 17 matching lines...) Expand all
426 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, 427 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
427 CondARM32::Cond Predicate) 428 CondARM32::Cond Predicate)
428 : InstARM32Pred(Func, K, 2, Dest, Predicate) { 429 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
429 addSource(Dest); 430 addSource(Dest);
430 addSource(Src); 431 addSource(Src);
431 } 432 }
432 433
433 static const char *Opcode; 434 static const char *Opcode;
434 }; 435 };
435 436
436 // Base class for assignment instructions. 437 /// Base class for assignment instructions.
437 // These can be tested for redundancy (and elided if redundant). 438 /// These can be tested for redundancy (and elided if redundant).
438 template <InstARM32::InstKindARM32 K> 439 template <InstARM32::InstKindARM32 K>
439 class InstARM32Movlike : public InstARM32Pred { 440 class InstARM32Movlike : public InstARM32Pred {
440 InstARM32Movlike() = delete; 441 InstARM32Movlike() = delete;
441 InstARM32Movlike(const InstARM32Movlike &) = delete; 442 InstARM32Movlike(const InstARM32Movlike &) = delete;
442 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; 443 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete;
443 444
444 public: 445 public:
445 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source, 446 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source,
446 CondARM32::Cond Predicate) { 447 CondARM32::Cond Predicate) {
447 return new (Func->allocate<InstARM32Movlike>()) 448 return new (Func->allocate<InstARM32Movlike>())
(...skipping 20 matching lines...) Expand all
468 private: 469 private:
469 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, 470 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source,
470 CondARM32::Cond Predicate) 471 CondARM32::Cond Predicate)
471 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 472 : InstARM32Pred(Func, K, 1, Dest, Predicate) {
472 addSource(Source); 473 addSource(Source);
473 } 474 }
474 475
475 static const char *Opcode; 476 static const char *Opcode;
476 }; 477 };
477 478
478 // Instructions of the form x := y op z. May have the side-effect of setting 479 /// Instructions of the form x := y op z. May have the side-effect of setting
479 // status flags. 480 /// status flags.
480 template <InstARM32::InstKindARM32 K> 481 template <InstARM32::InstKindARM32 K>
481 class InstARM32ThreeAddrGPR : public InstARM32Pred { 482 class InstARM32ThreeAddrGPR : public InstARM32Pred {
482 InstARM32ThreeAddrGPR() = delete; 483 InstARM32ThreeAddrGPR() = delete;
483 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; 484 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
484 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; 485 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
485 486
486 public: 487 public:
487 // Create an ordinary binary-op instruction like add, and sub. 488 /// Create an ordinary binary-op instruction like add, and sub.
488 // Dest and Src1 must be registers. 489 /// Dest and Src1 must be registers.
489 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 490 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
490 Variable *Src0, Operand *Src1, 491 Variable *Src0, Operand *Src1,
491 CondARM32::Cond Predicate, 492 CondARM32::Cond Predicate,
492 bool SetFlags = false) { 493 bool SetFlags = false) {
493 return new (Func->allocate<InstARM32ThreeAddrGPR>()) 494 return new (Func->allocate<InstARM32ThreeAddrGPR>())
494 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags); 495 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
495 } 496 }
496 void emit(const Cfg *Func) const override { 497 void emit(const Cfg *Func) const override {
497 if (!BuildDefs::dump()) 498 if (!BuildDefs::dump())
498 return; 499 return;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; 627 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor;
627 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; 628 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl;
628 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr; 629 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr;
629 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; 630 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul;
630 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; 631 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr;
631 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb; 632 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb;
632 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; 633 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc;
633 typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv; 634 typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv;
634 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; 635 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub;
635 typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv; 636 typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv;
636 // Move instruction (variable <- flex). This is more of a pseudo-inst. 637 /// Move instruction (variable <- flex). This is more of a pseudo-inst.
637 // If var is a register, then we use "mov". If var is stack, then we use 638 /// If var is a register, then we use "mov". If var is stack, then we use
638 // "str" to store to the stack. 639 /// "str" to store to the stack.
639 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; 640 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov;
640 // MovT leaves the bottom bits alone so dest is also a source. 641 /// MovT leaves the bottom bits alone so dest is also a source.
641 // This helps indicate that a previous MovW setting dest is not dead code. 642 /// This helps indicate that a previous MovW setting dest is not dead code.
642 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; 643 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt;
643 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; 644 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw;
644 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; 645 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn;
645 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation 646 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation
646 // operand as well (rotate source by 8, 16, 24 bits prior to extending), 647 // operand as well (rotate source by 8, 16, 24 bits prior to extending),
647 // but we aren't using that for now, so just model as a Unaryop. 648 // but we aren't using that for now, so just model as a Unaryop.
648 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt; 649 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt;
649 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt; 650 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt;
650 typedef InstARM32FourAddrGPR<InstARM32::Mla> InstARM32Mla; 651 typedef InstARM32FourAddrGPR<InstARM32::Mla> InstARM32Mla;
651 typedef InstARM32FourAddrGPR<InstARM32::Mls> InstARM32Mls; 652 typedef InstARM32FourAddrGPR<InstARM32::Mls> InstARM32Mls;
(...skipping 18 matching lines...) Expand all
670 void emit(const Cfg *Func) const override; 671 void emit(const Cfg *Func) const override;
671 void emitIAS(const Cfg *Func) const override; 672 void emitIAS(const Cfg *Func) const override;
672 void dump(const Cfg *Func) const override; 673 void dump(const Cfg *Func) const override;
673 674
674 private: 675 private:
675 InstARM32Label(Cfg *Func, TargetARM32 *Target); 676 InstARM32Label(Cfg *Func, TargetARM32 *Target);
676 677
677 SizeT Number; // used for unique label generation. 678 SizeT Number; // used for unique label generation.
678 }; 679 };
679 680
680 // Direct branch instruction. 681 /// Direct branch instruction.
681 class InstARM32Br : public InstARM32Pred { 682 class InstARM32Br : public InstARM32Pred {
682 InstARM32Br() = delete; 683 InstARM32Br() = delete;
683 InstARM32Br(const InstARM32Br &) = delete; 684 InstARM32Br(const InstARM32Br &) = delete;
684 InstARM32Br &operator=(const InstARM32Br &) = delete; 685 InstARM32Br &operator=(const InstARM32Br &) = delete;
685 686
686 public: 687 public:
687 // Create a conditional branch to one of two nodes. 688 /// Create a conditional branch to one of two nodes.
688 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, 689 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
689 CfgNode *TargetFalse, CondARM32::Cond Predicate) { 690 CfgNode *TargetFalse, CondARM32::Cond Predicate) {
690 assert(Predicate != CondARM32::AL); 691 assert(Predicate != CondARM32::AL);
691 constexpr InstARM32Label *NoLabel = nullptr; 692 constexpr InstARM32Label *NoLabel = nullptr;
692 return new (Func->allocate<InstARM32Br>()) 693 return new (Func->allocate<InstARM32Br>())
693 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); 694 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
694 } 695 }
695 // Create an unconditional branch to a node. 696 /// Create an unconditional branch to a node.
696 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 697 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
697 constexpr CfgNode *NoCondTarget = nullptr; 698 constexpr CfgNode *NoCondTarget = nullptr;
698 constexpr InstARM32Label *NoLabel = nullptr; 699 constexpr InstARM32Label *NoLabel = nullptr;
699 return new (Func->allocate<InstARM32Br>()) 700 return new (Func->allocate<InstARM32Br>())
700 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); 701 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
701 } 702 }
702 // Create a non-terminator conditional branch to a node, with a 703 /// Create a non-terminator conditional branch to a node, with a
703 // fallthrough to the next instruction in the current node. This is 704 /// fallthrough to the next instruction in the current node. This is
704 // used for switch lowering. 705 /// used for switch lowering.
705 static InstARM32Br *create(Cfg *Func, CfgNode *Target, 706 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
706 CondARM32::Cond Predicate) { 707 CondARM32::Cond Predicate) {
707 assert(Predicate != CondARM32::AL); 708 assert(Predicate != CondARM32::AL);
708 constexpr CfgNode *NoUncondTarget = nullptr; 709 constexpr CfgNode *NoUncondTarget = nullptr;
709 constexpr InstARM32Label *NoLabel = nullptr; 710 constexpr InstARM32Label *NoLabel = nullptr;
710 return new (Func->allocate<InstARM32Br>()) 711 return new (Func->allocate<InstARM32Br>())
711 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); 712 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
712 } 713 }
713 // Create a conditional intra-block branch (or unconditional, if 714 // Create a conditional intra-block branch (or unconditional, if
714 // Condition==AL) to a label in the current block. 715 // Condition==AL) to a label in the current block.
(...skipping 28 matching lines...) Expand all
743 744
744 private: 745 private:
745 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 746 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
746 const InstARM32Label *Label, CondARM32::Cond Predicate); 747 const InstARM32Label *Label, CondARM32::Cond Predicate);
747 748
748 const CfgNode *TargetTrue; 749 const CfgNode *TargetTrue;
749 const CfgNode *TargetFalse; 750 const CfgNode *TargetFalse;
750 const InstARM32Label *Label; // Intra-block branch target 751 const InstARM32Label *Label; // Intra-block branch target
751 }; 752 };
752 753
753 // AdjustStack instruction - subtracts SP by the given amount and 754 /// AdjustStack instruction - subtracts SP by the given amount and
754 // updates the stack offset during code emission. 755 /// updates the stack offset during code emission.
755 class InstARM32AdjustStack : public InstARM32 { 756 class InstARM32AdjustStack : public InstARM32 {
756 InstARM32AdjustStack() = delete; 757 InstARM32AdjustStack() = delete;
757 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; 758 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
758 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; 759 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
759 760
760 public: 761 public:
761 // Note: We need both Amount and SrcAmount. If Amount is too large then 762 /// Note: We need both Amount and SrcAmount. If Amount is too large then
762 // it needs to be copied to a register (so SrcAmount could be a register). 763 /// it needs to be copied to a register (so SrcAmount could be a register).
763 // However, we also need the numeric Amount for bookkeeping, and it's 764 /// However, we also need the numeric Amount for bookkeeping, and it's
764 // hard to pull that from the generic SrcAmount operand. 765 /// hard to pull that from the generic SrcAmount operand.
765 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount, 766 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
766 Operand *SrcAmount) { 767 Operand *SrcAmount) {
767 return new (Func->allocate<InstARM32AdjustStack>()) 768 return new (Func->allocate<InstARM32AdjustStack>())
768 InstARM32AdjustStack(Func, SP, Amount, SrcAmount); 769 InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
769 } 770 }
770 void emit(const Cfg *Func) const override; 771 void emit(const Cfg *Func) const override;
771 void emitIAS(const Cfg *Func) const override; 772 void emitIAS(const Cfg *Func) const override;
772 void dump(const Cfg *Func) const override; 773 void dump(const Cfg *Func) const override;
773 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } 774 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
774 775
775 private: 776 private:
776 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount, 777 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount,
777 Operand *SrcAmount); 778 Operand *SrcAmount);
778 const SizeT Amount; 779 const SizeT Amount;
779 }; 780 };
780 781
781 // Call instruction (bl/blx). Arguments should have already been pushed. 782 /// Call instruction (bl/blx). Arguments should have already been pushed.
782 // Technically bl and the register form of blx can be predicated, but we'll 783 /// Technically bl and the register form of blx can be predicated, but we'll
783 // leave that out until needed. 784 /// leave that out until needed.
784 class InstARM32Call : public InstARM32 { 785 class InstARM32Call : public InstARM32 {
785 InstARM32Call() = delete; 786 InstARM32Call() = delete;
786 InstARM32Call(const InstARM32Call &) = delete; 787 InstARM32Call(const InstARM32Call &) = delete;
787 InstARM32Call &operator=(const InstARM32Call &) = delete; 788 InstARM32Call &operator=(const InstARM32Call &) = delete;
788 789
789 public: 790 public:
790 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 791 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
791 return new (Func->allocate<InstARM32Call>()) 792 return new (Func->allocate<InstARM32Call>())
792 InstARM32Call(Func, Dest, CallTarget); 793 InstARM32Call(Func, Dest, CallTarget);
793 } 794 }
794 Operand *getCallTarget() const { return getSrc(0); } 795 Operand *getCallTarget() const { return getSrc(0); }
795 void emit(const Cfg *Func) const override; 796 void emit(const Cfg *Func) const override;
796 void emitIAS(const Cfg *Func) const override; 797 void emitIAS(const Cfg *Func) const override;
797 void dump(const Cfg *Func) const override; 798 void dump(const Cfg *Func) const override;
798 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } 799 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
799 800
800 private: 801 private:
801 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 802 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
802 }; 803 };
803 804
804 // Load instruction. 805 /// Load instruction.
805 class InstARM32Ldr : public InstARM32Pred { 806 class InstARM32Ldr : public InstARM32Pred {
806 InstARM32Ldr() = delete; 807 InstARM32Ldr() = delete;
807 InstARM32Ldr(const InstARM32Ldr &) = delete; 808 InstARM32Ldr(const InstARM32Ldr &) = delete;
808 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; 809 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete;
809 810
810 public: 811 public:
811 // Dest must be a register. 812 /// Dest must be a register.
812 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, 813 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
813 CondARM32::Cond Predicate) { 814 CondARM32::Cond Predicate) {
814 return new (Func->allocate<InstARM32Ldr>()) 815 return new (Func->allocate<InstARM32Ldr>())
815 InstARM32Ldr(Func, Dest, Mem, Predicate); 816 InstARM32Ldr(Func, Dest, Mem, Predicate);
816 } 817 }
817 void emit(const Cfg *Func) const override; 818 void emit(const Cfg *Func) const override;
818 void emitIAS(const Cfg *Func) const override; 819 void emitIAS(const Cfg *Func) const override;
819 void dump(const Cfg *Func) const override; 820 void dump(const Cfg *Func) const override;
820 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } 821 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); }
821 822
822 private: 823 private:
823 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, 824 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem,
824 CondARM32::Cond Predicate); 825 CondARM32::Cond Predicate);
825 }; 826 };
826 827
827 // Pop into a list of GPRs. Technically this can be predicated, but we don't 828 /// Pop into a list of GPRs. Technically this can be predicated, but we don't
828 // need that functionality. 829 /// need that functionality.
829 class InstARM32Pop : public InstARM32 { 830 class InstARM32Pop : public InstARM32 {
830 InstARM32Pop() = delete; 831 InstARM32Pop() = delete;
831 InstARM32Pop(const InstARM32Pop &) = delete; 832 InstARM32Pop(const InstARM32Pop &) = delete;
832 InstARM32Pop &operator=(const InstARM32Pop &) = delete; 833 InstARM32Pop &operator=(const InstARM32Pop &) = delete;
833 834
834 public: 835 public:
835 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { 836 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
836 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); 837 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
837 } 838 }
838 void emit(const Cfg *Func) const override; 839 void emit(const Cfg *Func) const override;
839 void emitIAS(const Cfg *Func) const override; 840 void emitIAS(const Cfg *Func) const override;
840 void dump(const Cfg *Func) const override; 841 void dump(const Cfg *Func) const override;
841 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } 842 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
842 843
843 private: 844 private:
844 InstARM32Pop(Cfg *Func, const VarList &Dests); 845 InstARM32Pop(Cfg *Func, const VarList &Dests);
845 846
846 VarList Dests; 847 VarList Dests;
847 }; 848 };
848 849
849 // Push a list of GPRs. Technically this can be predicated, but we don't 850 /// Push a list of GPRs. Technically this can be predicated, but we don't
850 // need that functionality. 851 /// need that functionality.
851 class InstARM32Push : public InstARM32 { 852 class InstARM32Push : public InstARM32 {
852 InstARM32Push() = delete; 853 InstARM32Push() = delete;
853 InstARM32Push(const InstARM32Push &) = delete; 854 InstARM32Push(const InstARM32Push &) = delete;
854 InstARM32Push &operator=(const InstARM32Push &) = delete; 855 InstARM32Push &operator=(const InstARM32Push &) = delete;
855 856
856 public: 857 public:
857 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 858 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
858 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 859 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
859 } 860 }
860 void emit(const Cfg *Func) const override; 861 void emit(const Cfg *Func) const override;
861 void emitIAS(const Cfg *Func) const override; 862 void emitIAS(const Cfg *Func) const override;
862 void dump(const Cfg *Func) const override; 863 void dump(const Cfg *Func) const override;
863 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } 864 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
864 865
865 private: 866 private:
866 InstARM32Push(Cfg *Func, const VarList &Srcs); 867 InstARM32Push(Cfg *Func, const VarList &Srcs);
867 }; 868 };
868 869
869 // Ret pseudo-instruction. This is actually a "bx" instruction with 870 /// Ret pseudo-instruction. This is actually a "bx" instruction with
870 // an "lr" register operand, but epilogue lowering will search for a Ret 871 /// an "lr" register operand, but epilogue lowering will search for a Ret
871 // instead of a generic "bx". This instruction also takes a Source 872 /// instead of a generic "bx". This instruction also takes a Source
872 // operand (for non-void returning functions) for liveness analysis, though 873 /// operand (for non-void returning functions) for liveness analysis, though
873 // a FakeUse before the ret would do just as well. 874 /// a FakeUse before the ret would do just as well.
874 // 875 ///
875 // NOTE: Even though "bx" can be predicated, for now leave out the predication 876 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
876 // since it's not yet known to be useful for Ret. That may complicate finding 877 /// since it's not yet known to be useful for Ret. That may complicate finding
877 // the terminator instruction if it's not guaranteed to be executed. 878 /// the terminator instruction if it's not guaranteed to be executed.
878 class InstARM32Ret : public InstARM32 { 879 class InstARM32Ret : public InstARM32 {
879 InstARM32Ret() = delete; 880 InstARM32Ret() = delete;
880 InstARM32Ret(const InstARM32Ret &) = delete; 881 InstARM32Ret(const InstARM32Ret &) = delete;
881 InstARM32Ret &operator=(const InstARM32Ret &) = delete; 882 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
882 883
883 public: 884 public:
884 static InstARM32Ret *create(Cfg *Func, Variable *LR, 885 static InstARM32Ret *create(Cfg *Func, Variable *LR,
885 Variable *Source = nullptr) { 886 Variable *Source = nullptr) {
886 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 887 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
887 } 888 }
888 void emit(const Cfg *Func) const override; 889 void emit(const Cfg *Func) const override;
889 void emitIAS(const Cfg *Func) const override; 890 void emitIAS(const Cfg *Func) const override;
890 void dump(const Cfg *Func) const override; 891 void dump(const Cfg *Func) const override;
891 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } 892 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
892 893
893 private: 894 private:
894 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 895 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
895 }; 896 };
896 897
897 // Store instruction. It's important for liveness that there is no Dest 898 /// Store instruction. It's important for liveness that there is no Dest
898 // operand (OperandARM32Mem instead of Dest Variable). 899 /// operand (OperandARM32Mem instead of Dest Variable).
899 class InstARM32Str : public InstARM32Pred { 900 class InstARM32Str : public InstARM32Pred {
900 InstARM32Str() = delete; 901 InstARM32Str() = delete;
901 InstARM32Str(const InstARM32Str &) = delete; 902 InstARM32Str(const InstARM32Str &) = delete;
902 InstARM32Str &operator=(const InstARM32Str &) = delete; 903 InstARM32Str &operator=(const InstARM32Str &) = delete;
903 904
904 public: 905 public:
905 // Value must be a register. 906 /// Value must be a register.
906 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 907 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
907 CondARM32::Cond Predicate) { 908 CondARM32::Cond Predicate) {
908 return new (Func->allocate<InstARM32Str>()) 909 return new (Func->allocate<InstARM32Str>())
909 InstARM32Str(Func, Value, Mem, Predicate); 910 InstARM32Str(Func, Value, Mem, Predicate);
910 } 911 }
911 void emit(const Cfg *Func) const override; 912 void emit(const Cfg *Func) const override;
912 void emitIAS(const Cfg *Func) const override; 913 void emitIAS(const Cfg *Func) const override;
913 void dump(const Cfg *Func) const override; 914 void dump(const Cfg *Func) const override;
914 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } 915 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
915 916
(...skipping 13 matching lines...) Expand all
929 } 930 }
930 void emit(const Cfg *Func) const override; 931 void emit(const Cfg *Func) const override;
931 void emitIAS(const Cfg *Func) const override; 932 void emitIAS(const Cfg *Func) const override;
932 void dump(const Cfg *Func) const override; 933 void dump(const Cfg *Func) const override;
933 static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); } 934 static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); }
934 935
935 private: 936 private:
936 explicit InstARM32Trap(Cfg *Func); 937 explicit InstARM32Trap(Cfg *Func);
937 }; 938 };
938 939
939 // Unsigned Multiply Long: d.lo, d.hi := x * y 940 /// Unsigned Multiply Long: d.lo, d.hi := x * y
940 class InstARM32Umull : public InstARM32Pred { 941 class InstARM32Umull : public InstARM32Pred {
941 InstARM32Umull() = delete; 942 InstARM32Umull() = delete;
942 InstARM32Umull(const InstARM32Umull &) = delete; 943 InstARM32Umull(const InstARM32Umull &) = delete;
943 InstARM32Umull &operator=(const InstARM32Umull &) = delete; 944 InstARM32Umull &operator=(const InstARM32Umull &) = delete;
944 945
945 public: 946 public:
946 // Everything must be a register. 947 /// Everything must be a register.
947 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, 948 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
948 Variable *Src0, Variable *Src1, 949 Variable *Src0, Variable *Src1,
949 CondARM32::Cond Predicate) { 950 CondARM32::Cond Predicate) {
950 return new (Func->allocate<InstARM32Umull>()) 951 return new (Func->allocate<InstARM32Umull>())
951 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); 952 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
952 } 953 }
953 void emit(const Cfg *Func) const override; 954 void emit(const Cfg *Func) const override;
954 void emitIAS(const Cfg *Func) const override; 955 void emitIAS(const Cfg *Func) const override;
955 void dump(const Cfg *Func) const override; 956 void dump(const Cfg *Func) const override;
956 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } 957 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
957 958
958 private: 959 private:
959 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, 960 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
960 Variable *Src1, CondARM32::Cond Predicate); 961 Variable *Src1, CondARM32::Cond Predicate);
961 962
962 Variable *DestHi; 963 Variable *DestHi;
963 }; 964 };
964 965
965 // Declare partial template specializations of emit() methods that 966 // Declare partial template specializations of emit() methods that
966 // already have default implementations. Without this, there is the 967 // already have default implementations. Without this, there is the
967 // possibility of ODR violations and link errors. 968 // possibility of ODR violations and link errors.
968 969
969 template <> void InstARM32Movw::emit(const Cfg *Func) const; 970 template <> void InstARM32Movw::emit(const Cfg *Func) const;
970 template <> void InstARM32Movt::emit(const Cfg *Func) const; 971 template <> void InstARM32Movt::emit(const Cfg *Func) const;
971 972
972 } // end of namespace Ice 973 } // end of namespace Ice
973 974
974 #endif // SUBZERO_SRC_ICEINSTARM32_H 975 #endif // SUBZERO_SRC_ICEINSTARM32_H
OLDNEW
« no previous file with comments | « src/IceInst.cpp ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698