Giter Club home page Giter Club logo

arm-neon-intrinsics's Introduction

Arm-neon-intrinsics

arm neon 方面的文档真的很少,所以整理下intrinsics指令的内容和文档 :)

更详细的armeabi-v7a文档可以看ARMV7 NEON汇编指令详解中文版.pdf

初始化寄存器

  • vcreate_type: 将一个64bit的数据装入vector中,并返回元素类型为type的vector。r=a
  • vdup_n_type/vmov_n_type: 用类型为type的数值,初始化一个元素类型为type的新vector的所有元素。ri=a
  • vdupq_n_type/vmovq_n_type:
  • vdup_lane_type: 用元素类型为type的vector的某个元素,初始化一个元素类型为type的新vector的所有元素。ri=a[b]
  • vdupq_lane_type:
  • vmovl_type: 将vector的元素bit位扩大到原来的两倍,元素值不变。
  • vmovn_type: 用旧vector创建一个新vector,新vector的元素bit位是旧vector的一半。新vector元素只保留旧vector元素的低半部分。
  • vqmovn_type: 用旧vector创建一个新vector,新vector的元素bit位是旧vector的一半。如果旧vector元素的值超过新vector元素的最大值,则新vector元素就取最大值。否则新vector元素就等于旧vector元素的值。
  • vqmovun_type: 作用与vqmovn_type类似,但它输入的是有符号vector,输出的是无符号vector。

从内存加载数据进neon寄存器

  • vld1_type: 按顺序将内存的数据装入neon寄存器,并返回元素类型为type格式的vector
  • vld1q_type:
  • vld1_lane_type:用旧vector创建一个同类型的新vector,同时将新vector中指定元素的值改为内存中的值。
  • vld1q_lane_type:
  • vld1_dup_type:用type类型的内存中第一个值,初始化一个元素类型为type的新vector的所有元素。
  • vld1q_dup_type:
  • vld2_type: 按交叉顺序将内存的数据装入2个neon寄存器(内存第1个数据放入第1个neon寄存器的第1个通道,内存第2个数据放入第2个neon寄存器的第1个通道,内存第3个数据放入第1个neon寄存器的第2个通道,内存第4个数据放入第2个neon寄存器的第2个通道。。。)。并返回有两个vector的结构体
  • vld2q_type:
  • vld2_lane_type:
  • vld2q_lane_type:
  • vld2_dup_type: 用type类型的内存中第一个值,初始化第一个新vector的所有元素,用内存中第二个值,初始化第二个新vector的所有元素。
  • vld3_type: 交叉存放,本质上与vld2_type类似,只是这里装载3个neon寄存器
  • vld3q_type:
  • vld3_lane_type:
  • vld3q_lane_type:
  • vld3_dup_type: 本质上与vld2_dup_type类似
  • vld4_type: 交叉存放,本质上与vld2_type类似,只是这里装载4个neon寄存器
  • vld4q_type:
  • vld4_lane_type:
  • vld4q_lane_type:
  • vld4q_dup_type: 本质上与vld2_dup_type类似

从neon寄存器加载数据进内存

  • vst1_type: 将元素类型为type格式的vector的所有元素装入内存
  • vst1q_type:
  • vst1_lane_type: 将元素类型为type格式的vector中指定的某个元素装入内存
  • vst1q_lane_type:
  • vst2_type: 交叉存放,vld2_type的逆过程
  • vst2q_type:
  • vst2_lane_type:
  • vst2q_lane_type:
  • vst3_type: 交叉存放,vld3_type的逆过程
  • vst3q_type:
  • vst3_lane_type:
  • vst3q_lane_type:
  • vst4_type: 交叉存放,vld4_type的逆过程
  • vst4q_type:
  • vst4_lane_type:
  • vst4q_lane_type:

直接获取neon寄存器某个通道的值

  • vget_low_type: 获取128bit vector的低半部分元素,输出的是元素类型相同的64bit vector。
  • vget_high_type: 获取128bit vector的高半部分元素,输出的是元素类型相同的64bit vector。
  • vget_lane_type: 获取元素类型为type的vector中指定的某个元素值。
  • vgetq_lane_type:

直接设置neon寄存器某个通道的值

  • vset_lane_type: 设置元素类型为type的vector中指定的某个元素的值,并返回新vector。
  • vsetq_lane_type:

