Ridistribuire bit meno significativi di un array di 4 byte ad un nibble
-
25-10-2019 - |
Domanda
desidero spostare bit 0,8,16,24 di un valore di 32 bit a bit 0,1,2,3 rispettivamente. Tutti gli altri bit in ingresso e in uscita sarà zero.
Ovviamente posso farlo in questo modo:
c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;
Ma c'è un modo più veloce (meno istruzioni)?
Soluzione
c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;
o attendere per il processore Intel Haswell, facendo tutto questo esattamente un'istruzione (Pext).
Aggiorna
Tenendo conto clarified constraints
e supponendo 32-bit unsigned values
, il codice può essere semplificata in questo:
c = (c * BITS_7_14_21_28) >> 28;
Altri suggerimenti
Se non si cura di portabilità, e può utilizzare le istruzioni SSE, sguardo al istruzione PMOVMSKB e la sua intrinseca compilatore. [I notato che le sue posizioni di bit più significativi (segno) bit dei 4 byte comprendenti la parola di 32 bit.]
Invece di scrivere un po 'offuscato goo una riga, il sottostante codice è quello che avrei scritto, per la massima portabilità e manutenibilità. Avrei lasciato la preoccupazione ottimizzatore circa se o non è il codice più 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;
}