使用硬浮点时未定义对“__floatundisf”的引用(PowerPC)
undefined reference to `__floatundisf' when using hard float (PowerPC)
我正在为带有硬浮动的 PowerPC 构建代码,突然遇到这个问题。
我知道这个符号属于 gcc 的 soft-float 库。我不明白的是为什么它要尝试使用它,尽管我努力告诉它使用硬浮动。
制作旗帜:
CFLAGS += -mcpu=750 -mhard-float -ffast-math -fno-math-errno -fsingle-precision-constant -shared -fpic -fno-exceptions -fno-asynchronous-unwind-tables -mrelocatable -fno-builtin -G0 -O3 -I$(GCBASE) -Iinclude -Iinclude/gc -I$(BUILDDIR)
ASFLAGS += -I include -mbroadway -mregnames -mrelocatable --fatal-warnings
LDFLAGS += -nostdlib -mhard-float $(LINKSCRIPTS) -Wl,--nmagic -Wl,--just-symbols=$(GLOBALSYMS)
有问题的代码:
static void checkTime() {
u64 ticks = __OSGetSystemTime();
//note timestamp here is seconds since 2000-01-01
float secs = ticks / 81000000.0f; //everything says this should be 162m / 4,
//but I only seem to get anything sensible with 162m / 2.
int days = secs / 86400.0f; //non-leap days
int years = secs / 31556908.8f; //approximate average
int yDay = days % 365;
debugPrintf("Y %d D %d", years, yDay);
}
我还需要什么来阻止 gcc 尝试使用软浮动?为什么突然决定这样做?
查看 GCC docs,__floatundisf
将 unsigned long 转换为 float。如果我们用 -O1 和 运行 objdump
编译您的代码*,我们可以看到 __floatundisf
确实来自将您的 u64 除以浮点数:
u64 ticks = __OSGetSystemTime();
20: 48 00 00 01 bl 20 <checkTime+0x20> # Call __OSGetSystemTime
20: R_PPC_PLTREL24 __OSGetSystemTime
//note timestamp here is seconds since 2000-01-01
float secs = ticks / 81000000.0f; //everything says this should be 162m / 4,
24: 48 00 00 01 bl 24 <checkTime+0x24> # Call __floatundisf
24: R_PPC_PLTREL24 __floatundisf
28: 81 3e 00 00 lwz r9,0(r30)
2a: R_PPC_GOT16 .LC0
2c: c0 09 00 00 lfs f0,0(r9) # load the constant 1/81000000
30: ec 21 00 32 fmuls f1,f1,f0 # do the multiplication ticks * 1/81000000
所以你得到它用于 u64 / float 计算。
如果您将 u64 转换为 u32,我也看到它消失了。
为什么会产生?查看 750CL 的手册,我希望它在很大程度上等同于您的芯片,没有任何指令可以从内存中读取 8 字节整数并将其转换为浮点数。 (看起来也没有直接将 32 位整数转换为浮点数的方法:gcc 相反内联了一系列令人困惑的整数和浮点数操作指令。)
我不知道 __OSGetSystemTime 的单位是什么,但是如果你可以通过丢弃一些较低的位或者对公约数做一些技巧来将它减少到 32 位整数,你可以摆脱这个电话。
*: 稍微修改以在我的系统上编译。
我正在为带有硬浮动的 PowerPC 构建代码,突然遇到这个问题。
我知道这个符号属于 gcc 的 soft-float 库。我不明白的是为什么它要尝试使用它,尽管我努力告诉它使用硬浮动。
制作旗帜:
CFLAGS += -mcpu=750 -mhard-float -ffast-math -fno-math-errno -fsingle-precision-constant -shared -fpic -fno-exceptions -fno-asynchronous-unwind-tables -mrelocatable -fno-builtin -G0 -O3 -I$(GCBASE) -Iinclude -Iinclude/gc -I$(BUILDDIR)
ASFLAGS += -I include -mbroadway -mregnames -mrelocatable --fatal-warnings
LDFLAGS += -nostdlib -mhard-float $(LINKSCRIPTS) -Wl,--nmagic -Wl,--just-symbols=$(GLOBALSYMS)
有问题的代码:
static void checkTime() {
u64 ticks = __OSGetSystemTime();
//note timestamp here is seconds since 2000-01-01
float secs = ticks / 81000000.0f; //everything says this should be 162m / 4,
//but I only seem to get anything sensible with 162m / 2.
int days = secs / 86400.0f; //non-leap days
int years = secs / 31556908.8f; //approximate average
int yDay = days % 365;
debugPrintf("Y %d D %d", years, yDay);
}
我还需要什么来阻止 gcc 尝试使用软浮动?为什么突然决定这样做?
查看 GCC docs,__floatundisf
将 unsigned long 转换为 float。如果我们用 -O1 和 运行 objdump
编译您的代码*,我们可以看到 __floatundisf
确实来自将您的 u64 除以浮点数:
u64 ticks = __OSGetSystemTime();
20: 48 00 00 01 bl 20 <checkTime+0x20> # Call __OSGetSystemTime
20: R_PPC_PLTREL24 __OSGetSystemTime
//note timestamp here is seconds since 2000-01-01
float secs = ticks / 81000000.0f; //everything says this should be 162m / 4,
24: 48 00 00 01 bl 24 <checkTime+0x24> # Call __floatundisf
24: R_PPC_PLTREL24 __floatundisf
28: 81 3e 00 00 lwz r9,0(r30)
2a: R_PPC_GOT16 .LC0
2c: c0 09 00 00 lfs f0,0(r9) # load the constant 1/81000000
30: ec 21 00 32 fmuls f1,f1,f0 # do the multiplication ticks * 1/81000000
所以你得到它用于 u64 / float 计算。
如果您将 u64 转换为 u32,我也看到它消失了。
为什么会产生?查看 750CL 的手册,我希望它在很大程度上等同于您的芯片,没有任何指令可以从内存中读取 8 字节整数并将其转换为浮点数。 (看起来也没有直接将 32 位整数转换为浮点数的方法:gcc 相反内联了一系列令人困惑的整数和浮点数操作指令。)
我不知道 __OSGetSystemTime 的单位是什么,但是如果你可以通过丢弃一些较低的位或者对公约数做一些技巧来将它减少到 32 位整数,你可以摆脱这个电话。
*: 稍微修改以在我的系统上编译。