aeabi_fmul 的链接来自哪里?

where is aeabi_fmul being linked from?

我已经 运行 在 ARM M0+ 内核上编写代码,我发现我的大部分时间都花在了浮点计算上。因此,我正在试验一种用于极低功耗应用的自定义浮点计算函数。

我一直在使用 ARM GCC 在 M0+(没有硬 FPU)上进行裸机编译。我看到浮点乘法得到 linked 到 __aeabi_fmul,然后 linked 生成最终的 ELF 文件。

我的问题如下:

  1. __aeabi_fmul在哪里定义的?是在GCC自带的预编译库里吗?
  2. 是否可以通过某种方式更改此定义?也许有预编译版本 my_fp_mul 而不是 link 而不是 __aeabi_fmul?

我知道第二部分需要我搞乱编译器。我一直在研究 CLANG/LLVM 来做这件事,因为普遍的共识似乎是它比 GCC 更容易修改!我只是想看看这是否有可能,或者我在这里咆哮完全错误的树。

谢谢

它是 gcc 的一部分,gcc 库,下载 gcc 源代码并搜索那些函数,您会找到它们。它们是软浮动例程并且是手动调整的,你不太可能做得更好,但会把你自己打倒。不知道为什么你会在这样的 MCU 上做任何浮点数,但幸运的是语言和工具允许你,尽管它会消耗大量的闪存和执行时间。 (不做任何浮点变量但自己用定点做浮点数学是一种可能的妥协或只做定点)。

如果你使用 gcc 到 link 那么 gcc 知道库在哪里并且会自动拉入它们,如果你使用 ld 到 link(使用 gcc 只是作为编译器而不是调用者工具链中的所有内容)然后 ld 不知道在哪里可以找到库,你可以简单地在命令行上添加你自己的对象,这是最简单的方法。

您可以获取特定功能的原样 gnu 源并将其添加到您的项目中,然后修改它或完全用您自己的功能替换它。

当然你可以进入编译器源代码并重命名然后重新构建编译器,不确定你想在这里做多少工作,如前所述,无误地替换浮点例程已经是一项艰巨的任务在评论中,我会单独使用编译器并使用它(将名称与 ld 保持相同 link)。

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);
}

内存映射

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

那些是手臂指令而不是拇指。检查 linker 通过了什么。

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 工具链,所以进入并在感兴趣的文件中放入语法错误,进行构建,然后使用长命令行来构建它item 现在在它失败时出现在屏幕上,隔离感兴趣的功能,使用 gcc 的长命令行作为指导,根据需要进行调整和调整......比尝试自己找出所有定义更快地到达那里代码。