hmmm...
was heisst denn elegent?
Elegant und korrekt als Inline Asm:
Code:
static inline unsigned char
swap_2_4_asm (unsigned char a)
{
unsigned char b;
asm volatile ("bst %[a],2" "\n\t"
"bld %[b],4" "\n\t"
"bst %[a],4" "\n\t"
"bld %[b],2"
: [b] "=&r" (b) : [a] "r" (a), "0" (a));
return b;
}
uint8_t foo_asm (uint8_t b)
{
return swap_2_4_asm (b);
}
Bei Inline-Assembler ist unbedingt darauf zu achten, daß der Effekt auf die Maschine dem Compiler korrekt mitgeteilt wird!
Das Ergebnis nur an einem Beispiel testen genügt nicht. Wenn sich das Programm ändert und der Compiler etwas anderen Code erzeugt, fliegen einem die obigen asm-Schnippsel um die Ohren (bzw. der AVR macht es).
In C kann man es elegant über Bitfelder lösen, was leider von GCC momentan noch -- gelinde gesagt -- suboptimal übersetzt wird:
Code:
typedef union
{
struct
{
unsigned b0 :1;
unsigned b1 :1;
unsigned b2 :1;
unsigned b3 :1;
unsigned b4 :1;
unsigned b5 :1;
unsigned b6 :1;
unsigned b7 :1;
};
unsigned char val;
} bit8_t;
static inline unsigned char
swap_2_4_c (unsigned char a)
{
bit8_t xa = {.val = a};
bit8_t xb = {.val = a};
xb.b4 = xa.b2;
xb.b2 = xa.b4;
return xb.val;
}
uint8_t foo_c (uint8_t b)
{
return swap_2_4_c (b);
}
Lesezeichen