2.4.5.Float 与 Double

在没有 FPU64 硬件支持的 C2000 器件上,当为 EABI 编译的应用程序对 double 类型执行操作时,会产生很大的开销。

在 EABI 中,double 类型映射为 64 位双精度浮点数。如需了解详情,请参阅应用程序二进制接口 (ABI)。为 EABI (--abi=eabi) 编译的应用程序可以通过以下方式引入双精度浮点运算:

  1. 显式使用 double 类型。除非应用程序需要额外的精度/范围,否则避免使用 double 类型。

  2. 通过浮点常量隐式使用。当常量可以被视为单精度浮点常量时,使用 f 后缀。

    不带 f 后缀的浮点常量被编译器视为双精度类型。这种行为是由 C 标准规定的。这可能会导致在应用程序中意外引入双精度运算。表 2.10 说明了这种低效率 - 该常量被视为双精度,导致 x 从 float 转换为双精度类型。乘法是双精度运算,结果被转换回单精度类型。

    表 2.9 单精度和双精度浮点常量
    常量(被视为 double) f 后缀的常量(被视为 float)
    floatfoo1(floatx){returnx*42.2;}
    floatfoo2(floatx){returnx*42.2f;}
    表 2.10 比较生成的汇编代码
    以双精度执行的运算 以单精度执行的运算
    ||foo1||: ADDB SP,#8 MOVZ AR4,SP SUBB XAR4,#8 MOVZ AR6,AR4 LCR #||__c28xabi_ftod|| ; call occurs [#||__c28xabi_ftod||] MOVZ AR4,SP MOVZ AR6,SP MOVL XAR5,#$C$FL1 SUBB XAR4,#8 SUBB XAR6,#4 MOVZ AR4,AR4 MOVZ AR6,AR6 LCR #||__c28xabi_mpyd|| ; call occurs [#||__c28xabi_mpyd||] MOVZ AR4,SP SUBB XAR4,#4 MOVZ AR4,AR4 LCR #||__c28xabi_dtof|| ; call occurs [#||__c28xabi_dtof||] SUBB SP,#8 LRETR ; return occurs
    ||foo2||: MOVIZ R1H,#16936 MOVXI R1H,#52429 MPYF32 R0H,R1H,R0H LRETR ; return occurs
  3. C 标准库中的数学例程,例如 sqrt。在 COFF 中,floatdouble 都是 32 位单精度,因此 sqrtsqrtf 之间没有差异。但是,使用 EABI 时,sqrtf 采用 float 参数,sqrt 采用 double

检测双精度运算

编译器选项--float_operations_allowed=32 可用于检测应用程序是否无意中使用了双精度运算。

此选项可限制应用程序中允许的浮点运算类型。默认为 all。如果设置为 none、32 或 64,则检查应用程序是否将在运行时执行运算。例如,如果在命令行上指定了 --float_operations_allowed=32,则在应用程序包含双精度运算时编译器会发出错误消息。有关详细信息,请参阅 TMS320C28x 优化 C/C++ 编译器用户指南