我一直在ARM M0 +核心上运行代码,我发现我的绝大部分时间花在了浮点计算上。所以我正在尝试使用自定义浮点计算功能,以便在极低功耗应用中使用。
我一直在使用ARM GCC在M0 +上进行裸机编译(没有硬FPU)。我看到浮点乘法与__aeabi_fmul相关联,然后链接以生成最终的ELF文件。
我的问题如下:
据我所知,第二部分需要我搞乱编译器。我一直在研究CLANG / LLVM这样做,因为普遍的共识似乎是它比GCC更容易修改!我只是想看看这是否有可能或者我在这里咆哮完全错误的树。
谢谢
答案 0 :(得分:2)
它是gcc的一部分,gcc库,下载gcc源代码并搜索这些函数,你会发现它们。它们是软浮动程序,并且是手动调整的,你不太可能做得更好,但是要把自己搞得一团糟。不知道为什么你会在这样的MCU上做任何浮点,但幸运的是语言和工具允许你,虽然它可以消耗大量的闪存和执行时间。 (没有做任何浮点变量,但用固定点做自己的浮点数学是一个可能的折衷方案或只做固定点)。
如果你使用gcc链接,那么gcc知道库的位置并将自动拉入它们,如果你使用ld链接(使用gcc作为编译器而不是工具链中所有东西的调用者)那么ld不知道在哪里可以找到库,您只需在命令行中添加自己的对象,这是最简单的方法。
您可以获取特定功能的as-is gnu源并将其添加到项目中然后修改它或者只是用您自己的功能完全替换它。
当然,您可以进入编译器源并重命名然后重新构建编译器,不确定您想在此处完成多少工作,替换浮点例程而不会出现错误已经是一项大任务,如注释中所述我会单独留下编译器并使用它(将名称保留为与ld相同的链接)。
的start.s
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
.thumb_func
hang: b .
so.c
float notmain ( float a, float b )
{
return(a+b);
}
MEMMAP
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > rom
}
构建
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -Xlinker -T -Xlinker memmap -nostdlib -nostartfiles -ffreestanding -mthumb start.o so.c -o so.elf -lgcc
arm-none-eabi-objdump -D so.elf
它没有抱怨,但是制作了一个完全破碎的二进制文件
20000048 <__addsf3>:
20000048: e1b02080 lsls r2, r0, #1
2000004c: 11b03081 lslsne r3, r1, #1
20000050: 11320003 teqne r2, r3
20000054: 11f0cc42 mvnsne r12, r2, asr #24
20000058: 11f0cc43 mvnsne r12, r3, asr #24
2000005c: 0a000047 beq 20000180 <__addsf3+0x138>
20000060: e1a02c22 lsr r2, r2, #24
20000064: e0723c23 rsbs r3, r2, r3, lsr #24
20000068: c0822003 addgt r2, r2, r3
2000006c: c0201001 eorgt r1, r0, r1
20000070: c0210000 eorgt r0, r1, r0
那些是手指不是拇指。检查链接器的传递内容。
0:[/opt/gnuarm/lib/gcc/arm-none-eabi/7.1.0/../../../../arm-none-eabi/bin/ld]
1:[-plugin]
2:[/opt/gnuarm/libexec/gcc/arm-none-eabi/7.1.0/liblto_plugin.so]
3:[-plugin-opt=/opt/gnuarm/libexec/gcc/arm-none-eabi/7.1.0/lto-wrapper]
4:[-plugin-opt=-fresolution=/tmp/ccSyISCJ.res]
5:[-X]
6:[-o]
7:[so.elf]
8:[-L/opt/gnuarm/lib/gcc/arm-none-eabi/7.1.0/thumb]
9:[-L/opt/gnuarm/lib/gcc/arm-none-eabi/7.1.0]
10:[-L/opt/gnuarm/lib/gcc/arm-none-eabi/7.1.0/../../../../arm-none-eabi/lib]
11:[-T]
12:[memmap]
13:[start.o]
14:[/tmp/ccrdRU2s.o]
15:[-lgcc]
另一种方法
arm-none-eabi-gcc -O2 -c -mthumb so.c -o so.o
arm-none-eabi-ld -T memmap start.o so.o /opt/gnuarm/lib/gcc/arm-none-eabi/7.1.0/thumb/libgcc.a -o so.elf
但这仍然是打破
20000038 <__addsf3>:
20000038: e1b02080 lsls r2, r0, #1
2000003c: 11b03081 lslsne r3, r1, #1
20000040: 11320003 teqne r2, r3
20000044: 11f0cc42 mvnsne r12, r2, asr #24
20000048: 11f0cc43 mvnsne r12, r3, asr #24
2000004c: 0a000047 beq 20000170 <__addsf3+0x138>
20000050: e1a02c22 lsr r2, r2, #24
20000054: e0723c23 rsbs r3, r2, r3, lsr #24
我还没有做我需要做的事情来获得正确的库,必须运行以后再重新编辑...
但我建议的解决方案是:
.thumb_func
.globl __aeabi_fadd
__aeabi_fadd:
bx lr
为了演示目的,我添加了start.s
arm-none-eabi-as start.s -o start.o
arm-none-eabi-ld -T memmap start.o so.o -o so.elf
arm-none-eabi-objdump -D so.elf
Disassembly of section .text:
20000000 <_start>:
20000000: 20001000 andcs r1, r0, r0
20000004: 20000015 andcs r0, r0, r5, lsl r0
20000008: 20000019 andcs r0, r0, r9, lsl r0
2000000c: 20000019 andcs r0, r0, r9, lsl r0
20000010: 20000019 andcs r0, r0, r9, lsl r0
20000014 <reset>:
20000014: f000 f802 bl 2000001c <notmain>
20000018 <hang>:
20000018: e7fe b.n 20000018 <hang>
2000001a <__aeabi_fadd>:
2000001a: 4770 bx lr
2000001c <notmain>:
2000001c: b510 push {r4, lr}
2000001e: f7ff fffc bl 2000001a <__aeabi_fadd>
20000022: bc10 pop {r4}
20000024: bc02 pop {r1}
20000026: 4708 bx r1
然后填写你想要的任何东西,显然这不是一个真正的程序,打破了许多规则,没有数字被传递,等等...
但是编译器生成了__aeabi_fadd,我提供了一个__aeabi_fadd,很高兴。
我过去所做的是,因为我构建了自己的gnu工具链,进入并在感兴趣的文件中输入语法错误,进行构建,然后用于构建该项目的长命令行是现在在屏幕上失败时,隔离感兴趣的功能,使用gcc的长命令行作为指导,根据需要进行调整和调整...比试图在代码中自己找出所有定义更快