在Raspberry Pi的armv6中使用log10数学函数得到错误的结果
我有这个非常简单的代码:
#include <stdio.h>
#include <math.h>
int main()
{
long v = 35;
double app = (double)v;
app /= 100;
app = log10(app);
printf("Calculated log10 %lfn", app);
return 0;
}
这段代码在x86上完美工作 , 但在arm上无效,结果为0.00000。 一些想法?
其他信息:
操作系统:linux 3.2.27
我用ct-ng构建arm工具链:arm-unknown-linux-gnueabi-
libc版本2.13
gcc -v
输出:
使用内置规格。 COLLECT_GCC = arm-unknown-linux-gnueabi-gcc COLLECT_LTO_WRAPPER = / opt / x-tools / arm-unknown-linux-gnueabi / libexec / gcc / arm-unknown-linux-gnueabi / 4.5.1 / lto-wrapper目标:arm -unknown-linux-gnueabi配置为:/home/mirko/misc/rasppi-ct-ng-files/.build/src/gcc-4.5.1/configure --build = x86_64-build_unknown-linux-gnu --host = x86_64-build_unknown-linux-gnu -target = arm-unknown-linux-gnueabi -prefix = / opt / x-tools / arm-unknown-linux-gnueabi -with-sysroot = / opt / x-tools / arm-unknown-linux-gnueabi / arm-unknown-linux-gnueabi // sys-root -enable-languages = c --disable-multilib --with-pkgversion = crosstool-NG-1.9.3 --enable -__ cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --with-host-libstdcxx =' - static-libgcc -Wl,-Bstatic,-lstdc ++, - Bdynamic -lm'--with-gmp = / home /mirko/misc/rasppi-ct-ng-files/.build/arm-unknown-linux-gnueabi/build/static --with-mpfr = / home / mirko / misc / rasppi-ct-ng-files / .build / arm-unknown-linux-gnueabi / build / static --with-mpc = / home / mirko / misc / rasppi-ct-ng-files / .build / arm- unknown-linux-gnueabi / build / static --with-ppl = / home / mirko / misc / rasppi -ct-ng-files / .build / arm-unknown-linux-gnueabi / build / static --with-cloog = /home/mirko/misc/rasppi-ct-ng-files/.build/arm-unknown-linux-gnueabi/build/static --with-libelf = / home / mirko / misc / rasppi-ct-ng-files / .build / arm-unknown-linux-gnueabi / build / static --enable-threads = posix --enable-target-optspace --with-local-prefix = / opt / x-tools / arm-unknown-linux-gnueabi / arm-unknown-linux-gnueabi // sys-root -disable-nls -enable-symvers = gnu -enable-c99 -enable-long-long线程模型:posix gcc版本4.5.1(crosstool-NG -1.9.3)
ARM Linux发行版上的浮点支持不是微不足道的。 因此,您应该使用与操作系统和硬件系统匹配的工具链,并使用正确的编译开关。
首先,您需要了解ARM的调用约定,即“调用函数时如何传递参数?” 。 ARM是RISC体系结构,只能在寄存器上工作。 没有指令直接操纵内存。 如果您需要更改内存中的值,您首先需要将其加载到寄存器中,然后修改它,然后您需要将其存储回内存中。
当你调用一个函数时,你可能需要将参数传递给它,你可以将参数放在栈(内存)上,但是由于ARM只能使用寄存器,所以你的函数可能会做的第一件事就是将它们加载回寄存器。 为了避免这种浪费,ARM调用约定使用寄存器来传递参数。 但是,由于ARM的寄存器数量有限,调用约定也会规定前四个参数只使用前四个(r0-r3)寄存器,其余的必须使用栈来传递。
第二件事是早期的ARM内核没有任何浮点支持,在软件中实现的操作。 (这仍然是通过gcc的-mfloat-abi=soft
。)
我们可以通过以下代码轻松演示这意味着什么。
float pi2(float a) {
return a * 3.14f;
}
通过-c -O3 -mfloat-abi=soft
和obdump
编译这个给我们
00000000 <pi2>:
0: f24f 51c3 movw r1, #62915 ; 0xf5c3
4: b508 push {r3, lr}
6: f2c4 0148 movt r1, #16456 ; 0x4048
a: f7ff fffe bl 0 <__aeabi_fmul>
e: bd08 pop {r3, pc}
正如你所看到的(实际上它不可见:)) pi2
在r0
获取它的参数,在r1
填充pi constant
并使用__aeabi_fmul
将这些参数相乘,并返回r0
结果。 由于__aeabi_fmul
也使用相同的调用约定,因此关于r0
详细信息不可见。 我们所有的函数都会填充r1
并将其委托给__aeabi_fmul
。
当将浮动硬件支持添加到ARM(也是因为架构风格)时,它带有自己的一组寄存器(s0,s1,...)。
如果我们使用-c -O3 -mfloat-abi=softfp
编译相同的片段并转储,我们就可以得到
00000000 <pi2>:
0: eddf 7a04 vldr s15, [pc, #16] ; 14 <pi2+0x14>
4: ee07 0a10 vmov s14, r0
8: ee27 7a27 vmul.f32 s14, s14, s15
c: ee17 0a10 vmov r0, s14
10: 4770 bx lr
12: bf00 nop
14: 4048f5c3 .word 0x4048f5c3
正如您现在所看到的,编译器不会创建对__aeabi_fmul
的调用,而是在它将位于r0
参数移动到s14
并在s15
上填充3.14
后创建一个vmul.f32
指令。 乘法指令后,它在移动可结果s14
返回到r0
,因为该功能的任何调用者所期望的,因为调用约定的它 。
现在,如果您认为pi2
是由某个第三方提供给您的库,您可以理解soft和softfp实现对您都是一样的,您可以互换使用它们。 如果系统为您提供它们,您不会关心您的应用是否在具有硬件浮点支持的系统上运行。 这对保持旧软件在新硬件上运行非常有用。
然而,在保持可兼容性的同时,这种方法引入了在ARM寄存器和FP寄存器之间移动值的开销。 这显然会影响性能,并通过一个新的调用约定来解决,这个约定被gcc
hard
调用。 这个新的约定规定,如果你的函数中有浮点参数,你可以利用浮点寄存器与正常寄存器交错,以及你可以返回浮点寄存器s0
中的浮点值。
再一次,如果我们用-c -O3 -mfloat-abi=hard
编译我们的代码片段并且转储,我们就可以得到
00000000 <pi2>:
0: eddf 7a02 vldr s15, [pc, #8] ; c <pi2+0xc>
4: ee20 0a27 vmul.f32 s0, s0, s15
8: 4770 bx lr
a: bf00 nop
c: 4048f5c3 .word 0x4048f5c3
你可以看到没有寄存器移动。 pi2
参数在s0
传递,编译器创建的代码在s15
填充3.14
,并使用vmul.f32 s0, s0, s15
在s0
获得我们想要的结果。
这个新约定的一个大问题是,当你改进编译器生成的代码时,你会完全丧失compability。 您不能指望使用hard
约定构建的应用程序与为soft/softfp
构建的库一起工作,而为softfp构建的应用程序将无法与用于硬构建的库一起使用。
有关调用约定的更多信息,您应该查看ARM的网站。
链接地址: http://www.djcxy.com/p/86893.html上一篇: Wrong result with log10 math function in armv6 on Raspberry Pi