寄存器数据重排

  • vext_type: 取第2个输入vector的低n个元素放入新vector的高位,新vector剩下的元素取自第1个输入vector最高的几个元素(可实现vector内元素位置的移动)

  • vextq_type: 如:src1 = {1,2,3,4,5,6,7,8} src2 = {9,10,11,12,13,14,15,16} dst = vext_type(src1,src2,3)时,则dst = {4,5,6,7,8, 9,10,11}

  • vtbl1_type: 第二个vector是索引,根据索引去第一个vector(相当于数组)中搜索相应的元素,并输出新的vector,超过范围的索引返回的是0. 如:src1 = {1,2,3,4,5,6,7,8} src2 = {0,0,1,1,2,2,7,8} dst = vtbl1_u8(src1,src2)时,则dst = {1,1,2,2,3,3,8,0}

  • vtbl2_type: 数组长度扩大到2个vector 如:src.val[0] = {1,2,3,4,5,6,7,8} src.val[1] = {9,10,11,12,13,14,15,16} src2 = {0,0,1,1,2,2,8,10} dst = vtbl2_u8(src,src2)时,则dst = {1,1,2,2,3,3,9,11}

  • vtbl3_type:

  • vtbl4_type:

  • vtbx1_type: 根vtbl1_type功能一样,不过搜索到的元素是用来替换第一个vector中的元素,并输出替换后的新vector,当索引超出范围时,则不替换第一个vector中相应的元素。

  • vtbx2_type:

  • vtbx3_type:

  • vtbx4_type:

  • vrev16_type: 将vector中的元素位置反转

  • vrev16q_type: 如:src1 = {1,2,3,4,5,6,7,8} dst = vrev16_u8(src1)时,则dst = {2,1,4,3,6,5,8,7}

  • vrev32_type:

  • vrev32q_type: 如:src1 = {1,2,3,4,5,6,7,8} dst = vrev32_u8(src1)时,则dst = {4,3,2,1,8,7,6,5}

  • vrev64_type:

  • vrev64q_type: 如:src1 = {1,2,3,4,5,6,7,8} dst = vrev32_u8(src1)时,则dst = {8,7,6,5,4,3,2,1}

  • vtrn_type: 将两个输入vector的元素通过转置生成一个有两个vector的矩阵

  • vtrnq_type: 如:src.val[0] = {1,2,3,4,5,6,7,8} src.val[1] = {9,10,11,12,13,14,15,16} dst = vtrn_u8(src.val[0], src.val[1])时, 则 dst.val[0] = {1,9, 3,11,5,13,7,15} dst.val[1] = {2,10,4,12,6,14,8,16}

  • vzip_type: 将两个输入vector的元素通过交叉生成一个有两个vector的矩阵

  • vzipq_type: 如:src.val[0] = {1,2,3,4,5,6,7,8} src.val[1] = {9,10,11,12,13,14,15,16} dst = vzip_u8(src.val[0], src.val[1])时, 则dst.val[0] = {1,9, 2,10,3,11,4,12} dst.val[1] = {5,13,6,14,7,15,8,16}

  • vuzp_type: 将两个输入vector的元素通过反交叉生成一个有两个vector的矩阵(通过这个可实现n-way 交织)

  • vuzpq_type: 如:src.val[0] = {1,2,3,4,5,6,7,8} src.val[1] = {9,10,11,12,13,14,15,16} dst = vuzp_u8(src.val[0], src.val[1])时, 则dst.val[0] = {1,3,5,7,9, 11,13,15} dst.val[1] = {2,4,6,8,10,12,14,16}

  • vcombine_type: 将两个元素类型相同的输入vector拼接成一个同类型但大小是输入vector两倍的新vector。新vector中低部分元素存放的是第一个输入vector元素。

  • vbsl_type:按位选择,参数为(mask, src1, src2)。mask的某个bit为1,则选择src1中对应的bit,为0,则选择src2中对应的bit。

  • vbslq_type:

加法

  • vadd_type: ri = ai + bi
  • vaddq_type:
  • vaddl_type: 变长加法运算,为了防止溢出
  • vaddw_type: 第一个vector元素宽度大于第二个vector元素
  • vaddhn_type: 结果vector元素的类型大小是输入vector元素的一半
  • vqadd_type: ri = sat(ai + bi) 饱和指令,相加结果超出元素的最大值时,元素就取最大值。
  • vqaddq_type:
  • vhadd_type: 相加结果再除2。ri = (ai + bi) >> 1;
  • vhaddq_type:
  • vrhadd_type: 相加结果再除2(四舍五入)。ri = (ai + bi + 1) >> 1
  • vrhaddq_type:
  • vpadd_type: r0 = a0 + a1, ..., r3 = a6 + a7, r4 = b0 + b1, ..., r7 = b6 + b7
  • vpaddl_type: r0 = a0 + a1, ..., r3 = a6 + a7;
  • vpaddlq_type:
  • vpadal_type: r0 = a0 + (b0 + b1), ..., r3 = a3 + (b6 + b7);

