从4字节阵列重新分发至少有显着的位
-
25-10-2019 - |
题
我希望将32位值的0,8,16,24分别移至0,1,2,3。输入和输出中的所有其他位将为零。
显然我可以这样做:
c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;
但是,是否有更快的(指示更少)?
解决方案
c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;
或等待Intel Haswell处理器,在一份指令(PEXT)中完成所有这些操作。
更新
考虑在内 clarified constraints
并假设 32-bit unsigned values
, ,可以简化代码:
c = (c * BITS_7_14_21_28) >> 28;
其他提示
如果您不关心可移植性,并且可以使用SSE说明,请查看 PMOVMSKB 指令及其编译器的固有。 [我注意到您的位置是包含32位单词的4个字节的最重要(标志)位。
以下代码是我要编写的,而不是编写一些混淆的单行胶粘剂,以实现最大的可移植性和可维护性。我会让优化器担心它是否是最有效的代码。
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#define BITS_TO_MOVE 4
static const uint32_t OLD_MASK [BITS_TO_MOVE] =
{
0x0008u,
0x0080u,
0x0800u,
0x8000u
};
static const uint32_t NEW_MASK [BITS_TO_MOVE] =
{
0x1000u,
0x2000u,
0x4000u,
0x8000u
};
int main()
{
uint32_t c = 0xAAAAu;
uint32_t new_c = 0;
uint8_t i;
printf("%.4X\n", c);
for(i=0; i<BITS_TO_MOVE; i++)
{
if ( (c & OLD_MASK[i]) > 0 )
{
new_c |= NEW_MASK[i];
}
}
printf("%.4X\n", new_c);
getchar();
return 0;
}
不隶属于 StackOverflow