| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 Adc, | 255 Adc, |
| 256 Add, | 256 Add, |
| 257 Adjuststack, | 257 Adjuststack, |
| 258 And, | 258 And, |
| 259 Asr, | 259 Asr, |
| 260 Bic, | 260 Bic, |
| 261 Br, | 261 Br, |
| 262 Call, | 262 Call, |
| 263 Cmp, | 263 Cmp, |
| 264 Eor, | 264 Eor, |
| 265 Label, |
| 265 Ldr, | 266 Ldr, |
| 266 Lsl, | 267 Lsl, |
| 267 Lsr, | 268 Lsr, |
| 268 Mla, | 269 Mla, |
| 270 Mls, |
| 269 Mov, | 271 Mov, |
| 270 Movt, | 272 Movt, |
| 271 Movw, | 273 Movw, |
| 272 Mul, | 274 Mul, |
| 273 Mvn, | 275 Mvn, |
| 274 Orr, | 276 Orr, |
| 275 Pop, | 277 Pop, |
| 276 Push, | 278 Push, |
| 277 Ret, | 279 Ret, |
| 278 Rsb, | 280 Rsb, |
| 279 Sbc, | 281 Sbc, |
| 282 Sdiv, |
| 280 Str, | 283 Str, |
| 281 Sub, | 284 Sub, |
| 282 Sxt, | 285 Sxt, |
| 286 Trap, |
| 287 Tst, |
| 288 Udiv, |
| 283 Umull, | 289 Umull, |
| 284 Uxt | 290 Uxt |
| 285 }; | 291 }; |
| 286 | 292 |
| 287 static const char *getWidthString(Type Ty); | 293 static const char *getWidthString(Type Ty); |
| 288 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); | 294 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); |
| 289 | 295 |
| 290 void dump(const Cfg *Func) const override; | 296 void dump(const Cfg *Func) const override; |
| 291 | 297 |
| 292 protected: | 298 protected: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 315 static const char *predString(CondARM32::Cond Predicate); | 321 static const char *predString(CondARM32::Cond Predicate); |
| 316 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; | 322 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; |
| 317 | 323 |
| 318 // Shared emit routines for common forms of instructions. | 324 // Shared emit routines for common forms of instructions. |
| 319 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst, | 325 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Inst, |
| 320 const Cfg *Func); | 326 const Cfg *Func); |
| 321 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, | 327 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 322 const Cfg *Func); | 328 const Cfg *Func); |
| 323 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, | 329 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 324 const Cfg *Func, bool SetFlags); | 330 const Cfg *Func, bool SetFlags); |
| 331 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 332 const Cfg *Func); |
| 333 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Inst, |
| 334 const Cfg *Func); |
| 325 | 335 |
| 326 protected: | 336 protected: |
| 327 CondARM32::Cond Predicate; | 337 CondARM32::Cond Predicate; |
| 328 }; | 338 }; |
| 329 | 339 |
| 330 template <typename StreamType> | 340 template <typename StreamType> |
| 331 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { | 341 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { |
| 332 Stream << InstARM32Pred::predString(Predicate); | 342 Stream << InstARM32Pred::predString(Predicate); |
| 333 return Stream; | 343 return Stream; |
| 334 } | 344 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 template <InstARM32::InstKindARM32 K> | 480 template <InstARM32::InstKindARM32 K> |
| 471 class InstARM32ThreeAddrGPR : public InstARM32Pred { | 481 class InstARM32ThreeAddrGPR : public InstARM32Pred { |
| 472 InstARM32ThreeAddrGPR() = delete; | 482 InstARM32ThreeAddrGPR() = delete; |
| 473 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; | 483 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; |
| 474 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; | 484 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; |
| 475 | 485 |
| 476 public: | 486 public: |
| 477 // Create an ordinary binary-op instruction like add, and sub. | 487 // Create an ordinary binary-op instruction like add, and sub. |
| 478 // Dest and Src1 must be registers. | 488 // Dest and Src1 must be registers. |
| 479 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, | 489 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, |
| 480 Variable *Src1, Operand *Src2, | 490 Variable *Src0, Operand *Src1, |
| 481 CondARM32::Cond Predicate, | 491 CondARM32::Cond Predicate, |
| 482 bool SetFlags = false) { | 492 bool SetFlags = false) { |
| 483 return new (Func->allocate<InstARM32ThreeAddrGPR>()) | 493 return new (Func->allocate<InstARM32ThreeAddrGPR>()) |
| 484 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, Predicate, SetFlags); | 494 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags); |
| 485 } | 495 } |
| 486 void emit(const Cfg *Func) const override { | 496 void emit(const Cfg *Func) const override { |
| 487 if (!BuildDefs::dump()) | 497 if (!BuildDefs::dump()) |
| 488 return; | 498 return; |
| 489 emitThreeAddr(Opcode, this, Func, SetFlags); | 499 emitThreeAddr(Opcode, this, Func, SetFlags); |
| 490 } | 500 } |
| 491 void emitIAS(const Cfg *Func) const override { | 501 void emitIAS(const Cfg *Func) const override { |
| 492 (void)Func; | 502 (void)Func; |
| 493 llvm::report_fatal_error("Not yet implemented"); | 503 llvm::report_fatal_error("Not yet implemented"); |
| 494 } | 504 } |
| 495 void dump(const Cfg *Func) const override { | 505 void dump(const Cfg *Func) const override { |
| 496 if (!BuildDefs::dump()) | 506 if (!BuildDefs::dump()) |
| 497 return; | 507 return; |
| 498 Ostream &Str = Func->getContext()->getStrDump(); | 508 Ostream &Str = Func->getContext()->getStrDump(); |
| 499 dumpDest(Func); | 509 dumpDest(Func); |
| 500 Str << " = "; | 510 Str << " = "; |
| 501 dumpOpcodePred(Str, Opcode, getDest()->getType()); | 511 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 502 Str << (SetFlags ? ".s " : " "); | 512 Str << (SetFlags ? ".s " : " "); |
| 503 dumpSources(Func); | 513 dumpSources(Func); |
| 504 } | 514 } |
| 505 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 515 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 506 | 516 |
| 507 private: | 517 private: |
| 508 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, | 518 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, |
| 509 Operand *Src2, CondARM32::Cond Predicate, bool SetFlags) | 519 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) |
| 510 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { | 520 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { |
| 521 addSource(Src0); |
| 511 addSource(Src1); | 522 addSource(Src1); |
| 512 addSource(Src2); | |
| 513 } | 523 } |
| 514 | 524 |
| 515 static const char *Opcode; | 525 static const char *Opcode; |
| 516 bool SetFlags; | 526 bool SetFlags; |
| 517 }; | 527 }; |
| 518 | 528 |
| 529 // Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate. |
| 530 template <InstARM32::InstKindARM32 K> |
| 531 class InstARM32FourAddrGPR : public InstARM32Pred { |
| 532 InstARM32FourAddrGPR() = delete; |
| 533 InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete; |
| 534 InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete; |
| 535 |
| 536 public: |
| 537 // Every operand must be a register. |
| 538 static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0, |
| 539 Variable *Src1, Variable *Src2, |
| 540 CondARM32::Cond Predicate) { |
| 541 return new (Func->allocate<InstARM32FourAddrGPR>()) |
| 542 InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate); |
| 543 } |
| 544 void emit(const Cfg *Func) const override { |
| 545 if (!BuildDefs::dump()) |
| 546 return; |
| 547 emitFourAddr(Opcode, this, Func); |
| 548 } |
| 549 void emitIAS(const Cfg *Func) const override { |
| 550 (void)Func; |
| 551 llvm::report_fatal_error("Not yet implemented"); |
| 552 } |
| 553 void dump(const Cfg *Func) const override { |
| 554 if (!BuildDefs::dump()) |
| 555 return; |
| 556 Ostream &Str = Func->getContext()->getStrDump(); |
| 557 dumpDest(Func); |
| 558 Str << " = "; |
| 559 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 560 Str << " "; |
| 561 dumpSources(Func); |
| 562 } |
| 563 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 564 |
| 565 private: |
| 566 InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, |
| 567 Variable *Src1, Variable *Src2, |
| 568 CondARM32::Cond Predicate) |
| 569 : InstARM32Pred(Func, K, 3, Dest, Predicate) { |
| 570 addSource(Src0); |
| 571 addSource(Src1); |
| 572 addSource(Src2); |
| 573 } |
| 574 |
| 575 static const char *Opcode; |
| 576 }; |
| 577 |
| 578 // Instructions of the form x cmpop y (setting flags). |
| 579 template <InstARM32::InstKindARM32 K> |
| 580 class InstARM32CmpLike : public InstARM32Pred { |
| 581 InstARM32CmpLike() = delete; |
| 582 InstARM32CmpLike(const InstARM32CmpLike &) = delete; |
| 583 InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete; |
| 584 |
| 585 public: |
| 586 static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1, |
| 587 CondARM32::Cond Predicate) { |
| 588 return new (Func->allocate<InstARM32CmpLike>()) |
| 589 InstARM32CmpLike(Func, Src0, Src1, Predicate); |
| 590 } |
| 591 void emit(const Cfg *Func) const override { |
| 592 if (!BuildDefs::dump()) |
| 593 return; |
| 594 emitCmpLike(Opcode, this, Func); |
| 595 } |
| 596 void emitIAS(const Cfg *Func) const override { |
| 597 (void)Func; |
| 598 llvm_unreachable("Not yet implemented"); |
| 599 } |
| 600 void dump(const Cfg *Func) const override { |
| 601 if (!BuildDefs::dump()) |
| 602 return; |
| 603 Ostream &Str = Func->getContext()->getStrDump(); |
| 604 dumpOpcodePred(Str, Opcode, getSrc(0)->getType()); |
| 605 Str << " "; |
| 606 dumpSources(Func); |
| 607 } |
| 608 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 609 |
| 610 private: |
| 611 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1, |
| 612 CondARM32::Cond Predicate) |
| 613 : InstARM32Pred(Func, K, 2, nullptr, Predicate) { |
| 614 addSource(Src0); |
| 615 addSource(Src1); |
| 616 } |
| 617 |
| 618 static const char *Opcode; |
| 619 }; |
| 620 |
| 519 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; | 621 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; |
| 520 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; | 622 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; |
| 521 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; | 623 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; |
| 522 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr; | 624 typedef InstARM32ThreeAddrGPR<InstARM32::Asr> InstARM32Asr; |
| 523 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic; | 625 typedef InstARM32ThreeAddrGPR<InstARM32::Bic> InstARM32Bic; |
| 524 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; | 626 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; |
| 525 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; | 627 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; |
| 526 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr; | 628 typedef InstARM32ThreeAddrGPR<InstARM32::Lsr> InstARM32Lsr; |
| 527 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; | 629 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; |
| 528 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; | 630 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; |
| 529 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb; | 631 typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb; |
| 530 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; | 632 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; |
| 633 typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv; |
| 531 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; | 634 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; |
| 635 typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv; |
| 532 // Move instruction (variable <- flex). This is more of a pseudo-inst. | 636 // Move instruction (variable <- flex). This is more of a pseudo-inst. |
| 533 // If var is a register, then we use "mov". If var is stack, then we use | 637 // If var is a register, then we use "mov". If var is stack, then we use |
| 534 // "str" to store to the stack. | 638 // "str" to store to the stack. |
| 535 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; | 639 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; |
| 536 // MovT leaves the bottom bits alone so dest is also a source. | 640 // MovT leaves the bottom bits alone so dest is also a source. |
| 537 // This helps indicate that a previous MovW setting dest is not dead code. | 641 // This helps indicate that a previous MovW setting dest is not dead code. |
| 538 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; | 642 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; |
| 539 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; | 643 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; |
| 540 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; | 644 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; |
| 541 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation | 645 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation |
| 542 // operand as well (rotate source by 8, 16, 24 bits prior to extending), | 646 // operand as well (rotate source by 8, 16, 24 bits prior to extending), |
| 543 // but we aren't using that for now, so just model as a Unaryop. | 647 // but we aren't using that for now, so just model as a Unaryop. |
| 544 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt; | 648 typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt; |
| 545 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt; | 649 typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt; |
| 650 typedef InstARM32FourAddrGPR<InstARM32::Mla> InstARM32Mla; |
| 651 typedef InstARM32FourAddrGPR<InstARM32::Mls> InstARM32Mls; |
| 652 typedef InstARM32CmpLike<InstARM32::Cmp> InstARM32Cmp; |
| 653 typedef InstARM32CmpLike<InstARM32::Tst> InstARM32Tst; |
| 654 |
| 655 // InstARM32Label represents an intra-block label that is the target |
| 656 // of an intra-block branch. The offset between the label and the |
| 657 // branch must be fit in the instruction immediate (considered "near"). |
| 658 class InstARM32Label : public InstARM32 { |
| 659 InstARM32Label() = delete; |
| 660 InstARM32Label(const InstARM32Label &) = delete; |
| 661 InstARM32Label &operator=(const InstARM32Label &) = delete; |
| 662 |
| 663 public: |
| 664 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) { |
| 665 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target); |
| 666 } |
| 667 uint32_t getEmitInstCount() const override { return 0; } |
| 668 IceString getName(const Cfg *Func) const; |
| 669 SizeT getNumber() const { return Number; } |
| 670 void emit(const Cfg *Func) const override; |
| 671 void emitIAS(const Cfg *Func) const override; |
| 672 void dump(const Cfg *Func) const override; |
| 673 |
| 674 private: |
| 675 InstARM32Label(Cfg *Func, TargetARM32 *Target); |
| 676 |
| 677 SizeT Number; // used for unique label generation. |
| 678 }; |
| 546 | 679 |
| 547 // Direct branch instruction. | 680 // Direct branch instruction. |
| 548 class InstARM32Br : public InstARM32Pred { | 681 class InstARM32Br : public InstARM32Pred { |
| 549 InstARM32Br() = delete; | 682 InstARM32Br() = delete; |
| 550 InstARM32Br(const InstARM32Br &) = delete; | 683 InstARM32Br(const InstARM32Br &) = delete; |
| 551 InstARM32Br &operator=(const InstARM32Br &) = delete; | 684 InstARM32Br &operator=(const InstARM32Br &) = delete; |
| 552 | 685 |
| 553 public: | 686 public: |
| 554 // Create a conditional branch to one of two nodes. | 687 // Create a conditional branch to one of two nodes. |
| 555 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, | 688 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, |
| 556 CfgNode *TargetFalse, CondARM32::Cond Predicate) { | 689 CfgNode *TargetFalse, CondARM32::Cond Predicate) { |
| 557 assert(Predicate != CondARM32::AL); | 690 assert(Predicate != CondARM32::AL); |
| 691 constexpr InstARM32Label *NoLabel = nullptr; |
| 558 return new (Func->allocate<InstARM32Br>()) | 692 return new (Func->allocate<InstARM32Br>()) |
| 559 InstARM32Br(Func, TargetTrue, TargetFalse, Predicate); | 693 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); |
| 560 } | 694 } |
| 561 // Create an unconditional branch to a node. | 695 // Create an unconditional branch to a node. |
| 562 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { | 696 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { |
| 563 const CfgNode *NoCondTarget = nullptr; | 697 constexpr CfgNode *NoCondTarget = nullptr; |
| 698 constexpr InstARM32Label *NoLabel = nullptr; |
| 564 return new (Func->allocate<InstARM32Br>()) | 699 return new (Func->allocate<InstARM32Br>()) |
| 565 InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL); | 700 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); |
| 566 } | 701 } |
| 567 // Create a non-terminator conditional branch to a node, with a | 702 // Create a non-terminator conditional branch to a node, with a |
| 568 // fallthrough to the next instruction in the current node. This is | 703 // fallthrough to the next instruction in the current node. This is |
| 569 // used for switch lowering. | 704 // used for switch lowering. |
| 570 static InstARM32Br *create(Cfg *Func, CfgNode *Target, | 705 static InstARM32Br *create(Cfg *Func, CfgNode *Target, |
| 571 CondARM32::Cond Predicate) { | 706 CondARM32::Cond Predicate) { |
| 572 assert(Predicate != CondARM32::AL); | 707 assert(Predicate != CondARM32::AL); |
| 573 const CfgNode *NoUncondTarget = nullptr; | 708 constexpr CfgNode *NoUncondTarget = nullptr; |
| 709 constexpr InstARM32Label *NoLabel = nullptr; |
| 574 return new (Func->allocate<InstARM32Br>()) | 710 return new (Func->allocate<InstARM32Br>()) |
| 575 InstARM32Br(Func, Target, NoUncondTarget, Predicate); | 711 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); |
| 712 } |
| 713 // Create a conditional intra-block branch (or unconditional, if |
| 714 // Condition==AL) to a label in the current block. |
| 715 static InstARM32Br *create(Cfg *Func, InstARM32Label *Label, |
| 716 CondARM32::Cond Predicate) { |
| 717 constexpr CfgNode *NoCondTarget = nullptr; |
| 718 constexpr CfgNode *NoUncondTarget = nullptr; |
| 719 return new (Func->allocate<InstARM32Br>()) |
| 720 InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate); |
| 576 } | 721 } |
| 577 const CfgNode *getTargetTrue() const { return TargetTrue; } | 722 const CfgNode *getTargetTrue() const { return TargetTrue; } |
| 578 const CfgNode *getTargetFalse() const { return TargetFalse; } | 723 const CfgNode *getTargetFalse() const { return TargetFalse; } |
| 579 bool optimizeBranch(const CfgNode *NextNode); | 724 bool optimizeBranch(const CfgNode *NextNode); |
| 580 uint32_t getEmitInstCount() const override { | 725 uint32_t getEmitInstCount() const override { |
| 581 uint32_t Sum = 0; | 726 uint32_t Sum = 0; |
| 727 if (Label) |
| 728 ++Sum; |
| 582 if (getTargetTrue()) | 729 if (getTargetTrue()) |
| 583 ++Sum; | 730 ++Sum; |
| 584 if (getTargetFalse()) | 731 if (getTargetFalse()) |
| 585 ++Sum; | 732 ++Sum; |
| 586 return Sum; | 733 return Sum; |
| 587 } | 734 } |
| 588 bool isUnconditionalBranch() const override { | 735 bool isUnconditionalBranch() const override { |
| 589 return getPredicate() == CondARM32::AL; | 736 return getPredicate() == CondARM32::AL; |
| 590 } | 737 } |
| 591 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; | 738 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |
| 592 void emit(const Cfg *Func) const override; | 739 void emit(const Cfg *Func) const override; |
| 593 void emitIAS(const Cfg *Func) const override; | 740 void emitIAS(const Cfg *Func) const override; |
| 594 void dump(const Cfg *Func) const override; | 741 void dump(const Cfg *Func) const override; |
| 595 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } | 742 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |
| 596 | 743 |
| 597 private: | 744 private: |
| 598 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 745 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 599 CondARM32::Cond Predicate); | 746 const InstARM32Label *Label, CondARM32::Cond Predicate); |
| 600 | 747 |
| 601 const CfgNode *TargetTrue; | 748 const CfgNode *TargetTrue; |
| 602 const CfgNode *TargetFalse; | 749 const CfgNode *TargetFalse; |
| 750 const InstARM32Label *Label; // Intra-block branch target |
| 603 }; | 751 }; |
| 604 | 752 |
| 605 // AdjustStack instruction - subtracts SP by the given amount and | 753 // AdjustStack instruction - subtracts SP by the given amount and |
| 606 // updates the stack offset during code emission. | 754 // updates the stack offset during code emission. |
| 607 class InstARM32AdjustStack : public InstARM32 { | 755 class InstARM32AdjustStack : public InstARM32 { |
| 608 InstARM32AdjustStack() = delete; | 756 InstARM32AdjustStack() = delete; |
| 609 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; | 757 InstARM32AdjustStack(const InstARM32AdjustStack &) = delete; |
| 610 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; | 758 InstARM32AdjustStack &operator=(const InstARM32AdjustStack &) = delete; |
| 611 | 759 |
| 612 public: | 760 public: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 Operand *getCallTarget() const { return getSrc(0); } | 794 Operand *getCallTarget() const { return getSrc(0); } |
| 647 void emit(const Cfg *Func) const override; | 795 void emit(const Cfg *Func) const override; |
| 648 void emitIAS(const Cfg *Func) const override; | 796 void emitIAS(const Cfg *Func) const override; |
| 649 void dump(const Cfg *Func) const override; | 797 void dump(const Cfg *Func) const override; |
| 650 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } | 798 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
| 651 | 799 |
| 652 private: | 800 private: |
| 653 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 801 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
| 654 }; | 802 }; |
| 655 | 803 |
| 656 // Integer compare instruction. | |
| 657 class InstARM32Cmp : public InstARM32Pred { | |
| 658 InstARM32Cmp() = delete; | |
| 659 InstARM32Cmp(const InstARM32Cmp &) = delete; | |
| 660 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; | |
| 661 | |
| 662 public: | |
| 663 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, | |
| 664 CondARM32::Cond Predicate) { | |
| 665 return new (Func->allocate<InstARM32Cmp>()) | |
| 666 InstARM32Cmp(Func, Src1, Src2, Predicate); | |
| 667 } | |
| 668 void emit(const Cfg *Func) const override; | |
| 669 void emitIAS(const Cfg *Func) const override; | |
| 670 void dump(const Cfg *Func) const override; | |
| 671 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } | |
| 672 | |
| 673 private: | |
| 674 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, | |
| 675 CondARM32::Cond Predicate); | |
| 676 }; | |
| 677 | |
| 678 // Load instruction. | 804 // Load instruction. |
| 679 class InstARM32Ldr : public InstARM32Pred { | 805 class InstARM32Ldr : public InstARM32Pred { |
| 680 InstARM32Ldr() = delete; | 806 InstARM32Ldr() = delete; |
| 681 InstARM32Ldr(const InstARM32Ldr &) = delete; | 807 InstARM32Ldr(const InstARM32Ldr &) = delete; |
| 682 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; | 808 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; |
| 683 | 809 |
| 684 public: | 810 public: |
| 685 // Dest must be a register. | 811 // Dest must be a register. |
| 686 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, | 812 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 687 CondARM32::Cond Predicate) { | 813 CondARM32::Cond Predicate) { |
| 688 return new (Func->allocate<InstARM32Ldr>()) | 814 return new (Func->allocate<InstARM32Ldr>()) |
| 689 InstARM32Ldr(Func, Dest, Mem, Predicate); | 815 InstARM32Ldr(Func, Dest, Mem, Predicate); |
| 690 } | 816 } |
| 691 void emit(const Cfg *Func) const override; | 817 void emit(const Cfg *Func) const override; |
| 692 void emitIAS(const Cfg *Func) const override; | 818 void emitIAS(const Cfg *Func) const override; |
| 693 void dump(const Cfg *Func) const override; | 819 void dump(const Cfg *Func) const override; |
| 694 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } | 820 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } |
| 695 | 821 |
| 696 private: | 822 private: |
| 697 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, | 823 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 698 CondARM32::Cond Predicate); | 824 CondARM32::Cond Predicate); |
| 699 }; | 825 }; |
| 700 | 826 |
| 701 // Multiply Accumulate: d := x * y + a | |
| 702 class InstARM32Mla : public InstARM32Pred { | |
| 703 InstARM32Mla() = delete; | |
| 704 InstARM32Mla(const InstARM32Mla &) = delete; | |
| 705 InstARM32Mla &operator=(const InstARM32Mla &) = delete; | |
| 706 | |
| 707 public: | |
| 708 // Everything must be a register. | |
| 709 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, | |
| 710 Variable *Src1, Variable *Acc, | |
| 711 CondARM32::Cond Predicate) { | |
| 712 return new (Func->allocate<InstARM32Mla>()) | |
| 713 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); | |
| 714 } | |
| 715 void emit(const Cfg *Func) const override; | |
| 716 void emitIAS(const Cfg *Func) const override; | |
| 717 void dump(const Cfg *Func) const override; | |
| 718 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } | |
| 719 | |
| 720 private: | |
| 721 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, | |
| 722 Variable *Acc, CondARM32::Cond Predicate); | |
| 723 }; | |
| 724 | |
| 725 // Pop into a list of GPRs. Technically this can be predicated, but we don't | 827 // Pop into a list of GPRs. Technically this can be predicated, but we don't |
| 726 // need that functionality. | 828 // need that functionality. |
| 727 class InstARM32Pop : public InstARM32 { | 829 class InstARM32Pop : public InstARM32 { |
| 728 InstARM32Pop() = delete; | 830 InstARM32Pop() = delete; |
| 729 InstARM32Pop(const InstARM32Pop &) = delete; | 831 InstARM32Pop(const InstARM32Pop &) = delete; |
| 730 InstARM32Pop &operator=(const InstARM32Pop &) = delete; | 832 InstARM32Pop &operator=(const InstARM32Pop &) = delete; |
| 731 | 833 |
| 732 public: | 834 public: |
| 733 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { | 835 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { |
| 734 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); | 836 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 void emit(const Cfg *Func) const override; | 911 void emit(const Cfg *Func) const override; |
| 810 void emitIAS(const Cfg *Func) const override; | 912 void emitIAS(const Cfg *Func) const override; |
| 811 void dump(const Cfg *Func) const override; | 913 void dump(const Cfg *Func) const override; |
| 812 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } | 914 static bool classof(const Inst *Inst) { return isClassof(Inst, Str); } |
| 813 | 915 |
| 814 private: | 916 private: |
| 815 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, | 917 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, |
| 816 CondARM32::Cond Predicate); | 918 CondARM32::Cond Predicate); |
| 817 }; | 919 }; |
| 818 | 920 |
| 921 class InstARM32Trap : public InstARM32 { |
| 922 InstARM32Trap() = delete; |
| 923 InstARM32Trap(const InstARM32Trap &) = delete; |
| 924 InstARM32Trap &operator=(const InstARM32Trap &) = delete; |
| 925 |
| 926 public: |
| 927 static InstARM32Trap *create(Cfg *Func) { |
| 928 return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func); |
| 929 } |
| 930 void emit(const Cfg *Func) const override; |
| 931 void emitIAS(const Cfg *Func) const override; |
| 932 void dump(const Cfg *Func) const override; |
| 933 static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); } |
| 934 |
| 935 private: |
| 936 explicit InstARM32Trap(Cfg *Func); |
| 937 }; |
| 938 |
| 819 // Unsigned Multiply Long: d.lo, d.hi := x * y | 939 // Unsigned Multiply Long: d.lo, d.hi := x * y |
| 820 class InstARM32Umull : public InstARM32Pred { | 940 class InstARM32Umull : public InstARM32Pred { |
| 821 InstARM32Umull() = delete; | 941 InstARM32Umull() = delete; |
| 822 InstARM32Umull(const InstARM32Umull &) = delete; | 942 InstARM32Umull(const InstARM32Umull &) = delete; |
| 823 InstARM32Umull &operator=(const InstARM32Umull &) = delete; | 943 InstARM32Umull &operator=(const InstARM32Umull &) = delete; |
| 824 | 944 |
| 825 public: | 945 public: |
| 826 // Everything must be a register. | 946 // Everything must be a register. |
| 827 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, | 947 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 828 Variable *Src0, Variable *Src1, | 948 Variable *Src0, Variable *Src1, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 845 // Declare partial template specializations of emit() methods that | 965 // Declare partial template specializations of emit() methods that |
| 846 // already have default implementations. Without this, there is the | 966 // already have default implementations. Without this, there is the |
| 847 // possibility of ODR violations and link errors. | 967 // possibility of ODR violations and link errors. |
| 848 | 968 |
| 849 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 969 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
| 850 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 970 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
| 851 | 971 |
| 852 } // end of namespace Ice | 972 } // end of namespace Ice |
| 853 | 973 |
| 854 #endif // SUBZERO_SRC_ICEINSTARM32_H | 974 #endif // SUBZERO_SRC_ICEINSTARM32_H |
| OLD | NEW |