SWAP in GCC

Gast #512703
Lesenswert?

Wenns nicht DERMASSEN(!!) schnell gehen muss..... warum nicht einfach in 
C mit einer Hilfsvariablen:

tmpbyte = swapbyte;
swapbyte = <<=4;
tmpbyte >>=4;
swapbyte |= tmpbyte;

Setzt der Compiler normal 1:1 um.

Grüßle
Gast #512774
Lesenswert?

> Geht mit inline Assembler:

Der Code, den man dort sieht:
1
static inline unsigned char swap (unsigned char x)
2
{
3
    asm volatile ("swap %0" : "=r" (x) : "0" (x));
4
    return x;
5
}

kann übrigens noch einen Tick verbessert werden. Inline-Assembler 
verhindert leider ein "constant folding", weshalb diese Berechnung auch 
in den Fällen zur Laufzeit durchgeführt wird, in denen es eigentlich 
nicht nötig wäre. Es gibt bei gcc einen Trick, um auch diese 
Optimierungen zu ermöglichen. Der geht so:
1
static inline unsigned char swap (unsigned char x)
2
{
3
    if (__builtin_constant_p(x))
4
        x = (x << 4) | (x >> 4);
5
    else
6
        asm volatile ("swap %0" : "=r" (x) : "0" (x));
7

8
    return x;
9
}

__builtin_constant_p wird zur Compileeit ausgewertet, wodurch das if() 
auch zur Compilezeit aufgelöst wird. Wenn swap() inline expandiert wird, 
wird ein zur Compilezeit bekannter übergebener Wert als solche erkannt 
und die C-Implementation verwendet, die dann ebenfalls zur Compilezeit 
durchgeführt wird.
Persönliche Seite #519965
Lesenswert?

Bei mir optimiert der Compiler leider
  a = (a<<4) | (a>>4);
überhaupt nicht zu einem SWAP Befehl.
Aus
1
typedef uint8_t u08;
2
static void rs232_receiveconfig(void) {
3
u08 k;
4
u08 a, b;
5
u08 * addr = (u08 *)eep_config;
6
for (k = 0; k < sizeof(eep_config); k++) {
7
  a = hextobyte(rs232_get_nextbyte());
8
  //swap the byte (the lower 4 bits will be zero afterwards)
9
  a = (a<<4) | (a>>4);
10
  b = hextobyte(rs232_get_nextbyte());
11
  eeprom_write_byte(addr+k, a | b);
12
  rs232_put_byte('A');
13
}
14
}
wird ein völlig umständliches
1
  rcall rs232_get_nextbyte
2
  rcall hextobyte
3
  mov r17,r24
4
  .stabn 68,0,64,.LM25-rs232_thread
5
.LM25:
6
  clr r25
7
  ldi r18,4
8
1:  lsl r24
9
  rol r25
10
  dec r18
11
  brne 1b
12
  swap r17
13
  andi r17,0x0f
14
  or r17,r24
15
  .stabn 68,0,65,.LM26-rs232_thread
16
.LM26:
17
  rcall rs232_get_nextbyte
18
  rcall hextobyte

mit einem Typecast
1
a = ((u08)(a<<4)) | ((u08)(a>>4));
sieht es nur geringfügig besser aus:
1
  rcall rs232_get_nextbyte
2
  rcall hextobyte
3
  mov r17,r24
4
  .stabn 68,0,64,.LM25-rs232_thread
5
.LM25:
6
  swap r24
7
  andi r24,0xf0
8
  swap r17
9
  andi r17,0x0f
10
  or r17,r24
11
  .stabn 68,0,65,.LM26-rs232_thread
12
.LM26:
13
  rcall rs232_get_nextbyte
14
  rcall hextobyte

Der GCC Compiler ist: 3.4.3

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren