替换__aeabi_dsub以节省空间(-flto问题)

时间:2018-09-20 15:49:29

标签: c gcc arm embedded lto

我正在尝试将大量代码填充到一个相当小的ARM微控制器中。我已经在尺寸优化上做了大量工作,但现在我需要双重运算,但是__aeabi_ddiv__aeabi_dadd__aeabi_dsub是其中的一些。整个设备上最大的功能。

尽管__aeabi_dadd__aeabi_dsub的工作原理基本相同(双精度字的最高位是符号位),但它们各自均为〜1700字节。两个函数都没有引用另一个。

实际上,我要做的就是将__aeabi_dsub替换为:

double __aeabi_dsub(double a, double b) {
  // flip top bit of 64 bit number (the sign bit)
  ((uint32_t*)&b)[1] ^= 0x80000000; // assume little endian
  return a + b;
}

我将节省〜1700个字节-因此翻转第二个参数的符号,然后使用__aeabi_dadd添加它们。

我知道这可能与IEEE规范不是100%兼容,但是在这个平台上我可以接受,以便节省超过1%的可用闪存。

我的问题是,当我添加该函数时,链接器会抱怨undefined reference to __aeabi_dsub,这是奇怪的,因为定义它的行为会导致错误。

这似乎与链接时间优化(-flto)有关-将其关闭意味着一切正常,但是它增加了8k的固件大小,不再适合可用的闪存!

那么当链接时间优化处于活动状态时,我需要怎么做才能替换内置函数__aeabi_dsub

谢谢!

1 个答案:

答案 0 :(得分:0)

我的解决方案(如@artless-noise 所建议的)是使用 -ffreestanding compiler flag。海湾合作委员会对此有话要说:

<块引用>

断言编译针对独立环境...独立环境是标准库可能不存在的环境,并且程序启动不一定在主环境中。最明显的例子是操作系统内核。

所以它似乎对嵌入式环境很有意义......

这为固件大小增加了大约 250 个字节(大约 0.1%),因为我猜它阻止了编译器利用有关内置运算符的一些假设,但是它确实允许我添加自己的 __aeabi_dsub 实现,总共节省了 1680 字节。