【问题标题】:Is it necessary to save the FPU state here?这里有必要保存FPU状态吗?
【发布时间】:2016-03-12 22:03:18
【问题描述】:

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

【问题讨论】:

  • 不,通常的约定要求 FPU 状态在进入和退出时为空(除非明显用于返回值)。
  • 谢谢,你有这个的来源吗?我自己找不到太多关于这个的信息。不必每次都保存和恢复 512 字节的缓冲区确实有助于提高性能,我想 100% 确定这不会导致任何问题。

标签: c++ assembly x86 cdecl


【解决方案1】:

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

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

%st(1) 到 %st(7): 浮点暂存寄存器在 标准调用顺序。这些寄存器在进入前必须为空 并在退出函数时。

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

另一个,newer version 说:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 澄清一下,我正在做自己的上下文切换,而不是使用操作系统管理的线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    相关资源
    最近更新 更多