OLD | NEW |
1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// | 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// |
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 |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 Dest->emit(Func); | 758 Dest->emit(Func); |
759 Str << ", "; | 759 Str << ", "; |
760 SrcLo->emit(Func); | 760 SrcLo->emit(Func); |
761 Str << ", "; | 761 Str << ", "; |
762 SrcHi->emit(Func); | 762 SrcHi->emit(Func); |
763 } | 763 } |
764 | 764 |
765 namespace { | 765 namespace { |
766 | 766 |
767 bool isVariableWithoutRegister(const Operand *Op) { | 767 bool isVariableWithoutRegister(const Operand *Op) { |
768 if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) { | 768 if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) { |
769 return !OpV->hasReg(); | 769 return !OpV->hasReg(); |
770 } | 770 } |
771 return false; | 771 return false; |
772 } | 772 } |
773 bool isMemoryAccess(Operand *Op) { | 773 bool isMemoryAccess(Operand *Op) { |
774 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); | 774 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); |
775 } | 775 } |
776 | 776 |
777 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { | 777 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { |
778 const Type DestTy = Dest->getType(); | 778 const Type DestTy = Dest->getType(); |
779 const Type SrcTy = Src->getType(); | 779 const Type SrcTy = Src->getType(); |
780 return !isVectorType(DestTy) && !isVectorType(SrcTy) && | 780 return !isVectorType(DestTy) && !isVectorType(SrcTy) && |
781 (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy)); | 781 (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy)); |
782 } | 782 } |
783 | 783 |
784 } // end of anonymous namespace | 784 } // end of anonymous namespace |
785 | 785 |
786 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { | 786 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { |
787 if (!BuildDefs::dump()) | 787 if (!BuildDefs::dump()) |
788 return; | 788 return; |
789 Ostream &Str = Func->getContext()->getStrEmit(); | 789 Ostream &Str = Func->getContext()->getStrEmit(); |
790 Variable *Dest = getDest(); | 790 Variable *Dest = getDest(); |
791 | 791 |
792 if (Dest->hasReg()) { | 792 if (!Dest->hasReg()) { |
793 Type Ty = Dest->getType(); | 793 llvm::report_fatal_error("mov can't store."); |
794 Operand *Src0 = getSrc(0); | 794 } |
795 const bool IsVector = isVectorType(Ty); | 795 |
796 const bool IsScalarFP = isScalarFloatingType(Ty); | 796 Operand *Src0 = getSrc(0); |
797 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); | 797 if (isMemoryAccess(Src0)) { |
798 const char *LoadOpcode = IsVector ? "vld1" : (IsScalarFP ? "vldr" : "ldr"); | 798 llvm::report_fatal_error("mov can't load."); |
799 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); | 799 } |
800 const char *RegMovOpcode = IsVMove ? "vmov" : "mov"; | 800 |
801 const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode; | 801 Type Ty = Dest->getType(); |
802 // when vmov{c}'ing, we need to emit a width string. Otherwise, the | 802 const bool IsVector = isVectorType(Ty); |
803 // assembler might be tempted to assume we want a vector vmov{c}, and that | 803 const bool IsScalarFP = isScalarFloatingType(Ty); |
804 // is disallowed because ARM. | 804 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); |
805 const char *NoWidthString = ""; | 805 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); |
806 const char *WidthString = | 806 const char *Opcode = IsVMove ? "vmov" : "mov"; |
807 isMemoryAccess(Src0) | 807 // when vmov{c}'ing, we need to emit a width string. Otherwise, the |
808 ? (IsVector ? ".64" : getWidthString(Ty)) | 808 // assembler might be tempted to assume we want a vector vmov{c}, and that |
809 : (!CoreVFPMove ? getVecWidthString(Ty) : NoWidthString); | 809 // is disallowed because ARM. |
810 Str << "\t" << ActualOpcode; | 810 const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : ""; |
811 const bool IsVInst = IsVMove || IsVector || IsScalarFP; | 811 Str << "\t" << Opcode; |
812 if (IsVInst) { | 812 if (IsVMove) { |
813 Str << getPredicate() << WidthString; | 813 Str << getPredicate() << WidthString; |
814 } else { | |
815 Str << WidthString << getPredicate(); | |
816 } | |
817 Str << "\t"; | |
818 Dest->emit(Func); | |
819 Str << ", "; | |
820 Src0->emit(Func); | |
821 } else { | 814 } else { |
822 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 815 Str << WidthString << getPredicate(); |
823 assert(Src0->hasReg()); | |
824 Type Ty = Src0->getType(); | |
825 const bool IsVector = isVectorType(Ty); | |
826 const bool IsScalarFP = isScalarFloatingType(Ty); | |
827 const char *ActualOpcode = | |
828 IsVector ? "vst1" : (IsScalarFP ? "vstr" : "str"); | |
829 const char *WidthString = IsVector ? ".64" : getWidthString(Ty); | |
830 Str << "\t" << ActualOpcode; | |
831 const bool IsVInst = IsVector || IsScalarFP; | |
832 if (IsVInst) { | |
833 Str << getPredicate() << WidthString; | |
834 } else { | |
835 Str << WidthString << getPredicate(); | |
836 } | |
837 Str << "\t"; | |
838 Src0->emit(Func); | |
839 Str << ", "; | |
840 Dest->emit(Func); | |
841 } | 816 } |
| 817 Str << "\t"; |
| 818 Dest->emit(Func); |
| 819 Str << ", "; |
| 820 Src0->emit(Func); |
842 } | 821 } |
843 | 822 |
844 void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { | 823 void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { |
845 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 824 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
846 Variable *Dest = getDest(); | 825 Variable *Dest = getDest(); |
847 Operand *Src0 = getSrc(0); | 826 Operand *Src0 = getSrc(0); |
848 if (Dest->hasReg()) { | 827 |
849 const Type DestTy = Dest->getType(); | 828 if (!Dest->hasReg()) { |
850 const bool DestIsVector = isVectorType(DestTy); | 829 llvm::report_fatal_error("mov can't store."); |
851 const bool DestIsScalarFP = isScalarFloatingType(DestTy); | |
852 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); | |
853 if (DestIsVector || DestIsScalarFP || CoreVFPMove) | |
854 return Asm->setNeedsTextFixup(); | |
855 if (isMemoryAccess(Src0)) { | |
856 // TODO(kschimpf) Figure out how to do ldr on CoreVPFMove? (see | |
857 // emitSingleDestSingleSource, local variable LoadOpcode). | |
858 return Asm->ldr(Dest, Src0, getPredicate(), Func->getTarget()); | |
859 } | |
860 return Asm->mov(Dest, Src0, getPredicate()); | |
861 } else { | |
862 const Type Src0Type = Src0->getType(); | |
863 const bool Src0IsVector = isVectorType(Src0Type); | |
864 const bool Src0IsScalarFP = isScalarFloatingType(Src0Type); | |
865 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); | |
866 if (Src0IsVector || Src0IsScalarFP || CoreVFPMove) | |
867 return Asm->setNeedsTextFixup(); | |
868 return Asm->str(Src0, Dest, getPredicate(), Func->getTarget()); | |
869 } | 830 } |
| 831 |
| 832 if (isMemoryAccess(Src0)) { |
| 833 llvm::report_fatal_error("mov can't load."); |
| 834 } |
| 835 |
| 836 const Type DestTy = Dest->getType(); |
| 837 const bool DestIsVector = isVectorType(DestTy); |
| 838 const bool DestIsScalarFP = isScalarFloatingType(DestTy); |
| 839 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); |
| 840 if (DestIsVector || DestIsScalarFP || CoreVFPMove) |
| 841 return Asm->setNeedsTextFixup(); |
| 842 return Asm->mov(Dest, Src0, getPredicate()); |
870 } | 843 } |
871 | 844 |
872 void InstARM32Mov::emit(const Cfg *Func) const { | 845 void InstARM32Mov::emit(const Cfg *Func) const { |
873 if (!BuildDefs::dump()) | 846 if (!BuildDefs::dump()) |
874 return; | 847 return; |
875 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); | 848 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); |
876 if (isMultiDest()) { | 849 if (isMultiDest()) { |
877 emitMultiDestSingleSource(Func); | 850 emitMultiDestSingleSource(Func); |
878 return; | 851 return; |
879 } | 852 } |
(...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1945 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 1918 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
1946 | 1919 |
1947 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 1920 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
1948 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 1921 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
1949 | 1922 |
1950 template class InstARM32CmpLike<InstARM32::Cmn>; | 1923 template class InstARM32CmpLike<InstARM32::Cmn>; |
1951 template class InstARM32CmpLike<InstARM32::Cmp>; | 1924 template class InstARM32CmpLike<InstARM32::Cmp>; |
1952 template class InstARM32CmpLike<InstARM32::Tst>; | 1925 template class InstARM32CmpLike<InstARM32::Tst>; |
1953 | 1926 |
1954 } // end of namespace Ice | 1927 } // end of namespace Ice |
OLD | NEW |