将两个x86 32位寄存器存储到128位xmm寄存器中

10

有没有更快的方法将两个x86 32位寄存器存储在一个128位xmm寄存器中?

movd  xmm0, edx
movd  xmm1, eax
pshufd xmm0, xmm0, $1
por   xmm0, xmm1 

如果EAX是0x12345678,EDX是0x87654321,那么xmm0中的结果必须为0x8765432112345678


哇!那是一个很酷的汇编器...我上次用的是32位的...不知道你可以买到一台128位的电脑... :P :) - t0mm13b
1
流式单指令多数据扩展(SSE)是一种SIMD指令集扩展,适用于x86架构,由英特尔设计并于1999年推出。 - GJ.
4
允许使用的SSE指令集版本是多少? - PhiS
尽量将 @PhiS 降至最低。 :) 嗯... 至少5年前,SSE2非常不错。 - GJ.
2个回答

16

使用 SSE 4.1,您可以使用 movd xmm0,eax / pinsrd xmm0,edx,1 在两条指令中完成操作。

对于旧的 CPU,您可以使用 2 个 movd 然后使用 punpckldq 总共需要 3 条指令:

movd xmm0, edx
movd xmm1, eax
punpckldq xmm0, xmm1

谢谢。但这是相对较新的扩展集,自2007年以来速度和代码大小几乎相同。 - GJ.
2
好的 - 现在已经添加了一个包含3个指令序列的SSE2 / SSE3。 - Paul R
1
使用SSE4.1,第一条指令仍应为movd。编写pinsrd x,r, 0的唯一原因是当您真正想要合并旧值而不是零扩展到整个寄存器以打破对旧值的依赖关系时。 pinsrd在Intel CPU上解码为2个uop:int->xmm和shuffle,因此它更紧凑,不需要一个临时寄存器,但在大多数CPU上基本上与SSE2版本运行相同。 - Peter Cordes
2
使用内部函数时,您不必担心这个问题,因为编译器知道在可能的情况下使用movd。 (在提取中更常见,其中_mm_extract_epi32(v,0)编译为movd。 pinsrd内部函数需要一个额外的源向量,希望大多数人意识到他们不应该使用它。) - Peter Cordes
@PeterCordes,谢谢,又发现了一个缺失的优化问题(一些编译器不支持https://godbolt.org/z/r7oe1fG8T)。 - Alex Guteniev
@AlexGuteniev:是的,MSVC和ICC通常根本不优化内部函数,但是当有一个具有特定功能要求的1:1替代方案时,它将是一个好主意。GCC和clang以相同的方式优化内部函数,它们并不总是将“+”编译为“add”指令。 - Peter Cordes

1

我对MMX不是很了解,但也许你想要PACKSSDW指令。

PACKSSDW指令将源操作数中的两个双字和目标操作数中的两个双字转换为四个带饱和度的有符号字。该指令将这四个字打包在一起,并将结果存储在目标MMX寄存器中。

(来自http://webster.cs.ucr.edu/AoA/Windows/HTML/TheMMXInstructionSeta2.html)

编辑:我刚意识到那些是SSE寄存器。哦,算了。


我喜欢使用xmm寄存器而不是mmx(64位),因为使用后它们不需要“emms”指令。 - GJ.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接