9

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

在非 SSE066h中,在 32 位(或 64 位)和 16 位操作之间切换。 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

这些的规格是什么?

4

2 回答 2

5

我不记得在疯狂组合随机前缀的情况下看过任何关于你应该期待什么的规范,所以我猜 CPU 行为可能是“未定义的”并且可能是特定于 CPU 的。(很明显,英特尔的文档中指定了一些内容,但许多情况并未涵盖)。并且可能会保留一些组合以供将来使用。

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

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通过0XMM70FFh

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 的手册中找到一些线索,我不会感到惊讶。

于 2010-03-09T11:46:20.163 回答
1

英特尔的 SDM vol.2 手册(指令集参考)将这些称为强制前缀。将它们视为操作码的一部分。

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

像往常一样,使用来自同一组的多个冲突前缀碰巧解码,最后一个优先于当前的英特尔硬件。我认为英特尔手册说这样做会产生不可预测的行为,因此不能保证或未来证明。这不是一件有意义的事情;如果您出于对齐原因想要填充指令以使其更长,我认为重复相同的前缀几次是安全的。

B.8 SSE 指令格式和编码

SSE 指令使用 ModR/M 格式,前面有 0FH 前缀字节。通常,操作不会重复以提供两个方向(即,单独的加载和存储变体)。

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


并且

2.1.2 操作码

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

通用指令和 SIMD 指令的两字节操作码格式包含以下内容之一:

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

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

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

例如,XMM 寄存器的 PHADDW 由以下序列组成:66 0F 38 01。第一个字节是强制前缀。

于 2019-12-04T13:59:07.497 回答