ARM Cortex M 的 gcc 不支持 FPU?

No FPU support with gcc for ARM Cortex M?

我使用 gcc-arm-none-eabi-10-2020-q4-major 编译的一个众所周知的基准测试有以下功能:

#include <unistd.h>

double b[1000], c[1000];

void tuned_STREAM_Scale(double scalar)
{
    ssize_t j;
    for (j = 0; j < 1000; j++)
        b[j] = scalar* c[j];
}

我正在使用以下编译器选项:

arm-none-eabi-gcc -O3 -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -c test.c

但是,如果我检查编译后的代码,编译器似乎无法使用基本的 FPU 乘法指令,而只是使用 libgcc 中的 __aeabi_dmul 函数(但是我们可以看到 FPU使用 vmov):

00000000 <tuned_STREAM_Scale>:
   0:   e92d 41f0       stmdb   sp!, {r4, r5, r6, r7, r8, lr}
   4:   4c08            ldr     r4, [pc, #32]   ; (28 <tuned_STREAM_Scale+0x28>)
   6:   4d09            ldr     r5, [pc, #36]   ; (2c <tuned_STREAM_Scale+0x2c>)
   8:   f504 58fa       add.w   r8, r4, #8000   ; 0x1f40
   c:   ec57 6b10       vmov    r6, r7, d0
  10:   e8f4 0102       ldrd    r0, r1, [r4], #8
  14:   4632            mov     r2, r6
  16:   463b            mov     r3, r7
  18:   f7ff fffe       bl      0 <__aeabi_dmul>
  1c:   4544            cmp     r4, r8
  1e:   e8e5 0102       strd    r0, r1, [r5], #8
  22:   d1f5            bne.n   10 <tuned_STREAM_Scale+0x10>
  24:   e8bd 81f0       ldmia.w sp!, {r4, r5, r6, r7, r8, pc}

如果我和其他编译器比较的话,代码效率是无与伦比的:

00000000 <tuned_STREAM_Scale>:
   0:   4808            ldr     r0, [pc, #32]   ; (24 <tuned_STREAM_Scale+0x24>)
   2:   b580            push    {r7, lr}
   4:   4b06            ldr     r3, [pc, #24]   ; (20 <tuned_STREAM_Scale+0x20>)
   6:   27c8            movs    r7, #200        ; 0xc8
   8:   c806            ldmia   r0!, {r1, r2}
   a:   ec42 1b11       vmov    d1, r1, r2
   e:   ee20 1b01       vmul.f64        d1, d0, d1
  12:   1e7f            subs    r7, r7, #1
  14:   ec52 1b11       vmov    r1, r2, d1
  18:   c306            stmia   r3!, {r1, r2}
  1a:   d1f5            bne.n   8 <tuned_STREAM_Scale+0x8>
  1c:   bd80            pop     {r7, pc}

如果我根据 CPU 或 FPU 选项在 gcc 包中检查各种 libgcc 目标文件,我在 __aeabi_dmul 或任何其他函数中找不到任何 FPU 指令。

我觉得很奇怪 gcc 不能使用基本的 FPU 乘法,而且我在任何文档或 README 中都找不到这个限制,所以我想知道我是否做错了什么。我已经检查了旧的 gcc 版本,但我仍然有这个问题。是因为 gcc 还是来自 ARM 的编译二进制文件?

线索在您已经发布的编译器选项中:

-mfpu=fpv5-sp-d16 "sp" 表示单精度。

您告诉它不要生成硬件双指令,这对于大多数 Cortex-M7 处理器来说是正确的,因为它们无法执行。如果您有 M7 可以,那么您需要设置正确的 fpu 参数。