ROUNDSS的RMI Instruction Operand Encoding是如何工作的?

How does the RMI Instruction Operand Encoding of ROUNDSS work?

ROUNDSS这样的一些x86指令需要这种看似晦涩的指令操作数编码,我在英特尔的软件开发人员手册中找不到任何文档或定义。

这个编码的比特是怎么用的?我将 66 0f 3a 0b c0 0c (roundsd xmm0,xmm0,0xc ) 放入反汇编程序并改变位以获得更好的理解,但只能访问一半的 XMM 寄存器。

我也不清楚

的意思

128-bit Legacy SSE version: The first source operand and the destination operand are the same.

作为电子。 G。 66 0f 3a 0b c1 0c 在没有 warning/error 的情况下反汇编为 roundsd xmm0,xmm1,0xc.

传统编码

编码如下:

66 0F 3A 0A /r ib

操作码是 0F 3A 操作码平面中的 0A。必须提供强制性 66 前缀。操作码后跟一个 modr/m 字节 (/r),编码 R 字段中的第一个操作数和 R/M 字段中的第二个操作数。该指令后跟一个 8 位立即数 (ib),对第三个操作数进行编码。

让我们编码例如

roundss xmm8, [rdx+r9*8+64], 0xc

我们有 xmm8r9 作为“高”寄存器,因此必须提供 REX.RX 前缀 46 来保存额外的位。

modr/m 字节是 44,表示 8 位位移(mod = 01),存在 SIB 字节(r/m = 100),并且 xmm8作为reg操作数(reg = 000,REX.R设置)。

SIB字节为CA表示rdx为base(base=010),r9为index(index=001,REX.Xset)和比例为 8(比例 = 11)。

然后是位移40(即十进制64)。

最后,我们有 8 位立即数 0c

然后按照遗留前缀、REX 前缀、操作码平面前缀、操作码、modr/m 字节、SIB 字节、位移、立即数的顺序组装这些位。所以整个指令是

66 46 0F 3A 0A 44 CA 40 0C
|  |  |     |  |  |  |  \... immediate
|  |  |     |  |  |  \...... displacement
|  |  |     |  |  \......... SIB byte
|  |  |     |  \............ modr/m byte
|  |  |     \............... opcode
|  |  \..................... opcode plane prefix
|  \........................ REX prefix
\........................... mandatory prefix

VEX 编码

128-bit Legacy SSE version: The first source operand and the destination operand are the same.

指令的 VEX 编码变体 vroundss 有一个额外的源操作数。而不是这个操作数,旧编码版本从目标操作数读取这个源操作数。

如果我们想将这条指令编码为 VEX 编码的变体

vroundss xmm8, xmm2, [rdx+r9*8+64], 0xc

相反,我们从 VEX 前缀开始。该前缀将强制前缀、REX 前缀和操作码平面前缀合并为一个 3 字节前缀。此前缀的格式为:

11000100 RXBmmmmm WvvvvLpp
R, X, B: complemented REX prefix bits
W: REX.W prefix bit (not complemented)
m: opcode plane (1: `0F`, 2: `0F 38`, 3: `0F 3A`)
L: vector length (0: 128 bit, 1: 256 bit)
p: mandatory prefix (0: none, 1: `66`, 2: `F3`, 3: `F2`)
v: complemented extra source register number

更短的 2 字节 VEX 前缀

11000101 RvvvvLpp

可以在REX.X、REX.B、REX.W明确且m=00000的情况下使用,这里不是这样。编码为

VEX.LIG.66.0F3A.WIG 0A /r ib VROUNDSS xmm1, xmm2, xmm3/m32, imm8

表示L和W字段被忽略,有一个强制性的66前缀并且操作码在0F 3A操作码平面中是0A,后面是modr/m 操作数和一个字节立即数。第一个和第三个操作数在 modr/m 字节中编码,第二个操作数是由 VEX 前缀编码的附加操作数。

所以我们有我们的指令

R = 0, indicating presence of REX.R
X = 0, indicating presence of REX.X
B = 1, indicating absence  of REX.B
W = 0, indicating absence  of REX.W (ignored)
L = 0, indicating a 128 bit operand size (ignored)
m = 00010, indicating the 0F 3A opcode plane
p = 01, indicating a 66 mandatory prefix
v = 1101, indicating xmm2 as a first operand

给出 VEX 前缀 C4 22 69。其余与旧编码相同,给出完整指令

C4 23 69 0A 44 CA 40 0C
|        |  |  |  |  \... immediate
|        |  |  |  \...... displacement
|        |  |  \......... SIB byte
|        |  \............ modr/m byte
|        \............... opcode
\........................ VEX prefix