Pregunta

Deseo mover bits 0,8,16,24 de un valor de 32 bits a BITS 0,1,2,3 respectivamente. Todos los demás bits en la entrada y salida serán cero.

Obviamente puedo hacer eso así:

c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;

¿Pero hay una forma más rápida (menos instrucciones)?

¿Fue útil?

Solución

c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;

O espera el procesador Intel Haswell, haciendo todo esto en exactamente una instrucción (PEXT).

Actualizar

Teniendo en cuenta clarified constraints y asumiendo 32-bit unsigned values, el código puede simplificarse con esto:

c = (c * BITS_7_14_21_28) >> 28;

Otros consejos

Si no le importa la portabilidad y puede usar las instrucciones de SSE, mire el PMOVMSKB instrucción y su compilador intrínseco. [Noté que sus posiciones de bits son los bits más significativos (de signo) de los 4 bytes que comprenden la palabra de 32 bits.

En lugar de escribir un poco de una línea de una línea, el siguiente código es lo que escribiría, para obtener la máxima portabilidad y mantenimiento. Dejaría que el optimizador se preocupe por si es o no el código más efectivo.

#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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top