ios

arm-neon

arm-neon 指令

Posted by nomadli on February 28, 2019

简介

  • 是一种SIMD协处理器,可选配置成向量浮点VFPv3
  • 16个128位寄存器Q0-Q15,32个64位寄存器D0-D31
  • 128位与64位寄存器是共用的,小新覆盖

armcc编译器

  • 开启优化等级-O2或者-O3, 开启–vectorize选项来使能向量化编译
  • 指定–cpu 7-A或–cpu Cortex-A8指定指令集架构和CPU类型
  • 指定-mfpu=vfpv3-fp16作为vfp协处理、
  • 指定-mfpu=neon-vfpv4NEON+VFP
  • 指定-mfloat-abi=soft使用软件浮点库不是用VFP或者NEON指令
  • 指定-mfloat-abi=softfp使用软件浮点的调用规则来使用VFP和NEON指令
  • 指定-mfloat-abi=hard使用VFP和NEON指令,改变ABI调用规则提供效率,如用vfp寄存器进行浮点数参数传递减少NEON寄存器和ARM寄存器的拷贝
  • 指定-ffast-math使用浮点数加速

gcc编译器

  • 开启-O3,开启-ftree-vectorize来使能向量化
  • 指定-mfpu=neon和-mcpu=cortex-a5
  • 指定-mfpu=vfpv3-fp16作为vfp协处理、
  • 指定-mfpu=neon-vfpv4 NEON+VFP
  • 指定-mfloat-abi=soft使用软件浮点库不是用VFP或者NEON指令
  • 指定-mfloat-abi=softfp使用软件浮点的调用规则来使用VFP和NEON指令
  • 指定-mfloat-abi=hard使用VFP和NEON指令,改变ABI调用规则提供效率,如用vfp寄存器进行浮点数参数传递减少NEON寄存器和ARM寄存器的拷贝
  • 指定-ffast-math使用浮点数加速

#cpu选择 CPU类型|CPU类型选项|FP选项|FP + SIMD选项|备注 :-|:-|:-|:-|:-| Cortex-A5|-mcpu=cortex-a5|-mfpu=vfpv3-fp16 -mfpu=vfpv3-d16-fp16|-mfpu=neon-fp16|-d16表明只有前16个浮点寄存器可用 Cortex-A7|-mcpu=cortex-a7|-mfpu=vfpv4 -mfpu=vfpv4-d16|-mfpu=neon-vfpv4|-fp16表明支持16bit半精度浮点操作 Cortex-A8|-mcpu=cortex-a8|-mfpu=vfpv3|-mfpu=neon| Cortex-A9|-mcpu=cortex-a9|-mfpu=vfpv3-fp16 -mfpu=vfpv3-d16-fp16|-mfpu=neon-fp16| Cortex-A15|-mcpu=cortex-a15|-mfpu=vfpv4|-mfpu=neon-vfpv4|

NEON 数据类型

  • 无符号整数 U8 U16 U32 U64
  • 有符号整数 S8 S16 S32 S64
  • 未指定类型的整数 I8 I16 I32 I64
  • 浮点数 F32
  • 多项式 P8 P16

NEON 指令

  • 分为正常指令、宽指令、窄指令、饱和指令、长指令
  • 正常指令:返回值与操作数类型及位数相同
  • 宽指令:操作数位数不同,返回值与最长的一样,以W结尾如VADDW指令
  • 窄指令:返回值是操作数的一半,以N结尾如果VMOVN
  • 饱和指令:操作数超过数据长度自动限制到范围,以Q为第二字母如VQSHRUN
  • 长指令:返回值是操作数的一倍,以L结尾如VADDL
  • VMOV 复制指令 ``` //正常指令 VMOV d0, r0, r1 //d0=(r0 « 32) | r1 VMOV r0, r1, d0 //r0=d0 & 0x00000000FFFFFFFF r1=(d0 » 32) & 0x00000000FFFFFFFF VMOV.U32 d0[0], r0 //d0=r0 VMOV.U32 r0, d0[0] //0=d0 & 0x00000000FFFFFFFF VMOV.U16 d0, #1 //d0=0x0001000100010001 VMOV.U32 q0, #1 //d0=0x00000001000000010000000100000001

//长指令 VMOVL.U16 q0, d0 //q0=(d0 & 0x0000000000FFFF)|((d0 & 0x000000FFFF0000) « 32)|… 16->32

//窄指令 VMOVN.I32 d0, q0 //d0=(q0 & 0x000000000000000000FFFFFFFF)|((q0 & 0x0000000000FFFFFFFF00000000) » 32)|.. 32->16

//饱和指令 VQMOVN.S32 d0, q0 //32->16,每部分取值0-65535 ```