正如@harold 所说,存储到内存已经被 MMX 覆盖movd
,或者pshufw
+movd
只提取 high float
。
您不能做的一件事是打开 3dNow!在没有存储/重新加载的情况下浮动到 x87 80 位浮点数。
可能有用的是一个 EMMS 版本,它将 32 位扩展float
为 80 位 x87 long double
in st0
,同时将 FPU 设置回 x87 模式而不是 MMX 模式1。或者甚至可以将多个mm
寄存器转换为多个 x87 寄存器?
即,这将是movd dword [esp], mm0
/ emms
/fld dword [esp]
在 SIMD 减少后设置进一步标量 FP 的捷径。
请记住,这些是 IEEE754 float
;您通常不希望它们在整数寄存器中,除非您要分离它们的位域(例如,对于exp
orlog
实现),但您可以使用 MMX 移位/掩码指令来做到这一点。
但是 movd 和 fld 很便宜,所以他们不会为了节省重新加载延迟而费心制作特殊指令。此外,作为单条指令实施可能会很慢。尽管 x86 不是 RISC ISA,但拥有一条非常复杂的指令通常比多条更简单的指令慢(尤其是在完全解码为多个微指令之前。)例如,英特尔和 AMDsysenter
以及syscall
替换int 0x80
系统调用的指令需要额外的指令之前/之后保存更多状态,但总体上仍然更快。
3dNow!femms
离开 MMX/3dNow! 寄存器内容未定义,仅将标记字设置为未使用,而不是保留从 MMX 寄存器到/从 x87 寄存器内容的映射。有关AMD 官方手册,请参阅http://refspecs.linuxbase.org/AMD-3Dnow.pdf 。IDK,如果 AMD 的微架构刚刚删除了寄存器重命名信息或什么,但可能使 store / femms / x87-load 成为快速方式可以节省大量晶体管。
甚至 FEMMS 仍然有些慢,所以他们不想鼓励编码人员离开/重新进入 MMX/3dNow!经常模式。
有趣的事实:3dNow!PREFETCHW
(带有写入意图的预取)仍在使用,并且有自己的 CPUID 功能位。
请参阅我对_builtin_prefetch() 中第二个参数的影响是什么的回答?
英特尔 CPU 很快增加了对将其解码为 NOP 的支持(因此 64 位 Windows 之类的软件可以在不检查的情况下使用它),但 Broadwell 和后来实际上使用 RFO 预取以使缓存线处于 MESI 独占状态,而不是共享状态,所以它可以在没有额外的非核心流量的情况下翻转到 Modified。
CPUID 特性位表明它确实会预取。
脚注 1:
请记住,MMX 寄存器是 x87 寄存器的别名,因此不需要新的操作系统支持来保存/恢复上下文切换上的架构状态。直到SSE,我们才获得了新的架构状态。所以直到SSE2+3dNow!那是一个 3dNow!无需切换回 x87 模式float
即可使用 SSE2 。double
你可以movq2dq xmm0, mm0
+ cvtps2pd xmm0, xmm0
。
他们本可以在寄存器中有一个 float->double mm
,但fld
/fst
硬件仅设计用于float
or double
->80-bit 和 80-bit-> float
or double
。并且用例是有限的;如果您使用的是 3dNow!,请坚持使用float
.