| !sum |
| # Add |
| - go: Add |
| asm: "VPADD[BWDQ]|VADDP[SD]" |
| in: |
| - &any |
| go: $t |
| - *any |
| out: |
| - *any |
| # Add Saturated |
| - go: AddSaturated |
| asm: "VPADDS[BWDQ]" |
| in: |
| - &int |
| go: $t |
| base: int |
| - *int |
| out: |
| - *int |
| - go: AddSaturated |
| asm: "VPADDS[BWDQ]" |
| in: |
| - &uint |
| go: $t |
| base: uint |
| - *uint |
| out: |
| - *uint |
| |
| # Sub |
| - go: Sub |
| asm: "VPSUB[BWDQ]|VSUBP[SD]" |
| in: &2any |
| - *any |
| - *any |
| out: &1any |
| - *any |
| # Sub Saturated |
| - go: SubSaturated |
| asm: "VPSUBS[BWDQ]" |
| in: &2int |
| - *int |
| - *int |
| out: &1int |
| - *int |
| - go: SubSaturated |
| asm: "VPSUBS[BWDQ]" |
| in: |
| - *uint |
| - *uint |
| out: |
| - *uint |
| - go: AddPairs |
| asm: "VPHADD[DW]" |
| in: *2any |
| out: *1any |
| - go: SubPairs |
| asm: "VPHSUB[DW]" |
| in: *2any |
| out: *1any |
| - go: AddPairs |
| asm: "VHADDP[SD]" # floats |
| in: *2any |
| out: *1any |
| - go: SubPairs |
| asm: "VHSUBP[SD]" # floats |
| in: *2any |
| out: *1any |
| - go: AddPairsSaturated |
| asm: "VPHADDS[DW]" |
| in: *2int |
| out: *1int |
| - go: SubPairsSaturated |
| asm: "VPHSUBS[DW]" |
| in: *2int |
| out: *1int |
| # In the XED data, *all* floating point bitwise logic operation has their |
| # operand type marked as uint. We are not trying to understand why Intel |
| # decided that they want FP bit-wise logic operations, but this irregularity |
| # has to be dealed with in separate rules with some overwrites. |
| |
| # For many bit-wise operations, we have the following non-orthogonal |
| # choices: |
| # |
| # - Non-masked AVX operations have no element width (because it |
| # doesn't matter), but only cover 128 and 256 bit vectors. |
| # |
| # - Masked AVX-512 operations have an element width (because it needs |
| # to know how to interpret the mask), and cover 128, 256, and 512 bit |
| # vectors. These only cover 32- and 64-bit element widths. |
| # |
| # - Non-masked AVX-512 operations still have an element width (because |
| # they're just the masked operations with an implicit K0 mask) but it |
| # doesn't matter! This is the only option for non-masked 512 bit |
| # operations, and we can pick any of the element widths. |
| # |
| # We unify with ALL of these operations and the compiler generator |
| # picks when there are multiple options. |
| |
| # TODO: We don't currently generate unmasked bit-wise operations on 512 bit |
| # vectors of 8- or 16-bit elements. AVX-512 only has *masked* bit-wise |
| # operations for 32- and 64-bit elements; while the element width doesn't matter |
| # for unmasked operations, right now we don't realize that we can just use the |
| # 32- or 64-bit version for the unmasked form. Maybe in the XED decoder we |
| # should recognize bit-wise operations when generating unmasked versions and |
| # omit the element width. |
| |
| # For binary operations, we constrain their two inputs and one output to the |
| # same Go type using a variable. |
| |
| - go: And |
| asm: "VPAND[DQ]?" |
| in: |
| - &any |
| go: $t |
| - *any |
| out: |
| - *any |
| |
| - go: And |
| asm: "VPANDD" # Fill in the gap, And is missing for Uint8x64 and Int8x64 |
| inVariant: [] |
| in: &twoI8x64 |
| - &i8x64 |
| go: $t |
| overwriteElementBits: 8 |
| - *i8x64 |
| out: &oneI8x64 |
| - *i8x64 |
| |
| - go: And |
| asm: "VPANDD" # Fill in the gap, And is missing for Uint16x32 and Int16x32 |
| inVariant: [] |
| in: &twoI16x32 |
| - &i16x32 |
| go: $t |
| overwriteElementBits: 16 |
| - *i16x32 |
| out: &oneI16x32 |
| - *i16x32 |
| |
| - go: AndNot |
| asm: "VPANDN[DQ]?" |
| operandOrder: "21" # switch the arg order |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| |
| - go: AndNot |
| asm: "VPANDND" # Fill in the gap, AndNot is missing for Uint8x64 and Int8x64 |
| operandOrder: "21" # switch the arg order |
| inVariant: [] |
| in: *twoI8x64 |
| out: *oneI8x64 |
| |
| - go: AndNot |
| asm: "VPANDND" # Fill in the gap, AndNot is missing for Uint16x32 and Int16x32 |
| operandOrder: "21" # switch the arg order |
| inVariant: [] |
| in: *twoI16x32 |
| out: *oneI16x32 |
| |
| - go: Or |
| asm: "VPOR[DQ]?" |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| |
| - go: Or |
| asm: "VPORD" # Fill in the gap, Or is missing for Uint8x64 and Int8x64 |
| inVariant: [] |
| in: *twoI8x64 |
| out: *oneI8x64 |
| |
| - go: Or |
| asm: "VPORD" # Fill in the gap, Or is missing for Uint16x32 and Int16x32 |
| inVariant: [] |
| in: *twoI16x32 |
| out: *oneI16x32 |
| |
| - go: Xor |
| asm: "VPXOR[DQ]?" |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| |
| - go: Xor |
| asm: "VPXORD" # Fill in the gap, Or is missing for Uint8x64 and Int8x64 |
| inVariant: [] |
| in: *twoI8x64 |
| out: *oneI8x64 |
| |
| - go: Xor |
| asm: "VPXORD" # Fill in the gap, Or is missing for Uint16x32 and Int16x32 |
| inVariant: [] |
| in: *twoI16x32 |
| out: *oneI16x32 |
| # Ints |
| - go: Equal |
| asm: "V?PCMPEQ[BWDQ]" |
| in: |
| - &any |
| go: $t |
| - *any |
| out: |
| - &anyvregToMask |
| go: $t |
| overwriteBase: int |
| overwriteClass: mask |
| - go: Greater |
| asm: "V?PCMPGT[BWDQ]" |
| in: |
| - &int |
| go: $t |
| base: int |
| - *int |
| out: |
| - *anyvregToMask |
| # 256-bit VCMPGTQ's output elemBits is marked 32-bit in the XED data, we |
| # believe this is an error, so add this definition to overwrite. |
| - go: Greater |
| asm: "VPCMPGTQ" |
| in: |
| - &int64 |
| go: $t |
| base: int |
| elemBits: 64 |
| - *int64 |
| out: |
| - base: int |
| elemBits: 32 |
| overwriteElementBits: 64 |
| overwriteClass: mask |
| overwriteBase: int |
| # AVX-512 compares produce masks. |
| - go: Equal |
| asm: "V?PCMPEQ[BWDQ]" |
| in: |
| - *any |
| - *any |
| out: |
| - class: mask |
| - go: Greater |
| asm: "V?PCMPGT[BWDQ]" |
| in: |
| - *int |
| - *int |
| out: |
| - class: mask |
| # The const imm predicated compares after AVX512, please see categories.yaml |
| # for const imm specification. |
| - go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual) |
| asm: "VPCMP[BWDQ]" |
| in: |
| - *int |
| - *int |
| - class: immediate |
| const: 0 # Just a placeholder, will be overwritten by const imm porting. |
| out: |
| - class: mask |
| - go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual) |
| asm: "VPCMPU[BWDQ]" |
| in: |
| - &uint |
| go: $t |
| base: uint |
| - *uint |
| - class: immediate |
| const: 0 |
| out: |
| - class: mask |
| |
| # Floats |
| - go: Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual|IsNan |
| asm: "VCMPP[SD]" |
| in: |
| - &float |
| go: $t |
| base: float |
| - *float |
| - class: immediate |
| const: 0 |
| out: |
| - go: $t |
| overwriteBase: int |
| overwriteClass: mask |
| - go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual|IsNan) |
| asm: "VCMPP[SD]" |
| in: |
| - *float |
| - *float |
| - class: immediate |
| const: 0 |
| out: |
| - class: mask |
| - go: ConvertToInt32 |
| asm: "VCVTTPS2DQ" |
| in: |
| - &fp |
| go: $t |
| base: float |
| out: |
| - &i32 |
| go: $u |
| base: int |
| elemBits: 32 |
| - go: ConvertToUint32 |
| asm: "VCVTPS2UDQ" |
| in: |
| - *fp |
| out: |
| - &u32 |
| go: $u |
| base: uint |
| elemBits: 32 |
| - go: Div |
| asm: "V?DIVP[SD]" |
| in: &2fp |
| - &fp |
| go: $t |
| base: float |
| - *fp |
| out: &1fp |
| - *fp |
| - go: Sqrt |
| asm: "V?SQRTP[SD]" |
| in: *1fp |
| out: *1fp |
| # TODO: Provide separate methods for 12-bit precision and 14-bit precision? |
| - go: ApproximateReciprocal |
| asm: "VRCP(14)?P[SD]" |
| in: *1fp |
| out: *1fp |
| - go: ApproximateReciprocalOfSqrt |
| asm: "V?RSQRT(14)?P[SD]" |
| in: *1fp |
| out: *1fp |
| - go: Scale |
| asm: "VSCALEFP[SD]" |
| in: *2fp |
| out: *1fp |
| |
| - go: "Round|Ceil|Floor|Trunc" |
| asm: "VROUNDP[SD]" |
| in: |
| - *fp |
| - class: immediate |
| const: 0 # place holder |
| out: *1fp |
| |
| - go: "(Round|Ceil|Floor|Trunc)Scaled" |
| asm: "VRNDSCALEP[SD]" |
| in: |
| - *fp |
| - class: immediate |
| const: 0 # place holder |
| immOffset: 4 # "M", round to numbers with M digits after dot(by means of binary number). |
| name: prec |
| out: *1fp |
| - go: "(Round|Ceil|Floor|Trunc)ScaledResidue" |
| asm: "VREDUCEP[SD]" |
| in: |
| - *fp |
| - class: immediate |
| const: 0 # place holder |
| immOffset: 4 # "M", round to numbers with M digits after dot(by means of binary number). |
| name: prec |
| out: *1fp |
| |
| - go: "AddSub" |
| asm: "VADDSUBP[SD]" |
| in: |
| - *fp |
| - *fp |
| out: |
| - *fp |
| - go: GaloisFieldAffineTransform |
| asm: VGF2P8AFFINEQB |
| operandOrder: 2I # 2nd operand, then immediate |
| in: &AffineArgs |
| - &uint8 |
| go: $t |
| base: uint |
| - &uint8x8 |
| go: $t2 |
| base: uint |
| - &pureImmVar |
| class: immediate |
| immOffset: 0 |
| name: b |
| out: |
| - *uint8 |
| |
| - go: GaloisFieldAffineTransformInverse |
| asm: VGF2P8AFFINEINVQB |
| operandOrder: 2I # 2nd operand, then immediate |
| in: *AffineArgs |
| out: |
| - *uint8 |
| |
| - go: GaloisFieldMul |
| asm: VGF2P8MULB |
| in: |
| - *uint8 |
| - *uint8 |
| out: |
| - *uint8 |
| # Average (unsigned byte, unsigned word) |
| # Instructions: VPAVGB, VPAVGW |
| - go: Average |
| asm: "VPAVG[BW]" # Matches VPAVGB (byte) and VPAVGW (word) |
| in: |
| - &uint_t # $t will be Uint8xN for VPAVGB, Uint16xN for VPAVGW |
| go: $t |
| base: uint |
| - *uint_t |
| out: |
| - *uint_t |
| |
| # Absolute Value (signed byte, word, dword, qword) |
| # Instructions: VPABSB, VPABSW, VPABSD, VPABSQ |
| - go: Absolute |
| asm: "VPABS[BWDQ]" # Matches VPABSB, VPABSW, VPABSD, VPABSQ |
| in: |
| - &int_t # $t will be Int8xN, Int16xN, Int32xN, Int64xN |
| go: $t |
| base: int |
| out: |
| - *int_t # Output is magnitude, fits in the same signed type |
| |
| # Sign Operation (signed byte, word, dword) |
| # Applies sign of second operand to the first. |
| # Instructions: VPSIGNB, VPSIGNW, VPSIGND |
| - go: Sign |
| asm: "VPSIGN[BWD]" # Matches VPSIGNB, VPSIGNW, VPSIGND |
| in: |
| - *int_t # value to apply sign to |
| - *int_t # value from which to take the sign |
| out: |
| - *int_t |
| |
| # Population Count (count set bits in each element) |
| # Instructions: VPOPCNTB, VPOPCNTW (AVX512_BITALG) |
| # VPOPCNTD, VPOPCNTQ (AVX512_VPOPCNTDQ) |
| - go: PopCount |
| asm: "VPOPCNT[BWDQ]" |
| in: |
| - &any |
| go: $t |
| out: |
| - *any |
| - go: PairDotProd |
| asm: VPMADDWD |
| in: |
| - &int |
| go: $t |
| base: int |
| - *int |
| out: |
| - &int2 # The elemBits are different |
| go: $t2 |
| base: int |
| - go: SaturatedUnsignedSignedPairDotProd |
| asm: VPMADDUBSW |
| in: |
| - &uint |
| go: $t |
| base: uint |
| overwriteElementBits: 8 |
| - &int3 |
| go: $t3 |
| base: int |
| overwriteElementBits: 8 |
| out: |
| - *int2 |
| - go: DotProdBroadcast |
| asm: VDPP[SD] |
| in: |
| - &dpb_src |
| go: $t |
| - *dpb_src |
| - class: immediate |
| const: 127 |
| out: |
| - *dpb_src |
| - go: UnsignedSignedQuadDotProdAccumulate |
| asm: "VPDPBUSD" |
| operandOrder: "31" # switch operand 3 and 1 |
| in: |
| - &qdpa_acc |
| go: $t_acc |
| base: int |
| elemBits: 32 |
| - &qdpa_src1 |
| go: $t_src1 |
| base: uint |
| overwriteElementBits: 8 |
| - &qdpa_src2 |
| go: $t_src2 |
| base: int |
| overwriteElementBits: 8 |
| out: |
| - *qdpa_acc |
| - go: SaturatedUnsignedSignedQuadDotProdAccumulate |
| asm: "VPDPBUSDS" |
| operandOrder: "31" # switch operand 3 and 1 |
| in: |
| - *qdpa_acc |
| - *qdpa_src1 |
| - *qdpa_src2 |
| out: |
| - *qdpa_acc |
| - go: AddDotProd |
| asm: "VPDPWSSD" |
| in: |
| - &pdpa_acc |
| go: $t_acc |
| base: int |
| elemBits: 32 |
| - &pdpa_src1 |
| go: $t_src1 |
| base: int |
| overwriteElementBits: 16 |
| - &pdpa_src2 |
| go: $t_src2 |
| base: int |
| overwriteElementBits: 16 |
| out: |
| - *pdpa_acc |
| - go: SaturatedAddDotProd |
| asm: "VPDPWSSDS" |
| in: |
| - *pdpa_acc |
| - *pdpa_src1 |
| - *pdpa_src2 |
| out: |
| - *pdpa_acc |
| - go: FusedMultiplyAdd |
| asm: "VFMADD213PS|VFMADD213PD" |
| in: |
| - &fma_op |
| go: $t |
| base: float |
| - *fma_op |
| - *fma_op |
| out: |
| - *fma_op |
| - go: FusedMultiplyAddSub |
| asm: "VFMADDSUB213PS|VFMADDSUB213PD" |
| in: |
| - *fma_op |
| - *fma_op |
| - *fma_op |
| out: |
| - *fma_op |
| - go: FusedMultiplySubAdd |
| asm: "VFMSUBADD213PS|VFMSUBADD213PD" |
| in: |
| - *fma_op |
| - *fma_op |
| - *fma_op |
| out: |
| - *fma_op |
| - go: Max |
| asm: "V?PMAXS[BWDQ]" |
| in: &2int |
| - &int |
| go: $t |
| base: int |
| - *int |
| out: &1int |
| - *int |
| - go: Max |
| asm: "V?PMAXU[BWDQ]" |
| in: &2uint |
| - &uint |
| go: $t |
| base: uint |
| - *uint |
| out: &1uint |
| - *uint |
| |
| - go: Min |
| asm: "V?PMINS[BWDQ]" |
| in: *2int |
| out: *1int |
| - go: Min |
| asm: "V?PMINU[BWDQ]" |
| in: *2uint |
| out: *1uint |
| |
| - go: Max |
| asm: "V?MAXP[SD]" |
| in: &2float |
| - &float |
| go: $t |
| base: float |
| - *float |
| out: &1float |
| - *float |
| - go: Min |
| asm: "V?MINP[SD]" |
| in: *2float |
| out: *1float |
| - go: SetElem |
| asm: "VPINSR[BWDQ]" |
| in: |
| - &t |
| class: vreg |
| base: $b |
| - class: greg |
| base: $b |
| lanes: 1 # Scalar, darn it! |
| - &imm |
| class: immediate |
| immOffset: 0 |
| name: index |
| out: |
| - *t |
| |
| - go: GetElem |
| asm: "VPEXTR[BWDQ]" |
| in: |
| - class: vreg |
| base: $b |
| elemBits: $e |
| - *imm |
| out: |
| - class: greg |
| base: $b |
| bits: $e |
| |
| - go: Set128 |
| asm: "VINSERTI128" |
| in: |
| - &i8x32 |
| class: vreg |
| base: $t |
| bits: 256 |
| OverwriteElementBits: 8 |
| - &i8x16 |
| class: vreg |
| base: $t |
| bits: 128 |
| OverwriteElementBits: 8 |
| - &imm01 # This immediate should be only 0 or 1 |
| class: immediate |
| immOffset: 0 |
| name: index |
| out: |
| - *i8x32 |
| |
| - go: Get128 |
| asm: "VEXTRACTI128" |
| in: |
| - *i8x32 |
| - *imm01 |
| out: |
| - *i8x16 |
| |
| - go: Set128 |
| asm: "VINSERTI128" |
| in: |
| - &i16x16 |
| class: vreg |
| base: $t |
| bits: 256 |
| OverwriteElementBits: 16 |
| - &i16x8 |
| class: vreg |
| base: $t |
| bits: 128 |
| OverwriteElementBits: 16 |
| - *imm01 |
| out: |
| - *i16x16 |
| |
| - go: Get128 |
| asm: "VEXTRACTI128" |
| in: |
| - *i16x16 |
| - *imm01 |
| out: |
| - *i16x8 |
| |
| - go: Set128 |
| asm: "VINSERTI128" |
| in: |
| - &i32x8 |
| class: vreg |
| base: $t |
| bits: 256 |
| OverwriteElementBits: 32 |
| - &i32x4 |
| class: vreg |
| base: $t |
| bits: 128 |
| OverwriteElementBits: 32 |
| - *imm01 |
| out: |
| - *i32x8 |
| |
| - go: Get128 |
| asm: "VEXTRACTI128" |
| in: |
| - *i32x8 |
| - *imm01 |
| out: |
| - *i32x4 |
| |
| - go: Set128 |
| asm: "VINSERTI128" |
| in: |
| - &i64x4 |
| class: vreg |
| base: $t |
| bits: 256 |
| OverwriteElementBits: 64 |
| - &i64x2 |
| class: vreg |
| base: $t |
| bits: 128 |
| OverwriteElementBits: 64 |
| - *imm01 |
| out: |
| - *i64x4 |
| |
| - go: Get128 |
| asm: "VEXTRACTI128" |
| in: |
| - *i64x4 |
| - *imm01 |
| out: |
| - *i64x2 |
| |
| - go: Set128 |
| asm: "VINSERTF128" |
| in: |
| - &f32x8 |
| class: vreg |
| base: $t |
| bits: 256 |
| OverwriteElementBits: 32 |
| - &f32x4 |
| class: vreg |
| base: $t |
| bits: 128 |
| OverwriteElementBits: 32 |
| - *imm01 |
| out: |
| - *f32x8 |
| |
| - go: Get128 |
| asm: "VEXTRACTF128" |
| in: |
| - *f32x8 |
| - *imm01 |
| out: |
| - *f32x4 |
| |
| - go: Set128 |
| asm: "VINSERTF128" |
| in: |
| - &f64x4 |
| class: vreg |
| base: $t |
| bits: 256 |
| - &f64x2 |
| class: vreg |
| base: $t |
| bits: 128 |
| - *imm01 |
| out: |
| - *f64x4 |
| |
| - go: Get128 |
| asm: "VEXTRACTF128" |
| in: |
| - *f64x4 |
| - *imm01 |
| out: |
| - *f64x2 |
| |
| - go: Permute |
| asm: "VPERM[BWDQ]|VPERMP[SD]" |
| operandOrder: "21Type1" |
| in: |
| - &anyindices |
| go: $t |
| name: indices |
| overwriteBase: uint |
| - &any |
| go: $t |
| out: |
| - *any |
| |
| - go: Permute2 |
| asm: "VPERMI2[BWDQ]|VPERMI2P[SD]" |
| # Because we are overwriting the receiver's type, we |
| # have to move the receiver to be a parameter so that |
| # we can have no duplication. |
| operandOrder: "231Type1" |
| in: |
| - *anyindices # result in arg 0 |
| - *any |
| - *any |
| out: |
| - *any |
| |
| - go: Compress |
| asm: "VPCOMPRESS[BWDQ]|VCOMPRESSP[SD]" |
| in: |
| # The mask in Compress is a control mask rather than a write mask, so it's not optional. |
| - class: mask |
| - *any |
| out: |
| - *any |
| |
| # For now a non-public method because |
| # (1) [OverwriteClass] must be set together with [OverwriteBase] |
| # (2) "simdgen does not support [OverwriteClass] in inputs". |
| # That means the signature is wrong. |
| - go: blend |
| asm: VPBLENDVB |
| in: |
| - &v |
| go: $t |
| class: vreg |
| base: int |
| - *v |
| - |
| class: vreg |
| base: int |
| name: mask |
| out: |
| - *v |
| |
| # For AVX512 |
| - go: blend |
| asm: VPBLENDM[BWDQ] |
| in: |
| - &v |
| go: $t |
| bits: 512 |
| class: vreg |
| base: int |
| - *v |
| inVariant: |
| - |
| class: mask |
| out: |
| - *v |
| |
| # "Normal" multiplication is only available for floats. |
| # This only covers the single and double precision. |
| - go: Mul |
| asm: "VMULP[SD]" |
| in: |
| - &fp |
| go: $t |
| base: float |
| - *fp |
| out: |
| - *fp |
| |
| # Integer multiplications. |
| |
| # MulEvenWiden |
| # Dword only. |
| - go: MulEvenWiden |
| asm: "VPMULDQ" |
| in: |
| - &int |
| go: $t |
| base: int |
| - *int |
| out: |
| - &int2 |
| go: $t2 |
| base: int |
| - go: MulEvenWiden |
| asm: "VPMULUDQ" |
| in: |
| - &uint |
| go: $t |
| base: uint |
| - *uint |
| out: |
| - &uint2 |
| go: $t2 |
| base: uint |
| |
| # MulHigh |
| # Word only. |
| - go: MulHigh |
| asm: "VPMULHW" |
| in: |
| - *int |
| - *int |
| out: |
| - *int2 |
| - go: MulHigh |
| asm: "VPMULHUW" |
| in: |
| - *uint |
| - *uint |
| out: |
| - *uint2 |
| |
| # MulLow |
| # Signed int only. |
| - go: Mul |
| asm: "VPMULL[WDQ]" |
| in: |
| - *int |
| - *int |
| out: |
| - *int2 |
| # Integers |
| # ShiftAll* |
| - go: ShiftAllLeft |
| asm: "VPSLL[WDQ]" |
| in: |
| - &any |
| go: $t |
| - &vecAsScalar64 |
| go: "Uint.*" |
| treatLikeAScalarOfSize: 64 |
| out: |
| - *any |
| - go: ShiftAllRight |
| signed: false |
| asm: "VPSRL[WDQ]" |
| in: |
| - &uint |
| go: $t |
| base: uint |
| - *vecAsScalar64 |
| out: |
| - *uint |
| - go: ShiftAllRight |
| signed: true |
| asm: "VPSRA[WDQ]" |
| in: |
| - &int |
| go: $t |
| base: int |
| - *vecAsScalar64 |
| out: |
| - *int |
| |
| - go: shiftAllLeftConst |
| asm: "VPSLL[WDQ]" |
| in: |
| - *any |
| - &imm |
| class: immediate |
| immOffset: 0 |
| out: |
| - *any |
| - go: shiftAllRightConst |
| asm: "VPSRL[WDQ]" |
| in: |
| - *int |
| - *imm |
| out: |
| - *int |
| - go: shiftAllRightConst |
| asm: "VPSRA[WDQ]" |
| in: |
| - *uint |
| - *imm |
| out: |
| - *uint |
| |
| # Shift* (variable) |
| - go: ShiftLeft |
| asm: "VPSLLV[WD]" |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| # XED data of VPSLLVQ marks the element bits 32 which is off to the actual semantic, we need to overwrite |
| # it to 64. |
| - go: ShiftLeft |
| asm: "VPSLLVQ" |
| in: |
| - &anyOverwriteElemBits |
| go: $t |
| overwriteElementBits: 64 |
| - *anyOverwriteElemBits |
| out: |
| - *anyOverwriteElemBits |
| - go: ShiftRight |
| signed: false |
| asm: "VPSRLV[WD]" |
| in: |
| - *uint |
| - *uint |
| out: |
| - *uint |
| # XED data of VPSRLVQ needs the same overwrite as VPSLLVQ. |
| - go: ShiftRight |
| signed: false |
| asm: "VPSRLVQ" |
| in: |
| - &uintOverwriteElemBits |
| go: $t |
| base: uint |
| overwriteElementBits: 64 |
| - *uintOverwriteElemBits |
| out: |
| - *uintOverwriteElemBits |
| - go: ShiftRight |
| signed: true |
| asm: "VPSRAV[WDQ]" |
| in: |
| - *int |
| - *int |
| out: |
| - *int |
| |
| # Rotate |
| - go: RotateAllLeft |
| asm: "VPROL[DQ]" |
| in: |
| - *any |
| - &pureImm |
| class: immediate |
| immOffset: 0 |
| name: shift |
| out: |
| - *any |
| - go: RotateAllRight |
| asm: "VPROR[DQ]" |
| in: |
| - *any |
| - *pureImm |
| out: |
| - *any |
| - go: RotateLeft |
| asm: "VPROLV[DQ]" |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| - go: RotateRight |
| asm: "VPRORV[DQ]" |
| in: |
| - *any |
| - *any |
| out: |
| - *any |
| |
| # Bizzare shifts. |
| - go: ShiftAllLeftConcat |
| asm: "VPSHLD[WDQ]" |
| in: |
| - *any |
| - *any |
| - *pureImm |
| out: |
| - *any |
| - go: ShiftAllRightConcat |
| asm: "VPSHRD[WDQ]" |
| in: |
| - *any |
| - *any |
| - *pureImm |
| out: |
| - *any |
| - go: ShiftLeftConcat |
| asm: "VPSHLDV[WDQ]" |
| in: |
| - *any |
| - *any |
| - *any |
| out: |
| - *any |
| - go: ShiftRightConcat |
| asm: "VPSHRDV[WDQ]" |
| in: |
| - *any |
| - *any |
| - *any |
| out: |
| - *any |