减法

  • vsub_type: ri = ai - bi
  • vsubq_type:
  • vsubl_type:
  • vsubw_type:
  • vsubhn_type:
  • vqsub_type: 饱和指令 ri = sat(ai - bi)
  • vqsubq_type:
  • vhsub_type: 相减结果再除2。ri = (ai - bi) >> 1
  • vhsubq_type:
  • vrsubhn_type: 相减结果再除2(四舍五入)。ri = (ai - bi + 1) >> 1

乘法

  • vmul_type: ri = ai * bi
  • vmulq_type:
  • vmul_n_type: ri = ai * b
  • vmulq_n_type:
  • vmul_lane_type: ri = ai * b[c]
  • vmulq_lane_type:
  • vmull_type: 变长乘法运算,为了防止溢出
  • vmull_n_type:
  • vmull_lane_type:
  • vqdmull_type: 变长乘法运算,参与运算的值是有符号数(所以可能溢出),当结果溢出时,取饱和值
  • vqdmull_n_type:
  • vqdmull_lane_type:
  • vqdmulh_type:
  • vqdmulhq_type:
  • vqdmulh_n_type:
  • vqdmulhq_n_type:
  • vqdmulh_lane_type:
  • vqdmulhq_lane_type:
  • vqrdmulh_type:
  • vqrdmulhq_type:
  • vqrdmulh_n_type:
  • vqrdmulhq_n_type:
  • vqrdmulh_lane_type:
  • vqrdmulhq_lane_type:

乘加组合运算

  • vmla_type: ri = ai + bi * ci
  • vmlaq_type:
  • vmla_n_type: ri = ai + bi * c
  • vmlaq_n_type:
  • vmla_lane_type: ri = ai + bi * c[d]
  • vmlaq_lane_type:
  • vmlal_type: 长指令 ri = ai + bi * ci
  • vmlal_n_type:
  • vmlal_lane_type:
  • vfma_f32:ri = ai + bi * ci 在加法之前,bi、ci相乘的结果不会被四舍五入
  • vqdmlal_type: ri = sat(ai + bi * ci) bi/ci的元素大小是ai的一半
  • vqdmlal_n_type: ri = sat(ai + bi * c)
  • vqdmlal_lane_type: ri = sat(ai + bi * c[d])

乘减组合运算

  • vmls_type: ri = ai - bi * ci
  • vmlsq_type:
  • vmls_n_type: ri = ai - bi * c
  • vmlsq_n_type:
  • vmls_lane_type: ri = ai - bi * c[d]
  • vmlsq_lane_type:
  • vmlsl_type: 长指令 ri = ai - bi * ci
  • vmlsl_n_type:
  • vmlsl_lane_type:
  • vfms_f32:ri = ai - bi * ci 在减法之前,bi、ci相乘的结果不会被四舍五入
  • vqdmlsl_type: ri = sat(ai - bi * ci) bi/ci的元素大小是ai的一半
  • vqdmlsl_n_type: ri = sat(ai - bi * c)
  • vqdmlsl_lane_type: ri = sat(ai - bi * c[d])

取整

  • vrndn_f32: to nearest, ties to even
  • vrndqn_f32:
  • vrnda_f32: to nearest, ties away from zero
  • vrndqa_f32:
  • vrndp_f32: towards +Inf
  • vrndqp_f32:
  • vrndm_f32: towards -Inf
  • vrndqm_f32:
  • vrnd_f32: towards 0
  • vrnqd_f32:

比较运算(结果为true,则所有的bit位被设置为1)

  • vceq_type: ri = ai == bi ? 1...1 : 0...0
  • vceqq_type:
  • vcge_type: ri = ai >= bi ? 1...1:0...0
  • vcgeq_type:
  • vcle_type: ri = ai <= bi ? 1...1:0...0
  • vcleq_type:
  • vcgt_type: ri = ai > bi ? 1...1:0...0
  • vcgtq_type:
  • vclt_type: ri = ai < bi ? 1...1:0...0
  • vcltq_type:
  • vcage_f32: ri = |ai| >= |bi| ? 1...1:0...0
  • vcageq_f32:
  • vcale_f32: ri = |ai| <= |bi| ? 1...1:0...0
  • vcaleq_f32:
  • vcagt_f32: ri = |ai| > |bi| ? 1...1:0...0
  • vcagtq_f32:
  • vcalt_f32: ri = |ai| < |bi| ? 1...1:0...0
  • vcaltq_f32:
  • vtst_type: ri = (ai & bi != 0) ? 1...1:0...0
  • vtstq_type:

