Frage

Ich möchte Bits 0,8,16,24 eines 32-Bit-Wertes auf Bits 0,1,2,3 verschieben. Alle anderen Bits in der Eingabe und Ausgabe sind Null.

Offensichtlich kann ich das so machen:

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

Aber gibt es eine schnellere (weniger Anweisungen) Weg?

War es hilfreich?

Lösung

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

Oder warten Sie auf den Intel -Haswell -Prozessor und erledigen Sie dies alles in genau einem Anweisungen (Pext).

Aktualisieren

Berücksichtigen clarified constraints und übernehmen 32-bit unsigned values, Der Code kann darauf vereinfacht werden:

c = (c * BITS_7_14_21_28) >> 28;

Andere Tipps

Wenn Sie sich nicht für die Portabilität interessieren und SSE -Anweisungen verwenden können, schauen Sie sich das an die PMOVMSKB Anweisung und sein Compiler intrinsisch. [Ich habe festgestellt, dass Ihre Bitpositionen die wichtigsten (Zeichen-) Bits der 4 Bytes sind, die das 32-Bit-Wort umfassen.

Anstatt einige verschleierte One-Line-Goo zu schreiben, würde ich den folgenden Code schreiben, um eine maximale Portabilität und Wartbarkeit zu erzielen. Ich würde den Optimierer Sorgen machen lassen, ob er der effektivste Code ist oder nicht.

#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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top