| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file declares the InstARM32 and OperandARM32 classes and | 10 // This file declares the InstARM32 and OperandARM32 classes and |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 using Operand::dump; | 53 using Operand::dump; |
| 54 void dump(const Cfg *, Ostream &Str) const override { | 54 void dump(const Cfg *, Ostream &Str) const override { |
| 55 if (ALLOW_DUMP) | 55 if (ALLOW_DUMP) |
| 56 Str << "<OperandARM32>"; | 56 Str << "<OperandARM32>"; |
| 57 } | 57 } |
| 58 | 58 |
| 59 protected: | 59 protected: |
| 60 OperandARM32(OperandKindARM32 Kind, Type Ty) | 60 OperandARM32(OperandKindARM32 Kind, Type Ty) |
| 61 : Operand(static_cast<OperandKind>(Kind), Ty) {} | 61 : Operand(static_cast<OperandKind>(Kind), Ty) {} |
| 62 ~OperandARM32() override {} | |
| 63 }; | 62 }; |
| 64 | 63 |
| 65 // OperandARM32Mem represents a memory operand in any of the various ARM32 | 64 // OperandARM32Mem represents a memory operand in any of the various ARM32 |
| 66 // addressing modes. | 65 // addressing modes. |
| 67 class OperandARM32Mem : public OperandARM32 { | 66 class OperandARM32Mem : public OperandARM32 { |
| 68 OperandARM32Mem() = delete; | 67 OperandARM32Mem() = delete; |
| 69 OperandARM32Mem(const OperandARM32Mem &) = delete; | 68 OperandARM32Mem(const OperandARM32Mem &) = delete; |
| 70 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete; | 69 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete; |
| 71 | 70 |
| 72 public: | 71 public: |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // can encode the Offset directly in the immediate field of the 32-bit | 133 // can encode the Offset directly in the immediate field of the 32-bit |
| 135 // ARM instruction. For some types, if the load is Sign extending, then | 134 // ARM instruction. For some types, if the load is Sign extending, then |
| 136 // the range is reduced. | 135 // the range is reduced. |
| 137 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); | 136 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); |
| 138 | 137 |
| 139 private: | 138 private: |
| 140 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, | 139 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, |
| 141 ConstantInteger32 *ImmOffset, AddrMode Mode); | 140 ConstantInteger32 *ImmOffset, AddrMode Mode); |
| 142 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, | 141 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, |
| 143 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); | 142 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); |
| 144 ~OperandARM32Mem() override {} | 143 |
| 145 Variable *Base; | 144 Variable *Base; |
| 146 ConstantInteger32 *ImmOffset; | 145 ConstantInteger32 *ImmOffset; |
| 147 Variable *Index; | 146 Variable *Index; |
| 148 ShiftKind ShiftOp; | 147 ShiftKind ShiftOp; |
| 149 uint16_t ShiftAmt; | 148 uint16_t ShiftAmt; |
| 150 AddrMode Mode; | 149 AddrMode Mode; |
| 151 }; | 150 }; |
| 152 | 151 |
| 153 // OperandARM32Flex represent the "flexible second operand" for | 152 // OperandARM32Flex represent the "flexible second operand" for |
| 154 // data-processing instructions. It can be a rotatable 8-bit constant, or | 153 // data-processing instructions. It can be a rotatable 8-bit constant, or |
| 155 // a register with an optional shift operand. The shift amount can even be | 154 // a register with an optional shift operand. The shift amount can even be |
| 156 // a third register. | 155 // 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 } |
| 167 | 166 |
| 168 protected: | 167 protected: |
| 169 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {} | 168 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {} |
| 170 ~OperandARM32Flex() override {} | |
| 171 }; | 169 }; |
| 172 | 170 |
| 173 // Rotated immediate variant. | 171 // Rotated immediate variant. |
| 174 class OperandARM32FlexImm : public OperandARM32Flex { | 172 class OperandARM32FlexImm : public OperandARM32Flex { |
| 175 OperandARM32FlexImm() = delete; | 173 OperandARM32FlexImm() = delete; |
| 176 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete; | 174 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete; |
| 177 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete; | 175 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete; |
| 178 | 176 |
| 179 public: | 177 public: |
| 180 // Immed_8 rotated by an even number of bits (2 * RotateAmt). | 178 // Immed_8 rotated by an even number of bits (2 * RotateAmt). |
| (...skipping 14 matching lines...) Expand all Loading... |
| 195 // 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. |
| 196 // Fills in the out-params RotateAmt and Immed_8 if Immediate fits. | 194 // Fills in the out-params RotateAmt and Immed_8 if Immediate fits. |
| 197 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, | 195 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, |
| 198 uint32_t *Immed_8); | 196 uint32_t *Immed_8); |
| 199 | 197 |
| 200 uint32_t getImm() const { return Imm; } | 198 uint32_t getImm() const { return Imm; } |
| 201 uint32_t getRotateAmt() const { return RotateAmt; } | 199 uint32_t getRotateAmt() const { return RotateAmt; } |
| 202 | 200 |
| 203 private: | 201 private: |
| 204 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); | 202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); |
| 205 ~OperandARM32FlexImm() override {} | |
| 206 | 203 |
| 207 uint32_t Imm; | 204 uint32_t Imm; |
| 208 uint32_t RotateAmt; | 205 uint32_t RotateAmt; |
| 209 }; | 206 }; |
| 210 | 207 |
| 211 // Shifted register variant. | 208 // Shifted register variant. |
| 212 class OperandARM32FlexReg : public OperandARM32Flex { | 209 class OperandARM32FlexReg : public OperandARM32Flex { |
| 213 OperandARM32FlexReg() = delete; | 210 OperandARM32FlexReg() = delete; |
| 214 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; | 211 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; |
| 215 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; | 212 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 231 } | 228 } |
| 232 | 229 |
| 233 Variable *getReg() const { return Reg; } | 230 Variable *getReg() const { return Reg; } |
| 234 ShiftKind getShiftOp() const { return ShiftOp; } | 231 ShiftKind getShiftOp() const { return ShiftOp; } |
| 235 // ShiftAmt can represent an immediate or a register. | 232 // ShiftAmt can represent an immediate or a register. |
| 236 Operand *getShiftAmt() const { return ShiftAmt; } | 233 Operand *getShiftAmt() const { return ShiftAmt; } |
| 237 | 234 |
| 238 private: | 235 private: |
| 239 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, | 236 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, |
| 240 Operand *ShiftAmt); | 237 Operand *ShiftAmt); |
| 241 ~OperandARM32FlexReg() override {} | |
| 242 | 238 |
| 243 Variable *Reg; | 239 Variable *Reg; |
| 244 ShiftKind ShiftOp; | 240 ShiftKind ShiftOp; |
| 245 Operand *ShiftAmt; | 241 Operand *ShiftAmt; |
| 246 }; | 242 }; |
| 247 | 243 |
| 248 // Base class for ARM instructions. While most ARM instructions can be | 244 // Base class for ARM instructions. While most ARM instructions can be |
| 249 // conditionally executed, a few of them are not predicable (halt, | 245 // conditionally executed, a few of them are not predicable (halt, |
| 250 // memory barriers, etc.). | 246 // memory barriers, etc.). |
| 251 class InstARM32 : public InstTarget { | 247 class InstARM32 : public InstTarget { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 }; | 284 }; |
| 289 | 285 |
| 290 static const char *getWidthString(Type Ty); | 286 static const char *getWidthString(Type Ty); |
| 291 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); | 287 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); |
| 292 | 288 |
| 293 void dump(const Cfg *Func) const override; | 289 void dump(const Cfg *Func) const override; |
| 294 | 290 |
| 295 protected: | 291 protected: |
| 296 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) | 292 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) |
| 297 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 293 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 298 ~InstARM32() override {} | 294 |
| 299 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { | 295 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { |
| 300 return Inst->getKind() == static_cast<InstKind>(MyKind); | 296 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 301 } | 297 } |
| 302 }; | 298 }; |
| 303 | 299 |
| 304 // A predicable ARM instruction. | 300 // A predicable ARM instruction. |
| 305 class InstARM32Pred : public InstARM32 { | 301 class InstARM32Pred : public InstARM32 { |
| 306 InstARM32Pred() = delete; | 302 InstARM32Pred() = delete; |
| 307 InstARM32Pred(const InstARM32Pred &) = delete; | 303 InstARM32Pred(const InstARM32Pred &) = delete; |
| 308 InstARM32Pred &operator=(const InstARM32Pred &) = delete; | 304 InstARM32Pred &operator=(const InstARM32Pred &) = delete; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 dumpSources(Func); | 365 dumpSources(Func); |
| 370 } | 366 } |
| 371 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 367 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 372 | 368 |
| 373 private: | 369 private: |
| 374 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, | 370 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, |
| 375 CondARM32::Cond Predicate) | 371 CondARM32::Cond Predicate) |
| 376 : InstARM32Pred(Func, K, 1, Dest, Predicate) { | 372 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
| 377 addSource(Src); | 373 addSource(Src); |
| 378 } | 374 } |
| 379 ~InstARM32UnaryopGPR() override {} | 375 |
| 380 static const char *Opcode; | 376 static const char *Opcode; |
| 381 }; | 377 }; |
| 382 | 378 |
| 383 // Instructions of the form x := x op y. | 379 // Instructions of the form x := x op y. |
| 384 template <InstARM32::InstKindARM32 K> | 380 template <InstARM32::InstKindARM32 K> |
| 385 class InstARM32TwoAddrGPR : public InstARM32Pred { | 381 class InstARM32TwoAddrGPR : public InstARM32Pred { |
| 386 InstARM32TwoAddrGPR() = delete; | 382 InstARM32TwoAddrGPR() = delete; |
| 387 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; | 383 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; |
| 388 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; | 384 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; |
| 389 | 385 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 415 } | 411 } |
| 416 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 412 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 417 | 413 |
| 418 private: | 414 private: |
| 419 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, | 415 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, |
| 420 CondARM32::Cond Predicate) | 416 CondARM32::Cond Predicate) |
| 421 : InstARM32Pred(Func, K, 2, Dest, Predicate) { | 417 : InstARM32Pred(Func, K, 2, Dest, Predicate) { |
| 422 addSource(Dest); | 418 addSource(Dest); |
| 423 addSource(Src); | 419 addSource(Src); |
| 424 } | 420 } |
| 425 ~InstARM32TwoAddrGPR() override {} | 421 |
| 426 static const char *Opcode; | 422 static const char *Opcode; |
| 427 }; | 423 }; |
| 428 | 424 |
| 429 // Base class for assignment instructions. | 425 // Base class for assignment instructions. |
| 430 // These can be tested for redundancy (and elided if redundant). | 426 // These can be tested for redundancy (and elided if redundant). |
| 431 template <InstARM32::InstKindARM32 K> | 427 template <InstARM32::InstKindARM32 K> |
| 432 class InstARM32Movlike : public InstARM32Pred { | 428 class InstARM32Movlike : public InstARM32Pred { |
| 433 InstARM32Movlike() = delete; | 429 InstARM32Movlike() = delete; |
| 434 InstARM32Movlike(const InstARM32Movlike &) = delete; | 430 InstARM32Movlike(const InstARM32Movlike &) = delete; |
| 435 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; | 431 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 457 dumpSources(Func); | 453 dumpSources(Func); |
| 458 } | 454 } |
| 459 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 455 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 460 | 456 |
| 461 private: | 457 private: |
| 462 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, | 458 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, |
| 463 CondARM32::Cond Predicate) | 459 CondARM32::Cond Predicate) |
| 464 : InstARM32Pred(Func, K, 1, Dest, Predicate) { | 460 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
| 465 addSource(Source); | 461 addSource(Source); |
| 466 } | 462 } |
| 467 ~InstARM32Movlike() override {} | |
| 468 | 463 |
| 469 static const char *Opcode; | 464 static const char *Opcode; |
| 470 }; | 465 }; |
| 471 | 466 |
| 472 // Instructions of the form x := y op z. May have the side-effect of setting | 467 // Instructions of the form x := y op z. May have the side-effect of setting |
| 473 // status flags. | 468 // status flags. |
| 474 template <InstARM32::InstKindARM32 K> | 469 template <InstARM32::InstKindARM32 K> |
| 475 class InstARM32ThreeAddrGPR : public InstARM32Pred { | 470 class InstARM32ThreeAddrGPR : public InstARM32Pred { |
| 476 InstARM32ThreeAddrGPR() = delete; | 471 InstARM32ThreeAddrGPR() = delete; |
| 477 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; | 472 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 508 } | 503 } |
| 509 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 504 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 510 | 505 |
| 511 private: | 506 private: |
| 512 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, | 507 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, |
| 513 Operand *Src2, CondARM32::Cond Predicate, bool SetFlags) | 508 Operand *Src2, CondARM32::Cond Predicate, bool SetFlags) |
| 514 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { | 509 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { |
| 515 addSource(Src1); | 510 addSource(Src1); |
| 516 addSource(Src2); | 511 addSource(Src2); |
| 517 } | 512 } |
| 518 ~InstARM32ThreeAddrGPR() override {} | 513 |
| 519 static const char *Opcode; | 514 static const char *Opcode; |
| 520 bool SetFlags; | 515 bool SetFlags; |
| 521 }; | 516 }; |
| 522 | 517 |
| 523 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; | 518 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; |
| 524 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; | 519 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; |
| 525 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; | 520 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; |
| 526 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr; | 521 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr; |
| 527 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic; | 522 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic; |
| 528 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; | 523 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 } | 589 } |
| 595 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; | 590 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |
| 596 void emit(const Cfg *Func) const override; | 591 void emit(const Cfg *Func) const override; |
| 597 void emitIAS(const Cfg *Func) const override; | 592 void emitIAS(const Cfg *Func) const override; |
| 598 void dump(const Cfg *Func) const override; | 593 void dump(const Cfg *Func) const override; |
| 599 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } | 594 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |
| 600 | 595 |
| 601 private: | 596 private: |
| 602 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 597 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 603 CondARM32::Cond Predicate); | 598 CondARM32::Cond Predicate); |
| 604 ~InstARM32Br() override {} | 599 |
| 605 const CfgNode *TargetTrue; | 600 const CfgNode *TargetTrue; |
| 606 const CfgNode *TargetFalse; | 601 const CfgNode *TargetFalse; |
| 607 }; | 602 }; |
| 608 | 603 |
| 609 // Call instruction (bl/blx). Arguments should have already been pushed. | 604 // Call instruction (bl/blx). Arguments should have already been pushed. |
| 610 // Technically bl and the register form of blx can be predicated, but we'll | 605 // Technically bl and the register form of blx can be predicated, but we'll |
| 611 // leave that out until needed. | 606 // leave that out until needed. |
| 612 class InstARM32Call : public InstARM32 { | 607 class InstARM32Call : public InstARM32 { |
| 613 InstARM32Call() = delete; | 608 InstARM32Call() = delete; |
| 614 InstARM32Call(const InstARM32Call &) = delete; | 609 InstARM32Call(const InstARM32Call &) = delete; |
| 615 InstARM32Call &operator=(const InstARM32Call &) = delete; | 610 InstARM32Call &operator=(const InstARM32Call &) = delete; |
| 616 | 611 |
| 617 public: | 612 public: |
| 618 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | 613 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |
| 619 return new (Func->allocate<InstARM32Call>()) | 614 return new (Func->allocate<InstARM32Call>()) |
| 620 InstARM32Call(Func, Dest, CallTarget); | 615 InstARM32Call(Func, Dest, CallTarget); |
| 621 } | 616 } |
| 622 Operand *getCallTarget() const { return getSrc(0); } | 617 Operand *getCallTarget() const { return getSrc(0); } |
| 623 void emit(const Cfg *Func) const override; | 618 void emit(const Cfg *Func) const override; |
| 624 void emitIAS(const Cfg *Func) const override; | 619 void emitIAS(const Cfg *Func) const override; |
| 625 void dump(const Cfg *Func) const override; | 620 void dump(const Cfg *Func) const override; |
| 626 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } | 621 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
| 627 | 622 |
| 628 private: | 623 private: |
| 629 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 624 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
| 630 ~InstARM32Call() override {} | |
| 631 }; | 625 }; |
| 632 | 626 |
| 633 // Integer compare instruction. | 627 // Integer compare instruction. |
| 634 class InstARM32Cmp : public InstARM32Pred { | 628 class InstARM32Cmp : public InstARM32Pred { |
| 635 InstARM32Cmp() = delete; | 629 InstARM32Cmp() = delete; |
| 636 InstARM32Cmp(const InstARM32Cmp &) = delete; | 630 InstARM32Cmp(const InstARM32Cmp &) = delete; |
| 637 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; | 631 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; |
| 638 | 632 |
| 639 public: | 633 public: |
| 640 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, | 634 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, |
| 641 CondARM32::Cond Predicate) { | 635 CondARM32::Cond Predicate) { |
| 642 return new (Func->allocate<InstARM32Cmp>()) | 636 return new (Func->allocate<InstARM32Cmp>()) |
| 643 InstARM32Cmp(Func, Src1, Src2, Predicate); | 637 InstARM32Cmp(Func, Src1, Src2, Predicate); |
| 644 } | 638 } |
| 645 void emit(const Cfg *Func) const override; | 639 void emit(const Cfg *Func) const override; |
| 646 void emitIAS(const Cfg *Func) const override; | 640 void emitIAS(const Cfg *Func) const override; |
| 647 void dump(const Cfg *Func) const override; | 641 void dump(const Cfg *Func) const override; |
| 648 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } | 642 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } |
| 649 | 643 |
| 650 private: | 644 private: |
| 651 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, | 645 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, |
| 652 CondARM32::Cond Predicate); | 646 CondARM32::Cond Predicate); |
| 653 ~InstARM32Cmp() override {} | |
| 654 }; | 647 }; |
| 655 | 648 |
| 656 // Load instruction. | 649 // Load instruction. |
| 657 class InstARM32Ldr : public InstARM32Pred { | 650 class InstARM32Ldr : public InstARM32Pred { |
| 658 InstARM32Ldr() = delete; | 651 InstARM32Ldr() = delete; |
| 659 InstARM32Ldr(const InstARM32Ldr &) = delete; | 652 InstARM32Ldr(const InstARM32Ldr &) = delete; |
| 660 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; | 653 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; |
| 661 | 654 |
| 662 public: | 655 public: |
| 663 // Dest must be a register. | 656 // Dest must be a register. |
| 664 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, | 657 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 665 CondARM32::Cond Predicate) { | 658 CondARM32::Cond Predicate) { |
| 666 return new (Func->allocate<InstARM32Ldr>()) | 659 return new (Func->allocate<InstARM32Ldr>()) |
| 667 InstARM32Ldr(Func, Dest, Mem, Predicate); | 660 InstARM32Ldr(Func, Dest, Mem, Predicate); |
| 668 } | 661 } |
| 669 void emit(const Cfg *Func) const override; | 662 void emit(const Cfg *Func) const override; |
| 670 void emitIAS(const Cfg *Func) const override; | 663 void emitIAS(const Cfg *Func) const override; |
| 671 void dump(const Cfg *Func) const override; | 664 void dump(const Cfg *Func) const override; |
| 672 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } | 665 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } |
| 673 | 666 |
| 674 private: | 667 private: |
| 675 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, | 668 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 676 CondARM32::Cond Predicate); | 669 CondARM32::Cond Predicate); |
| 677 ~InstARM32Ldr() override {} | |
| 678 }; | 670 }; |
| 679 | 671 |
| 680 // Multiply Accumulate: d := x * y + a | 672 // Multiply Accumulate: d := x * y + a |
| 681 class InstARM32Mla : public InstARM32Pred { | 673 class InstARM32Mla : public InstARM32Pred { |
| 682 InstARM32Mla() = delete; | 674 InstARM32Mla() = delete; |
| 683 InstARM32Mla(const InstARM32Mla &) = delete; | 675 InstARM32Mla(const InstARM32Mla &) = delete; |
| 684 InstARM32Mla &operator=(const InstARM32Mla &) = delete; | 676 InstARM32Mla &operator=(const InstARM32Mla &) = delete; |
| 685 | 677 |
| 686 public: | 678 public: |
| 687 // Everything must be a register. | 679 // Everything must be a register. |
| 688 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, | 680 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, |
| 689 Variable *Src1, Variable *Acc, | 681 Variable *Src1, Variable *Acc, |
| 690 CondARM32::Cond Predicate) { | 682 CondARM32::Cond Predicate) { |
| 691 return new (Func->allocate<InstARM32Mla>()) | 683 return new (Func->allocate<InstARM32Mla>()) |
| 692 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); | 684 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); |
| 693 } | 685 } |
| 694 void emit(const Cfg *Func) const override; | 686 void emit(const Cfg *Func) const override; |
| 695 void emitIAS(const Cfg *Func) const override; | 687 void emitIAS(const Cfg *Func) const override; |
| 696 void dump(const Cfg *Func) const override; | 688 void dump(const Cfg *Func) const override; |
| 697 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } | 689 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } |
| 698 | 690 |
| 699 private: | 691 private: |
| 700 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, | 692 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, |
| 701 Variable *Acc, CondARM32::Cond Predicate); | 693 Variable *Acc, CondARM32::Cond Predicate); |
| 702 ~InstARM32Mla() override {} | |
| 703 }; | 694 }; |
| 704 | 695 |
| 705 // Pop into a list of GPRs. Technically this can be predicated, but we don't | 696 // Pop into a list of GPRs. Technically this can be predicated, but we don't |
| 706 // need that functionality. | 697 // need that functionality. |
| 707 class InstARM32Pop : public InstARM32 { | 698 class InstARM32Pop : public InstARM32 { |
| 708 InstARM32Pop() = delete; | 699 InstARM32Pop() = delete; |
| 709 InstARM32Pop(const InstARM32Pop &) = delete; | 700 InstARM32Pop(const InstARM32Pop &) = delete; |
| 710 InstARM32Pop &operator=(const InstARM32Pop &) = delete; | 701 InstARM32Pop &operator=(const InstARM32Pop &) = delete; |
| 711 | 702 |
| 712 public: | 703 public: |
| 713 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { | 704 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { |
| 714 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); | 705 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); |
| 715 } | 706 } |
| 716 void emit(const Cfg *Func) const override; | 707 void emit(const Cfg *Func) const override; |
| 717 void emitIAS(const Cfg *Func) const override; | 708 void emitIAS(const Cfg *Func) const override; |
| 718 void dump(const Cfg *Func) const override; | 709 void dump(const Cfg *Func) const override; |
| 719 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } | 710 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } |
| 720 | 711 |
| 721 private: | 712 private: |
| 722 InstARM32Pop(Cfg *Func, const VarList &Dests); | 713 InstARM32Pop(Cfg *Func, const VarList &Dests); |
| 723 ~InstARM32Pop() override {} | 714 |
| 724 VarList Dests; | 715 VarList Dests; |
| 725 }; | 716 }; |
| 726 | 717 |
| 727 // Push a list of GPRs. Technically this can be predicated, but we don't | 718 // Push a list of GPRs. Technically this can be predicated, but we don't |
| 728 // need that functionality. | 719 // need that functionality. |
| 729 class InstARM32Push : public InstARM32 { | 720 class InstARM32Push : public InstARM32 { |
| 730 InstARM32Push() = delete; | 721 InstARM32Push() = delete; |
| 731 InstARM32Push(const InstARM32Push &) = delete; | 722 InstARM32Push(const InstARM32Push &) = delete; |
| 732 InstARM32Push &operator=(const InstARM32Push &) = delete; | 723 InstARM32Push &operator=(const InstARM32Push &) = delete; |
| 733 | 724 |
| 734 public: | 725 public: |
| 735 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { | 726 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { |
| 736 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); | 727 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); |
| 737 } | 728 } |
| 738 void emit(const Cfg *Func) const override; | 729 void emit(const Cfg *Func) const override; |
| 739 void emitIAS(const Cfg *Func) const override; | 730 void emitIAS(const Cfg *Func) const override; |
| 740 void dump(const Cfg *Func) const override; | 731 void dump(const Cfg *Func) const override; |
| 741 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } | 732 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } |
| 742 | 733 |
| 743 private: | 734 private: |
| 744 InstARM32Push(Cfg *Func, const VarList &Srcs); | 735 InstARM32Push(Cfg *Func, const VarList &Srcs); |
| 745 ~InstARM32Push() override {} | |
| 746 }; | 736 }; |
| 747 | 737 |
| 748 // Ret pseudo-instruction. This is actually a "bx" instruction with | 738 // Ret pseudo-instruction. This is actually a "bx" instruction with |
| 749 // an "lr" register operand, but epilogue lowering will search for a Ret | 739 // an "lr" register operand, but epilogue lowering will search for a Ret |
| 750 // instead of a generic "bx". This instruction also takes a Source | 740 // instead of a generic "bx". This instruction also takes a Source |
| 751 // operand (for non-void returning functions) for liveness analysis, though | 741 // operand (for non-void returning functions) for liveness analysis, though |
| 752 // a FakeUse before the ret would do just as well. | 742 // a FakeUse before the ret would do just as well. |
| 753 // | 743 // |
| 754 // NOTE: Even though "bx" can be predicated, for now leave out the predication | 744 // NOTE: Even though "bx" can be predicated, for now leave out the predication |
| 755 // since it's not yet known to be useful for Ret. That may complicate finding | 745 // since it's not yet known to be useful for Ret. That may complicate finding |
| 756 // the terminator instruction if it's not guaranteed to be executed. | 746 // the terminator instruction if it's not guaranteed to be executed. |
| 757 class InstARM32Ret : public InstARM32 { | 747 class InstARM32Ret : public InstARM32 { |
| 758 InstARM32Ret() = delete; | 748 InstARM32Ret() = delete; |
| 759 InstARM32Ret(const InstARM32Ret &) = delete; | 749 InstARM32Ret(const InstARM32Ret &) = delete; |
| 760 InstARM32Ret &operator=(const InstARM32Ret &) = delete; | 750 InstARM32Ret &operator=(const InstARM32Ret &) = delete; |
| 761 | 751 |
| 762 public: | 752 public: |
| 763 static InstARM32Ret *create(Cfg *Func, Variable *LR, | 753 static InstARM32Ret *create(Cfg *Func, Variable *LR, |
| 764 Variable *Source = nullptr) { | 754 Variable *Source = nullptr) { |
| 765 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); | 755 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); |
| 766 } | 756 } |
| 767 void emit(const Cfg *Func) const override; | 757 void emit(const Cfg *Func) const override; |
| 768 void emitIAS(const Cfg *Func) const override; | 758 void emitIAS(const Cfg *Func) const override; |
| 769 void dump(const Cfg *Func) const override; | 759 void dump(const Cfg *Func) const override; |
| 770 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 760 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
| 771 | 761 |
| 772 private: | 762 private: |
| 773 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); | 763 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); |
| 774 ~InstARM32Ret() override {} | |
| 775 }; | 764 }; |
| 776 | 765 |
| 777 // Store instruction. It's important for liveness that there is no Dest | 766 // Store instruction. It's important for liveness that there is no Dest |
| 778 // operand (OperandARM32Mem instead of Dest Variable). | 767 // operand (OperandARM32Mem instead of Dest Variable). |
| 779 class InstARM32Str : public InstARM32Pred { | 768 class InstARM32Str : public InstARM32Pred { |
| 780 InstARM32Str() = delete; | 769 InstARM32Str() = delete; |
| 781 InstARM32Str(const InstARM32Str &) = delete; | 770 InstARM32Str(const InstARM32Str &) = delete; |
| 782 InstARM32Str &operator=(const InstARM32Str &) = delete; | 771 InstARM32Str &operator=(const InstARM32Str &) = delete; |
| 783 | 772 |
| 784 public: | 773 public: |
| 785 // Value must be a register. | 774 // Value must be a register. |
| 786 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, | 775 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, |
| 787 CondARM32::Cond Predicate) { | 776 CondARM32::Cond Predicate) { |
| 788 return new (Func->allocate<InstARM32Str>()) | 777 return new (Func->allocate<InstARM32Str>()) |
| 789 InstARM32Str(Func, Value, Mem, Predicate); | 778 InstARM32Str(Func, Value, Mem, Predicate); |
| 790 } | 779 } |
| 791 void emit(const Cfg *Func) const override; | 780 void emit(const Cfg *Func) const override; |
| 792 void emitIAS(const Cfg *Func) const override; | 781 void emitIAS(const Cfg *Func) const override; |
| 793 void dump(const Cfg *Func) const override; | 782 void dump(const Cfg *Func) const override; |
| 794 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } | 783 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } |
| 795 | 784 |
| 796 private: | 785 private: |
| 797 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, | 786 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, |
| 798 CondARM32::Cond Predicate); | 787 CondARM32::Cond Predicate); |
| 799 ~InstARM32Str() override {} | |
| 800 }; | 788 }; |
| 801 | 789 |
| 802 // Unsigned Multiply Long: d.lo, d.hi := x * y | 790 // Unsigned Multiply Long: d.lo, d.hi := x * y |
| 803 class InstARM32Umull : public InstARM32Pred { | 791 class InstARM32Umull : public InstARM32Pred { |
| 804 InstARM32Umull() = delete; | 792 InstARM32Umull() = delete; |
| 805 InstARM32Umull(const InstARM32Umull &) = delete; | 793 InstARM32Umull(const InstARM32Umull &) = delete; |
| 806 InstARM32Umull &operator=(const InstARM32Umull &) = delete; | 794 InstARM32Umull &operator=(const InstARM32Umull &) = delete; |
| 807 | 795 |
| 808 public: | 796 public: |
| 809 // Everything must be a register. | 797 // Everything must be a register. |
| 810 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, | 798 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 811 Variable *Src0, Variable *Src1, | 799 Variable *Src0, Variable *Src1, |
| 812 CondARM32::Cond Predicate) { | 800 CondARM32::Cond Predicate) { |
| 813 return new (Func->allocate<InstARM32Umull>()) | 801 return new (Func->allocate<InstARM32Umull>()) |
| 814 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); | 802 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); |
| 815 } | 803 } |
| 816 void emit(const Cfg *Func) const override; | 804 void emit(const Cfg *Func) const override; |
| 817 void emitIAS(const Cfg *Func) const override; | 805 void emitIAS(const Cfg *Func) const override; |
| 818 void dump(const Cfg *Func) const override; | 806 void dump(const Cfg *Func) const override; |
| 819 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } | 807 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } |
| 820 | 808 |
| 821 private: | 809 private: |
| 822 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, | 810 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, |
| 823 Variable *Src1, CondARM32::Cond Predicate); | 811 Variable *Src1, CondARM32::Cond Predicate); |
| 824 ~InstARM32Umull() override {} | 812 |
| 825 Variable *DestHi; | 813 Variable *DestHi; |
| 826 }; | 814 }; |
| 827 | 815 |
| 828 // Declare partial template specializations of emit() methods that | 816 // Declare partial template specializations of emit() methods that |
| 829 // already have default implementations. Without this, there is the | 817 // already have default implementations. Without this, there is the |
| 830 // possibility of ODR violations and link errors. | 818 // possibility of ODR violations and link errors. |
| 831 | 819 |
| 832 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 820 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
| 833 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 821 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
| 834 | 822 |
| 835 } // end of namespace Ice | 823 } // end of namespace Ice |
| 836 | 824 |
| 837 #endif // SUBZERO_SRC_ICEINSTARM32_H | 825 #endif // SUBZERO_SRC_ICEINSTARM32_H |
| OLD | NEW |