这里需要保存FPU状态吗?

Is it necessary to save the FPU state here?

我写了一个简单的协作多线程库。目前我总是在切换到新上下文时使用 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 状态做出任何假设?

没有。您不必对状态进行任何保存。如果一个线程正在进行浮点计算,例如设置了非规范化标志,并且该线程被中断,那么当它恢复时 O/S 或内核将设置标志,就像它一样将恢复其他寄存器。同样,您不必在 yield() 中担心它。

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

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

%st(0): If the function does not return a floating-point value, then this register must be empty. This register must be empty before entry to a function.

%st(1) through %st(7): Floating-point scratch registers have no specified role in the standard calling sequence. These registers must be empty before entry and upon exit from a function.

因此,您不需要对它们进行上下文切换。

另一个,newer version 是这样说的:

The CPU shall be in x87 mode upon entry to a function. Therefore, every function that uses the MMX registers is required to issue an emms or femms instruction after using MMX registers, before returning or calling another function. [...] The control bits of the MXCSR register are callee-saved (preserved across calls), while the status bits are caller-saved (not preserved). The x87 status word register is caller-saved, whereas the x87 control word is callee-saved. [...] All x87 registers are caller-saved, so callees that make use of the MMX registers may use the faster femms instruction.

所以,您可能需要保存控制字。