通常,最明显的解决方案也是最好的。如果我必须对一个 24 位数字进行符号扩展并将其转换为浮点类型,我将首先编写如下内容:
// See Dric512's answer; I happen to know my compiler's ABI implements
// 'float' with the appropriate IEEE 754 single-precision format
typedef float float32_t;
float32_t conv_func(unsigned int int24) {
return (int)(int24 << 8) >> 8;
}
既然你提到了 CMSIS 和关键时序,我会安全地假设你的微机有一个带有硬件 FPU 的 Cortex-M4(或可能是 Cortex-M7)——“性能”和“软件浮点 FFT”这两个词一起出现非常可笑 - 因为现在是 21 世纪,你正在使用一个半体面的优化编译器,所以我编译了上面的内容:
$arm-none-eabi-gcc -c -Os -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb float.c
并从中得到它(为清楚起见添加了评论):
0: f340 0017 sbfx r0, r0, #0, #24 @ sign-extend 24-bit value from argument
4: ee07 0a90 vmov s15, r0 @ move 32-bit result to FPU register
8: eeb8 0ae7 vcvt.f32.s32 s0, s15 @ convert signed int to 32-bit float
c: 4770 bx lr @ return (with final result in FPU)
好吧,这看起来已经是最佳代码了 - 任何手动位旋转都无法击败仅仅 2 个单周期指令。任务完成!
如果你碰巧在没有 FPU 的情况下被卡住,那么答案的基本点保持不变 - 让编译器/库来做脏活,因为 soft-fp 库的转换实现将是:
- 可靠正确。
- 优化得很好。
- 与计算本身的开销相比,完全沉浸在噪音中。