解压缩位域(movmskb 的逆)

Posted

技术标签:

【中文标题】解压缩位域(movmskb 的逆)【英文标题】:Unpacking a bitfield (Inverse of movmskb) 【发布时间】:2016-02-23 22:05:27 【问题描述】:

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 代码。

【问题讨论】:

对于那些对具有内在函数here it is 的 SSSE3(和 32 位的 AVX2)解决方案感兴趣的人。 @Zboson,SSSE3 只是一个简单的SHUFB 【参考方案1】:

幸运的是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 个。

【讨论】:

是的,它可以用SHUFPS 短接,但我不确定整数和浮点 sse 指令的混合是否不会引起惩罚。 (我隐约记得在处理这些问题的 SSE 指令中生成非标准化单项会受到惩罚。 不,您的SHUFPS 版本错误。 SHUFPS 也像 PSHUFD 一样对双字进行洗牌,因此需要额外的解包。 嗯,第一个和第二个版本在我的机器上工作(TM)。我从一个单词开始,所以第一个解包给了我一个 dword。 @Johan 查看更新。你不同意吗?另外,SHUFPS 的意义何在,它的功能与PSHUFD 的功能完全相同,因此您可以离开PSHUFD 笨蛋,错过了,但是简短的版本可能仍然有用,如果您能够处理位的混合,完全同意SHUFPS 的无用性。它确实为您提供了一种您可以使用的结果 - 咳嗽类型 - 以额外的复杂性为代价。

以上是关于解压缩位域(movmskb 的逆)的主要内容,如果未能解决你的问题,请参考以下文章

压缩解压缩 和 打包解打包 命令

压缩解压缩

linux 压缩/解压缩/打包命令

gzip压缩解压缩

nodejs压缩解压缩(加密)

mac解压缩软件哪个好