| 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 |