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

Side by Side Diff: src/IceInstARM32.h

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 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.def ('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 /// \file 10 /// \file
11 /// This file declares the InstARM32 and OperandARM32 classes and 11 /// This file declares the InstARM32 and OperandARM32 classes and their
12 /// their subclasses. This represents the machine instructions and 12 /// subclasses. This represents the machine instructions and operands used for
13 /// operands used for ARM32 code selection. 13 /// ARM32 code selection.
14 /// 14 ///
15 //===----------------------------------------------------------------------===// 15 //===----------------------------------------------------------------------===//
16 16
17 #ifndef SUBZERO_SRC_ICEINSTARM32_H 17 #ifndef SUBZERO_SRC_ICEINSTARM32_H
18 #define SUBZERO_SRC_ICEINSTARM32_H 18 #define SUBZERO_SRC_ICEINSTARM32_H
19 19
20 #include "IceConditionCodesARM32.h" 20 #include "IceConditionCodesARM32.h"
21 #include "IceDefs.h" 21 #include "IceDefs.h"
22 #include "IceInst.h" 22 #include "IceInst.h"
23 #include "IceInstARM32.def" 23 #include "IceInstARM32.def"
24 #include "IceOperand.h" 24 #include "IceOperand.h"
25 25
26 namespace Ice { 26 namespace Ice {
27 27
28 class TargetARM32; 28 class TargetARM32;
29 29
30 /// OperandARM32 extends the Operand hierarchy. Its subclasses are 30 /// OperandARM32 extends the Operand hierarchy. Its subclasses are
31 /// OperandARM32Mem and OperandARM32Flex. 31 /// OperandARM32Mem and OperandARM32Flex.
32 class OperandARM32 : public Operand { 32 class OperandARM32 : public Operand {
33 OperandARM32() = delete; 33 OperandARM32() = delete;
34 OperandARM32(const OperandARM32 &) = delete; 34 OperandARM32(const OperandARM32 &) = delete;
35 OperandARM32 &operator=(const OperandARM32 &) = delete; 35 OperandARM32 &operator=(const OperandARM32 &) = delete;
36 36
37 public: 37 public:
38 enum OperandKindARM32 { 38 enum OperandKindARM32 {
39 k__Start = Operand::kTarget, 39 k__Start = Operand::kTarget,
40 kMem, 40 kMem,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback 80 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback
81 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)
82 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback 82 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
83 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback 83 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
84 }; 84 };
85 85
86 /// Provide two constructors. 86 /// Provide two constructors.
87 /// NOTE: The Variable-typed operands have to be registers. 87 /// NOTE: The Variable-typed operands have to be registers.
88 /// 88 ///
89 /// (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
90 /// for encoding, so check canHoldOffset first. It cannot handle 90 /// for encoding, so check canHoldOffset first. It cannot handle general
91 /// general Constant operands like ConstantRelocatable, since a relocatable 91 /// Constant operands like ConstantRelocatable, since a relocatable can
92 /// can potentially take up too many bits. 92 /// potentially take up too many bits.
93 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 93 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
94 ConstantInteger32 *ImmOffset, 94 ConstantInteger32 *ImmOffset,
95 AddrMode Mode = Offset) { 95 AddrMode Mode = Offset) {
96 return new (Func->allocate<OperandARM32Mem>()) 96 return new (Func->allocate<OperandARM32Mem>())
97 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode); 97 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
98 } 98 }
99 /// (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. Note that
100 /// Note that this mode is disallowed in the NaCl sandbox. 100 /// this mode is disallowed in the NaCl sandbox.
101 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 101 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
102 Variable *Index, ShiftKind ShiftOp = kNoShift, 102 Variable *Index, ShiftKind ShiftOp = kNoShift,
103 uint16_t ShiftAmt = 0, 103 uint16_t ShiftAmt = 0,
104 AddrMode Mode = Offset) { 104 AddrMode Mode = Offset) {
105 return new (Func->allocate<OperandARM32Mem>()) 105 return new (Func->allocate<OperandARM32Mem>())
106 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode); 106 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
107 } 107 }
108 Variable *getBase() const { return Base; } 108 Variable *getBase() const { return Base; }
109 ConstantInteger32 *getOffset() const { return ImmOffset; } 109 ConstantInteger32 *getOffset() const { return ImmOffset; }
110 Variable *getIndex() const { return Index; } 110 Variable *getIndex() const { return Index; }
(...skipping 12 matching lines...) Expand all
123 } 123 }
124 124
125 void emit(const Cfg *Func) const override; 125 void emit(const Cfg *Func) const override;
126 using OperandARM32::dump; 126 using OperandARM32::dump;
127 void dump(const Cfg *Func, Ostream &Str) const override; 127 void dump(const Cfg *Func, Ostream &Str) const override;
128 128
129 static bool classof(const Operand *Operand) { 129 static bool classof(const Operand *Operand) {
130 return Operand->getKind() == static_cast<OperandKind>(kMem); 130 return Operand->getKind() == static_cast<OperandKind>(kMem);
131 } 131 }
132 132
133 /// 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 can
134 /// can encode the Offset directly in the immediate field of the 32-bit 134 /// encode the Offset directly in the immediate field of the 32-bit ARM
135 /// ARM instruction. For some types, if the load is Sign extending, then 135 /// instruction. For some types, if the load is Sign extending, then the range
136 /// the range is reduced. 136 /// is reduced.
137 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); 137 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
138 138
139 private: 139 private:
140 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, 140 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
141 ConstantInteger32 *ImmOffset, AddrMode Mode); 141 ConstantInteger32 *ImmOffset, AddrMode Mode);
142 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, 142 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
143 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); 143 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
144 144
145 Variable *Base; 145 Variable *Base;
146 ConstantInteger32 *ImmOffset; 146 ConstantInteger32 *ImmOffset;
147 Variable *Index; 147 Variable *Index;
148 ShiftKind ShiftOp; 148 ShiftKind ShiftOp;
149 uint16_t ShiftAmt; 149 uint16_t ShiftAmt;
150 AddrMode Mode; 150 AddrMode Mode;
151 }; 151 };
152 152
153 /// OperandARM32Flex represent the "flexible second operand" for 153 /// OperandARM32Flex represent the "flexible second operand" for data-processing
154 /// data-processing instructions. It can be a rotatable 8-bit constant, or 154 /// instructions. It can be a rotatable 8-bit constant, or a register with an
155 /// a register with an optional shift operand. The shift amount can even be 155 /// optional shift operand. The shift amount can even be a third register.
156 /// a third register.
157 class OperandARM32Flex : public OperandARM32 { 156 class OperandARM32Flex : public OperandARM32 {
158 OperandARM32Flex() = delete; 157 OperandARM32Flex() = delete;
159 OperandARM32Flex(const OperandARM32Flex &) = delete; 158 OperandARM32Flex(const OperandARM32Flex &) = delete;
160 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete; 159 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
161 160
162 public: 161 public:
163 static bool classof(const Operand *Operand) { 162 static bool classof(const Operand *Operand) {
164 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() && 163 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
165 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd); 164 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
166 } 165 }
(...skipping 17 matching lines...) Expand all
184 } 183 }
185 184
186 void emit(const Cfg *Func) const override; 185 void emit(const Cfg *Func) const override;
187 using OperandARM32::dump; 186 using OperandARM32::dump;
188 void dump(const Cfg *Func, Ostream &Str) const override; 187 void dump(const Cfg *Func, Ostream &Str) const override;
189 188
190 static bool classof(const Operand *Operand) { 189 static bool classof(const Operand *Operand) {
191 return Operand->getKind() == static_cast<OperandKind>(kFlexImm); 190 return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
192 } 191 }
193 192
194 /// Return true if the Immediate can fit in the ARM flexible operand. 193 /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
195 /// Fills in the out-params RotateAmt and Immed_8 if Immediate fits. 194 /// the out-params RotateAmt and Immed_8 if Immediate fits.
196 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, 195 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
197 uint32_t *Immed_8); 196 uint32_t *Immed_8);
198 197
199 uint32_t getImm() const { return Imm; } 198 uint32_t getImm() const { return Imm; }
200 uint32_t getRotateAmt() const { return RotateAmt; } 199 uint32_t getRotateAmt() const { return RotateAmt; }
201 200
202 private: 201 private:
203 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); 202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
204 203
205 uint32_t Imm; 204 uint32_t Imm;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, 236 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
238 Operand *ShiftAmt); 237 Operand *ShiftAmt);
239 238
240 Variable *Reg; 239 Variable *Reg;
241 ShiftKind ShiftOp; 240 ShiftKind ShiftOp;
242 Operand *ShiftAmt; 241 Operand *ShiftAmt;
243 }; 242 };
244 243
245 /// StackVariable represents a Var that isn't assigned a register (stack-only). 244 /// StackVariable represents a Var that isn't assigned a register (stack-only).
246 /// It is assigned a stack slot, but the slot's offset may be too large to 245 /// It is assigned a stack slot, but the slot's offset may be too large to
247 /// represent in the native addressing mode, and so it has a separate 246 /// represent in the native addressing mode, and so it has a separate base
248 /// base register from SP/FP, where the offset from that base register is 247 /// register from SP/FP, where the offset from that base register is then in
249 /// then in range. 248 /// range.
250 class StackVariable final : public Variable { 249 class StackVariable final : public Variable {
251 StackVariable() = delete; 250 StackVariable() = delete;
252 StackVariable(const StackVariable &) = delete; 251 StackVariable(const StackVariable &) = delete;
253 StackVariable &operator=(const StackVariable &) = delete; 252 StackVariable &operator=(const StackVariable &) = delete;
254 253
255 public: 254 public:
256 static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) { 255 static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
257 return new (Func->allocate<StackVariable>()) StackVariable(Ty, Index); 256 return new (Func->allocate<StackVariable>()) StackVariable(Ty, Index);
258 } 257 }
259 const static OperandKind StackVariableKind = 258 const static OperandKind StackVariableKind =
260 static_cast<OperandKind>(kVariable_Target); 259 static_cast<OperandKind>(kVariable_Target);
261 static bool classof(const Operand *Operand) { 260 static bool classof(const Operand *Operand) {
262 return Operand->getKind() == StackVariableKind; 261 return Operand->getKind() == StackVariableKind;
263 } 262 }
264 void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; } 263 void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
265 int32_t getBaseRegNum() const override { return BaseRegNum; } 264 int32_t getBaseRegNum() const override { return BaseRegNum; }
266 // Inherit dump() and emit() from Variable. 265 // Inherit dump() and emit() from Variable.
267 266
268 private: 267 private:
269 StackVariable(Type Ty, SizeT Index) 268 StackVariable(Type Ty, SizeT Index)
270 : Variable(StackVariableKind, Ty, Index) {} 269 : Variable(StackVariableKind, Ty, Index) {}
271 int32_t BaseRegNum = Variable::NoRegister; 270 int32_t BaseRegNum = Variable::NoRegister;
272 }; 271 };
273 272
274 /// Base class for ARM instructions. While most ARM instructions can be 273 /// Base class for ARM instructions. While most ARM instructions can be
275 /// conditionally executed, a few of them are not predicable (halt, 274 /// conditionally executed, a few of them are not predicable (halt, memory
276 /// memory barriers, etc.). 275 /// barriers, etc.).
277 class InstARM32 : public InstTarget { 276 class InstARM32 : public InstTarget {
278 InstARM32() = delete; 277 InstARM32() = delete;
279 InstARM32(const InstARM32 &) = delete; 278 InstARM32(const InstARM32 &) = delete;
280 InstARM32 &operator=(const InstARM32 &) = delete; 279 InstARM32 &operator=(const InstARM32 &) = delete;
281 280
282 public: 281 public:
283 enum InstKindARM32 { 282 enum InstKindARM32 {
284 k__Start = Inst::Target, 283 k__Start = Inst::Target,
285 Adc, 284 Adc,
286 Add, 285 Add,
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, 517 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
519 CondARM32::Cond Predicate) 518 CondARM32::Cond Predicate)
520 : InstARM32Pred(Func, K, 2, Dest, Predicate) { 519 : InstARM32Pred(Func, K, 2, Dest, Predicate) {
521 addSource(Dest); 520 addSource(Dest);
522 addSource(Src); 521 addSource(Src);
523 } 522 }
524 523
525 static const char *Opcode; 524 static const char *Opcode;
526 }; 525 };
527 526
528 /// Base class for assignment instructions. 527 /// Base class for assignment instructions. These can be tested for redundancy
529 /// These can be tested for redundancy (and elided if redundant). 528 /// (and elided if redundant).
530 template <InstARM32::InstKindARM32 K> 529 template <InstARM32::InstKindARM32 K>
531 class InstARM32Movlike : public InstARM32Pred { 530 class InstARM32Movlike : public InstARM32Pred {
532 InstARM32Movlike() = delete; 531 InstARM32Movlike() = delete;
533 InstARM32Movlike(const InstARM32Movlike &) = delete; 532 InstARM32Movlike(const InstARM32Movlike &) = delete;
534 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; 533 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete;
535 534
536 public: 535 public:
537 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source, 536 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source,
538 CondARM32::Cond Predicate) { 537 CondARM32::Cond Predicate) {
539 return new (Func->allocate<InstARM32Movlike>()) 538 return new (Func->allocate<InstARM32Movlike>())
(...skipping 29 matching lines...) Expand all
569 568
570 /// Instructions of the form x := y op z. May have the side-effect of setting 569 /// Instructions of the form x := y op z. May have the side-effect of setting
571 /// status flags. 570 /// status flags.
572 template <InstARM32::InstKindARM32 K> 571 template <InstARM32::InstKindARM32 K>
573 class InstARM32ThreeAddrGPR : public InstARM32Pred { 572 class InstARM32ThreeAddrGPR : public InstARM32Pred {
574 InstARM32ThreeAddrGPR() = delete; 573 InstARM32ThreeAddrGPR() = delete;
575 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; 574 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
576 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; 575 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
577 576
578 public: 577 public:
579 /// Create an ordinary binary-op instruction like add, and sub. 578 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
580 /// Dest and Src1 must be registers. 579 /// must be registers.
581 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 580 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
582 Variable *Src0, Operand *Src1, 581 Variable *Src0, Operand *Src1,
583 CondARM32::Cond Predicate, 582 CondARM32::Cond Predicate,
584 bool SetFlags = false) { 583 bool SetFlags = false) {
585 return new (Func->allocate<InstARM32ThreeAddrGPR>()) 584 return new (Func->allocate<InstARM32ThreeAddrGPR>())
586 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags); 585 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
587 } 586 }
588 void emit(const Cfg *Func) const override { 587 void emit(const Cfg *Func) const override {
589 if (!BuildDefs::dump()) 588 if (!BuildDefs::dump())
590 return; 589 return;
(...skipping 20 matching lines...) Expand all
611 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) 610 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
612 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { 611 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
613 addSource(Src0); 612 addSource(Src0);
614 addSource(Src1); 613 addSource(Src1);
615 } 614 }
616 615
617 static const char *Opcode; 616 static const char *Opcode;
618 bool SetFlags; 617 bool SetFlags;
619 }; 618 };
620 619
621 /// Instructions of the form x := y op z, for vector/FP. We leave these as 620 /// Instructions of the form x := y op z, for vector/FP. We leave these as
622 /// unconditional: "ARM deprecates the conditional execution of any instruction 621 /// unconditional: "ARM deprecates the conditional execution of any instruction
623 /// encoding provided by the Advanced SIMD Extension that is not also provided 622 /// encoding provided by the Advanced SIMD Extension that is not also provided
624 /// by the Floating-point (VFP) extension". They do not set flags. 623 /// by the Floating-point (VFP) extension". They do not set flags.
625 template <InstARM32::InstKindARM32 K> 624 template <InstARM32::InstKindARM32 K>
626 class InstARM32ThreeAddrFP : public InstARM32 { 625 class InstARM32ThreeAddrFP : public InstARM32 {
627 InstARM32ThreeAddrFP() = delete; 626 InstARM32ThreeAddrFP() = delete;
628 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete; 627 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
629 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete; 628 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
630 629
631 public: 630 public:
632 /// Create a vector/FP binary-op instruction like vadd, and vsub. 631 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
633 /// Everything must be a register. 632 /// must be a register.
634 static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0, 633 static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
635 Variable *Src1) { 634 Variable *Src1) {
636 return new (Func->allocate<InstARM32ThreeAddrFP>()) 635 return new (Func->allocate<InstARM32ThreeAddrFP>())
637 InstARM32ThreeAddrFP(Func, Dest, Src0, Src1); 636 InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
638 } 637 }
639 void emit(const Cfg *Func) const override { 638 void emit(const Cfg *Func) const override {
640 if (!BuildDefs::dump()) 639 if (!BuildDefs::dump())
641 return; 640 return;
642 emitThreeAddrFP(Opcode, this, Func); 641 emitThreeAddrFP(Opcode, this, Func);
643 } 642 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>; 771 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
773 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>; 772 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
774 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>; 773 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
775 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>; 774 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
776 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>; 775 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
777 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>; 776 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
778 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>; 777 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
779 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>; 778 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
780 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>; 779 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
781 using InstARM32Ldr = InstARM32Movlike<InstARM32::Ldr>; 780 using InstARM32Ldr = InstARM32Movlike<InstARM32::Ldr>;
782 /// Move instruction (variable <- flex). This is more of a pseudo-inst. 781 /// Move instruction (variable <- flex). This is more of a pseudo-inst. If var
783 /// If var is a register, then we use "mov". If var is stack, then we use 782 /// is a register, then we use "mov". If var is stack, then we use "str" to
784 /// "str" to store to the stack. 783 /// store to the stack.
785 using InstARM32Mov = InstARM32Movlike<InstARM32::Mov>; 784 using InstARM32Mov = InstARM32Movlike<InstARM32::Mov>;
786 /// Represents various vector mov instruction forms (simple single source, 785 /// Represents various vector mov instruction forms (simple single source,
787 /// single dest forms only, not the 2 GPR <-> 1 D reg forms, etc.). 786 /// single dest forms only, not the 2 GPR <-> 1 D reg forms, etc.).
788 using InstARM32Vldr = InstARM32Movlike<InstARM32::Vldr>; 787 using InstARM32Vldr = InstARM32Movlike<InstARM32::Vldr>;
789 /// MovT leaves the bottom bits alone so dest is also a source. 788 /// MovT leaves the bottom bits alone so dest is also a source. This helps
790 /// This helps indicate that a previous MovW setting dest is not dead code. 789 /// indicate that a previous MovW setting dest is not dead code.
791 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; 790 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
792 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; 791 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
793 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; 792 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
794 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; 793 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
795 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; 794 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
796 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; 795 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
797 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation 796 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
798 // operand as well (rotate source by 8, 16, 24 bits prior to extending), 797 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
799 // but we aren't using that for now, so just model as a Unaryop. 798 // using that for now, so just model as a Unaryop.
800 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; 799 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
801 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; 800 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
802 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; 801 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
803 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; 802 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
804 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; 803 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
805 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; 804 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
806 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; 805 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
807 806
808 // InstARM32Label represents an intra-block label that is the target 807 // InstARM32Label represents an intra-block label that is the target of an
809 // of an intra-block branch. The offset between the label and the 808 // intra-block branch. The offset between the label and the branch must be fit
810 // branch must be fit in the instruction immediate (considered "near"). 809 // in the instruction immediate (considered "near").
811 class InstARM32Label : public InstARM32 { 810 class InstARM32Label : public InstARM32 {
812 InstARM32Label() = delete; 811 InstARM32Label() = delete;
813 InstARM32Label(const InstARM32Label &) = delete; 812 InstARM32Label(const InstARM32Label &) = delete;
814 InstARM32Label &operator=(const InstARM32Label &) = delete; 813 InstARM32Label &operator=(const InstARM32Label &) = delete;
815 814
816 public: 815 public:
817 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) { 816 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
818 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target); 817 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
819 } 818 }
820 uint32_t getEmitInstCount() const override { return 0; } 819 uint32_t getEmitInstCount() const override { return 0; }
(...skipping 24 matching lines...) Expand all
845 return new (Func->allocate<InstARM32Br>()) 844 return new (Func->allocate<InstARM32Br>())
846 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); 845 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
847 } 846 }
848 /// Create an unconditional branch to a node. 847 /// Create an unconditional branch to a node.
849 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 848 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
850 constexpr CfgNode *NoCondTarget = nullptr; 849 constexpr CfgNode *NoCondTarget = nullptr;
851 constexpr InstARM32Label *NoLabel = nullptr; 850 constexpr InstARM32Label *NoLabel = nullptr;
852 return new (Func->allocate<InstARM32Br>()) 851 return new (Func->allocate<InstARM32Br>())
853 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); 852 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
854 } 853 }
855 /// Create a non-terminator conditional branch to a node, with a 854 /// Create a non-terminator conditional branch to a node, with a fallthrough
856 /// fallthrough to the next instruction in the current node. This is 855 /// to the next instruction in the current node. This is used for switch
857 /// used for switch lowering. 856 /// lowering.
858 static InstARM32Br *create(Cfg *Func, CfgNode *Target, 857 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
859 CondARM32::Cond Predicate) { 858 CondARM32::Cond Predicate) {
860 assert(Predicate != CondARM32::AL); 859 assert(Predicate != CondARM32::AL);
861 constexpr CfgNode *NoUncondTarget = nullptr; 860 constexpr CfgNode *NoUncondTarget = nullptr;
862 constexpr InstARM32Label *NoLabel = nullptr; 861 constexpr InstARM32Label *NoLabel = nullptr;
863 return new (Func->allocate<InstARM32Br>()) 862 return new (Func->allocate<InstARM32Br>())
864 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); 863 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
865 } 864 }
866 // Create a conditional intra-block branch (or unconditional, if 865 // Create a conditional intra-block branch (or unconditional, if
867 // Condition==AL) to a label in the current block. 866 // Condition==AL) to a label in the current block.
(...skipping 28 matching lines...) Expand all
896 895
897 private: 896 private:
898 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 897 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
899 const InstARM32Label *Label, CondARM32::Cond Predicate); 898 const InstARM32Label *Label, CondARM32::Cond Predicate);
900 899
901 const CfgNode *TargetTrue; 900 const CfgNode *TargetTrue;
902 const CfgNode *TargetFalse; 901 const CfgNode *TargetFalse;
903 const InstARM32Label *Label; // Intra-block branch target 902 const InstARM32Label *Label; // Intra-block branch target
904 }; 903 };
905 904
906 /// AdjustStack instruction - subtracts SP by the given amount and 905 /// AdjustStack instruction - subtracts SP by the given amount and updates the
907 /// updates the stack offset during code emission. 906 /// stack offset during code emission.
908 class InstARM32AdjustStack : public InstARM32 { 907 class InstARM32AdjustStack : public InstARM32 {
909 InstARM32AdjustStack() = delete; 908 InstARM32AdjustStack() = delete;
910 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; 909 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
911 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; 910 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
912 911
913 public: 912 public:
914 /// Note: We need both Amount and SrcAmount. If Amount is too large then 913 /// Note: We need both Amount and SrcAmount. If Amount is too large then it
915 /// it needs to be copied to a register (so SrcAmount could be a register). 914 /// needs to be copied to a register (so SrcAmount could be a register).
916 /// However, we also need the numeric Amount for bookkeeping, and it's 915 /// However, we also need the numeric Amount for bookkeeping, and it's hard to
917 /// hard to pull that from the generic SrcAmount operand. 916 /// pull that from the generic SrcAmount operand.
918 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount, 917 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
919 Operand *SrcAmount) { 918 Operand *SrcAmount) {
920 return new (Func->allocate<InstARM32AdjustStack>()) 919 return new (Func->allocate<InstARM32AdjustStack>())
921 InstARM32AdjustStack(Func, SP, Amount, SrcAmount); 920 InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
922 } 921 }
923 void emit(const Cfg *Func) const override; 922 void emit(const Cfg *Func) const override;
924 void emitIAS(const Cfg *Func) const override; 923 void emitIAS(const Cfg *Func) const override;
925 void dump(const Cfg *Func) const override; 924 void dump(const Cfg *Func) const override;
926 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } 925 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
927 SizeT getAmount() const { return Amount; } 926 SizeT getAmount() const { return Amount; }
928 927
929 private: 928 private:
930 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount, 929 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount,
931 Operand *SrcAmount); 930 Operand *SrcAmount);
932 const SizeT Amount; 931 const SizeT Amount;
933 }; 932 };
934 933
935 /// Call instruction (bl/blx). Arguments should have already been pushed. 934 /// Call instruction (bl/blx). Arguments should have already been pushed.
936 /// Technically bl and the register form of blx can be predicated, but we'll 935 /// Technically bl and the register form of blx can be predicated, but we'll
937 /// leave that out until needed. 936 /// leave that out until needed.
938 class InstARM32Call : public InstARM32 { 937 class InstARM32Call : public InstARM32 {
939 InstARM32Call() = delete; 938 InstARM32Call() = delete;
940 InstARM32Call(const InstARM32Call &) = delete; 939 InstARM32Call(const InstARM32Call &) = delete;
941 InstARM32Call &operator=(const InstARM32Call &) = delete; 940 InstARM32Call &operator=(const InstARM32Call &) = delete;
942 941
943 public: 942 public:
944 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 943 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
945 return new (Func->allocate<InstARM32Call>()) 944 return new (Func->allocate<InstARM32Call>())
(...skipping 24 matching lines...) Expand all
970 void emitIAS(const Cfg *Func) const override; 969 void emitIAS(const Cfg *Func) const override;
971 void dump(const Cfg *Func) const override; 970 void dump(const Cfg *Func) const override;
972 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } 971 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
973 972
974 private: 973 private:
975 InstARM32Pop(Cfg *Func, const VarList &Dests); 974 InstARM32Pop(Cfg *Func, const VarList &Dests);
976 975
977 VarList Dests; 976 VarList Dests;
978 }; 977 };
979 978
980 /// Push a list of GPRs. Technically this can be predicated, but we don't 979 /// Push a list of GPRs. Technically this can be predicated, but we don't need
981 /// need that functionality. 980 /// that functionality.
982 class InstARM32Push : public InstARM32 { 981 class InstARM32Push : public InstARM32 {
983 InstARM32Push() = delete; 982 InstARM32Push() = delete;
984 InstARM32Push(const InstARM32Push &) = delete; 983 InstARM32Push(const InstARM32Push &) = delete;
985 InstARM32Push &operator=(const InstARM32Push &) = delete; 984 InstARM32Push &operator=(const InstARM32Push &) = delete;
986 985
987 public: 986 public:
988 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 987 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
989 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 988 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
990 } 989 }
991 void emit(const Cfg *Func) const override; 990 void emit(const Cfg *Func) const override;
992 void emitIAS(const Cfg *Func) const override; 991 void emitIAS(const Cfg *Func) const override;
993 void dump(const Cfg *Func) const override; 992 void dump(const Cfg *Func) const override;
994 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } 993 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
995 994
996 private: 995 private:
997 InstARM32Push(Cfg *Func, const VarList &Srcs); 996 InstARM32Push(Cfg *Func, const VarList &Srcs);
998 }; 997 };
999 998
1000 /// Ret pseudo-instruction. This is actually a "bx" instruction with 999 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1001 /// an "lr" register operand, but epilogue lowering will search for a Ret 1000 /// register operand, but epilogue lowering will search for a Ret instead of a
1002 /// instead of a generic "bx". This instruction also takes a Source 1001 /// generic "bx". This instruction also takes a Source operand (for non-void
1003 /// operand (for non-void returning functions) for liveness analysis, though 1002 /// returning functions) for liveness analysis, though a FakeUse before the ret
1004 /// a FakeUse before the ret would do just as well. 1003 /// would do just as well.
1005 /// 1004 ///
1006 /// NOTE: Even though "bx" can be predicated, for now leave out the predication 1005 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
1007 /// since it's not yet known to be useful for Ret. That may complicate finding 1006 /// since it's not yet known to be useful for Ret. That may complicate finding
1008 /// the terminator instruction if it's not guaranteed to be executed. 1007 /// the terminator instruction if it's not guaranteed to be executed.
1009 class InstARM32Ret : public InstARM32 { 1008 class InstARM32Ret : public InstARM32 {
1010 InstARM32Ret() = delete; 1009 InstARM32Ret() = delete;
1011 InstARM32Ret(const InstARM32Ret &) = delete; 1010 InstARM32Ret(const InstARM32Ret &) = delete;
1012 InstARM32Ret &operator=(const InstARM32Ret &) = delete; 1011 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1013 1012
1014 public: 1013 public:
1015 static InstARM32Ret *create(Cfg *Func, Variable *LR, 1014 static InstARM32Ret *create(Cfg *Func, Variable *LR,
1016 Variable *Source = nullptr) { 1015 Variable *Source = nullptr) {
1017 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 1016 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1018 } 1017 }
1019 void emit(const Cfg *Func) const override; 1018 void emit(const Cfg *Func) const override;
1020 void emitIAS(const Cfg *Func) const override; 1019 void emitIAS(const Cfg *Func) const override;
1021 void dump(const Cfg *Func) const override; 1020 void dump(const Cfg *Func) const override;
1022 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } 1021 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
1023 1022
1024 private: 1023 private:
1025 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 1024 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1026 }; 1025 };
1027 1026
1028 /// Store instruction. It's important for liveness that there is no Dest 1027 /// Store instruction. It's important for liveness that there is no Dest operand
1029 /// operand (OperandARM32Mem instead of Dest Variable). 1028 /// (OperandARM32Mem instead of Dest Variable).
1030 class InstARM32Str : public InstARM32Pred { 1029 class InstARM32Str : public InstARM32Pred {
1031 InstARM32Str() = delete; 1030 InstARM32Str() = delete;
1032 InstARM32Str(const InstARM32Str &) = delete; 1031 InstARM32Str(const InstARM32Str &) = delete;
1033 InstARM32Str &operator=(const InstARM32Str &) = delete; 1032 InstARM32Str &operator=(const InstARM32Str &) = delete;
1034 1033
1035 public: 1034 public:
1036 /// Value must be a register. 1035 /// Value must be a register.
1037 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1036 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1038 CondARM32::Cond Predicate) { 1037 CondARM32::Cond Predicate) {
1039 return new (Func->allocate<InstARM32Str>()) 1038 return new (Func->allocate<InstARM32Str>())
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 return getSrcSize() > 1; 1197 return getSrcSize() > 1;
1199 } 1198 }
1200 1199
1201 void emitMultiDestSingleSource(const Cfg *Func) const; 1200 void emitMultiDestSingleSource(const Cfg *Func) const;
1202 void emitSingleDestMultiSource(const Cfg *Func) const; 1201 void emitSingleDestMultiSource(const Cfg *Func) const;
1203 void emitSingleDestSingleSource(const Cfg *Func) const; 1202 void emitSingleDestSingleSource(const Cfg *Func) const;
1204 1203
1205 Variable *Dest1 = nullptr; 1204 Variable *Dest1 = nullptr;
1206 }; 1205 };
1207 1206
1208 // Declare partial template specializations of emit() methods that 1207 // Declare partial template specializations of emit() methods that already have
1209 // already have default implementations. Without this, there is the 1208 // default implementations. Without this, there is the possibility of ODR
1210 // possibility of ODR violations and link errors. 1209 // violations and link errors.
1211 1210
1212 template <> void InstARM32Ldr::emit(const Cfg *Func) const; 1211 template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1213 template <> void InstARM32Mov::emit(const Cfg *Func) const; 1212 template <> void InstARM32Mov::emit(const Cfg *Func) const;
1214 template <> void InstARM32Movw::emit(const Cfg *Func) const; 1213 template <> void InstARM32Movw::emit(const Cfg *Func) const;
1215 template <> void InstARM32Movt::emit(const Cfg *Func) const; 1214 template <> void InstARM32Movt::emit(const Cfg *Func) const;
1216 template <> void InstARM32Vldr::emit(const Cfg *Func) const; 1215 template <> void InstARM32Vldr::emit(const Cfg *Func) const;
1217 1216
1218 } // end of namespace Ice 1217 } // end of namespace Ice
1219 1218
1220 #endif // SUBZERO_SRC_ICEINSTARM32_H 1219 #endif // SUBZERO_SRC_ICEINSTARM32_H
OLDNEW
« no previous file with comments | « src/IceInst.def ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698