我希望将 32 位值的 0、8、16、24 位分别移动到 0、1、2、3 位。输入和输出中的所有其他位都将为零。
显然我可以这样做:
c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;
但是有更快(更少指令)的方法吗?
我希望将 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;
或者等待英特尔 Haswell 处理器,在一条指令 (pext) 中完成所有这些。
更新
考虑clarified constraints
并假设32-bit unsigned values
,代码可以简化为:
c = (c * BITS_7_14_21_28) >> 28;
如果您不关心可移植性,并且可以使用 SSE 指令,请查看PMOVMSKB指令及其编译器内在函数。[我注意到您的位位置是构成 32 位字的 4 个字节的最高有效位(符号)。]
为了最大的可移植性和可维护性,我将编写以下代码,而不是编写一些模糊的单行 goo。我会让优化器担心它是否是最有效的代码。
#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;
}