Redistribuer les bits les moins significatifs à partir d'une matrice de 4 octets à un quartet
-
25-10-2019 - |
Question
Je souhaite déplacer les bits 0,8,16,24 d'une valeur de 32 bits pour les bits 0,1,2,3 respectivement. Tous les autres bits de l'entrée et la sortie sera zéro.
Il est évident que je peux le faire comme ceci:
c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;
Mais est-il un moyen plus rapide (moins d'instructions)?
La solution
c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;
Ou attendre pour le processeur Intel Haswell, faisant tout cela exactement une instruction (pext).
Mise à jour
La prise en compte clarified constraints
et en supposant 32-bit unsigned values
, le code peut être simplifié à ceci:
c = (c * BITS_7_14_21_28) >> 28;
Autres conseils
Si vous ne se soucient pas de la portabilité, et peut utiliser des instructions SSE, consultez la page instruction de PMOVMSKB et son intrinsèque du compilateur. [J'ai remarqué que vos positions de bits sont bits les plus significatifs (signe) des 4 octets comprenant le mot de 32 bits.]
Au lieu d'écrire un peu obscurcie goo une ligne, le code est ci-dessous ce que je voulais écrire, pour une portabilité maximale et la maintenabilité. Je laisserais le souci optimiseur de savoir si elle est ou non le code le plus efficace.
#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;
}