向 xmm 寄存器广播一个词

Broadcast a word to an xmm register

我需要将一个 16 位字移动八次到 xmm 寄存器中以进行 SSE 操作

E. g.: 我想把 16 位字 ABCD 写入 xmm0 寄存器,这样最后的结果看起来像

ABCD | ABCD | ABCD | ABCD | ABCD | ABCD | ABCD | ABCD

我想这样做是为了稍后使用 paddw 操作。到目前为止,我已经找到了 pushfd 操作,它可以完成我想做的事情,但仅限于双字(32 位)。 pshufw 仅适用于 - 如果我没记错的话 - 64 位寄存器。是否有我正在寻找的操作,或者我是否必须以某种方式用多个 pshufw?

来模拟它

您可以通过执行随机播放然后解包来实现预期的目标。在 NASM 语法中:

    # load 16 bit from memory into all words of xmm0
    # assuming 16-byte alignment
    pshuflw xmm0, [mem], 0 # gives you [ M, M, M, M, ?, ?, ?, ? ]
    punpcklwd xmm0, xmm0   # gives you [ M, M, M, M, M, M, M, M ]

请注意,这会从 mem 读取 16 个字节,因此 需要 16 字节对齐

实际只使用了前2个字节。如果该数字不在内存中或者您不能保证可以读取到末尾,请使用如下内容:

    # load ax into all words of xmm0
    movd      xmm0, eax                  ; or movd xmm0, [mem]  4-byte load
    pshuflw   xmm0, xmm0, 0
    punpcklwd xmm0, xmm0

借助 AVX2,您可以使用 vpbroadcast* 广播负载或来自注册源的广播。如果你愿意,目的地可以是YMM。

    vpbroadcastw  xmm0, [mem]            ; 16-bit load + broadcast

    vmovd         xmm0, eax
    vpbroadcastw  xmm0, xmm0

Memory-source 1 或 2 字节元素的广播在 Intel CPU 上仍然解码为加载+洗牌 uop,但 4 字节或 8 字节块的 broadcast-loads 甚至更便宜:已处理在不需要随机播放的加载端口中。

无论哪种方式,这仍然比没有 AVX2 或 SSSE3 的 2 个独立洗牌便宜 pshufb