浮点指令除了VFP还有NEON。
NEON 支持整数、定点和单精度浮点 SIMD 运算。
NEON 是针对高级媒体和信号处理应用程序以及嵌入式处理器的 64/128 位混合 SIMD 技术。 它是作为 ARM内核的一部分实现的,但有自己的执行管道和寄存器组,该寄存器组不同于ARM 核心寄存器组。
VFP指令用FADD,NEON指令用VADD。
NEON指令集比VFP指令集更广泛,因此,尽管大多数VFP指令具有等效的NEON指令,但仍有许多NEON指令执行VFP指令无法执行的操作。
ARMv5开始引入了VFP(Vector Floating Point)指令,该指令用于向量化加速浮点运算。自ARMv7开始正式引入NEON指令,NEON性能远超VFP,因此VFP指令被废弃。类似于Intel CPU下的MMX/SSE/AVX/FMA指令。
VFP Instruction |
Equivalent NEON Instruction |
Description |
FADD[S|D]{cond} Fd, Fn, Fm |
VADD.[F32|F64] Fd, Fn, Fm |
Single and double precision add |
FSUB[S|D]{cond} Fd, Fn, Fm |
VSUB.[F32|F64] Fd, Fn, Fm |
Single and double precision subtract |
FMUL[S|D]{cond} Fd, Fn, Fm |
VMUL.[F32|F64] Fd, Fn, Fm |
Single and double precision multiply and multiply-and-negate |
FNMUL[S|D]{cond} Fd, Fn, Fm |
VNMUL.[F32|F64] Fd, Fn, Fm |
|
FDIV[S|D]{cond} Fd, Fn, Fm |
VDIV.[F32|F64] Fd, Fn, Fm |
Single and double precision divide |
FABS[S|D]{cond} Fd, Fm |
VABS.[F32|F64] Fd, Fn, Fm |
Single and double precision absolute value |
FNEG[S|D]{cond} Fd, Fm |
VNEG.[F32|F64] Fd, Fn, Fm |
Single and double precision negate |
FSQRT[S|D]{cond} Fd, Fm |
VSQRT.[F32|F64] Fd, Fn, Fm |
Single and double precision square root |
FCVTSD{cond} Fd, Fm |
VCVT.F32.F64 Fd, Fm |
Convert double precision to single precision |
FCVTDS{cond} Fd, Fm |
VCVT.F64.F32 Fd, Fm |
Convert single precision to double precision |
|
VCVT.[S|U][32|16].[F32|F64], #fbits Fd, Fm |
Convert floating point to fixed point |
|
VCVT.[F32|F64].[S|U][32|16],#fbits Fd, Fm, #fbits |
Convert floating point to fixed point |
FMAC[S|D]{cond} Fd, Fn, Fm |
VMLA.[F32|F64] Fd, Fn, Fm |
Single and double precision floating point multiply-accumulate, calculates Rd = Fn * Fm + Fd |
There are similar instructions that negate the contents of Fd, Fn, or both prior to use, for example, FNMSC[S|D], VNMLS[.F32|.F64] |
||
FLD[S|D]{cond} Fd,<address > |
VLDR{cond} Rd, < address > |
Single and double precision floating point load/store |
FST[S|D]{cond} Fd,<address > |
LSTR{cond} Rd, < address > |
|
FLDMI[S|D]{cond} < address >, < FPRegs > |
VLDM{cond} Rn{!}, < FPRegs > |
Single and double precision floating point load/store multiple |
FSTMI[S|D]{cond} < address >, < FPRegs > |
VSTM{cond} Rn{!}, < FPRegs > |
|
FMRX{cond} Rd |
VMRX Rd |
Move from/to floating point status and control |
FMXR{cond} Rm |
VMXR Rm |
register |
FCPY[S|D]{cond} Fd,Fm |
VMOV{cond} Fd,Fm |
Copy floating point register |
编译器编译可以选择。
编译器将生成用于单精度和双精度浮点运算的VFPv3指令
编译器将为SIMD整数运算生成NEON指令。 它不会生成NEON指令来向量化浮点运算。
如果未启用VFP,则不允许浮点NEON指令的动机是因为可以实现NEON的仅整数变量。 为了使NEON单元支持浮点运算,必须存在VFPv3协处理器。
在这种模式下,编译器将生成NEON和VFP指令的混合。 NEON指令可以是整数或浮点数。
Neon指令遵循如下的规则:
16x8-bit, 8x16-bit,4x32-bit,2x64-bit 整形操作
8x16-bit*,4x32-bit,2x64-bit 浮点操作
VMOV:
两个arm寄存器和d之间
vmov d0, r0, r1:将r1的内容送到d0到低半部分,r0的内容送到d0到高半部分
vmov r0, r1, d0:将d0的低半部分送到r0,d0的高半部分内容送到r1
一个arm寄存器和d之间
vmov.U32 d0[0], r0:将r0的内容送到d0[0]中,d0[0]指d0到低32位
vmov.U32 r0, d0[0]:将d0[0]的内容送到r0中
做neon乘法指令的时候会有大约2个clock的阻塞时间,如果要立即使用乘法的结果,则就会阻塞,在写neon指令的时候需要特别注意。乘法的结果不能立即使用,可以将一些其他的操作插入到乘法后面而不会有时间的消耗。
先来看下64位的NEON指令。是基于32位的NEON指令的。
加载LDR和存储STR指令还可以访问浮点/NEON寄存器。 此处,大小仅由加载或存储的寄存器确定,该寄存器可以是B,H,S,D或Q寄存器中的任何一个。
有如下的变化。
将float转换为整数(FCVTxU,FCVTxS)指令可编码有向舍入模式:
—趋于零。
—朝+∞。
—朝–∞。
—与偶数关系最近。
—距离最近。
寄存器:
32×64位D寄存器D0-D31。 D寄存器称为双精度寄存器,
包含双精度浮点值。
32×32位S寄存器S0-S31。 S寄存器称为单精度寄存器,而
包含单精度浮点值。
32×16位H寄存器H0-H31。 H寄存器称为半精度寄存器,
包含半精度浮点值。
以上视图中的寄存器组合。