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

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: 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
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 InstARM32Vmov = InstARM32Movlike<InstARM32::Vmov>; 787 using InstARM32Vmov = InstARM32Movlike<InstARM32::Vmov>;
789 using InstARM32Vldr = InstARM32Movlike<InstARM32::Vldr>; 788 using InstARM32Vldr = InstARM32Movlike<InstARM32::Vldr>;
790 /// MovT leaves the bottom bits alone so dest is also a source. 789 /// MovT leaves the bottom bits alone so dest is also a source. This helps
791 /// This helps indicate that a previous MovW setting dest is not dead code. 790 /// indicate that a previous MovW setting dest is not dead code.
792 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; 791 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
793 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; 792 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
794 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; 793 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
795 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; 794 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
796 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; 795 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
797 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; 796 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
798 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation 797 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
799 // operand as well (rotate source by 8, 16, 24 bits prior to extending), 798 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
800 // but we aren't using that for now, so just model as a Unaryop. 799 // using that for now, so just model as a Unaryop.
801 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; 800 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
802 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; 801 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
803 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; 802 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
804 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; 803 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
805 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; 804 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
806 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; 805 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
807 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; 806 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
808 807
809 // InstARM32Label represents an intra-block label that is the target 808 // InstARM32Label represents an intra-block label that is the target of an
810 // of an intra-block branch. The offset between the label and the 809 // intra-block branch. The offset between the label and the branch must be fit
811 // branch must be fit in the instruction immediate (considered "near"). 810 // in the instruction immediate (considered "near").
812 class InstARM32Label : public InstARM32 { 811 class InstARM32Label : public InstARM32 {
813 InstARM32Label() = delete; 812 InstARM32Label() = delete;
814 InstARM32Label(const InstARM32Label &) = delete; 813 InstARM32Label(const InstARM32Label &) = delete;
815 InstARM32Label &operator=(const InstARM32Label &) = delete; 814 InstARM32Label &operator=(const InstARM32Label &) = delete;
816 815
817 public: 816 public:
818 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) { 817 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
819 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target); 818 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
820 } 819 }
821 uint32_t getEmitInstCount() const override { return 0; } 820 uint32_t getEmitInstCount() const override { return 0; }
(...skipping 24 matching lines...) Expand all
846 return new (Func->allocate<InstARM32Br>()) 845 return new (Func->allocate<InstARM32Br>())
847 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); 846 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
848 } 847 }
849 /// Create an unconditional branch to a node. 848 /// Create an unconditional branch to a node.
850 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 849 static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
851 constexpr CfgNode *NoCondTarget = nullptr; 850 constexpr CfgNode *NoCondTarget = nullptr;
852 constexpr InstARM32Label *NoLabel = nullptr; 851 constexpr InstARM32Label *NoLabel = nullptr;
853 return new (Func->allocate<InstARM32Br>()) 852 return new (Func->allocate<InstARM32Br>())
854 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); 853 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
855 } 854 }
856 /// Create a non-terminator conditional branch to a node, with a 855 /// Create a non-terminator conditional branch to a node, with a fallthrough
857 /// fallthrough to the next instruction in the current node. This is 856 /// to the next instruction in the current node. This is used for switch
858 /// used for switch lowering. 857 /// lowering.
859 static InstARM32Br *create(Cfg *Func, CfgNode *Target, 858 static InstARM32Br *create(Cfg *Func, CfgNode *Target,
860 CondARM32::Cond Predicate) { 859 CondARM32::Cond Predicate) {
861 assert(Predicate != CondARM32::AL); 860 assert(Predicate != CondARM32::AL);
862 constexpr CfgNode *NoUncondTarget = nullptr; 861 constexpr CfgNode *NoUncondTarget = nullptr;
863 constexpr InstARM32Label *NoLabel = nullptr; 862 constexpr InstARM32Label *NoLabel = nullptr;
864 return new (Func->allocate<InstARM32Br>()) 863 return new (Func->allocate<InstARM32Br>())
865 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); 864 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
866 } 865 }
867 // Create a conditional intra-block branch (or unconditional, if 866 // Create a conditional intra-block branch (or unconditional, if
868 // Condition==AL) to a label in the current block. 867 // Condition==AL) to a label in the current block.
(...skipping 28 matching lines...) Expand all
897 896
898 private: 897 private:
899 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 898 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
900 const InstARM32Label *Label, CondARM32::Cond Predicate); 899 const InstARM32Label *Label, CondARM32::Cond Predicate);
901 900
902 const CfgNode *TargetTrue; 901 const CfgNode *TargetTrue;
903 const CfgNode *TargetFalse; 902 const CfgNode *TargetFalse;
904 const InstARM32Label *Label; // Intra-block branch target 903 const InstARM32Label *Label; // Intra-block branch target
905 }; 904 };
906 905
907 /// AdjustStack instruction - subtracts SP by the given amount and 906 /// AdjustStack instruction - subtracts SP by the given amount and updates the
908 /// updates the stack offset during code emission. 907 /// stack offset during code emission.
909 class InstARM32AdjustStack : public InstARM32 { 908 class InstARM32AdjustStack : public InstARM32 {
910 InstARM32AdjustStack() = delete; 909 InstARM32AdjustStack() = delete;
911 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; 910 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete;
912 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; 911 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete;
913 912
914 public: 913 public:
915 /// Note: We need both Amount and SrcAmount. If Amount is too large then 914 /// Note: We need both Amount and SrcAmount. If Amount is too large then it
916 /// it needs to be copied to a register (so SrcAmount could be a register). 915 /// needs to be copied to a register (so SrcAmount could be a register).
917 /// However, we also need the numeric Amount for bookkeeping, and it's 916 /// However, we also need the numeric Amount for bookkeeping, and it's hard to
918 /// hard to pull that from the generic SrcAmount operand. 917 /// pull that from the generic SrcAmount operand.
919 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount, 918 static InstARM32AdjustStack *create(Cfg *Func, Variable *SP, SizeT Amount,
920 Operand *SrcAmount) { 919 Operand *SrcAmount) {
921 return new (Func->allocate<InstARM32AdjustStack>()) 920 return new (Func->allocate<InstARM32AdjustStack>())
922 InstARM32AdjustStack(Func, SP, Amount, SrcAmount); 921 InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
923 } 922 }
924 void emit(const Cfg *Func) const override; 923 void emit(const Cfg *Func) const override;
925 void emitIAS(const Cfg *Func) const override; 924 void emitIAS(const Cfg *Func) const override;
926 void dump(const Cfg *Func) const override; 925 void dump(const Cfg *Func) const override;
927 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } 926 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
928 SizeT getAmount() const { return Amount; } 927 SizeT getAmount() const { return Amount; }
929 928
930 private: 929 private:
931 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount, 930 InstARM32AdjustStack(Cfg *Func, Variable *SP, SizeT Amount,
932 Operand *SrcAmount); 931 Operand *SrcAmount);
933 const SizeT Amount; 932 const SizeT Amount;
934 }; 933 };
935 934
936 /// Call instruction (bl/blx). Arguments should have already been pushed. 935 /// Call instruction (bl/blx). Arguments should have already been pushed.
937 /// Technically bl and the register form of blx can be predicated, but we'll 936 /// Technically bl and the register form of blx can be predicated, but we'll
938 /// leave that out until needed. 937 /// leave that out until needed.
939 class InstARM32Call : public InstARM32 { 938 class InstARM32Call : public InstARM32 {
940 InstARM32Call() = delete; 939 InstARM32Call() = delete;
941 InstARM32Call(const InstARM32Call &) = delete; 940 InstARM32Call(const InstARM32Call &) = delete;
942 InstARM32Call &operator=(const InstARM32Call &) = delete; 941 InstARM32Call &operator=(const InstARM32Call &) = delete;
943 942
944 public: 943 public:
945 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 944 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
946 return new (Func->allocate<InstARM32Call>()) 945 return new (Func->allocate<InstARM32Call>())
(...skipping 24 matching lines...) Expand all
971 void emitIAS(const Cfg *Func) const override; 970 void emitIAS(const Cfg *Func) const override;
972 void dump(const Cfg *Func) const override; 971 void dump(const Cfg *Func) const override;
973 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } 972 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
974 973
975 private: 974 private:
976 InstARM32Pop(Cfg *Func, const VarList &Dests); 975 InstARM32Pop(Cfg *Func, const VarList &Dests);
977 976
978 VarList Dests; 977 VarList Dests;
979 }; 978 };
980 979
981 /// Push a list of GPRs. Technically this can be predicated, but we don't 980 /// Push a list of GPRs. Technically this can be predicated, but we don't need
982 /// need that functionality. 981 /// that functionality.
983 class InstARM32Push : public InstARM32 { 982 class InstARM32Push : public InstARM32 {
984 InstARM32Push() = delete; 983 InstARM32Push() = delete;
985 InstARM32Push(const InstARM32Push &) = delete; 984 InstARM32Push(const InstARM32Push &) = delete;
986 InstARM32Push &operator=(const InstARM32Push &) = delete; 985 InstARM32Push &operator=(const InstARM32Push &) = delete;
987 986
988 public: 987 public:
989 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 988 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
990 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 989 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
991 } 990 }
992 void emit(const Cfg *Func) const override; 991 void emit(const Cfg *Func) const override;
993 void emitIAS(const Cfg *Func) const override; 992 void emitIAS(const Cfg *Func) const override;
994 void dump(const Cfg *Func) const override; 993 void dump(const Cfg *Func) const override;
995 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } 994 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
996 995
997 private: 996 private:
998 InstARM32Push(Cfg *Func, const VarList &Srcs); 997 InstARM32Push(Cfg *Func, const VarList &Srcs);
999 }; 998 };
1000 999
1001 /// Ret pseudo-instruction. This is actually a "bx" instruction with 1000 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1002 /// an "lr" register operand, but epilogue lowering will search for a Ret 1001 /// register operand, but epilogue lowering will search for a Ret instead of a
1003 /// instead of a generic "bx". This instruction also takes a Source 1002 /// generic "bx". This instruction also takes a Source operand (for non-void
1004 /// operand (for non-void returning functions) for liveness analysis, though 1003 /// returning functions) for liveness analysis, though a FakeUse before the ret
1005 /// a FakeUse before the ret would do just as well. 1004 /// would do just as well.
1006 /// 1005 ///
1007 /// NOTE: Even though "bx" can be predicated, for now leave out the predication 1006 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
1008 /// since it's not yet known to be useful for Ret. That may complicate finding 1007 /// since it's not yet known to be useful for Ret. That may complicate finding
1009 /// the terminator instruction if it's not guaranteed to be executed. 1008 /// the terminator instruction if it's not guaranteed to be executed.
1010 class InstARM32Ret : public InstARM32 { 1009 class InstARM32Ret : public InstARM32 {
1011 InstARM32Ret() = delete; 1010 InstARM32Ret() = delete;
1012 InstARM32Ret(const InstARM32Ret &) = delete; 1011 InstARM32Ret(const InstARM32Ret &) = delete;
1013 InstARM32Ret &operator=(const InstARM32Ret &) = delete; 1012 InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1014 1013
1015 public: 1014 public:
1016 static InstARM32Ret *create(Cfg *Func, Variable *LR, 1015 static InstARM32Ret *create(Cfg *Func, Variable *LR,
1017 Variable *Source = nullptr) { 1016 Variable *Source = nullptr) {
1018 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 1017 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1019 } 1018 }
1020 void emit(const Cfg *Func) const override; 1019 void emit(const Cfg *Func) const override;
1021 void emitIAS(const Cfg *Func) const override; 1020 void emitIAS(const Cfg *Func) const override;
1022 void dump(const Cfg *Func) const override; 1021 void dump(const Cfg *Func) const override;
1023 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } 1022 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
1024 1023
1025 private: 1024 private:
1026 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 1025 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1027 }; 1026 };
1028 1027
1029 /// Store instruction. It's important for liveness that there is no Dest 1028 /// Store instruction. It's important for liveness that there is no Dest operand
1030 /// operand (OperandARM32Mem instead of Dest Variable). 1029 /// (OperandARM32Mem instead of Dest Variable).
1031 class InstARM32Str : public InstARM32Pred { 1030 class InstARM32Str : public InstARM32Pred {
1032 InstARM32Str() = delete; 1031 InstARM32Str() = delete;
1033 InstARM32Str(const InstARM32Str &) = delete; 1032 InstARM32Str(const InstARM32Str &) = delete;
1034 InstARM32Str &operator=(const InstARM32Str &) = delete; 1033 InstARM32Str &operator=(const InstARM32Str &) = delete;
1035 1034
1036 public: 1035 public:
1037 /// Value must be a register. 1036 /// Value must be a register.
1038 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1037 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1039 CondARM32::Cond Predicate) { 1038 CondARM32::Cond Predicate) {
1040 return new (Func->allocate<InstARM32Str>()) 1039 return new (Func->allocate<InstARM32Str>())
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 void dump(const Cfg *Func) const override; 1111 void dump(const Cfg *Func) const override;
1113 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); } 1112 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
1114 1113
1115 private: 1114 private:
1116 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant, 1115 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1117 CondARM32::Cond Predicate); 1116 CondARM32::Cond Predicate);
1118 1117
1119 const VcvtVariant Variant; 1118 const VcvtVariant Variant;
1120 }; 1119 };
1121 1120
1122 // Declare partial template specializations of emit() methods that 1121 // Declare partial template specializations of emit() methods that already have
1123 // already have default implementations. Without this, there is the 1122 // default implementations. Without this, there is the possibility of ODR
1124 // possibility of ODR violations and link errors. 1123 // violations and link errors.
1125 1124
1126 template <> void InstARM32Ldr::emit(const Cfg *Func) const; 1125 template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1127 template <> void InstARM32Mov::emit(const Cfg *Func) const; 1126 template <> void InstARM32Mov::emit(const Cfg *Func) const;
1128 template <> void InstARM32Movw::emit(const Cfg *Func) const; 1127 template <> void InstARM32Movw::emit(const Cfg *Func) const;
1129 template <> void InstARM32Movt::emit(const Cfg *Func) const; 1128 template <> void InstARM32Movt::emit(const Cfg *Func) const;
1130 template <> void InstARM32Vldr::emit(const Cfg *Func) const; 1129 template <> void InstARM32Vldr::emit(const Cfg *Func) const;
1131 template <> void InstARM32Vmov::emit(const Cfg *Func) const; 1130 template <> void InstARM32Vmov::emit(const Cfg *Func) const;
1132 1131
1133 } // end of namespace Ice 1132 } // end of namespace Ice
1134 1133
1135 #endif // SUBZERO_SRC_ICEINSTARM32_H 1134 #endif // SUBZERO_SRC_ICEINSTARM32_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698