ARMv7 gcc 选项强制本地划分



我正在使用GCC为支持本机划分的ARMv7内核构建裸机应用程序。 我已经删除了所有库依赖项。

GCC C 编译器有时会引用 __aeabi_uidiv((。 其他时候,它会选择使用硬件除法(对于无符号整数除法(。 我无法找到一个编译器标志来强制它使用硬件划分(而不是 __aeabi_* lib 调用(。 有人知道这样的标志吗?

编辑:我应该澄清一下,我适当地使用编译器标志-mtune=cortex-a7和-march=armv7-a作为i.MX6ULL。

示例错误:

uint32_t GenerateError(uint32_t num, uint32_t den) {
return num / den; //generates undefined reference to __aeabi_uidiv
}

gcc 就是这样一个编译器。

uint8_t fun_u8 ( uint8_t a, uint8_t b )
{
return(a/b);
}
uint16_t fun_u16 ( uint16_t a, uint16_t b )
{
return(a/b);
}
uint32_t fun_u32 ( uint32_t a, uint32_t b )
{
return(a/b);
}
uint64_t fun_u64 ( uint64_t a, uint64_t b )
{
return(a/b);
}
int8_t fun_s8 ( int8_t a, int8_t b )
{
return(a/b);
}
int16_t fun_s16 ( int16_t a, int16_t b )
{
return(a/b);
}
int32_t fun_s32 ( int32_t a, int32_t b )
{
return(a/b);
}
int64_t fun_s64 ( int64_t a, int64_t b )
{
return(a/b);
}

arm-none-eabi-gcc -O2 -mcpu=cortex-a7 -c so.c -o so.o

结果

00000000 <fun_u8>:
0:   e730f110    udiv    r0, r0, r1
4:   e12fff1e    bx  lr
00000008 <fun_u16>:
8:   e730f110    udiv    r0, r0, r1
c:   e12fff1e    bx  lr
00000010 <fun_u32>:
10:   e730f110    udiv    r0, r0, r1
14:   e12fff1e    bx  lr
00000018 <fun_u64>:
18:   e92d4010    push    {r4, lr}
1c:   ebfffffe    bl  0 <__aeabi_uldivmod>
20:   e8bd8010    pop {r4, pc}
00000024 <fun_s8>:
24:   e730f110    udiv    r0, r0, r1
28:   e12fff1e    bx  lr
0000002c <fun_s16>:
2c:   e710f110    sdiv    r0, r0, r1
30:   e6bf0070    sxth    r0, r0
34:   e12fff1e    bx  lr
00000038 <fun_s32>:
38:   e710f110    sdiv    r0, r0, r1
3c:   e12fff1e    bx  lr
00000040 <fun_s64>:
40:   e92d4010    push    {r4, lr}
44:   ebfffffe    bl  0 <__aeabi_ldivmod>
48:   e8bd8010    pop {r4, pc}

从正确的手臂文档中,有高达 32 位/32 位的硬件支持。 在此之上,您必须调用一个库(乘法也是如此(只是为了确认期望可以添加:

uint8_t fun_m8 ( uint32_t a, uint8_t b )
{
return(a/b);
}
uint16_t fun_m16 ( uint32_t a, uint16_t b )
{
return(a/b);
}
uint32_t fun_m32 ( uint32_t a, uint32_t b )
{
return(a/b);
}
0000004c <fun_m8>:
4c:   e730f110    udiv    r0, r0, r1
50:   e6ef0070    uxtb    r0, r0
54:   e12fff1e    bx  lr
00000058 <fun_m16>:
58:   e730f110    udiv    r0, r0, r1
5c:   e6ff0070    uxth    r0, r0
60:   e12fff1e    bx  lr
00000064 <fun_m32>:
64:   e730f110    udiv    r0, r0, r1
68:   e12fff1e    bx  lr

不足为奇。

现在这是 ARM 模式,编译器经常做拇指模式......

00000000 <fun_u8>:
0:   fbb0 f0f1   udiv    r0, r0, r1
4:   4770        bx  lr
6:   bf00        nop
00000008 <fun_u16>:
8:   fbb0 f0f1   udiv    r0, r0, r1
c:   4770        bx  lr
e:   bf00        nop
...

没有变化 这个平台上的thumb2也支持划分,所以它比它支持正在编译的代码的要求更大,这些要求决定了它是否可以使用硬件指令,对于这个测试,gcc选择了所需的硬件指令而不是gcclib调用(对于它可以的(。

如果希望编译器使用硬件指令,请指示编译器使用所需的指令集。 并将您的代码保持在该指令集的功能范围内。 并且使用同样为感兴趣的指令集编译的库,并且代码保持在该指令集的限制范围内。 (然后查看编译器是否使用整个指令集或至少使用感兴趣的指令,如果没有,则创建自己的库函数用于汇编中的除法并调用它(。

您要查找的是-march=armv7ve。这将针对带有硬件划分指令的Armv7。-mcpu=cortex-a15cortex-a7以此体系结构为目标,因此他们将生成除法指令。

最新更新