是否有必要在此处保存FPU状态?

时间:2016-03-12 22:03:18

标签: c++ assembly x86 cdecl

我写了一个简单的合作多线程库。目前,我总是在切换到新上下文时使用fxsave / fxrstor保存和恢复fpu状态。但这在cdecl调用约定中是否必要?

举个简单的例子:

float thread_using_fpu(float x)
{
    float y = x / 2; // do some fpu operation
    yield();         // context switch, possibly altering fpu state.
    y = y / 2;       // another fpu operation
    return y;
}

编译器调用yield()后可能会对FPU状态做出任何假设吗?

2 个答案:

答案 0 :(得分:3)

根据SYSTEM V APPLICATION BINARY INTERFACE Intel386TM Architecture Processor Supplement,第3-12页:

  

%st(0):如果函数没有返回浮点值,那么这个          注册必须为空。此寄存器必须为空          进入一个功能。

     

%st(1)到%st(7):   浮点临时寄存器在中没有指定的作用   标准呼叫序列。输入前这些寄存器必须为空   退出某个职能部门。

因此,您无需上下文切换它们。

另一个,newer version说:

  

进入某个功能后,CPU应处于x87模式。因此,每个使用MMX寄存器的函数都需要发出   返回之前使用MMX寄存器后的emms或femms指令   或者调用另一个函数。 [...]       MXCSR寄存器的控制位是被调用者保存的(保留在调用之间),而状态位是调用者保存的(不保留)。   x87状态字寄存器是调用者保存的,而x87控件   单词是被调用者保存的。   [...]所有x87寄存器都被调用者保存,因此使用MMX寄存器的被调用者可以使用更快的femms指令。

因此,您可能需要保存控制字。

答案 1 :(得分:2)

没有。您无需保存状态。如果一个线程处于浮点计算的中间,例如,设置了非规范化的标志,并且该线程被中断,那么当它恢复时,O / S或内核将设置标志,就像它将恢复一样其他登记册。同样,您不必在yield()中担心它。

编辑:如果您正在进行自己的上下文切换,则可能需要保存精度和舍入控制标志(如果需要将它们设置为非默认值)。否则,你再次没事。