一般来说,若要支持浮点,必须支持IEEE745, IEEE745主要规定了:
- 硬件支持的浮点操作
结果的舍入和精度,4种选项
什么时候一个结果被看作是异常:除以0或负数平方根或其他等。。
当一个操作产生异常结果时采取的动作:用户让计算中断并发出信号 或者 不想让用户知道给出一个规定的值。
- 软件仿真的操作
- 存储方式
包括指数,尾数和符号位。例如,MIPS单精度和双精度存储结构如下:
支持浮点计算一般有两种方法:
- 硬件实现
- 软件仿真
IEEE异常处理
浮点协处理器拥有专门的浮点寄存器和浮点流水线,对于产生IEEE异常结果时,协处理器可以选择:
- 硬件信号报告
这样会导致停止整个流水线
- 硬件自陷
这要求在去指令的时决定是否自陷。自陷的结果一般交给软件实现的自陷处理程序处理(实际上就是异常处理程序)或者产生默认的结果(例如溢出异常会产生一个无穷大的值)
浮点协处理器寄存器
- 32/64通用寄存器,支持单精度和双精度计算
- 控制寄存器,FCSR/FIR/FCR/FEXR/FENR
- 控制寄存器通过指令ctc1/cfc1来操作浮点寄存器访问,通用寄存器和其他通用寄存器访问方式一样。
指令集
汇编程序需要考虑时序问题:
修改浮点协处理器的控制寄存器和状态寄存器时,会影响浮点流水线的结果。一般在ctc1之后加上一两条nop
浮点和通用寄存器之间的数据传送完成的时间比较晚,因此后续的指令要使用传送的结果需要等待
浮点寄存器加载和整数加载一样慢,后面紧跟的指令不能立即使用刚加载的值
测试指令和分支,条件分支不能紧跟测试指令之后
现代MIPS FPU常常是完全流水线化的,允许每个始终启动一个心的浮点乘法、加法或者乘加计算,但是如果你要在下一个指令使用某天指令的结果的花,就会让程序停下来等待。对于浮点来说,乘法和加减法一样快。一般将除法转换为乘法进行加速。
即需初始化和使能
FPU使能后,在中断和上下文切换时需要保存和恢复浮点寄存器。所以:
新任务默认禁止浮点(这样不需要保存和恢复浮点寄存器)
当发生CU1不可用的自陷时,表示该任务为浮点用户,返回之前使能浮点。
当处于核心态或中断例程直接间接调用的软件中,禁止浮点(这样可以避免中断时保存浮点寄存器)
应当用你选用的舍入模式和自陷使能设置控制/状态寄存器。
即需初始化和使能一般发生在进程切换。
- 初始化
在进程第一次使用浮点部件的时候,由于浮点部件默认是不可用的,因此会产生浮点部件不可用异常,异常检查进程是否是第一次使用,如果是第一次使用则初始化task_struct ,thread_info等结构体相应的标识,并打开浮点部件。
- 浮点现场保存
在进程切换的时候检查进程是否使用了浮点部件(即检查上述初始化的标识),如果没使用则不保存,否则保存现场并关闭浮点部件。
- 浮点现场恢复
浮点现场恢复并不是在进程切换的时候,而是在进程切换后第一次使用浮点部件的时候。因为进程切换后浮点部件一定是关闭的。(原因是浮点部件默认关闭,而且即使前一个进程打开了浮点部件,切换时也会关闭)。在第一次使用时会产生浮点部件不可用例外,例外检查到进程不是第一次使用浮点部件则恢复浮点部件现场,并打开浮点部件。
浮点仿真
对于不支持浮点协处理器来说,一般通过软件浮点库或者自陷仿真程序支持浮点计算
软浮点:计算操作使用库函数实现,数据传送加载存储使用和整数一样的方式处理
自陷和仿真:硬件检测到浮点指令而发生自陷
不管是那种方式,仿真比硬件实现要慢50-300倍
MIPS浮点相关编译选项
-
-mfp32
- Assume that floating-point registers are 32 bits wide.
-
假定浮点寄存器32bit.
-mfp64
- Assume that floating-point registers are 64 bits wide.
-
假定浮点寄存器64bit.
-mhard-float
-
Use floating-point coprocessor instructions. 使用浮点协处理器指令.
-msoft-float
-
Do not use floating-point coprocessor instructions. Implement floating-point calculations using library calls instead.
不时用浮点协处理器指令. 而使用浮点库.
-
-msingle-float
- Assume that the floating-point coprocessor only supports single-precision operations.
- 设定浮点协处理器只支持单精度操作. -mdouble-float
- Assume that the floating-point coprocessor supports double-precision operations. This is the default. 双精度操作.
-
-