| //===-- ARMInstrNEON.td - NEON support for ARM -------------*- tablegen -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file describes the ARM NEON instruction set. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| |
| //===----------------------------------------------------------------------===// |
| // NEON-specific Operands. |
| //===----------------------------------------------------------------------===// |
| def nModImm : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| } |
| |
| def nImmSplatI8AsmOperand : AsmOperandClass { let Name = "NEONi8splat"; } |
| def nImmSplatI8 : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmSplatI8AsmOperand; |
| } |
| def nImmSplatI16AsmOperand : AsmOperandClass { let Name = "NEONi16splat"; } |
| def nImmSplatI16 : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmSplatI16AsmOperand; |
| } |
| def nImmSplatI32AsmOperand : AsmOperandClass { let Name = "NEONi32splat"; } |
| def nImmSplatI32 : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmSplatI32AsmOperand; |
| } |
| def nImmSplatNotI16AsmOperand : AsmOperandClass { let Name = "NEONi16splatNot"; } |
| def nImmSplatNotI16 : Operand<i32> { |
| let ParserMatchClass = nImmSplatNotI16AsmOperand; |
| } |
| def nImmSplatNotI32AsmOperand : AsmOperandClass { let Name = "NEONi32splatNot"; } |
| def nImmSplatNotI32 : Operand<i32> { |
| let ParserMatchClass = nImmSplatNotI32AsmOperand; |
| } |
| def nImmVMOVI32AsmOperand : AsmOperandClass { let Name = "NEONi32vmov"; } |
| def nImmVMOVI32 : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmVMOVI32AsmOperand; |
| } |
| |
| class nImmVMOVIAsmOperandReplicate<ValueType From, ValueType To> |
| : AsmOperandClass { |
| let Name = "NEONi" # To.Size # "vmovi" # From.Size # "Replicate"; |
| let PredicateMethod = "isNEONmovReplicate<" # From.Size # ", " # To.Size # ">"; |
| let RenderMethod = "addNEONvmovi" # From.Size # "ReplicateOperands"; |
| } |
| |
| class nImmVINVIAsmOperandReplicate<ValueType From, ValueType To> |
| : AsmOperandClass { |
| let Name = "NEONi" # To.Size # "invi" # From.Size # "Replicate"; |
| let PredicateMethod = "isNEONinvReplicate<" # From.Size # ", " # To.Size # ">"; |
| let RenderMethod = "addNEONinvi" # From.Size # "ReplicateOperands"; |
| } |
| |
| class nImmVMOVIReplicate<ValueType From, ValueType To> : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmVMOVIAsmOperandReplicate<From, To>; |
| } |
| |
| class nImmVINVIReplicate<ValueType From, ValueType To> : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmVINVIAsmOperandReplicate<From, To>; |
| } |
| |
| def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; } |
| def nImmVMOVI32Neg : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmVMOVI32NegAsmOperand; |
| } |
| def nImmVMOVF32 : Operand<i32> { |
| let PrintMethod = "printFPImmOperand"; |
| let ParserMatchClass = FPImmOperand; |
| } |
| def nImmSplatI64AsmOperand : AsmOperandClass { let Name = "NEONi64splat"; } |
| def nImmSplatI64 : Operand<i32> { |
| let PrintMethod = "printVMOVModImmOperand"; |
| let ParserMatchClass = nImmSplatI64AsmOperand; |
| } |
| |
| def VectorIndex8Operand : AsmOperandClass { let Name = "VectorIndex8"; } |
| def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; } |
| def VectorIndex32Operand : AsmOperandClass { let Name = "VectorIndex32"; } |
| def VectorIndex64Operand : AsmOperandClass { let Name = "VectorIndex64"; } |
| def VectorIndex8 : Operand<i32>, ImmLeaf<i32, [{ |
| return ((uint64_t)Imm) < 8; |
| }]> { |
| let ParserMatchClass = VectorIndex8Operand; |
| let PrintMethod = "printVectorIndex"; |
| let MIOperandInfo = (ops i32imm); |
| } |
| def VectorIndex16 : Operand<i32>, ImmLeaf<i32, [{ |
| return ((uint64_t)Imm) < 4; |
| }]> { |
| let ParserMatchClass = VectorIndex16Operand; |
| let PrintMethod = "printVectorIndex"; |
| let MIOperandInfo = (ops i32imm); |
| } |
| def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{ |
| return ((uint64_t)Imm) < 2; |
| }]> { |
| let ParserMatchClass = VectorIndex32Operand; |
| let PrintMethod = "printVectorIndex"; |
| let MIOperandInfo = (ops i32imm); |
| } |
| def VectorIndex64 : Operand<i32>, ImmLeaf<i32, [{ |
| return ((uint64_t)Imm) < 1; |
| }]> { |
| let ParserMatchClass = VectorIndex64Operand; |
| let PrintMethod = "printVectorIndex"; |
| let MIOperandInfo = (ops i32imm); |
| } |
| |
| // Register list of one D register. |
| def VecListOneDAsmOperand : AsmOperandClass { |
| let Name = "VecListOneD"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListOneD : RegisterOperand<DPR, "printVectorListOne"> { |
| let ParserMatchClass = VecListOneDAsmOperand; |
| } |
| // Register list of two sequential D registers. |
| def VecListDPairAsmOperand : AsmOperandClass { |
| let Name = "VecListDPair"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListDPair : RegisterOperand<DPair, "printVectorListTwo"> { |
| let ParserMatchClass = VecListDPairAsmOperand; |
| } |
| // Register list of three sequential D registers. |
| def VecListThreeDAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeD"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListThreeD : RegisterOperand<DPR, "printVectorListThree"> { |
| let ParserMatchClass = VecListThreeDAsmOperand; |
| } |
| // Register list of four sequential D registers. |
| def VecListFourDAsmOperand : AsmOperandClass { |
| let Name = "VecListFourD"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListFourD : RegisterOperand<DPR, "printVectorListFour"> { |
| let ParserMatchClass = VecListFourDAsmOperand; |
| } |
| // Register list of two D registers spaced by 2 (two sequential Q registers). |
| def VecListDPairSpacedAsmOperand : AsmOperandClass { |
| let Name = "VecListDPairSpaced"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListDPairSpaced : RegisterOperand<DPair, "printVectorListTwoSpaced"> { |
| let ParserMatchClass = VecListDPairSpacedAsmOperand; |
| } |
| // Register list of three D registers spaced by 2 (three Q registers). |
| def VecListThreeQAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeQ"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListThreeQ : RegisterOperand<DPR, "printVectorListThreeSpaced"> { |
| let ParserMatchClass = VecListThreeQAsmOperand; |
| } |
| // Register list of three D registers spaced by 2 (three Q registers). |
| def VecListFourQAsmOperand : AsmOperandClass { |
| let Name = "VecListFourQ"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListFourQ : RegisterOperand<DPR, "printVectorListFourSpaced"> { |
| let ParserMatchClass = VecListFourQAsmOperand; |
| } |
| |
| // Register list of one D register, with "all lanes" subscripting. |
| def VecListOneDAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListOneDAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListOneDAllLanes : RegisterOperand<DPR, "printVectorListOneAllLanes"> { |
| let ParserMatchClass = VecListOneDAllLanesAsmOperand; |
| } |
| // Register list of two D registers, with "all lanes" subscripting. |
| def VecListDPairAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListDPairAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListDPairAllLanes : RegisterOperand<DPair, |
| "printVectorListTwoAllLanes"> { |
| let ParserMatchClass = VecListDPairAllLanesAsmOperand; |
| } |
| // Register list of two D registers spaced by 2 (two sequential Q registers). |
| def VecListDPairSpacedAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListDPairSpacedAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListDPairSpacedAllLanes : RegisterOperand<DPairSpc, |
| "printVectorListTwoSpacedAllLanes"> { |
| let ParserMatchClass = VecListDPairSpacedAllLanesAsmOperand; |
| } |
| // Register list of three D registers, with "all lanes" subscripting. |
| def VecListThreeDAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeDAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListThreeDAllLanes : RegisterOperand<DPR, |
| "printVectorListThreeAllLanes"> { |
| let ParserMatchClass = VecListThreeDAllLanesAsmOperand; |
| } |
| // Register list of three D registers spaced by 2 (three sequential Q regs). |
| def VecListThreeQAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeQAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListThreeQAllLanes : RegisterOperand<DPR, |
| "printVectorListThreeSpacedAllLanes"> { |
| let ParserMatchClass = VecListThreeQAllLanesAsmOperand; |
| } |
| // Register list of four D registers, with "all lanes" subscripting. |
| def VecListFourDAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListFourDAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListFourDAllLanes : RegisterOperand<DPR, "printVectorListFourAllLanes"> { |
| let ParserMatchClass = VecListFourDAllLanesAsmOperand; |
| } |
| // Register list of four D registers spaced by 2 (four sequential Q regs). |
| def VecListFourQAllLanesAsmOperand : AsmOperandClass { |
| let Name = "VecListFourQAllLanes"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListOperands"; |
| } |
| def VecListFourQAllLanes : RegisterOperand<DPR, |
| "printVectorListFourSpacedAllLanes"> { |
| let ParserMatchClass = VecListFourQAllLanesAsmOperand; |
| } |
| |
| |
| // Register list of one D register, with byte lane subscripting. |
| def VecListOneDByteIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListOneDByteIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListOneDByteIndexed : Operand<i32> { |
| let ParserMatchClass = VecListOneDByteIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with half-word lane subscripting. |
| def VecListOneDHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListOneDHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListOneDHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListOneDHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListOneDWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListOneDWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListOneDWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListOneDWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| |
| // Register list of two D registers with byte lane subscripting. |
| def VecListTwoDByteIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListTwoDByteIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListTwoDByteIndexed : Operand<i32> { |
| let ParserMatchClass = VecListTwoDByteIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with half-word lane subscripting. |
| def VecListTwoDHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListTwoDHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListTwoDHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListTwoDHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListTwoDWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListTwoDWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListTwoDWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListTwoDWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // Register list of two Q registers with half-word lane subscripting. |
| def VecListTwoQHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListTwoQHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListTwoQHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListTwoQHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListTwoQWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListTwoQWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListTwoQWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListTwoQWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| |
| |
| // Register list of three D registers with byte lane subscripting. |
| def VecListThreeDByteIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeDByteIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListThreeDByteIndexed : Operand<i32> { |
| let ParserMatchClass = VecListThreeDByteIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with half-word lane subscripting. |
| def VecListThreeDHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeDHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListThreeDHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListThreeDHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListThreeDWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeDWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListThreeDWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListThreeDWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // Register list of three Q registers with half-word lane subscripting. |
| def VecListThreeQHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeQHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListThreeQHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListThreeQHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListThreeQWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListThreeQWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListThreeQWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListThreeQWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| |
| // Register list of four D registers with byte lane subscripting. |
| def VecListFourDByteIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListFourDByteIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListFourDByteIndexed : Operand<i32> { |
| let ParserMatchClass = VecListFourDByteIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with half-word lane subscripting. |
| def VecListFourDHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListFourDHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListFourDHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListFourDHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListFourDWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListFourDWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListFourDWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListFourDWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // Register list of four Q registers with half-word lane subscripting. |
| def VecListFourQHWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListFourQHWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListFourQHWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListFourQHWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| // ...with word lane subscripting. |
| def VecListFourQWordIndexAsmOperand : AsmOperandClass { |
| let Name = "VecListFourQWordIndexed"; |
| let ParserMethod = "parseVectorList"; |
| let RenderMethod = "addVecListIndexedOperands"; |
| } |
| def VecListFourQWordIndexed : Operand<i32> { |
| let ParserMatchClass = VecListFourQWordIndexAsmOperand; |
| let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); |
| } |
| |
| def dword_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ |
| return cast<LoadSDNode>(N)->getAlignment() >= 8; |
| }]>; |
| def dword_alignedstore : PatFrag<(ops node:$val, node:$ptr), |
| (store node:$val, node:$ptr), [{ |
| return cast<StoreSDNode>(N)->getAlignment() >= 8; |
| }]>; |
| def word_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ |
| return cast<LoadSDNode>(N)->getAlignment() == 4; |
| }]>; |
| def word_alignedstore : PatFrag<(ops node:$val, node:$ptr), |
| (store node:$val, node:$ptr), [{ |
| return cast<StoreSDNode>(N)->getAlignment() == 4; |
| }]>; |
| def hword_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ |
| return cast<LoadSDNode>(N)->getAlignment() == 2; |
| }]>; |
| def hword_alignedstore : PatFrag<(ops node:$val, node:$ptr), |
| (store node:$val, node:$ptr), [{ |
| return cast<StoreSDNode>(N)->getAlignment() == 2; |
| }]>; |
| def byte_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ |
| return cast<LoadSDNode>(N)->getAlignment() == 1; |
| }]>; |
| def byte_alignedstore : PatFrag<(ops node:$val, node:$ptr), |
| (store node:$val, node:$ptr), [{ |
| return cast<StoreSDNode>(N)->getAlignment() == 1; |
| }]>; |
| def non_word_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ |
| return cast<LoadSDNode>(N)->getAlignment() < 4; |
| }]>; |
| def non_word_alignedstore : PatFrag<(ops node:$val, node:$ptr), |
| (store node:$val, node:$ptr), [{ |
| return cast<StoreSDNode>(N)->getAlignment() < 4; |
| }]>; |
| |
| //===----------------------------------------------------------------------===// |
| // NEON-specific DAG Nodes. |
| //===----------------------------------------------------------------------===// |
| |
| def SDTARMVTST : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<1, 2>]>; |
| def NEONvtst : SDNode<"ARMISD::VTST", SDTARMVTST>; |
| |
| // Types for vector shift by immediates. The "SHX" version is for long and |
| // narrow operations where the source and destination vectors have different |
| // types. The "SHINS" version is for shift and insert operations. |
| def SDTARMVSHXIMM : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, |
| SDTCisVT<2, i32>]>; |
| def SDTARMVSHINSIMM : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, |
| SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; |
| |
| def NEONvshrnImm : SDNode<"ARMISD::VSHRNIMM", SDTARMVSHXIMM>; |
| |
| def NEONvrshrsImm : SDNode<"ARMISD::VRSHRsIMM", SDTARMVSHIMM>; |
| def NEONvrshruImm : SDNode<"ARMISD::VRSHRuIMM", SDTARMVSHIMM>; |
| def NEONvrshrnImm : SDNode<"ARMISD::VRSHRNIMM", SDTARMVSHXIMM>; |
| |
| def NEONvqshlsImm : SDNode<"ARMISD::VQSHLsIMM", SDTARMVSHIMM>; |
| def NEONvqshluImm : SDNode<"ARMISD::VQSHLuIMM", SDTARMVSHIMM>; |
| def NEONvqshlsuImm : SDNode<"ARMISD::VQSHLsuIMM", SDTARMVSHIMM>; |
| def NEONvqshrnsImm : SDNode<"ARMISD::VQSHRNsIMM", SDTARMVSHXIMM>; |
| def NEONvqshrnuImm : SDNode<"ARMISD::VQSHRNuIMM", SDTARMVSHXIMM>; |
| def NEONvqshrnsuImm : SDNode<"ARMISD::VQSHRNsuIMM", SDTARMVSHXIMM>; |
| |
| def NEONvqrshrnsImm : SDNode<"ARMISD::VQRSHRNsIMM", SDTARMVSHXIMM>; |
| def NEONvqrshrnuImm : SDNode<"ARMISD::VQRSHRNuIMM", SDTARMVSHXIMM>; |
| def NEONvqrshrnsuImm : SDNode<"ARMISD::VQRSHRNsuIMM", SDTARMVSHXIMM>; |
| |
| def NEONvsliImm : SDNode<"ARMISD::VSLIIMM", SDTARMVSHINSIMM>; |
| def NEONvsriImm : SDNode<"ARMISD::VSRIIMM", SDTARMVSHINSIMM>; |
| |
| def NEONvbsp : SDNode<"ARMISD::VBSP", |
| SDTypeProfile<1, 3, [SDTCisVec<0>, |
| SDTCisSameAs<0, 1>, |
| SDTCisSameAs<0, 2>, |
| SDTCisSameAs<0, 3>]>>; |
| |
| def SDTARMVEXT : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, |
| SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; |
| def NEONvext : SDNode<"ARMISD::VEXT", SDTARMVEXT>; |
| |
| def SDTARMVSHUF2 : SDTypeProfile<2, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, |
| SDTCisSameAs<0, 2>, |
| SDTCisSameAs<0, 3>]>; |
| def NEONzip : SDNode<"ARMISD::VZIP", SDTARMVSHUF2>; |
| def NEONuzp : SDNode<"ARMISD::VUZP", SDTARMVSHUF2>; |
| def NEONtrn : SDNode<"ARMISD::VTRN", SDTARMVSHUF2>; |
| |
| def SDTARMVTBL1 : SDTypeProfile<1, 2, [SDTCisVT<0, v8i8>, SDTCisVT<1, v8i8>, |
| SDTCisVT<2, v8i8>]>; |
| def SDTARMVTBL2 : SDTypeProfile<1, 3, [SDTCisVT<0, v8i8>, SDTCisVT<1, v8i8>, |
| SDTCisVT<2, v8i8>, SDTCisVT<3, v8i8>]>; |
| def NEONvtbl1 : SDNode<"ARMISD::VTBL1", SDTARMVTBL1>; |
| def NEONvtbl2 : SDNode<"ARMISD::VTBL2", SDTARMVTBL2>; |
| |
| |
| //===----------------------------------------------------------------------===// |
| // NEON load / store instructions |
| //===----------------------------------------------------------------------===// |
| |
| // Use VLDM to load a Q register as a D register pair. |
| // This is a pseudo instruction that is expanded to VLDMD after reg alloc. |
| def VLDMQIA |
| : PseudoVFPLdStM<(outs DPair:$dst), (ins GPR:$Rn), |
| IIC_fpLoad_m, "", |
| [(set DPair:$dst, (v2f64 (word_alignedload GPR:$Rn)))]>; |
| |
| // Use VSTM to store a Q register as a D register pair. |
| // This is a pseudo instruction that is expanded to VSTMD after reg alloc. |
| def VSTMQIA |
| : PseudoVFPLdStM<(outs), (ins DPair:$src, GPR:$Rn), |
| IIC_fpStore_m, "", |
| [(word_alignedstore (v2f64 DPair:$src), GPR:$Rn)]>; |
| |
| // Classes for VLD* pseudo-instructions with multi-register operands. |
| // These are expanded to real instructions after register allocation. |
| class VLDQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst), (ins addrmode6:$addr), itin, "">; |
| class VLDQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset), itin, |
| "$addr.addr = $wb">; |
| class VLDQWBfixedPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr), itin, |
| "$addr.addr = $wb">; |
| class VLDQWBregisterPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, rGPR:$offset), itin, |
| "$addr.addr = $wb">; |
| |
| class VLDQQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst), (ins addrmode6:$addr), itin, "">; |
| class VLDQQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset), itin, |
| "$addr.addr = $wb">; |
| class VLDQQWBfixedPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr), itin, |
| "$addr.addr = $wb">; |
| class VLDQQWBregisterPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, rGPR:$offset), itin, |
| "$addr.addr = $wb">; |
| |
| |
| class VLDQQQQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin, |
| "$src = $dst">; |
| class VLDQQQQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, |
| "$addr.addr = $wb, $src = $dst">; |
| |
| let mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 in { |
| |
| // VLD1 : Vector Load (multiple single elements) |
| class VLD1D<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0,0b10,0b0111,op7_4, (outs VecListOneD:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD1, |
| "vld1", Dt, "$Vd, $Rn", "", []>, Sched<[WriteVLD1]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| class VLD1Q<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0,0b10,0b1010,op7_4, (outs VecListDPair:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD1x2, |
| "vld1", Dt, "$Vd, $Rn", "", []>, Sched<[WriteVLD2]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| |
| def VLD1d8 : VLD1D<{0,0,0,?}, "8", addrmode6align64>; |
| def VLD1d16 : VLD1D<{0,1,0,?}, "16", addrmode6align64>; |
| def VLD1d32 : VLD1D<{1,0,0,?}, "32", addrmode6align64>; |
| def VLD1d64 : VLD1D<{1,1,0,?}, "64", addrmode6align64>; |
| |
| def VLD1q8 : VLD1Q<{0,0,?,?}, "8", addrmode6align64or128>; |
| def VLD1q16 : VLD1Q<{0,1,?,?}, "16", addrmode6align64or128>; |
| def VLD1q32 : VLD1Q<{1,0,?,?}, "32", addrmode6align64or128>; |
| def VLD1q64 : VLD1Q<{1,1,?,?}, "64", addrmode6align64or128>; |
| |
| // ...with address register writeback: |
| multiclass VLD1DWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b10, 0b0111,op7_4, (outs VecListOneD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1u, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b10,0b0111,op7_4, (outs VecListOneD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1u, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| multiclass VLD1QWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b10,0b1010,op7_4, (outs VecListDPair:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD2]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b10,0b1010,op7_4, (outs VecListDPair:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD2]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| defm VLD1d8wb : VLD1DWB<{0,0,0,?}, "8", addrmode6align64>; |
| defm VLD1d16wb : VLD1DWB<{0,1,0,?}, "16", addrmode6align64>; |
| defm VLD1d32wb : VLD1DWB<{1,0,0,?}, "32", addrmode6align64>; |
| defm VLD1d64wb : VLD1DWB<{1,1,0,?}, "64", addrmode6align64>; |
| defm VLD1q8wb : VLD1QWB<{0,0,?,?}, "8", addrmode6align64or128>; |
| defm VLD1q16wb : VLD1QWB<{0,1,?,?}, "16", addrmode6align64or128>; |
| defm VLD1q32wb : VLD1QWB<{1,0,?,?}, "32", addrmode6align64or128>; |
| defm VLD1q64wb : VLD1QWB<{1,1,?,?}, "64", addrmode6align64or128>; |
| |
| // ...with 3 registers |
| class VLD1D3<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0,0b10,0b0110,op7_4, (outs VecListThreeD:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD1x3, "vld1", Dt, |
| "$Vd, $Rn", "", []>, Sched<[WriteVLD3]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| multiclass VLD1D3WB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b10,0b0110, op7_4, (outs VecListThreeD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD3]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b10,0b0110,op7_4, (outs VecListThreeD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD3]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| def VLD1d8T : VLD1D3<{0,0,0,?}, "8", addrmode6align64>; |
| def VLD1d16T : VLD1D3<{0,1,0,?}, "16", addrmode6align64>; |
| def VLD1d32T : VLD1D3<{1,0,0,?}, "32", addrmode6align64>; |
| def VLD1d64T : VLD1D3<{1,1,0,?}, "64", addrmode6align64>; |
| |
| defm VLD1d8Twb : VLD1D3WB<{0,0,0,?}, "8", addrmode6align64>; |
| defm VLD1d16Twb : VLD1D3WB<{0,1,0,?}, "16", addrmode6align64>; |
| defm VLD1d32Twb : VLD1D3WB<{1,0,0,?}, "32", addrmode6align64>; |
| defm VLD1d64Twb : VLD1D3WB<{1,1,0,?}, "64", addrmode6align64>; |
| |
| def VLD1d8TPseudo : VLDQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d8TPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d8TPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d16TPseudo : VLDQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d16TPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d16TPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d32TPseudo : VLDQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d32TPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d32TPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d64TPseudo : VLDQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d64TPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1d64TPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| |
| def VLD1q8HighTPseudo : VLDQQQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q8HighTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q8LowTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q16HighTPseudo : VLDQQQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q16HighTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q16LowTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q32HighTPseudo : VLDQQQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q32HighTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q32LowTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q64HighTPseudo : VLDQQQQPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q64HighTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| def VLD1q64LowTPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x3>, Sched<[WriteVLD3]>; |
| |
| // ...with 4 registers |
| class VLD1D4<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0, 0b10, 0b0010, op7_4, (outs VecListFourD:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD1x4, "vld1", Dt, |
| "$Vd, $Rn", "", []>, Sched<[WriteVLD4]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| multiclass VLD1D4WB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b10,0b0010, op7_4, (outs VecListFourD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD4]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b10,0b0010,op7_4, (outs VecListFourD:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1x2u, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD4]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| def VLD1d8Q : VLD1D4<{0,0,?,?}, "8", addrmode6align64or128or256>; |
| def VLD1d16Q : VLD1D4<{0,1,?,?}, "16", addrmode6align64or128or256>; |
| def VLD1d32Q : VLD1D4<{1,0,?,?}, "32", addrmode6align64or128or256>; |
| def VLD1d64Q : VLD1D4<{1,1,?,?}, "64", addrmode6align64or128or256>; |
| |
| defm VLD1d8Qwb : VLD1D4WB<{0,0,?,?}, "8", addrmode6align64or128or256>; |
| defm VLD1d16Qwb : VLD1D4WB<{0,1,?,?}, "16", addrmode6align64or128or256>; |
| defm VLD1d32Qwb : VLD1D4WB<{1,0,?,?}, "32", addrmode6align64or128or256>; |
| defm VLD1d64Qwb : VLD1D4WB<{1,1,?,?}, "64", addrmode6align64or128or256>; |
| |
| def VLD1d8QPseudo : VLDQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d8QPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d8QPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d16QPseudo : VLDQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d16QPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d16QPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d32QPseudo : VLDQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d32QPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d32QPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d64QPseudo : VLDQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d64QPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1d64QPseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| |
| def VLD1q8LowQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q8HighQPseudo : VLDQQQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q8HighQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q16LowQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q16HighQPseudo : VLDQQQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q16HighQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q32LowQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q32HighQPseudo : VLDQQQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q32HighQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q64LowQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q64HighQPseudo : VLDQQQQPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| def VLD1q64HighQPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD1x4>, Sched<[WriteVLD4]>; |
| |
| // VLD2 : Vector Load (multiple 2-element structures) |
| class VLD2<bits<4> op11_8, bits<4> op7_4, string Dt, RegisterOperand VdTy, |
| InstrItinClass itin, Operand AddrMode> |
| : NLdSt<0, 0b10, op11_8, op7_4, (outs VdTy:$Vd), |
| (ins AddrMode:$Rn), itin, |
| "vld2", Dt, "$Vd, $Rn", "", []> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| |
| def VLD2d8 : VLD2<0b1000, {0,0,?,?}, "8", VecListDPair, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| def VLD2d16 : VLD2<0b1000, {0,1,?,?}, "16", VecListDPair, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| def VLD2d32 : VLD2<0b1000, {1,0,?,?}, "32", VecListDPair, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| |
| def VLD2q8 : VLD2<0b0011, {0,0,?,?}, "8", VecListFourD, IIC_VLD2x2, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| def VLD2q16 : VLD2<0b0011, {0,1,?,?}, "16", VecListFourD, IIC_VLD2x2, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| def VLD2q32 : VLD2<0b0011, {1,0,?,?}, "32", VecListFourD, IIC_VLD2x2, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| |
| def VLD2q8Pseudo : VLDQQPseudo<IIC_VLD2x2>, Sched<[WriteVLD4]>; |
| def VLD2q16Pseudo : VLDQQPseudo<IIC_VLD2x2>, Sched<[WriteVLD4]>; |
| def VLD2q32Pseudo : VLDQQPseudo<IIC_VLD2x2>, Sched<[WriteVLD4]>; |
| |
| // ...with address register writeback: |
| multiclass VLD2WB<bits<4> op11_8, bits<4> op7_4, string Dt, |
| RegisterOperand VdTy, InstrItinClass itin, Operand AddrMode> { |
| def _fixed : NLdSt<0, 0b10, op11_8, op7_4, (outs VdTy:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), itin, |
| "vld2", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| def _register : NLdSt<0, 0b10, op11_8, op7_4, (outs VdTy:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), itin, |
| "vld2", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| } |
| |
| defm VLD2d8wb : VLD2WB<0b1000, {0,0,?,?}, "8", VecListDPair, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| defm VLD2d16wb : VLD2WB<0b1000, {0,1,?,?}, "16", VecListDPair, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| defm VLD2d32wb : VLD2WB<0b1000, {1,0,?,?}, "32", VecListDPair, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| |
| defm VLD2q8wb : VLD2WB<0b0011, {0,0,?,?}, "8", VecListFourD, IIC_VLD2x2u, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| defm VLD2q16wb : VLD2WB<0b0011, {0,1,?,?}, "16", VecListFourD, IIC_VLD2x2u, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| defm VLD2q32wb : VLD2WB<0b0011, {1,0,?,?}, "32", VecListFourD, IIC_VLD2x2u, |
| addrmode6align64or128or256>, Sched<[WriteVLD4]>; |
| |
| def VLD2q8PseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| def VLD2q16PseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| def VLD2q32PseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| def VLD2q8PseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| def VLD2q16PseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| def VLD2q32PseudoWB_register : VLDQQWBregisterPseudo<IIC_VLD2x2u>, Sched<[WriteVLD4]>; |
| |
| // ...with double-spaced registers |
| def VLD2b8 : VLD2<0b1001, {0,0,?,?}, "8", VecListDPairSpaced, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| def VLD2b16 : VLD2<0b1001, {0,1,?,?}, "16", VecListDPairSpaced, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| def VLD2b32 : VLD2<0b1001, {1,0,?,?}, "32", VecListDPairSpaced, IIC_VLD2, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| defm VLD2b8wb : VLD2WB<0b1001, {0,0,?,?}, "8", VecListDPairSpaced, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| defm VLD2b16wb : VLD2WB<0b1001, {0,1,?,?}, "16", VecListDPairSpaced, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| defm VLD2b32wb : VLD2WB<0b1001, {1,0,?,?}, "32", VecListDPairSpaced, IIC_VLD2u, |
| addrmode6align64or128>, Sched<[WriteVLD2]>; |
| |
| // VLD3 : Vector Load (multiple 3-element structures) |
| class VLD3D<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), |
| (ins addrmode6:$Rn), IIC_VLD3, |
| "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []>, Sched<[WriteVLD3]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST3Instruction"; |
| } |
| |
| def VLD3d8 : VLD3D<0b0100, {0,0,0,?}, "8">; |
| def VLD3d16 : VLD3D<0b0100, {0,1,0,?}, "16">; |
| def VLD3d32 : VLD3D<0b0100, {1,0,0,?}, "32">; |
| |
| def VLD3d8Pseudo : VLDQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| def VLD3d16Pseudo : VLDQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| def VLD3d32Pseudo : VLDQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| |
| // ...with address register writeback: |
| class VLD3DWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD3u, |
| "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD3]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST3Instruction"; |
| } |
| |
| def VLD3d8_UPD : VLD3DWB<0b0100, {0,0,0,?}, "8">; |
| def VLD3d16_UPD : VLD3DWB<0b0100, {0,1,0,?}, "16">; |
| def VLD3d32_UPD : VLD3DWB<0b0100, {1,0,0,?}, "32">; |
| |
| def VLD3d8Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3d16Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3d32Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| |
| // ...with double-spaced registers: |
| def VLD3q8 : VLD3D<0b0101, {0,0,0,?}, "8">; |
| def VLD3q16 : VLD3D<0b0101, {0,1,0,?}, "16">; |
| def VLD3q32 : VLD3D<0b0101, {1,0,0,?}, "32">; |
| def VLD3q8_UPD : VLD3DWB<0b0101, {0,0,0,?}, "8">; |
| def VLD3q16_UPD : VLD3DWB<0b0101, {0,1,0,?}, "16">; |
| def VLD3q32_UPD : VLD3DWB<0b0101, {1,0,0,?}, "32">; |
| |
| def VLD3q8Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3q16Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3q32Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| |
| // ...alternate versions to be allocated odd register numbers: |
| def VLD3q8oddPseudo : VLDQQQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| def VLD3q16oddPseudo : VLDQQQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| def VLD3q32oddPseudo : VLDQQQQPseudo<IIC_VLD3>, Sched<[WriteVLD3]>; |
| |
| def VLD3q8oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3q16oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| def VLD3q32oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3u>, Sched<[WriteVLD3]>; |
| |
| // VLD4 : Vector Load (multiple 4-element structures) |
| class VLD4D<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), |
| (ins addrmode6:$Rn), IIC_VLD4, |
| "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []>, |
| Sched<[WriteVLD4]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST4Instruction"; |
| } |
| |
| def VLD4d8 : VLD4D<0b0000, {0,0,?,?}, "8">; |
| def VLD4d16 : VLD4D<0b0000, {0,1,?,?}, "16">; |
| def VLD4d32 : VLD4D<0b0000, {1,0,?,?}, "32">; |
| |
| def VLD4d8Pseudo : VLDQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| def VLD4d16Pseudo : VLDQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| def VLD4d32Pseudo : VLDQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| |
| // ...with address register writeback: |
| class VLD4DWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD4u, |
| "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD4]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST4Instruction"; |
| } |
| |
| def VLD4d8_UPD : VLD4DWB<0b0000, {0,0,?,?}, "8">; |
| def VLD4d16_UPD : VLD4DWB<0b0000, {0,1,?,?}, "16">; |
| def VLD4d32_UPD : VLD4DWB<0b0000, {1,0,?,?}, "32">; |
| |
| def VLD4d8Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4d16Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4d32Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| |
| // ...with double-spaced registers: |
| def VLD4q8 : VLD4D<0b0001, {0,0,?,?}, "8">; |
| def VLD4q16 : VLD4D<0b0001, {0,1,?,?}, "16">; |
| def VLD4q32 : VLD4D<0b0001, {1,0,?,?}, "32">; |
| def VLD4q8_UPD : VLD4DWB<0b0001, {0,0,?,?}, "8">; |
| def VLD4q16_UPD : VLD4DWB<0b0001, {0,1,?,?}, "16">; |
| def VLD4q32_UPD : VLD4DWB<0b0001, {1,0,?,?}, "32">; |
| |
| def VLD4q8Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4q16Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4q32Pseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| |
| // ...alternate versions to be allocated odd register numbers: |
| def VLD4q8oddPseudo : VLDQQQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| def VLD4q16oddPseudo : VLDQQQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| def VLD4q32oddPseudo : VLDQQQQPseudo<IIC_VLD4>, Sched<[WriteVLD4]>; |
| |
| def VLD4q8oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4q16oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| def VLD4q32oddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4u>, Sched<[WriteVLD4]>; |
| |
| } // mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 |
| |
| // Classes for VLD*LN pseudo-instructions with multi-register operands. |
| // These are expanded to real instructions after register allocation. |
| class VLDQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst), |
| (ins addrmode6:$addr, QPR:$src, nohash_imm:$lane), |
| itin, "$src = $dst">; |
| class VLDQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; |
| class VLDQQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst), |
| (ins addrmode6:$addr, QQPR:$src, nohash_imm:$lane), |
| itin, "$src = $dst">; |
| class VLDQQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; |
| class VLDQQQQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQQQPR:$dst), |
| (ins addrmode6:$addr, QQQQPR:$src, nohash_imm:$lane), |
| itin, "$src = $dst">; |
| class VLDQQQQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; |
| |
| // VLD1LN : Vector Load (single element to one lane) |
| class VLD1LN<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty, |
| PatFrag LoadOp> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd), |
| (ins addrmode6:$Rn, DPR:$src, nohash_imm:$lane), |
| IIC_VLD1ln, "vld1", Dt, "\\{$Vd[$lane]\\}, $Rn", |
| "$src = $Vd", |
| [(set DPR:$Vd, (vector_insert (Ty DPR:$src), |
| (i32 (LoadOp addrmode6:$Rn)), |
| imm:$lane))]> { |
| let Rm = 0b1111; |
| let DecoderMethod = "DecodeVLD1LN"; |
| } |
| class VLD1LN32<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty, |
| PatFrag LoadOp> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd), |
| (ins addrmode6oneL32:$Rn, DPR:$src, nohash_imm:$lane), |
| IIC_VLD1ln, "vld1", Dt, "\\{$Vd[$lane]\\}, $Rn", |
| "$src = $Vd", |
| [(set DPR:$Vd, (vector_insert (Ty DPR:$src), |
| (i32 (LoadOp addrmode6oneL32:$Rn)), |
| imm:$lane))]>, Sched<[WriteVLD1]> { |
| let Rm = 0b1111; |
| let DecoderMethod = "DecodeVLD1LN"; |
| } |
| class VLD1QLNPseudo<ValueType Ty, PatFrag LoadOp> : VLDQLNPseudo<IIC_VLD1ln>, |
| Sched<[WriteVLD1]> { |
| let Pattern = [(set QPR:$dst, (vector_insert (Ty QPR:$src), |
| (i32 (LoadOp addrmode6:$addr)), |
| imm:$lane))]; |
| } |
| |
| def VLD1LNd8 : VLD1LN<0b0000, {?,?,?,0}, "8", v8i8, extloadi8> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD1LNd16 : VLD1LN<0b0100, {?,?,0,?}, "16", v4i16, extloadi16> { |
| let Inst{7-6} = lane{1-0}; |
| let Inst{5-4} = Rn{5-4}; |
| } |
| def VLD1LNd32 : VLD1LN32<0b1000, {?,0,?,?}, "32", v2i32, load> { |
| let Inst{7} = lane{0}; |
| let Inst{5-4} = Rn{5-4}; |
| } |
| |
| def VLD1LNq8Pseudo : VLD1QLNPseudo<v16i8, extloadi8>; |
| def VLD1LNq16Pseudo : VLD1QLNPseudo<v8i16, extloadi16>; |
| def VLD1LNq32Pseudo : VLD1QLNPseudo<v4i32, load>; |
| |
| let Predicates = [HasNEON] in { |
| def : Pat<(vector_insert (v4f16 DPR:$src), |
| (f16 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNd16 addrmode6:$addr, DPR:$src, imm:$lane)>; |
| def : Pat<(vector_insert (v8f16 QPR:$src), |
| (f16 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNq16Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; |
| def : Pat<(vector_insert (v4bf16 DPR:$src), |
| (bf16 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNd16 addrmode6:$addr, DPR:$src, imm:$lane)>; |
| def : Pat<(vector_insert (v8bf16 QPR:$src), |
| (bf16 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNq16Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; |
| def : Pat<(vector_insert (v2f32 DPR:$src), |
| (f32 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNd32 addrmode6:$addr, DPR:$src, imm:$lane)>; |
| def : Pat<(vector_insert (v4f32 QPR:$src), |
| (f32 (load addrmode6:$addr)), imm:$lane), |
| (VLD1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; |
| |
| // A 64-bit subvector insert to the first 128-bit vector position |
| // is a subregister copy that needs no instruction. |
| def : Pat<(insert_subvector undef, (v1i64 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| def : Pat<(insert_subvector undef, (v2i32 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| def : Pat<(insert_subvector undef, (v2f32 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| def : Pat<(insert_subvector undef, (v4i16 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| def : Pat<(insert_subvector undef, (v4f16 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| def : Pat<(insert_subvector (v16i8 undef), (v8i8 DPR:$src), (i32 0)), |
| (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; |
| } |
| |
| |
| let mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 in { |
| |
| // ...with address register writeback: |
| class VLD1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$src, nohash_imm:$lane), IIC_VLD1lnu, "vld1", Dt, |
| "\\{$Vd[$lane]\\}, $Rn$Rm", |
| "$src = $Vd, $Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let DecoderMethod = "DecodeVLD1LN"; |
| } |
| |
| def VLD1LNd8_UPD : VLD1LNWB<0b0000, {?,?,?,0}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD1LNd16_UPD : VLD1LNWB<0b0100, {?,?,0,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| let Inst{4} = Rn{4}; |
| } |
| def VLD1LNd32_UPD : VLD1LNWB<0b1000, {?,0,?,?}, "32"> { |
| let Inst{7} = lane{0}; |
| let Inst{5} = Rn{4}; |
| let Inst{4} = Rn{4}; |
| } |
| |
| def VLD1LNq8Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD1lnu>, Sched<[WriteVLD1]>; |
| def VLD1LNq16Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD1lnu>, Sched<[WriteVLD1]>; |
| def VLD1LNq32Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD1lnu>, Sched<[WriteVLD1]>; |
| |
| // VLD2LN : Vector Load (single 2-element structure to one lane) |
| class VLD2LN<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2), |
| (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, nohash_imm:$lane), |
| IIC_VLD2ln, "vld2", Dt, "\\{$Vd[$lane], $dst2[$lane]\\}, $Rn", |
| "$src1 = $Vd, $src2 = $dst2", []>, Sched<[WriteVLD1]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD2LN"; |
| } |
| |
| def VLD2LNd8 : VLD2LN<0b0001, {?,?,?,?}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD2LNd16 : VLD2LN<0b0101, {?,?,0,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD2LNd32 : VLD2LN<0b1001, {?,0,0,?}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD2LNd8Pseudo : VLDQLNPseudo<IIC_VLD2ln>, Sched<[WriteVLD1]>; |
| def VLD2LNd16Pseudo : VLDQLNPseudo<IIC_VLD2ln>, Sched<[WriteVLD1]>; |
| def VLD2LNd32Pseudo : VLDQLNPseudo<IIC_VLD2ln>, Sched<[WriteVLD1]>; |
| |
| // ...with double-spaced registers: |
| def VLD2LNq16 : VLD2LN<0b0101, {?,?,1,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD2LNq32 : VLD2LN<0b1001, {?,1,0,?}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD2LNq16Pseudo : VLDQQLNPseudo<IIC_VLD2ln>, Sched<[WriteVLD1]>; |
| def VLD2LNq32Pseudo : VLDQQLNPseudo<IIC_VLD2ln>, Sched<[WriteVLD1]>; |
| |
| // ...with address register writeback: |
| class VLD2LNWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$src1, DPR:$src2, nohash_imm:$lane), IIC_VLD2lnu, "vld2", Dt, |
| "\\{$Vd[$lane], $dst2[$lane]\\}, $Rn$Rm", |
| "$src1 = $Vd, $src2 = $dst2, $Rn.addr = $wb", []> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD2LN"; |
| } |
| |
| def VLD2LNd8_UPD : VLD2LNWB<0b0001, {?,?,?,?}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD2LNd16_UPD : VLD2LNWB<0b0101, {?,?,0,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD2LNd32_UPD : VLD2LNWB<0b1001, {?,0,0,?}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD2LNd8Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD2lnu>, Sched<[WriteVLD1]>; |
| def VLD2LNd16Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD2lnu>, Sched<[WriteVLD1]>; |
| def VLD2LNd32Pseudo_UPD : VLDQLNWBPseudo<IIC_VLD2lnu>, Sched<[WriteVLD1]>; |
| |
| def VLD2LNq16_UPD : VLD2LNWB<0b0101, {?,?,1,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD2LNq32_UPD : VLD2LNWB<0b1001, {?,1,0,?}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD2LNq16Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD2lnu>, Sched<[WriteVLD1]>; |
| def VLD2LNq32Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD2lnu>, Sched<[WriteVLD1]>; |
| |
| // VLD3LN : Vector Load (single 3-element structure to one lane) |
| class VLD3LN<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), |
| (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, DPR:$src3, |
| nohash_imm:$lane), IIC_VLD3ln, "vld3", Dt, |
| "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn", |
| "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3", []>, Sched<[WriteVLD2]> { |
| let Rm = 0b1111; |
| let DecoderMethod = "DecodeVLD3LN"; |
| } |
| |
| def VLD3LNd8 : VLD3LN<0b0010, {?,?,?,0}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD3LNd16 : VLD3LN<0b0110, {?,?,0,0}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD3LNd32 : VLD3LN<0b1010, {?,0,0,0}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD3LNd8Pseudo : VLDQQLNPseudo<IIC_VLD3ln>, Sched<[WriteVLD2]>; |
| def VLD3LNd16Pseudo : VLDQQLNPseudo<IIC_VLD3ln>, Sched<[WriteVLD2]>; |
| def VLD3LNd32Pseudo : VLDQQLNPseudo<IIC_VLD3ln>, Sched<[WriteVLD2]>; |
| |
| // ...with double-spaced registers: |
| def VLD3LNq16 : VLD3LN<0b0110, {?,?,1,0}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD3LNq32 : VLD3LN<0b1010, {?,1,0,0}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD3LNq16Pseudo : VLDQQQQLNPseudo<IIC_VLD3ln>, Sched<[WriteVLD2]>; |
| def VLD3LNq32Pseudo : VLDQQQQLNPseudo<IIC_VLD3ln>, Sched<[WriteVLD2]>; |
| |
| // ...with address register writeback: |
| class VLD3LNWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$src1, DPR:$src2, DPR:$src3, nohash_imm:$lane), |
| IIC_VLD3lnu, "vld3", Dt, |
| "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn$Rm", |
| "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $Rn.addr = $wb", |
| []>, Sched<[WriteVLD2]> { |
| let DecoderMethod = "DecodeVLD3LN"; |
| } |
| |
| def VLD3LNd8_UPD : VLD3LNWB<0b0010, {?,?,?,0}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD3LNd16_UPD : VLD3LNWB<0b0110, {?,?,0,0}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD3LNd32_UPD : VLD3LNWB<0b1010, {?,0,0,0}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD3LNd8Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD3lnu>, Sched<[WriteVLD2]>; |
| def VLD3LNd16Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD3lnu>, Sched<[WriteVLD2]>; |
| def VLD3LNd32Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD3lnu>, Sched<[WriteVLD2]>; |
| |
| def VLD3LNq16_UPD : VLD3LNWB<0b0110, {?,?,1,0}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD3LNq32_UPD : VLD3LNWB<0b1010, {?,1,0,0}, "32"> { |
| let Inst{7} = lane{0}; |
| } |
| |
| def VLD3LNq16Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD3lnu>, Sched<[WriteVLD2]>; |
| def VLD3LNq32Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD3lnu>, Sched<[WriteVLD2]>; |
| |
| // VLD4LN : Vector Load (single 4-element structure to one lane) |
| class VLD4LN<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), |
| (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, |
| nohash_imm:$lane), IIC_VLD4ln, "vld4", Dt, |
| "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $Rn", |
| "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []>, |
| Sched<[WriteVLD2]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD4LN"; |
| } |
| |
| def VLD4LNd8 : VLD4LN<0b0011, {?,?,?,?}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD4LNd16 : VLD4LN<0b0111, {?,?,0,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD4LNd32 : VLD4LN<0b1011, {?,0,?,?}, "32"> { |
| let Inst{7} = lane{0}; |
| let Inst{5} = Rn{5}; |
| } |
| |
| def VLD4LNd8Pseudo : VLDQQLNPseudo<IIC_VLD4ln>, Sched<[WriteVLD2]>; |
| def VLD4LNd16Pseudo : VLDQQLNPseudo<IIC_VLD4ln>, Sched<[WriteVLD2]>; |
| def VLD4LNd32Pseudo : VLDQQLNPseudo<IIC_VLD4ln>, Sched<[WriteVLD2]>; |
| |
| // ...with double-spaced registers: |
| def VLD4LNq16 : VLD4LN<0b0111, {?,?,1,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD4LNq32 : VLD4LN<0b1011, {?,1,?,?}, "32"> { |
| let Inst{7} = lane{0}; |
| let Inst{5} = Rn{5}; |
| } |
| |
| def VLD4LNq16Pseudo : VLDQQQQLNPseudo<IIC_VLD4ln>, Sched<[WriteVLD2]>; |
| def VLD4LNq32Pseudo : VLDQQQQLNPseudo<IIC_VLD4ln>, Sched<[WriteVLD2]>; |
| |
| // ...with address register writeback: |
| class VLD4LNWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdStLn<1, 0b10, op11_8, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, nohash_imm:$lane), |
| IIC_VLD4lnu, "vld4", Dt, |
| "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $Rn$Rm", |
| "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4, $Rn.addr = $wb", |
| []> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD4LN" ; |
| } |
| |
| def VLD4LNd8_UPD : VLD4LNWB<0b0011, {?,?,?,?}, "8"> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VLD4LNd16_UPD : VLD4LNWB<0b0111, {?,?,0,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD4LNd32_UPD : VLD4LNWB<0b1011, {?,0,?,?}, "32"> { |
| let Inst{7} = lane{0}; |
| let Inst{5} = Rn{5}; |
| } |
| |
| def VLD4LNd8Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD4lnu>, Sched<[WriteVLD2]>; |
| def VLD4LNd16Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD4lnu>, Sched<[WriteVLD2]>; |
| def VLD4LNd32Pseudo_UPD : VLDQQLNWBPseudo<IIC_VLD4lnu>, Sched<[WriteVLD2]>; |
| |
| def VLD4LNq16_UPD : VLD4LNWB<0b0111, {?,?,1,?}, "16"> { |
| let Inst{7-6} = lane{1-0}; |
| } |
| def VLD4LNq32_UPD : VLD4LNWB<0b1011, {?,1,?,?}, "32"> { |
| let Inst{7} = lane{0}; |
| let Inst{5} = Rn{5}; |
| } |
| |
| def VLD4LNq16Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD4lnu>, Sched<[WriteVLD2]>; |
| def VLD4LNq32Pseudo_UPD : VLDQQQQLNWBPseudo<IIC_VLD4lnu>, Sched<[WriteVLD2]>; |
| |
| } // mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 |
| |
| // VLD1DUP : Vector Load (single element to all lanes) |
| class VLD1DUP<bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp, |
| Operand AddrMode> |
| : NLdSt<1, 0b10, 0b1100, op7_4, (outs VecListOneDAllLanes:$Vd), |
| (ins AddrMode:$Rn), |
| IIC_VLD1dup, "vld1", Dt, "$Vd, $Rn", "", |
| [(set VecListOneDAllLanes:$Vd, |
| (Ty (ARMvdup (i32 (LoadOp AddrMode:$Rn)))))]>, |
| Sched<[WriteVLD2]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| def VLD1DUPd8 : VLD1DUP<{0,0,0,?}, "8", v8i8, extloadi8, |
| addrmode6dupalignNone>; |
| def VLD1DUPd16 : VLD1DUP<{0,1,0,?}, "16", v4i16, extloadi16, |
| addrmode6dupalign16>; |
| def VLD1DUPd32 : VLD1DUP<{1,0,0,?}, "32", v2i32, load, |
| addrmode6dupalign32>; |
| |
| let Predicates = [HasNEON] in { |
| def : Pat<(v2f32 (ARMvdup (f32 (load addrmode6dup:$addr)))), |
| (VLD1DUPd32 addrmode6:$addr)>; |
| } |
| |
| class VLD1QDUP<bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp, |
| Operand AddrMode> |
| : NLdSt<1, 0b10, 0b1100, op7_4, (outs VecListDPairAllLanes:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD1dup, |
| "vld1", Dt, "$Vd, $Rn", "", |
| [(set VecListDPairAllLanes:$Vd, |
| (Ty (ARMvdup (i32 (LoadOp AddrMode:$Rn)))))]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| |
| def VLD1DUPq8 : VLD1QDUP<{0,0,1,0}, "8", v16i8, extloadi8, |
| addrmode6dupalignNone>; |
| def VLD1DUPq16 : VLD1QDUP<{0,1,1,?}, "16", v8i16, extloadi16, |
| addrmode6dupalign16>; |
| def VLD1DUPq32 : VLD1QDUP<{1,0,1,?}, "32", v4i32, load, |
| addrmode6dupalign32>; |
| |
| let Predicates = [HasNEON] in { |
| def : Pat<(v4f32 (ARMvdup (f32 (load addrmode6dup:$addr)))), |
| (VLD1DUPq32 addrmode6:$addr)>; |
| } |
| |
| let mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 in { |
| // ...with address register writeback: |
| multiclass VLD1DUPWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<1, 0b10, 0b1100, op7_4, |
| (outs VecListOneDAllLanes:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1dupu, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| def _register : NLdSt<1, 0b10, 0b1100, op7_4, |
| (outs VecListOneDAllLanes:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1dupu, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| } |
| multiclass VLD1QDUPWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<1, 0b10, 0b1100, op7_4, |
| (outs VecListDPairAllLanes:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD1dupu, |
| "vld1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| def _register : NLdSt<1, 0b10, 0b1100, op7_4, |
| (outs VecListDPairAllLanes:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD1dupu, |
| "vld1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD1DupInstruction"; |
| } |
| } |
| |
| defm VLD1DUPd8wb : VLD1DUPWB<{0,0,0,0}, "8", addrmode6dupalignNone>; |
| defm VLD1DUPd16wb : VLD1DUPWB<{0,1,0,?}, "16", addrmode6dupalign16>; |
| defm VLD1DUPd32wb : VLD1DUPWB<{1,0,0,?}, "32", addrmode6dupalign32>; |
| |
| defm VLD1DUPq8wb : VLD1QDUPWB<{0,0,1,0}, "8", addrmode6dupalignNone>; |
| defm VLD1DUPq16wb : VLD1QDUPWB<{0,1,1,?}, "16", addrmode6dupalign16>; |
| defm VLD1DUPq32wb : VLD1QDUPWB<{1,0,1,?}, "32", addrmode6dupalign32>; |
| |
| // VLD2DUP : Vector Load (single 2-element structure to all lanes) |
| class VLD2DUP<bits<4> op7_4, string Dt, RegisterOperand VdTy, Operand AddrMode> |
| : NLdSt<1, 0b10, 0b1101, op7_4, (outs VdTy:$Vd), |
| (ins AddrMode:$Rn), IIC_VLD2dup, |
| "vld2", Dt, "$Vd, $Rn", "", []> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD2DupInstruction"; |
| } |
| |
| def VLD2DUPd8 : VLD2DUP<{0,0,0,?}, "8", VecListDPairAllLanes, |
| addrmode6dupalign16>; |
| def VLD2DUPd16 : VLD2DUP<{0,1,0,?}, "16", VecListDPairAllLanes, |
| addrmode6dupalign32>; |
| def VLD2DUPd32 : VLD2DUP<{1,0,0,?}, "32", VecListDPairAllLanes, |
| addrmode6dupalign64>; |
| |
| // HACK this one, VLD2DUPd8x2 must be changed at the same time with VLD2b8 or |
| // "vld2.8 {d0[], d2[]}, [r4:32]" will become "vld2.8 {d0, d2}, [r4:32]". |
| // ...with double-spaced registers |
| def VLD2DUPd8x2 : VLD2DUP<{0,0,1,?}, "8", VecListDPairSpacedAllLanes, |
| addrmode6dupalign16>; |
| def VLD2DUPd16x2 : VLD2DUP<{0,1,1,?}, "16", VecListDPairSpacedAllLanes, |
| addrmode6dupalign32>; |
| def VLD2DUPd32x2 : VLD2DUP<{1,0,1,?}, "32", VecListDPairSpacedAllLanes, |
| addrmode6dupalign64>; |
| |
| def VLD2DUPq8EvenPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq8OddPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq16EvenPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq16OddPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq32EvenPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq32OddPseudo : VLDQQPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| |
| // ...with address register writeback: |
| multiclass VLD2DUPWB<bits<4> op7_4, string Dt, RegisterOperand VdTy, |
| Operand AddrMode> { |
| def _fixed : NLdSt<1, 0b10, 0b1101, op7_4, |
| (outs VdTy:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn), IIC_VLD2dupu, |
| "vld2", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD2DupInstruction"; |
| } |
| def _register : NLdSt<1, 0b10, 0b1101, op7_4, |
| (outs VdTy:$Vd, GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm), IIC_VLD2dupu, |
| "vld2", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD1]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD2DupInstruction"; |
| } |
| } |
| |
| defm VLD2DUPd8wb : VLD2DUPWB<{0,0,0,0}, "8", VecListDPairAllLanes, |
| addrmode6dupalign16>; |
| defm VLD2DUPd16wb : VLD2DUPWB<{0,1,0,?}, "16", VecListDPairAllLanes, |
| addrmode6dupalign32>; |
| defm VLD2DUPd32wb : VLD2DUPWB<{1,0,0,?}, "32", VecListDPairAllLanes, |
| addrmode6dupalign64>; |
| |
| defm VLD2DUPd8x2wb : VLD2DUPWB<{0,0,1,0}, "8", VecListDPairSpacedAllLanes, |
| addrmode6dupalign16>; |
| defm VLD2DUPd16x2wb : VLD2DUPWB<{0,1,1,?}, "16", VecListDPairSpacedAllLanes, |
| addrmode6dupalign32>; |
| defm VLD2DUPd32x2wb : VLD2DUPWB<{1,0,1,?}, "32", VecListDPairSpacedAllLanes, |
| addrmode6dupalign64>; |
| |
| def VLD2DUPq8OddPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq16OddPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq32OddPseudoWB_fixed : VLDQQWBfixedPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq8OddPseudoWB_register : VLDQQWBPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq16OddPseudoWB_register : VLDQQWBPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| def VLD2DUPq32OddPseudoWB_register : VLDQQWBPseudo<IIC_VLD2dup>, Sched<[WriteVLD2]>; |
| |
| // VLD3DUP : Vector Load (single 3-element structure to all lanes) |
| class VLD3DUP<bits<4> op7_4, string Dt> |
| : NLdSt<1, 0b10, 0b1110, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), |
| (ins addrmode6dup:$Rn), IIC_VLD3dup, |
| "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []>, |
| Sched<[WriteVLD2]> { |
| let Rm = 0b1111; |
| let Inst{4} = 0; |
| let DecoderMethod = "DecodeVLD3DupInstruction"; |
| } |
| |
| def VLD3DUPd8 : VLD3DUP<{0,0,0,?}, "8">; |
| def VLD3DUPd16 : VLD3DUP<{0,1,0,?}, "16">; |
| def VLD3DUPd32 : VLD3DUP<{1,0,0,?}, "32">; |
| |
| def VLD3DUPd8Pseudo : VLDQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPd16Pseudo : VLDQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPd32Pseudo : VLDQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| |
| // ...with double-spaced registers (not used for codegen): |
| def VLD3DUPq8 : VLD3DUP<{0,0,1,?}, "8">; |
| def VLD3DUPq16 : VLD3DUP<{0,1,1,?}, "16">; |
| def VLD3DUPq32 : VLD3DUP<{1,0,1,?}, "32">; |
| |
| def VLD3DUPq8EvenPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPq8OddPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPq16EvenPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPq16OddPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPq32EvenPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| def VLD3DUPq32OddPseudo : VLDQQQQPseudo<IIC_VLD3dup>, Sched<[WriteVLD2]>; |
| |
| // ...with address register writeback: |
| class VLD3DUPWB<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<1, 0b10, 0b1110, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), |
| (ins AddrMode:$Rn, am6offset:$Rm), IIC_VLD3dupu, |
| "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD2]> { |
| let Inst{4} = 0; |
| let DecoderMethod = "DecodeVLD3DupInstruction"; |
| } |
| |
| def VLD3DUPd8_UPD : VLD3DUPWB<{0,0,0,0}, "8", addrmode6dupalign64>; |
| def VLD3DUPd16_UPD : VLD3DUPWB<{0,1,0,?}, "16", addrmode6dupalign64>; |
| def VLD3DUPd32_UPD : VLD3DUPWB<{1,0,0,?}, "32", addrmode6dupalign64>; |
| |
| def VLD3DUPq8_UPD : VLD3DUPWB<{0,0,1,0}, "8", addrmode6dupalign64>; |
| def VLD3DUPq16_UPD : VLD3DUPWB<{0,1,1,?}, "16", addrmode6dupalign64>; |
| def VLD3DUPq32_UPD : VLD3DUPWB<{1,0,1,?}, "32", addrmode6dupalign64>; |
| |
| def VLD3DUPd8Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| def VLD3DUPd16Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| def VLD3DUPd32Pseudo_UPD : VLDQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| |
| def VLD3DUPq8OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| def VLD3DUPq16OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| def VLD3DUPq32OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD3dupu>, Sched<[WriteVLD2]>; |
| |
| // VLD4DUP : Vector Load (single 4-element structure to all lanes) |
| class VLD4DUP<bits<4> op7_4, string Dt> |
| : NLdSt<1, 0b10, 0b1111, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), |
| (ins addrmode6dup:$Rn), IIC_VLD4dup, |
| "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD4DupInstruction"; |
| } |
| |
| def VLD4DUPd8 : VLD4DUP<{0,0,0,?}, "8">; |
| def VLD4DUPd16 : VLD4DUP<{0,1,0,?}, "16">; |
| def VLD4DUPd32 : VLD4DUP<{1,?,0,?}, "32"> { let Inst{6} = Rn{5}; } |
| |
| def VLD4DUPd8Pseudo : VLDQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPd16Pseudo : VLDQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPd32Pseudo : VLDQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| |
| // ...with double-spaced registers (not used for codegen): |
| def VLD4DUPq8 : VLD4DUP<{0,0,1,?}, "8">; |
| def VLD4DUPq16 : VLD4DUP<{0,1,1,?}, "16">; |
| def VLD4DUPq32 : VLD4DUP<{1,?,1,?}, "32"> { let Inst{6} = Rn{5}; } |
| |
| def VLD4DUPq8EvenPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPq8OddPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPq16EvenPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPq16OddPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPq32EvenPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| def VLD4DUPq32OddPseudo : VLDQQQQPseudo<IIC_VLD4dup>, Sched<[WriteVLD2]>; |
| |
| // ...with address register writeback: |
| class VLD4DUPWB<bits<4> op7_4, string Dt> |
| : NLdSt<1, 0b10, 0b1111, op7_4, |
| (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), |
| (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD4dupu, |
| "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVLD2]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLD4DupInstruction"; |
| } |
| |
| def VLD4DUPd8_UPD : VLD4DUPWB<{0,0,0,0}, "8">; |
| def VLD4DUPd16_UPD : VLD4DUPWB<{0,1,0,?}, "16">; |
| def VLD4DUPd32_UPD : VLD4DUPWB<{1,?,0,?}, "32"> { let Inst{6} = Rn{5}; } |
| |
| def VLD4DUPq8_UPD : VLD4DUPWB<{0,0,1,0}, "8">; |
| def VLD4DUPq16_UPD : VLD4DUPWB<{0,1,1,?}, "16">; |
| def VLD4DUPq32_UPD : VLD4DUPWB<{1,?,1,?}, "32"> { let Inst{6} = Rn{5}; } |
| |
| def VLD4DUPd8Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| def VLD4DUPd16Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| def VLD4DUPd32Pseudo_UPD : VLDQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| |
| def VLD4DUPq8OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| def VLD4DUPq16OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| def VLD4DUPq32OddPseudo_UPD : VLDQQQQWBPseudo<IIC_VLD4dupu>, Sched<[WriteVLD2]>; |
| |
| } // mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 |
| |
| let mayStore = 1, hasSideEffects = 0, hasExtraSrcRegAllocReq = 1 in { |
| |
| // Classes for VST* pseudo-instructions with multi-register operands. |
| // These are expanded to real instructions after register allocation. |
| class VSTQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QPR:$src), itin, "">; |
| class VSTQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QPR:$src), itin, |
| "$addr.addr = $wb">; |
| class VSTQWBfixedPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, QPR:$src), itin, |
| "$addr.addr = $wb">; |
| class VSTQWBregisterPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, rGPR:$offset, QPR:$src), itin, |
| "$addr.addr = $wb">; |
| class VSTQQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQPR:$src), itin, "">; |
| class VSTQQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQPR:$src), itin, |
| "$addr.addr = $wb">; |
| class VSTQQWBfixedPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, QQPR:$src), itin, |
| "$addr.addr = $wb">; |
| class VSTQQWBregisterPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, rGPR:$offset, QQPR:$src), itin, |
| "$addr.addr = $wb">; |
| |
| class VSTQQQQPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQQQPR:$src), itin, "">; |
| class VSTQQQQWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, |
| "$addr.addr = $wb">; |
| |
| // VST1 : Vector Store (multiple single elements) |
| class VST1D<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0,0b00,0b0111,op7_4, (outs), (ins AddrMode:$Rn, VecListOneD:$Vd), |
| IIC_VST1, "vst1", Dt, "$Vd, $Rn", "", []>, Sched<[WriteVST1]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| class VST1Q<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0,0b00,0b1010,op7_4, (outs), (ins AddrMode:$Rn, VecListDPair:$Vd), |
| IIC_VST1x2, "vst1", Dt, "$Vd, $Rn", "", []>, Sched<[WriteVST2]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| |
| def VST1d8 : VST1D<{0,0,0,?}, "8", addrmode6align64>; |
| def VST1d16 : VST1D<{0,1,0,?}, "16", addrmode6align64>; |
| def VST1d32 : VST1D<{1,0,0,?}, "32", addrmode6align64>; |
| def VST1d64 : VST1D<{1,1,0,?}, "64", addrmode6align64>; |
| |
| def VST1q8 : VST1Q<{0,0,?,?}, "8", addrmode6align64or128>; |
| def VST1q16 : VST1Q<{0,1,?,?}, "16", addrmode6align64or128>; |
| def VST1q32 : VST1Q<{1,0,?,?}, "32", addrmode6align64or128>; |
| def VST1q64 : VST1Q<{1,1,?,?}, "64", addrmode6align64or128>; |
| |
| // ...with address register writeback: |
| multiclass VST1DWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b00, 0b0111,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VecListOneD:$Vd), IIC_VLD1u, |
| "vst1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST1]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b00,0b0111,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VecListOneD:$Vd), |
| IIC_VLD1u, |
| "vst1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST1]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| multiclass VST1QWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b00,0b1010,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VecListDPair:$Vd), IIC_VLD1x2u, |
| "vst1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST2]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b00,0b1010,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VecListDPair:$Vd), |
| IIC_VLD1x2u, |
| "vst1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST2]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| defm VST1d8wb : VST1DWB<{0,0,0,?}, "8", addrmode6align64>; |
| defm VST1d16wb : VST1DWB<{0,1,0,?}, "16", addrmode6align64>; |
| defm VST1d32wb : VST1DWB<{1,0,0,?}, "32", addrmode6align64>; |
| defm VST1d64wb : VST1DWB<{1,1,0,?}, "64", addrmode6align64>; |
| |
| defm VST1q8wb : VST1QWB<{0,0,?,?}, "8", addrmode6align64or128>; |
| defm VST1q16wb : VST1QWB<{0,1,?,?}, "16", addrmode6align64or128>; |
| defm VST1q32wb : VST1QWB<{1,0,?,?}, "32", addrmode6align64or128>; |
| defm VST1q64wb : VST1QWB<{1,1,?,?}, "64", addrmode6align64or128>; |
| |
| // ...with 3 registers |
| class VST1D3<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0, 0b00, 0b0110, op7_4, (outs), |
| (ins AddrMode:$Rn, VecListThreeD:$Vd), |
| IIC_VST1x3, "vst1", Dt, "$Vd, $Rn", "", []>, Sched<[WriteVST3]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| multiclass VST1D3WB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b00,0b0110,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VecListThreeD:$Vd), IIC_VLD1x3u, |
| "vst1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST3]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b00,0b0110,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VecListThreeD:$Vd), |
| IIC_VLD1x3u, |
| "vst1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST3]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| def VST1d8T : VST1D3<{0,0,0,?}, "8", addrmode6align64>; |
| def VST1d16T : VST1D3<{0,1,0,?}, "16", addrmode6align64>; |
| def VST1d32T : VST1D3<{1,0,0,?}, "32", addrmode6align64>; |
| def VST1d64T : VST1D3<{1,1,0,?}, "64", addrmode6align64>; |
| |
| defm VST1d8Twb : VST1D3WB<{0,0,0,?}, "8", addrmode6align64>; |
| defm VST1d16Twb : VST1D3WB<{0,1,0,?}, "16", addrmode6align64>; |
| defm VST1d32Twb : VST1D3WB<{1,0,0,?}, "32", addrmode6align64>; |
| defm VST1d64Twb : VST1D3WB<{1,1,0,?}, "64", addrmode6align64>; |
| |
| def VST1d8TPseudo : VSTQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1d8TPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d8TPseudoWB_register : VSTQQWBPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d16TPseudo : VSTQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1d16TPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d16TPseudoWB_register : VSTQQWBPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d32TPseudo : VSTQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1d32TPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d32TPseudoWB_register : VSTQQWBPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d64TPseudo : VSTQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1d64TPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| def VST1d64TPseudoWB_register : VSTQQWBPseudo<IIC_VST1x3u>, Sched<[WriteVST3]>; |
| |
| def VST1q8HighTPseudo : VSTQQQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q16HighTPseudo : VSTQQQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q32HighTPseudo : VSTQQQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q64HighTPseudo : VSTQQQQPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| |
| def VST1q8HighTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q16HighTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q32HighTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q64HighTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| |
| def VST1q8LowTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q16LowTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q32LowTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| def VST1q64LowTPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x3>, Sched<[WriteVST3]>; |
| |
| // ...with 4 registers |
| class VST1D4<bits<4> op7_4, string Dt, Operand AddrMode> |
| : NLdSt<0, 0b00, 0b0010, op7_4, (outs), |
| (ins AddrMode:$Rn, VecListFourD:$Vd), |
| IIC_VST1x4, "vst1", Dt, "$Vd, $Rn", "", |
| []>, Sched<[WriteVST4]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| multiclass VST1D4WB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0,0b00,0b0010,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VecListFourD:$Vd), IIC_VLD1x4u, |
| "vst1", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST4]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| def _register : NLdSt<0,0b00,0b0010,op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VecListFourD:$Vd), |
| IIC_VLD1x4u, |
| "vst1", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST4]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST1Instruction"; |
| } |
| } |
| |
| def VST1d8Q : VST1D4<{0,0,?,?}, "8", addrmode6align64or128or256>; |
| def VST1d16Q : VST1D4<{0,1,?,?}, "16", addrmode6align64or128or256>; |
| def VST1d32Q : VST1D4<{1,0,?,?}, "32", addrmode6align64or128or256>; |
| def VST1d64Q : VST1D4<{1,1,?,?}, "64", addrmode6align64or128or256>; |
| |
| defm VST1d8Qwb : VST1D4WB<{0,0,?,?}, "8", addrmode6align64or128or256>; |
| defm VST1d16Qwb : VST1D4WB<{0,1,?,?}, "16", addrmode6align64or128or256>; |
| defm VST1d32Qwb : VST1D4WB<{1,0,?,?}, "32", addrmode6align64or128or256>; |
| defm VST1d64Qwb : VST1D4WB<{1,1,?,?}, "64", addrmode6align64or128or256>; |
| |
| def VST1d8QPseudo : VSTQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1d8QPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d8QPseudoWB_register : VSTQQWBPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d16QPseudo : VSTQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1d16QPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d16QPseudoWB_register : VSTQQWBPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d32QPseudo : VSTQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1d32QPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d32QPseudoWB_register : VSTQQWBPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d64QPseudo : VSTQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1d64QPseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| def VST1d64QPseudoWB_register : VSTQQWBPseudo<IIC_VST1x4u>, Sched<[WriteVST4]>; |
| |
| def VST1q8HighQPseudo : VSTQQQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q16HighQPseudo : VSTQQQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q32HighQPseudo : VSTQQQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q64HighQPseudo : VSTQQQQPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| |
| def VST1q8HighQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q16HighQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q32HighQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q64HighQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| |
| def VST1q8LowQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q16LowQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q32LowQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| def VST1q64LowQPseudo_UPD : VSTQQQQWBPseudo<IIC_VST1x4>, Sched<[WriteVST4]>; |
| |
| // VST2 : Vector Store (multiple 2-element structures) |
| class VST2<bits<4> op11_8, bits<4> op7_4, string Dt, RegisterOperand VdTy, |
| InstrItinClass itin, Operand AddrMode> |
| : NLdSt<0, 0b00, op11_8, op7_4, (outs), (ins AddrMode:$Rn, VdTy:$Vd), |
| itin, "vst2", Dt, "$Vd, $Rn", "", []> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| |
| def VST2d8 : VST2<0b1000, {0,0,?,?}, "8", VecListDPair, IIC_VST2, |
| addrmode6align64or128>, Sched<[WriteVST2]>; |
| def VST2d16 : VST2<0b1000, {0,1,?,?}, "16", VecListDPair, IIC_VST2, |
| addrmode6align64or128>, Sched<[WriteVST2]>; |
| def VST2d32 : VST2<0b1000, {1,0,?,?}, "32", VecListDPair, IIC_VST2, |
| addrmode6align64or128>, Sched<[WriteVST2]>; |
| |
| def VST2q8 : VST2<0b0011, {0,0,?,?}, "8", VecListFourD, IIC_VST2x2, |
| addrmode6align64or128or256>, Sched<[WriteVST4]>; |
| def VST2q16 : VST2<0b0011, {0,1,?,?}, "16", VecListFourD, IIC_VST2x2, |
| addrmode6align64or128or256>, Sched<[WriteVST4]>; |
| def VST2q32 : VST2<0b0011, {1,0,?,?}, "32", VecListFourD, IIC_VST2x2, |
| addrmode6align64or128or256>, Sched<[WriteVST4]>; |
| |
| def VST2q8Pseudo : VSTQQPseudo<IIC_VST2x2>, Sched<[WriteVST4]>; |
| def VST2q16Pseudo : VSTQQPseudo<IIC_VST2x2>, Sched<[WriteVST4]>; |
| def VST2q32Pseudo : VSTQQPseudo<IIC_VST2x2>, Sched<[WriteVST4]>; |
| |
| // ...with address register writeback: |
| multiclass VST2DWB<bits<4> op11_8, bits<4> op7_4, string Dt, |
| RegisterOperand VdTy, Operand AddrMode> { |
| def _fixed : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VdTy:$Vd), IIC_VLD1u, |
| "vst2", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST2]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| def _register : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VdTy:$Vd), IIC_VLD1u, |
| "vst2", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST2]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| } |
| multiclass VST2QWB<bits<4> op7_4, string Dt, Operand AddrMode> { |
| def _fixed : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, VecListFourD:$Vd), IIC_VLD1u, |
| "vst2", Dt, "$Vd, $Rn!", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST4]> { |
| let Rm = 0b1101; // NLdSt will assign to the right encoding bits. |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| def _register : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb), |
| (ins AddrMode:$Rn, rGPR:$Rm, VecListFourD:$Vd), |
| IIC_VLD1u, |
| "vst2", Dt, "$Vd, $Rn, $Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST4]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST2Instruction"; |
| } |
| } |
| |
| defm VST2d8wb : VST2DWB<0b1000, {0,0,?,?}, "8", VecListDPair, |
| addrmode6align64or128>; |
| defm VST2d16wb : VST2DWB<0b1000, {0,1,?,?}, "16", VecListDPair, |
| addrmode6align64or128>; |
| defm VST2d32wb : VST2DWB<0b1000, {1,0,?,?}, "32", VecListDPair, |
| addrmode6align64or128>; |
| |
| defm VST2q8wb : VST2QWB<{0,0,?,?}, "8", addrmode6align64or128or256>; |
| defm VST2q16wb : VST2QWB<{0,1,?,?}, "16", addrmode6align64or128or256>; |
| defm VST2q32wb : VST2QWB<{1,0,?,?}, "32", addrmode6align64or128or256>; |
| |
| def VST2q8PseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| def VST2q16PseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| def VST2q32PseudoWB_fixed : VSTQQWBfixedPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| def VST2q8PseudoWB_register : VSTQQWBregisterPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| def VST2q16PseudoWB_register : VSTQQWBregisterPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| def VST2q32PseudoWB_register : VSTQQWBregisterPseudo<IIC_VST2x2u>, Sched<[WriteVST4]>; |
| |
| // ...with double-spaced registers |
| def VST2b8 : VST2<0b1001, {0,0,?,?}, "8", VecListDPairSpaced, IIC_VST2, |
| addrmode6align64or128>; |
| def VST2b16 : VST2<0b1001, {0,1,?,?}, "16", VecListDPairSpaced, IIC_VST2, |
| addrmode6align64or128>; |
| def VST2b32 : VST2<0b1001, {1,0,?,?}, "32", VecListDPairSpaced, IIC_VST2, |
| addrmode6align64or128>; |
| defm VST2b8wb : VST2DWB<0b1001, {0,0,?,?}, "8", VecListDPairSpaced, |
| addrmode6align64or128>; |
| defm VST2b16wb : VST2DWB<0b1001, {0,1,?,?}, "16", VecListDPairSpaced, |
| addrmode6align64or128>; |
| defm VST2b32wb : VST2DWB<0b1001, {1,0,?,?}, "32", VecListDPairSpaced, |
| addrmode6align64or128>; |
| |
| // VST3 : Vector Store (multiple 3-element structures) |
| class VST3D<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b00, op11_8, op7_4, (outs), |
| (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3), IIC_VST3, |
| "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []>, Sched<[WriteVST3]> { |
| let Rm = 0b1111; |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST3Instruction"; |
| } |
| |
| def VST3d8 : VST3D<0b0100, {0,0,0,?}, "8">; |
| def VST3d16 : VST3D<0b0100, {0,1,0,?}, "16">; |
| def VST3d32 : VST3D<0b0100, {1,0,0,?}, "32">; |
| |
| def VST3d8Pseudo : VSTQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| def VST3d16Pseudo : VSTQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| def VST3d32Pseudo : VSTQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| |
| // ...with address register writeback: |
| class VST3DWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$Vd, DPR:$src2, DPR:$src3), IIC_VST3u, |
| "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST3]> { |
| let Inst{4} = Rn{4}; |
| let DecoderMethod = "DecodeVLDST3Instruction"; |
| } |
| |
| def VST3d8_UPD : VST3DWB<0b0100, {0,0,0,?}, "8">; |
| def VST3d16_UPD : VST3DWB<0b0100, {0,1,0,?}, "16">; |
| def VST3d32_UPD : VST3DWB<0b0100, {1,0,0,?}, "32">; |
| |
| def VST3d8Pseudo_UPD : VSTQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3d16Pseudo_UPD : VSTQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3d32Pseudo_UPD : VSTQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| |
| // ...with double-spaced registers: |
| def VST3q8 : VST3D<0b0101, {0,0,0,?}, "8">; |
| def VST3q16 : VST3D<0b0101, {0,1,0,?}, "16">; |
| def VST3q32 : VST3D<0b0101, {1,0,0,?}, "32">; |
| def VST3q8_UPD : VST3DWB<0b0101, {0,0,0,?}, "8">; |
| def VST3q16_UPD : VST3DWB<0b0101, {0,1,0,?}, "16">; |
| def VST3q32_UPD : VST3DWB<0b0101, {1,0,0,?}, "32">; |
| |
| def VST3q8Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3q16Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3q32Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| |
| // ...alternate versions to be allocated odd register numbers: |
| def VST3q8oddPseudo : VSTQQQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| def VST3q16oddPseudo : VSTQQQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| def VST3q32oddPseudo : VSTQQQQPseudo<IIC_VST3>, Sched<[WriteVST3]>; |
| |
| def VST3q8oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3q16oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| def VST3q32oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST3u>, Sched<[WriteVST3]>; |
| |
| // VST4 : Vector Store (multiple 4-element structures) |
| class VST4D<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b00, op11_8, op7_4, (outs), |
| (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), |
| IIC_VST4, "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn", |
| "", []>, Sched<[WriteVST4]> { |
| let Rm = 0b1111; |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST4Instruction"; |
| } |
| |
| def VST4d8 : VST4D<0b0000, {0,0,?,?}, "8">; |
| def VST4d16 : VST4D<0b0000, {0,1,?,?}, "16">; |
| def VST4d32 : VST4D<0b0000, {1,0,?,?}, "32">; |
| |
| def VST4d8Pseudo : VSTQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| def VST4d16Pseudo : VSTQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| def VST4d32Pseudo : VSTQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| |
| // ...with address register writeback: |
| class VST4DWB<bits<4> op11_8, bits<4> op7_4, string Dt> |
| : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), |
| (ins addrmode6:$Rn, am6offset:$Rm, |
| DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST4u, |
| "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", |
| "$Rn.addr = $wb", []>, Sched<[WriteVST4]> { |
| let Inst{5-4} = Rn{5-4}; |
| let DecoderMethod = "DecodeVLDST4Instruction"; |
| } |
| |
| def VST4d8_UPD : VST4DWB<0b0000, {0,0,?,?}, "8">; |
| def VST4d16_UPD : VST4DWB<0b0000, {0,1,?,?}, "16">; |
| def VST4d32_UPD : VST4DWB<0b0000, {1,0,?,?}, "32">; |
| |
| def VST4d8Pseudo_UPD : VSTQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4d16Pseudo_UPD : VSTQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4d32Pseudo_UPD : VSTQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| |
| // ...with double-spaced registers: |
| def VST4q8 : VST4D<0b0001, {0,0,?,?}, "8">; |
| def VST4q16 : VST4D<0b0001, {0,1,?,?}, "16">; |
| def VST4q32 : VST4D<0b0001, {1,0,?,?}, "32">; |
| def VST4q8_UPD : VST4DWB<0b0001, {0,0,?,?}, "8">; |
| def VST4q16_UPD : VST4DWB<0b0001, {0,1,?,?}, "16">; |
| def VST4q32_UPD : VST4DWB<0b0001, {1,0,?,?}, "32">; |
| |
| def VST4q8Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4q16Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4q32Pseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| |
| // ...alternate versions to be allocated odd register numbers: |
| def VST4q8oddPseudo : VSTQQQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| def VST4q16oddPseudo : VSTQQQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| def VST4q32oddPseudo : VSTQQQQPseudo<IIC_VST4>, Sched<[WriteVST4]>; |
| |
| def VST4q8oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4q16oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| def VST4q32oddPseudo_UPD : VSTQQQQWBPseudo<IIC_VST4u>, Sched<[WriteVST4]>; |
| |
| } // mayStore = 1, hasSideEffects = 0, hasExtraSrcRegAllocReq = 1 |
| |
| // Classes for VST*LN pseudo-instructions with multi-register operands. |
| // These are expanded to real instructions after register allocation. |
| class VSTQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QPR:$src, nohash_imm:$lane), |
| itin, "">; |
| class VSTQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb">; |
| class VSTQQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQPR:$src, nohash_imm:$lane), |
| itin, "">; |
| class VSTQQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb">; |
| class VSTQQQQLNPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQQQPR:$src, nohash_imm:$lane), |
| itin, "">; |
| class VSTQQQQLNWBPseudo<InstrItinClass itin> |
| : PseudoNLdSt<(outs GPR:$wb), |
| (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src, |
| nohash_imm:$lane), itin, "$addr.addr = $wb">; |
| |
| // VST1LN : Vector Store (single element from one lane) |
| class VST1LN<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty, |
| PatFrag StoreOp, SDNode ExtractOp, Operand AddrMode> |
| : NLdStLn<1, 0b00, op11_8, op7_4, (outs), |
| (ins AddrMode:$Rn, DPR:$Vd, nohash_imm:$lane), |
| IIC_VST1ln, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn", "", |
| [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), AddrMode:$Rn)]>, |
| Sched<[WriteVST1]> { |
| let Rm = 0b1111; |
| let DecoderMethod = "DecodeVST1LN"; |
| } |
| class VST1QLNPseudo<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp> |
| : VSTQLNPseudo<IIC_VST1ln>, Sched<[WriteVST1]> { |
| let Pattern = [(StoreOp (ExtractOp (Ty QPR:$src), imm:$lane), |
| addrmode6:$addr)]; |
| } |
| |
| def VST1LNd8 : VST1LN<0b0000, {?,?,?,0}, "8", v8i8, truncstorei8, |
| ARMvgetlaneu, addrmode6> { |
| let Inst{7-5} = lane{2-0}; |
| } |
| def VST1LNd16 : VST1LN<0b0100, {?,?,0,?}, "16", v4i16, truncstorei16, |
| ARMvgetlaneu, addrmode6> { |
| let Inst{7-6} = lane{1-0}; |
| let Inst{4} = Rn{4}; |
|