Forum: Mikrocontroller und Digitale Elektronik Swap Befehl für Byte bei Atmega 32


von Bernd H. (bernd79)


Lesenswert?

AVR Studio, Atmega32

Hallo,

Gibt es einen Swap-Befehl, um eingelesene high und low Bits zutauschen 
und wie sieht der aus ?

Also mache

0101 1100  (0x5C)

zu

1100 0101 (0xC5)

von Εrnst B. (ernst)


Lesenswert?

mit __builtin_avr_insert_bits könnte das (und noch viel mehr) gehen, 
aber ob's schneller ist als per Hand maskieren und schieben?

oder meintest du in ASM?

von Bernd H. (bernd79)


Lesenswert?

Εrnst B✶ schrieb:
> mit __builtin_avr_insert_bits könnte das (und noch viel mehr) gehen,
> aber ob's schneller ist als per Hand maskieren und schieben?
>
> oder meintest du in ASM?

__builtin_avr_insert_bits  sagt mir nichts!

Per Hand wäre es möglich. Dachte aber es gibt einen Befehl dafür in C

von Clemens M. (panko)


Lesenswert?

http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc#swap_Nibbles

1
static inline unsigned char swap (unsigned char x)
2
{
3
    asm volatile ("swap %0" : "=r" (x) : "0" (x));
4
    return x;
5
}


Meinst du so? Einziger Nachteil (vielleicht): Hilfsfunktion musst du 
u.U. auf anderen Prozessor anpassen. Falls das kein low level Code ist - 
wobei ja dann eher swappen unwichtiger würde.

von Stefan N. (stefan_n)


Lesenswert?

was spricht gegen:
1
x = (x << 4) | (x >> 4)

Ein halbwegs vernünftiger compiler sollte dann ein swp draus machen.

von Peter II (Gast)


Lesenswert?

Stefan Noack schrieb:
> Ein halbwegs vernünftiger compiler sollte dann ein swp draus machen.

daruf würde ich nicht wetten.

schon ein
x >> 4

ist auf einem atmel langsam, weil es in 4 schritten gemacht werden muss.

von test (Gast)


Lesenswert?

Clemens M. schrieb:
> http://www.rn-wissen.de/index.php/Inline-Assembler...
>
> static inline unsigned char swap (unsigned char x)
> {
>     asm volatile ("swap %0" : "=r" (x) : "0" (x));
>     return x;
> }
>
>
> Meinst du so? Einziger Nachteil (vielleicht): Hilfsfunktion musst du
> u.U. auf anderen Prozessor anpassen. Falls das kein low level Code ist -
> wobei ja dann eher swappen unwichtiger würde.

Das gibts schon als intrinsic function im Header: avr/builtin.h
1
extern unsigned char __builtin_avr_swap(unsigned char __b);

Ist aber natürlich auch nicht portabel.

von eProfi (Gast)


Lesenswert?

schon ein
x >> 4

ist auf einem atmel langsam, weil es in 4 schritten gemacht werden muss.


und was spricht dagegen (zumindest bei unsigned), das mit swap und and 
(0f) zu machen?

von Stefan N. (stefan_n)


Lesenswert?

Peter II schrieb:
> Stefan Noack schrieb:
>> Ein halbwegs vernünftiger compiler sollte dann ein swp draus machen.
>
> daruf würde ich nicht wetten.
>
> schon ein
> x >> 4
>
> ist auf einem atmel langsam, weil es in 4 schritten gemacht werden muss.

http://sdcc.svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/src/avr/gen.c?revision=8097&view=markup 
in Zeile 3116:
1
                if (shCount >= 4) {
2
                          if (AOP_ISHIGHREG(AOP(result),0)) {
3
                                  emitcode ("swap", "%s", aopGet (AOP (result), 0));
4
                                  emitcode ("andi", "%s,0xf0");
5
                          } else {
6
                                  emitcode ("ldi","r24,0xf0");
7
                                  emitcode ("swap", "%s", aopGet (AOP (result), 0));
8
                                  emitcode ("and", "%s,r24");
9
                          }
10
                          shCount -= 4;
11
                  }

Ich wette stark darauf, zumindest für diesen compiler, beim avr-gcc kann 
man ja auch mal gucken ;-)

von Stefan N. (stefan_n)


Lesenswert?

eProfi schrieb:
> und was spricht dagegen (zumindest bei unsigned), das mit swap und and
> (0f) zu machen?

dass der compiler einem die arbeit normalerweise abnimmt, das so zu 
schreiben? (siehe oben) ansonsten kann man gleich in assembler schreiben 
(was ich übrigens durchaus befürworte)...

von Oliver J. (skriptkiddy)


Lesenswert?

Peter II schrieb:
> schon ein
> x >> 4
>
> ist auf einem atmel langsam, weil es in 4 schritten gemacht werden muss.

Der avr-gcc erledigt das aber mit swap und andi und nicht über 
Schiebebefehle oder add. Also braucht das nur 2 Zyklen.
(Betrachtung ohne Speicherzugriffe)


Mit -Os erledigt der avr-gcc die swap-Geschichte in C zuverlässig:
1
uint8_t c;
2
3
void main(void)
4
{
5
  c = (c<<4) | (c>>4);
6
  7c:  80 91 60 00   lds  r24, 0x0060
7
  80:  82 95         swap  r24
8
  82:  80 93 60 00   sts  0x0060, r24
9
}
10
  86:  08 95         ret

Gruß Oliver

von Stefan N. (stefan_n)


Lesenswert?

Oliver J. schrieb:

> Mit -Os erledigt der avr-gcc die swap-Geschichte in C zuverlässig:
>
1
> uint8_t c;
2
> 
3
> void main(void)
4
> {
5
>   c = (c<<4) | (c>>4);
6
>   7c:  80 91 60 00   lds  r24, 0x0060
7
>   80:  82 95         swap  r24
8
>   82:  80 93 60 00   sts  0x0060, r24
9
> }
10
>   86:  08 95         ret
11
> 
12
>
>
> Gruß Oliver

Sehr schön, damit hätten wir das eindeutig geklärt (und die Wette hätte 
ich gewonnen ^^)...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.