绝对值

  • vabs_type: ri = |ai|
  • vabsq_type:
  • vqabs_type: ri = sat(|ai|)
  • vqabsq_type:
  • vabd_type: ri = |ai - bi|
  • vabdq_type:
  • vabdl_type: 长指令
  • vaba_type: ri = ai + |bi - ci|
  • vabaq_type:
  • vabal_type: 长指令

取最大最小值

  • vmax_type: ri = ai >= bi ? ai : bi
  • vmaxq_type:
  • vpmax_type: r0 = a0 >= a1 ? a0 : a1, ..., r4 = b0 >= b1 ? b0 : b1, ...
  • vmin_type: ri = ai <= bi ? ai : bi
  • vminq_type:
  • vpmin_type: r0 = a0 <= a1 ? a0 : a1, ..., r4 = b0 <= b1 ? b0 : b1, ...

倒数

  • vrecpe_type: 求近似倒数,type是f32或者u32
  • vrecpeq_type:
  • vrecps_f32:(牛顿 - 拉夫逊迭代)
  • vrecpsq_f32 注:vrecpe_type计算倒数能保证千分之一左右的精度,如1.0的倒数为0.998047。执行完如下语句后能提高百万分之一精度 float32x4_t recip = vrecpeq_f32(src);此时能达到千分之一左右的精度,如1.0的倒数为0.998047 recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec);执行后能达到百万分之一左右的精度,如1.0的倒数为0.999996 recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec);再次执行后能基本能达到完全精度,如1.0的倒数为1.000000

平方根倒数

  • vrsqrte_type: 计算输入值的平方根的倒数,type是f32或者u32。输入值不能是负数,否则计算出来的值是nan。
  • vrsqrteq_type:
  • vrsqrts_f32
  • vrsqrtsq_f32

移位运算

  • vshl_type: ri = ai << bi 如果bi是负数,则变成右移

  • vshlq_type:

  • vshl_n_type: ri = ai << b 这里b是常数,如果传入的不是常数(即在编译的时候就要知道b的值),编译时会报错

  • vshlq_n_type:

  • vqshl_type: ri = sat(ai << bi)

  • vqshlq_type:

  • vrshl_type: ri = round(ai << bi)

  • vrshlq_type:

  • vqrshl_type: ri = sat&round(ai << bi)

  • vqrshlq_type:

  • vqshl_n_type: ri = sat(ai << b)

  • vqshlq_n_type:

  • vqshlu_n_type: ri = ai << b 输入vector是有符号,输出vector是无符号

  • vqshluq_n_type:

  • vshll_n_type:

  • vshr_n_type: ri = ai >> b

  • vshrq_n_type:

  • vrshr_n_type: ri = round(ai >> b)

  • vrshrq_n_type:

  • vsra_n_type: ri = (ai >> c) + (bi >> c)

  • vsraq_n_type:

  • vrsra_n_type: ri = round((ai >> c) + (bi >> c))

  • vrsraq_n_type:

  • vshrn_n_type: 窄指令ri = ai >> b

  • vqshrun_n_type:

  • vqrshrun_n_type:

  • vqshrn_n_type:

  • vrshrn_n_type:

  • vqrshrn_n_type:

  • vsri_n_type:

  • vsriq_n_type:

  • vsli_n_type:

  • vsliq_n_type:

取负

  • vneg_type: ri = -ai
  • vnegq_type:
  • vqneg_type: ri = sat(-ai)
  • vqnegq_type:

按位运算

  • vmvn_type: ri = ~ai
  • vmvnq_type:
  • vand_type: ri = ai & bi
  • vandq_type:
  • vorr_type: ri = ai | bi
  • vorrq_type:
  • veor_type: ri = ai ^ bi
  • veorq_type:
  • vbic_type: ri = ~ai & bi
  • vbicq_type:
  • vorn_type: ri = ai | (~bi) -vornq_type:

统计

  • vcls_type:
  • vclz_type:
  • vcnt_type: 统计向量每个元素有多少bit位是1
  • vcntq_type:

数据类型转换

  • vcvt_type1_type2: f32、u32、s32之间的转换。在f32转到u32时,是向下取整,且如果是负数,则转换后为0
  • vcvtq_type1_type2:
  • vcvt_n_type1_type2:
  • vcvtq_n_type1_type2:
  • vreinterpret_type1_type2: 将元素类型为type2的vector转换为元素类型为type1的vector。数据重新解析
  • vreinterpretq_type1_type2:

arm-neon-intrinsics's People

Contributors

rogerou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arm-neon-intrinsics's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.