www.mikrocontroller.net

Forum: Compiler & IDEs SWAP in GCC


Autor: ein verzweifelter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es in GCC auch den SWAP Befehl analog zu Assembler
der das untere mit dem oberen Nibbel bei einem Byte vertauscht?

Danke schonmal

Autor: dins (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hättest du gesucht, hättest du das gefunden
uint8_t swapbyte
swapbyte = (swapbyte << 4) && (swapbyte >> 4);
vorher ggf. nach unsigned casten

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oups!
natürlich:
swapbyte = (swapbyte << 4) & (swapbyte >> 4);
sorry

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Geht mit inline Assembler:

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

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:
static inline unsigned char swap (unsigned char x)
{
    if (__builtin_constant_p(x))
        x = (x << 4) | (x >> 4);
    else
        asm volatile ("swap %0" : "=r" (x) : "0" (x));

    return x;
}

__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.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg

"oups!
natürlich:

swapbyte = (swapbyte << 4) & (swapbyte >> 4);

sorry"

Sollte da nicht ein | anstatt des & stehen?!

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Doch, sollte es.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Walter (Gast):
autsch,
ja natürlich!

Autor: ein nicht mehr verzweifelter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dankfür die schnelle Hilfe.

Habe wieder was gelernt. Klasse Forum.

Bis dann 73 & 55





Autor: Malte __ (malte) Benutzerseite
Datum:

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

mit einem Typecast
a = ((u08)(a<<4)) | ((u08)(a>>4));
sieht es nur geringfügig besser aus:
  rcall rs232_get_nextbyte
  rcall hextobyte
  mov r17,r24
  .stabn 68,0,64,.LM25-rs232_thread
.LM25:
  swap r24
  andi r24,0xf0
  swap r17
  andi r17,0x0f
  or r17,r24
  .stabn 68,0,65,.LM26-rs232_thread
.LM26:
  rcall rs232_get_nextbyte
  rcall hextobyte

Der GCC Compiler ist: 3.4.3

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besser als das zweite wird's wohl im Moment nicht.  Es müsste jemand,
der hinreichend viel RTL versteht, sich mal hinsetzen und gucken,
wie man es erreicht, dass er die überflüssigen 4 Befehle einfach
weglässt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.