原帖地址:http://blog.sina.com.cn/s/blog_602f87700100r5xe.html
一:早期ARM上的浮点模拟器:
早期的ARM没有协处理器,所以浮点运算是由CPU来模拟的,即所需浮点运算均在浮点运算模拟器(float math emulation)上进行,需要的浮点运算,常要耗费数千个循环才能执行完毕,因此特别缓慢。
直到今天,在ARM Kernel配置时,都有如下选项:
Floating point emulation
[ ] NWFPE math emulation
[ ] FastFPE math emulation (EXPERIMENTAL)
在这里,可以配置ARM 浮点模拟器。
浮点模拟器 模拟浮点是利用了undefined instrction handler,这么做带来的后果是带来极频繁的exception,大大增加中断延迟,降低系统实时性。
二:软浮点技术:
软浮点支持是由交叉工具链提供的功能,与Linux内核无关。当使用软浮点工具链编译浮点操作时,编译器会用内联的浮点库替换掉浮点操作,使得生成的机器码完全不含浮点指令,但是又能够完成正确的浮点操作。
三:浮点协处理器:
在较新版本的ARM中,可以添加协处理器。 一些ARM CPU为了更好的处理浮点计算的需要,添加了浮点协处理器。
并定义了浮点指令集。 如果不存在实际的硬件,则这些指令被截获并由浮点模拟器模块(FPEmulator)来执行。
四: 硬件浮点协处理器以及对应指令集的使用:
这里Sam是这样理解的:
想要使用硬件浮点协处理器来帮助运算Application中的浮点运算。需要以下几个前提条件:
1. Kernel中设置支持 硬件协处理器。
2. 编译器支持将浮点运算翻译成硬件浮点运算指令。
1. Kernle的支持:
如果Kernel不支持浮点协处理器,则因为协处理器寄存器等使用权限等问题,协处理器对应指令无法运行。
网络上有位高手指出:
CP15 c1 协处理器访问控制寄存器,这个寄存器规定了用户模式和特权对协处理器的访问权限。我们要使用VFP当然要运行用户模式访问CP10和CP11。
另外一个寄存器是VFP的FPEXC Bit30这是VFP功能的使用位。
其实操作系统在做了这两件事情之后,用户程序就可以使用VFP了。当然,Kernel 除了这2件事外,还处理了其他一些事情。
Sam看了看Kernel中对应代码,发现是汇编后就放弃继续研究了。
Floating point emulation
[*] VFP-format floating point maths
Include VFP support code in the kernel. This is needed IF your hardware includes a VFP unit.
2. 编译器指定浮点指令:
编译器可以显式指定将浮点运算翻译成何种浮点指令。
如果编译器支持软浮点,则其可能会将浮点运算翻译成编译器中自带的浮点库。则不会有真正的浮点运算。
否则,可以翻译成FPA(Floating
还可以将浮点运算指定为VFP(vector
五. 编译器指定编译硬浮点指令:
Sam有个测试程序,测试CPU浮点性能。例如:浮点加减乘除等运算的时间长度:
float src_mem_32[1024] = {1.024};
float dst_mem_32[1024] = {0.933};
for(j = 0; j < 1024; j++)
{
}
通过printf 计算前后毫秒数的差值来看计算能力。
编译:
arm-hisiv200-linux-gcc -c
arm-hisiv200-linux-gcc fcpu.o -o FCPU -L./
运行,则得到32位浮点数加1024次所需要时间。
如果要使用VFP呢?
arm-hisiv200-linux-gcc -c
arm-hisiv200-linux-gcc -Wall -mfpu=vfp -mfloat-abi=softfp
则运行后发现,所需要时间几乎减小了一半。 说明还是非常有效果的。
关于-mfpu
另外,如何才能在直观的检查出是否使用VFP呢?
可以通过察看编译出的ASM程序得到结论。
#arm-hisiv200-linux-objdump -d fcpu.o
00000000 <test_F32bit_addition>:
这里明显包含vfp指令。 所以是使用vfp指令的:
arm-hisiv200-linux-gcc -c
注意:VFP 指令指令在附录1中。
如果使用:
arm-hisiv200-linux-gcc -c
#arm-hisiv200-linux-objdump -d fcpu.o
00000000 <test_F32bit_addition>:
则不包含VFP指令。
且去调用 __aeabi_fadd
六:新一代ARM 浮点引擎---Neon:
Neon是ARM核心附带的浮点SIMD引擎,可以把它当一个DSP用。
如果不使用Neon,就只能有CPU自带的VFP进行浮点运算。标准A8的VFP没有管线化,速度是比较低的。A9的VFP管线化后,效能有明显提升,但还是不如Neon。
Neon支持与VFP类似,都需要编译器和Kernel双方支持才可以。
Kernel配置中:
Floating point emulation
[*] VFP-format floating point maths
[ ]
需要选中。
编译器支持分析如下:
http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/ARM-Options.html#ARM-Options
七: ARM浮点相关编译选项:
1。 -mfloat-abi=name:
Specifies which floating-point ABI to use.指定浮点应用程序二进制接口
可选值:soft,softfp,hard
soft: 编译器将浮点操作编译成调用输出库....(没吃透,也许是调用编译器中的软浮点实现??)
softfp: 编译器生成硬件浮点指令(汇编语句见附录1)。但继续使用软浮点调用规则。
hard:编译器生成硬件浮点指令(汇编语句见附录1)。使用FPU指定的调用规则。
2.
3.
-mfpu=
name
指定在此平台上,何种硬件浮点设备或者硬件浮点模拟器可用。
可用参数:fpa,fpe2,fpe3,maverick,vfp,vfpv3,vfpv3-fp16,vfpv3-d16,vfpv3-d16-fp16,vfpv3xd,vfpv3xd-fp16,neon,neon-fp16,vfpv4,vfpv4-d16,fpv4-sp-d16,neon-vfpv4
vfp: 之前已经详细谈过。
neon:前面也谈过。但neon并不完全支持 IEEE 754。
4.
-mfpe=
number
-mfp=
number
-mfpe=X -mfp=X 等同于-mfpu=fpeX 其中X为fpe后面的数字。为了与老版本GCC统一。
附录1 :VFP 指令
-
浮点绝对值、求反和平方根。
-
浮点加法、减法和除法。
-
VMUL、VMLA、VMLS、VNMUL、VNMLA 和 VNMLS
浮点乘法和乘加,包含可选求反。
-
浮点数比较。
-
在单精度数和双精度数之间转换。
-
在浮点数和整数之间转换。
-
在浮点数和定点数之间转换。
-
在半精度和单精度浮点数之间转换。
-
将浮点常数插入单精度或双精度寄存器。
附录2:
-mfloat-abi=name
Sam不明白为什么 hard不能使用。只好使用softfp
附录3:
RVCT
ARM公司提供的一套编译器。RVCT(RealView Compilation Tools)业内公认的能够支持所有ARM处理器,并提供最好的执行性能的编译器。
RVDS
附录4:
其它与浮点有关的编译选项:
-ffast-math:
-fno-signed-zeros:高版本GCC才有的优化选项。与浮点里面的 正负0 有关。
点选 Documentation
从list中选中GCC. : http://www.gnu.org/software/gcc/
从中选中Documentation->Manual
此处就是GNU GCC 所有document.
http://gcc.gnu.org/onlinedocs/
Sam需要看得是: GCC 4.6.0 Manual
http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/
LD:
LD则在list中选择:Binutils (as bfd binutils gprof ld)
http://sourceware.org/binutils/docs/ld/
Hi3716C:
Sam在Hi3716C 平台通常使用如下选项:
-mcpu=cortex-a9
-mfpu=vfp
-mfloat-abi=softfp
-march=armv7
-fsigned-char
-mcpu:
指出目标代码运行于何种ARM processor(ARM处理器)
可用的name
-march=armv7
-march 指出目标ARM architecture(ARM指令集)。
可以使用的为:armv2, armv2a, armv3, armv3m, armv4, armv4t, armv5, armv5t, armv5e, armv5te, armv6, armv6j,armv6t2, armv6z, armv6zk, armv6-m, armv7, armv7-a, armv7-r, armv7-m, iwmmxt, iwmmxt2, ep9312