在SSE中,前缀066h
(操作数大小覆盖)0F2H
(REPNE)和0F3h
(REPE)是操作码的一部分。
在32位(或64位)和16位操作之间的非SSE 066h
切换。 0F2h
和0F3h
用于字符串操作。它们可以组合在一起,以便066h
和0F2h
(或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
这些规格是什么?
答案 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
但是,我也知道CS
和DS
段覆盖前缀已获取新的函数作为SSE2分支提示前缀(预测分支取= 3Eh
= DS
覆盖;当应用于条件跳转指令时,预测分支未被取消= 2Eh
= CS
覆盖。
无论如何,我查看了上面的示例,始终通过
将XMM1
设置为所有0
和XMM7
设置为所有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
作为主要操作码,第二个操作码字节。- 强制性前缀(
66H
,F2H
或F3H
),转义操作码字节和第二个操作码字节(与上一个相同) 项目符号)。例如,CVTDQ2PD由以下序列组成:
F3 0F E6
。 第一个字节是必填前缀(不是 视为重复前缀)。 通用和SIMD指令的三字节操作码格式由以下之一组成:
- 一个转义操作码字节0FH作为主要操作码,外加两个附加操作码字节。
- 一个强制性前缀(66H,F2H或F3H),一个转义操作码字节以及两个附加的操作码字节(与 上一个项目符号)。
例如,用于XMM寄存器的PHADDW由以下序列组成:66 0F 3801。第一个字节是必需的前缀。