如何在软件中模拟浮点运算?
How are floating point operations emulated in software?
当 CPU 没有(或有问题的)浮点单元时,软件如何执行浮点运算?例如 PIC、AVR 和 8051 微控制器架构。
浮点数不是 "emulated"。通常,它们的存储方式如 IEEE754.
中所述
不动点是一种不同的实现类型。数字2,54可以定点或浮点实现。
软件实现VS FPU(浮点单元)
一些现代 MCU,如 ARM cortex M4F 有一个浮点单元,可以在硬件中进行浮点运算(如乘法、除法、加法)比软件快得多做。
在像AVR、PIC和8051这样的8位单片机中,运算仅在软件中完成(一次除法可能需要数百次运算)。它必须分别处理尾数(分数)部分和指数部分以及所有特殊情况(例如 NaN)。编译器通常有许多例程来威胁同一个操作(例如除法),并且会根据优化(size/speed)和其他参数(例如,如果它知道数字总是正数...)进行选择
浮点数只是以 2 为基数的科学记数法。尾数和指数都是整数,softfloat 库会将浮点部分操作分解为影响尾数和指数的操作,可以使用 CPU 整数支持。
例如,(x 2n) * (y 2m) = x * y 2n +m.
通常还需要规范化步骤来保持浮点表示规范,但在规范化之前可能会执行多个操作。此外,由于 IEEE-754 存储带有偏差的指数,因此必须考虑这一点。
有一个 that covers what C/C++ standards require from floating points numbers. So, strictly speaking, float can be represented any any form which compiler prefers. But practically if you floating point implementation differs significantly from IEEE754 然后你可以预料到习惯 IEEE754 的程序会导致很多错误。并且编译器必须对程序员友好,并且不应该在利用未指定的标准位置时造成麻烦。因此,在大多数情况下,浮点数将 以相同的方式表示 ,因为它们在所有其他体系结构(包括 x86)上的表示方式相同。定点运算太不一样了
如果 AVR 和 PIC 的编译器知道没有可用的 fpu,那么它会将每个操作转换为 CPU 支持的一堆命令。它必须将两个操作数归一化为一个共同的指数,然后像对整数一样对尾数执行操作,然后调整指数。这是相当多的操作,因此模拟浮点数很慢。而且,除此之外,如果您针对大小进行优化,则每个浮点运算都可能成为函数调用。
在 ARM arch 上,事情可能很奇怪。有带 FPU 和不带 FPU 的 ARM。你可能想要一个通用的应用程序,它会在两者上 运行。在这种情况下,有一个棘手(且缓慢)的方案。应用程序使用 FPU 命令。如果您的 CPU 没有 FPU,那么这样的命令将触发一个中断,其中 OS 将模拟指令,清除错误位和 return 对应用程序的控制。但是该方案发生得非常慢并且不常用。
"Emulated"在PIC、AVR和8051的上下文中是错误的术语。浮点emulation是指在具有 FPU 选项但并非所有部分都包含 FPU 的体系结构上模拟 FPU 硬件。这允许包含浮点指令的二进制文件在没有 FPU 的变体上 运行。在使用时,FPU 仿真被实现为 无效指令异常处理程序 ;当遇到FPU指令但不存在FPU时,发生异常,处理程序读取指令值并在软件中实现操作。
但是,您列出的架构中 none 定义了一个 FPU 或 FPU 指令,因此没有什么可以模拟的。相反,在这些情况下,浮点运算完全在软件中实现,编译器生成代码以在必要时调用浮点例程。例如,表达式 x = y * z ;
将生成等同于函数调用 x = _fmul( y, z ) ;
的代码。事实上,如果您查看包含浮点运算的构建的链接器映射输出,您可能会看到常规符号名称,例如 _fmul
、_fdiv
等 - 这些函数是 固有的 给编译器。
当 CPU 没有(或有问题的)浮点单元时,软件如何执行浮点运算?例如 PIC、AVR 和 8051 微控制器架构。
浮点数不是 "emulated"。通常,它们的存储方式如 IEEE754.
中所述不动点是一种不同的实现类型。数字2,54可以定点或浮点实现。
软件实现VS FPU(浮点单元)
一些现代 MCU,如 ARM cortex M4F 有一个浮点单元,可以在硬件中进行浮点运算(如乘法、除法、加法)比软件快得多做。
在像AVR、PIC和8051这样的8位单片机中,运算仅在软件中完成(一次除法可能需要数百次运算)。它必须分别处理尾数(分数)部分和指数部分以及所有特殊情况(例如 NaN)。编译器通常有许多例程来威胁同一个操作(例如除法),并且会根据优化(size/speed)和其他参数(例如,如果它知道数字总是正数...)进行选择
浮点数只是以 2 为基数的科学记数法。尾数和指数都是整数,softfloat 库会将浮点部分操作分解为影响尾数和指数的操作,可以使用 CPU 整数支持。
例如,(x 2n) * (y 2m) = x * y 2n +m.
通常还需要规范化步骤来保持浮点表示规范,但在规范化之前可能会执行多个操作。此外,由于 IEEE-754 存储带有偏差的指数,因此必须考虑这一点。
有一个
如果 AVR 和 PIC 的编译器知道没有可用的 fpu,那么它会将每个操作转换为 CPU 支持的一堆命令。它必须将两个操作数归一化为一个共同的指数,然后像对整数一样对尾数执行操作,然后调整指数。这是相当多的操作,因此模拟浮点数很慢。而且,除此之外,如果您针对大小进行优化,则每个浮点运算都可能成为函数调用。
在 ARM arch 上,事情可能很奇怪。有带 FPU 和不带 FPU 的 ARM。你可能想要一个通用的应用程序,它会在两者上 运行。在这种情况下,有一个棘手(且缓慢)的方案。应用程序使用 FPU 命令。如果您的 CPU 没有 FPU,那么这样的命令将触发一个中断,其中 OS 将模拟指令,清除错误位和 return 对应用程序的控制。但是该方案发生得非常慢并且不常用。
"Emulated"在PIC、AVR和8051的上下文中是错误的术语。浮点emulation是指在具有 FPU 选项但并非所有部分都包含 FPU 的体系结构上模拟 FPU 硬件。这允许包含浮点指令的二进制文件在没有 FPU 的变体上 运行。在使用时,FPU 仿真被实现为 无效指令异常处理程序 ;当遇到FPU指令但不存在FPU时,发生异常,处理程序读取指令值并在软件中实现操作。
但是,您列出的架构中 none 定义了一个 FPU 或 FPU 指令,因此没有什么可以模拟的。相反,在这些情况下,浮点运算完全在软件中实现,编译器生成代码以在必要时调用浮点例程。例如,表达式 x = y * z ;
将生成等同于函数调用 x = _fmul( y, z ) ;
的代码。事实上,如果您查看包含浮点运算的构建的链接器映射输出,您可能会看到常规符号名称,例如 _fmul
、_fdiv
等 - 这些函数是 固有的 给编译器。