X86 在st0中存储通用寄存器

X86 在st0中存储通用寄存器,x86,floating-point,x86-64,x87,X86,Floating Point,X86 64,X87,如果我有一些值位模式,比如rax中的全零,我可以将其存储在st0中,而无需存储和从内存加载吗?有许多指令可用于将常量加载到FPU寄存器堆栈中。我认为这里最有用的是FLD1和FLDZ,它们分别将+1.0和+0.0加载到堆栈中。如果RAX可能持有的唯一可能的整数是1和0,那么您可以有条件地执行FLD1或FLDZ 通常,无符号或2的补码格式中的任何64位整数都可以用80位扩展精度浮点格式表示。可以在零内存访问的情况下将RAX中的任何整数值加载到FPU堆栈上。这可以通过使用一系列x87算术指令来实现,这

如果我有一些值位模式,比如rax中的全零,我可以将其存储在st0中,而无需存储和从内存加载吗?

有许多指令可用于将常量加载到FPU寄存器堆栈中。我认为这里最有用的是FLD1和FLDZ,它们分别将+1.0和+0.0加载到堆栈中。如果RAX可能持有的唯一可能的整数是1和0,那么您可以有条件地执行FLD1或FLDZ

通常,无符号或2的补码格式中的任何64位整数都可以用80位扩展精度浮点格式表示。可以在零内存访问的情况下将RAX中的任何整数值加载到FPU堆栈上。这可以通过使用一系列x87算术指令来实现,这些指令可能在一个循环中执行,该循环的跳闸计数保存在GP寄存器中。一种方法是对负整数使用FADD或FSUB,直到st0包含所需的整数值,尽管这对于较大的绝对值可能非常慢。对于2次幂的整数,一种可能的优化方法是加载常数+1.0,使用FADD添加1以获得数字2,然后使用FMUL直到达到所需的2次幂。在某些情况下,另一种可能更快的方法是首先对RAX中的整数进行因式分解,使用FADD构造每个素因子,然后使用FMUL乘以素因子


所有这些指令在所有Intel和AMD x86处理器上都受支持。

我认为您实际上希望它用于 其中movd/movq+sqrtss或sqrtsd比???->fsqrt

将整数依赖项耦合到x87依赖项可以通过整数标志来完成,而不是通过传输位模式。在Skylake上,这是一个4-uop指令,但它是4个ALU uop

在另一个方向,fcomi+setcc或cmovcc,甚至只是fcom+fnstsw ax

正如@Hadi指出的,您可以使用fldz 1 uop或fld1 2 uop在x87寄存器中创建值。然后使用fcmovne st0、st1或类似工具,根据您的需要进行调整

可能的答案是,并没有完全研究过,因为它不太可能对你们有用,可能涉及微代码EMM:Skylake上10个UOP,Haswell上31个UOP

也许您可以使用movq mm0、rax和EMM离开MMX状态。这会将所有x87寄存器标记标记为空

据介绍,在当前的AMD上,FEMMS与EMM是相同的,但我似乎记得读到旧AMD CPU上的FEMMS没有定义x87寄存器。也许这是有用的。它仍然设置了标记字,因此未定义的内容可能仅适用于可能希望在EMMS之后找到mm0..7内容,然后运行另一条MMX指令的情况。或查找处于fxsave状态的数据

64位MMX寄存器别名80位x87寄存器的有效位尾数。我想。st0..7堆栈映射到那些基础80位寄存器,从x87状态字中3位顶部字段索引的寄存器开始。用左轮手枪枪管的类比很好地描述了这一点

我不确定这是否真的可用,但我认为emms不会清除mm/st寄存器内容,只清除x87标记。表示将x87 FPU标记字中所有标记的值设置为清空所有1

如果浮点指令在EMMS指令重置x87 FPU标记字之前加载x87 FPU数据寄存器堆栈中的一个寄存器,则可能会发生x87浮点寄存器堆栈溢出,从而导致x87浮点异常或不正确的结果

它只说可以,不说愿意。也许在x87元数据处于已知状态的情况下,您可以将MMX指令和x87指令与某种一致的行为混合使用?至少在特定的微体系结构上

您无法读取其标记字为11表示为空的x87寄存器,也没有任何乐趣,只需将单个标记字设置为11,而不会影响堆栈顶部指针或内容

然后,您必须在保存的x87状态元数据28字节(包括32/64位模式中的填充)中fstenv并修改标记字

或者,您可以为fldenv准备一个预定义的x87环境,并将一些标记词设置为“未使用”。但阿格纳·福格甚至都没有给这个指令计时。很明显,它将被微码化,而且速度可能很慢。您可能可以在没有EMM的情况下使用它,但它仍然是一条微代码指令


相关:有一些链接,我挖了一段时间前关于FEMM和多么少3dNow!可以与SSE互动。嗯,显然它仍然将标记字设置为所有未使用的,但不保留mm0..7和x87寄存器之间的已知映射。

No.[必需的填充符]