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)?

È stato utile?

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top