在SSE中组合前缀

时间:2010-03-08 20:09:35

标签: assembly x86 sse prefixes

在SSE中,前缀066h(操作数大小覆盖)0F2H(REPNE)和0F3h(REPE)是操作码的一部分。

在32位(或64位)和16位操作之间的非SSE 066h切换。 0F2h0F3h用于字符串操作。它们可以组合在一起,以便066h0F2h(或0F3h)可以在同一条指令中使用,因为这是有意义的。 SSE指令中的行为是什么?例如,我们(现在忽略mod / rm):

0f 58 - > addps

66 0f 58 - > addpd

f2 0f 58 - > addsd

f3 0f 58 - > addss

但是这是什么?

66 f2 0f 58

怎么样?

f2 66 0f 58

更不用说以下有两个冲突的REP前缀:

f2 f3 0f 58

这些规格是什么?

2 个答案:

答案 0 :(得分:3)

我不记得曾经看到过任何关于在随机前缀中疯狂组合你应该期望什么的规范,所以我猜CPU行为可能是“未定义的”并且可能是CPU特定的。 (显然,有些事情在例如英特尔的文档中有详细说明,但很多案例都没有涉及)。并且可以保留一些组合以供将来使用。

我天真的假设通常是额外的前缀是无操作,但不能保证。这似乎是合理的,例如一些优化手册建议使用前缀为NOP的多字节90h(规范66h),例如:

db 66h, 90h; 2-byte NOP
db 66h, 66h, 90h; 3-byte NOP
db 66h, 66h, 66h, 90h; 4-byte NOP

但是,我也知道CSDS段覆盖前缀已获取新的函数作为SSE2分支提示前缀(预测分支取= 3Eh = DS覆盖;当应用于条件跳转指令时,预测分支未被取消= 2Eh = CS覆盖。

无论如何,我查看了上面的示例,始终通过

XMM1设置为所有0XMM7设置为所有0FFh
pxor xmm1, xmm1    ; xmm1 <- 0s
pcmpeqw xmm7, xmm7 ; xmm7 <- FFs 

然后是有问题的代码,带有xmm1, xmm7个参数。我观察到的(Win64系统和Intel T7300 Core 2 Duo上的32位代码)是:

1)通过添加addsd前缀

66h未发现任何变化
db 66h 
addsd xmm1, xmm7 ;total sequence = 66 F2 0F 58 CF     

2)通过添加addss前缀

0F2h未发现任何变化
db 0f2h     
addss xmm1,xmm7 ;total sequence = F2 F3 0F 58 CF

3)但是,我通过addpd前缀0F2h来观察更改:

db 0f2h    
addpd xmm1, xmm7 ;total sequence = F2 66 0F 58 CF

在这种情况下,XMM1中的结果为0000000000000000FFFFFFFFFFFFFFFFh而不是FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFh

所以我的结论是,人们不应做出任何假设并期望“未定义”的行为。但是,如果你能在Agner fog manuals找到一些线索,我不会感到惊讶。

答案 1 :(得分:1)

Intel的SDM vol.2手册(指令集参考)将其称为强制性前缀。将它们视为操作码的一部分。

但是,是的,它们是 前缀,可以在实际转义字节+操作码之前与其他前缀混合。实际上,REX前缀必须在其他前缀之后。

通常,使用来自同一组的多个有冲突的前缀进行解码时,最后一个在当前Intel硬件上具有优先权。我认为Intel手册说这样做会带来不可预测的行为,因此不能保证或将来会得到证明。这不是一件有意义的事情。如果您出于对齐原因而希望填充指令以使其更长,我认为重复几次 same 前缀是安全的。

  

B.8 SSE INSTRUCTION FORMATS AND ENCODINGS

     

SSE指令使用ModR / M格式,并以0FH开头   前缀字节。通常,不重复操作以提供两个   方向(即分别的加载方式和存储方式)。

     

以下三个表(表B-22,B-23和B-24)显示了   SSE SIMD浮点,SIMD整数,   以及可缓存性和内存排序指令。 有些   SSE指令要求将强制性前缀(66H,F2H,F3H)作为   两字节的操作码。表格中包含强制性前缀。


还有

  

2.1.2操作码

     

主要操作码的长度可以为1、2或3个字节。有时,附加的3位操作码字段会在   ModR / M字节。较小的字段可以在主操作码中定义。这些字段定义了操作方向,位移大小,寄存器编码,条件代码或符号扩展名。编码所使用的字段   操作码因操作类别而异。

     

用于通用和SIMD指令的两字节操作码格式由以下之一组成:

     
      
  • 转义操作码字节0FH作为主要操作码,第二个操作码字节。
  •   
  • 强制性前缀(66HF2HF3H),转义操作码字节和第二个操作码字节(与上一个相同)   项目符号)。
  •   
     

例如,CVTDQ2PD由以下序列组成:F3 0F E6第一个字节是必填前缀(不是   视为重复前缀)。   通用和SIMD指令的三字节操作码格式由以下之一组成:

     
      
  • 一个转义操作码字节0FH作为主要操作码,外加两个附加操作码字节。
  •   
  • 一个强制性前缀(66H,F2H或F3H),一个转义操作码字节以及两个附加的操作码字节(与   上一个项目符号)。
  •   
     

例如,用于XMM寄存器的PHADDW由以下序列组成:66 0F 3801。第一个字节是必需的前缀。