解包位域(反转movmskb)

时间:2016-02-23 22:05:28

标签: assembly bit-manipulation sse sse2

MOVMSKB能很好地将字节字段打包成位 但是我想做相反的事 我有一个16位的字段,我想放入XMM寄存器 每位1字节字段。
优选地,设置位应该设置每个字节字段的MSB(0x80),但是我可以使用设置位,从而在字节字段中产生0xFF结果。

我在https://software.intel.com/en-us/forums/intel-isa-extensions/topic/298374上看到了以下选项:

movd mm0, eax
punpcklbw mm0, mm0
pshufw mm0, mm0, 0x00
pand mm0, [mask8040201008040201h]
pcmpeb mm0, [mask8040201008040201h]

但是,此代码仅适用于MMX寄存器,不能与XMM regs一起使用,因为pshufw不允许这样做。

我知道我可以使用PSHUFB,但那是SSSE3而我想拥有SSE2代码,因为它需要在任何AMD64系统上运行。

有没有办法做到这一点是纯SSE2代码?
没有内在函数,只需简单的intel x64代码。

1 个答案:

答案 0 :(得分:5)

幸运的是pshufd是SSE2,你只需要再次解压缩它。我相信这应该有效:

movd xmm0, eax
punpcklbw xmm0, xmm0
punpcklbw xmm0, xmm0
pshufd xmm0, xmm0, 0x50
pand xmm0, [mask]
pcmpeqb xmm0, [mask]
约翰说:

  

如果你从一个单词开始,第一个解压缩会给你一个dword,允许你像这样缩短它:

movd xmm0, eax
punpcklbw xmm0, xmm0
pshufd xmm0, xmm0, 0x00
pand xmm0, [mask]
pcmpeqb xmm0, [mask]

但是这段代码不起作用。示例:假设输入为0x00FF(字),即我们希望设置低8字节。

punpcklbw xmm0, xmm0    ; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF
pshufd xmm0, xmm0, 0x00 ; 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00 FF FF
pand xmm0, [mask]       ; 00 00 02 01 00 00 02 01 00 00 02 01 00 00 02 01
pcmpeqb xmm0, [mask]    ; 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00 FF FF

这是错误的结果,因为我们想要00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF。当然,它确实给你8个字节,而不是8个对应的位。