替换 __aeabi_dsub 以保存 space(-flto 问题)

Replacing __aeabi_dsub to save space (-flto issues)

我正在尝试将大量代码塞入一个相当小的 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.

添加它们

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

我的问题是,当我添加该函数时,linker 抱怨 undefined reference to __aeabi_dsub - 这看起来很奇怪,因为定义它的行为导致了错误。

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

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

谢谢!

我的解决方案(正如@artless-noise 所建议的那样)是使用 -ffreestanding compiler flag。 GCC 对此有话要说:

Assert that compilation targets a freestanding environment... A freestanding environment is one in which the standard library may not exist, and program startup may not necessarily be at main. The most obvious example is an OS kernel.

所以对于嵌入式环境来说似乎很有意义...

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