Yan*_*aud 11 c floating-point arm ieee-754 ios
在将应用程序从Linux x86移植到iOS ARM(iPhone 4)时,我发现浮点算术和小值的行为存在差异.
在IEEE 754-1985/IEEE 754-2008标准中,小于[+/-] 2.2250738585072014E-308的64位浮点数(双)被称为非正规/非正规化/次正规数.
在iPhone 4上,这样的小数字被视为零(0),而在x86上,可以使用次正规数字进行计算.
我无法在Apple的文档Mac OS X手册页上找到有关符合IEEE-754标准的任何解释.对于float(3).
但由于对堆栈溢出(一些答案刷新到零的行为在浮点运算,双VS浮在iPhone上),我已经找到了一些线索.
根据一些搜索,似乎沿着ARM内核使用的VFP(或NEON)数学协处理器正在使用Flush-To-Zero(FTZ)模式(例如,在输出处将次正常值转换为0)和Denormals-Are-Zero( DAZ)模式(例如,当用作输入参数时,将正常值转换为0)以提供快速硬件处理的IEEE 754计算.
- 完全符合IEEE754标准的ARM支持代码
- 运行快速模式,符合IEEE754标准(仅限硬件)
关于FTZ和DAZ的一个很好的解释可以在IA-32中的 x87和SSE浮点辅助中找到:清零(FTZ)和非正规零(DAZ):
FTZ和DAZ模式都处理发生无效浮点数据或使用下溢或非正常条件处理的情况.[...].FTZ和DAZ处理的数字之间的差异非常微妙.FTZ处理下溢情况,而DAZ处理非正规数.当计算导致非正规时,发生下溢情况.在这种情况下,FTZ模式将输出设置为零.DAZ修复了非正规用作输入时的情况,可以是常量,也可以是将无效内存读入寄存器.DAZ模式在计算之前将计算的输入设置为零.然后可以说FTZ处理[输出]而DAZ处理[输入].
关于Apple开发者网站上FTZ的唯一内容似乎是在iOS ABI函数调用指南中:
VFP状态寄存器| FPSCR | 特别| 函数调用不保留条件代码位(28-31)和饱和位(0-4).异常控制(8-12),舍入模式(22-23)和清零到零(24)位应仅由影响应用程序状态的特定例程(包括框架API函数)修改.在函数进入和退出时,短向量长度(16-18)和步长(20-21)位必须为零.不得修改所有其他位.
根据ARM1176JZF-S技术参考手册,18.5操作模式(第一个iPhone处理器),VFP可以配置为完全支持IEEE 754(子正常算术),但在这种情况下它需要一些软件支持(陷入内核到用软件计算).
注意:我还阅读了Debian的ARM Hard Float Port和VFP比较页面.
我的问题是:
哪里可以找到关于跨iOS设备的次正规数处理的明确答案?
是否可以设置iOS系统以支持次正规数而无需编译器仅生成完整的软件浮点代码?
谢谢.
是否可以设置iOS系统以支持次正规数而无需编译器仅生成完整的软件浮点代码?
是.这可以通过将FPSCR中的FZ位设置为零来实现:
static inline void DisableFZ( )
{
    __asm__ volatile("vmrs r0, fpscr\n"
                     "bic r0, $(1 << 24)\n"
                     "vmsr fpscr, r0" : : : "r0");
}
请注意,当遇到可观数量的非正常值时,这会导致应用程序性能显着下降.在调用任何不能使ABI保证在非默认模式下正常工作的代码之前,您可以(并且应该)恢复默认浮点状态:
static inline void RestoreFZ( ) {
    __asm__ volatile("vmrs r0, fpscr\n"
                     "orr r0, $(1 << 24)\n"
                     "vmsr fpscr, r0" : : : "r0");
}
请提交错误报告,请求为iOS中的FP操作模式提供更好的文档.