Forum: Mikrocontroller und Digitale Elektronik Wie kann ich Bitschieberei beschleunigen


von AVR Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

Ich brauche innerhalb meiner Timerinterruptroutine eine Bitschieberei 
wie im Bild gezeigt.
ich habe das so in C programmiert:
1
unsigned short int Bla1;
2
unsigned short int Bla2;
3
unsigned short int Bla3;
4
unsigned short int Bla4;
5
unsigned short int Bla5;
6
unsigned char Blub;
7
8
9
int main(void)
10
{
11
//Hier passiert noch viel anderes,
12
//was jetzt unwichtig ist!
13
14
15
16
17
18
}
19
20
//********************************************
21
22
ISR(TIMER1_OVF_vect)
23
24
{
25
//Hier passiert noch viel anderes,
26
//was jetzt unwichtig ist!
27
28
      Blub = (Bla1 & 0x8000)>>15 
29
          |(Bla2 & 0x8000)>>14
30
          |(Bla3 & 0x8000)>>13
31
          |(Bla4 & 0x8000)>>12      
32
          |(Bla5 & 0x8000)>>11;
33
34
}
Das funktioniert auch, könnte aber schneller sein.
In Pseudo-Assembler würde ich das etwas so schreiben:
1
    CLR   R9
2
    MOV   R10,Highbyte[Bla5]
3
    ROL   R10
4
    ROL   R9
5
    MOV   R10,Highbyte[Bla4]
6
    ROL   R10
7
    ROL   R9
8
    MOV   R10,Highbyte[Bla3]
9
    ROL   R10
10
    ROL   R9
11
    MOV   R10,Highbyte[Bla2]
12
    ROL   R10
13
    ROL   R9
14
    MOV   R10,Highbyte[Bla1]
15
    ROL   R10
16
    ROL   R9
17
    MOV   [Blub],R9
Ich arbeite mit AVR Studio4, GCC und meine CPU ist ein ATtiny25
Was kann ich in C tun um meine Bitschieberei zu beschleunigen?

von Karl H. (kbuchegg)


Lesenswert?

AVR Anfänger schrieb:

> Was kann ich in C tun um meine Bitschieberei zu beschleunigen?

Gar nicht schieben?
1
     Blub = ( ( Bla1 & 0x8000 ) ? 0x10 : 0x00 ) |
2
            ( ( Bla2 & 0x8000 ) ? 0x08 : 0x00 ) |
3
            ( ( Bla3 & 0x8000 ) ? 0x04 : 0x00 ) |
4
            ( ( Bla4 & 0x8000 ) ? 0x02 : 0x00 ) |      
5
            ( ( Bla5 & 0x8000 ) ? 0x01 : 0x00 ) );

von Bernd O. (bitshifter)


Lesenswert?

AVR Anfänger schrieb:
>       Blub = (Bla1 & 0x8000)>>15
>           |(Bla2 & 0x8000)>>14
>           |(Bla3 & 0x8000)>>13
>           |(Bla4 & 0x8000)>>12
>           |(Bla5 & 0x8000)>>11;
> [...]
> Ich arbeite mit AVR Studio4, GCC und meine CPU ist ein ATtiny25
> Was kann ich in C tun um meine Bitschieberei zu beschleunigen?
Mein erster Gedanke:
Du musst doch nicht zwingend schieben, du kannst doch einfach Konstanten 
verodern:

Blub = 0;
if (Bla1 & 0x8000) Blub |= 1;
if (Bla2 & 0x8000) Blub |= 2;
if (Bla3 & 0x8000) Blub |= 4;
   :
   :

Gruß,
Bernd

von spess53 (Gast)


Lesenswert?

Hi

In Assembler braucht man überhaupt nichts schieben. Der Bittransfer geht 
einfacher über das T-Flag im Statusregister mit 'bld' und 'bst'. Braucht 
pro Bit 2 Befehle.

MfG Spess

von AVR Anfänger (Gast)


Lesenswert?

Vielen Dank für die schnellen Antworten.

von (prx) A. K. (prx)


Lesenswert?

Fies ist, dass GCC praktisch alle Versuche, Schiebeoperationen zu 
vermeiden, ziemlich konsequent als solche identifiziert und auf die 
Schiebeoperation zurückführt.

Irgendwann kam wohl mal ein kluger Geist drauf, dass alle Prozessoren 
(die er kannte?) billige Schiebeoperationen besitzen. Billiger 
jedenfalls als Sprünge. Also optimiert man alles was irgendwie geht 
entsprechend um. Und weil das so selbstverständlich ist muss man, anders 
als sonst, dafür auch keinen eigenen Schalter vorsehen.

Und irgendwie fehlt entweder dem AVR backend die richtige Peilung über 
die Kosten von Operationen, oder diese Optimierungsstufe fragt danach 
erst garnicht. Und so werden eben bei AVRs billige set-conditional 
Operationen (über skip conditional) durch sauteure Schiebeschleifen 
ersetzt.

Auch KHBs und Bernds Versionen werden von avr-gcc 4.3.4 entsprechend 
grauenvoll umgearbeitet

Es gab hier mal einen Thread dazu.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:

> Auch KHBs und Bernds Versionen werden von avr-gcc 4.3.4 entsprechend
> grauenvoll umgearbeitet

Ehrlich?
Das ist in der Tat fies!

von Bernd O. (bitshifter)


Lesenswert?

A. K. schrieb:
> Auch KHBs und Bernds Versionen werden von avr-gcc 4.3.4 entsprechend
> grauenvoll umgearbeitet
Hast Du's wirklich ausprobiert oder geraten?

Ich hab's gerade mal durch den avr-gcc-4.3.3 laufen lassen, da sieht 
zumindest meine Version ganz ordentlich aus:

    Blub = 0;

    if (Bla1 & 0x8000) Blub |= 1;
    if (Bla2 & 0x8000) Blub |= 2;
 100:   57 fd           sbrc    r21, 7
 102:   32 60           ori r19, 0x02   ; 2
    if (Bla3 & 0x8000) Blub |= 4;
 104:   77 fd           sbrc    r23, 7
 106:   34 60           ori r19, 0x04   ; 4
    if (Bla4 & 0x8000) Blub |= 8;
 108:   f7 fd           sbrc    r31, 7
 10a:   38 60           ori r19, 0x08   ; 8
    if (Bla5 & 0x8000) Blub |= 16;
 10c:   b7 fd           sbrc    r27, 7
 10e:   30 61           ori r19, 0x10   ; 16

    target = Blub;
 110:   39 83           std Y+1, r19    ; 0x01


Gruß,
Bernd

von (prx) A. K. (prx)


Lesenswert?

Wo ist bla1 abgeblieben?

von (prx) A. K. (prx)


Angehängte Dateien:

Lesenswert?

Bernd O. schrieb:

> Hast Du's wirklich ausprobiert oder geraten?

Anbei. Nicht wörtlich aber sinngemäss. Es wird nicht alles umgearbeitet,
aber stets mindestens eine der Operationen.

von Bernd O. (bitshifter)


Lesenswert?

A. K. schrieb:
> Wo ist bla1 abgeblieben?

Vor meinem Code kam der Schiebe-Code von "AVR-Anfänger", der wohl R19 
schon "vorbehandelt" hat, weshalb für das erste Bit nichts mehr zu tun 
war.

Ich habe jetzt den Schiebe-Code entfernt und es sieht nun folgendermaßen 
aus:

    Blub = 0;

    if (Bla1 & 0x8000) Blub |= 1;
  b2:   8b 2f           mov r24, r27
  b4:   88 1f           adc r24, r24
  b6:   88 27           eor r24, r24
  b8:   88 1f           adc r24, r24
    if (Bla2 & 0x8000) Blub |= 2;
  ba:   57 fd           sbrc    r21, 7
  bc:   82 60           ori r24, 0x02   ; 2
    if (Bla3 & 0x8000) Blub |= 4;
  be:   77 fd           sbrc    r23, 7
  c0:   84 60           ori r24, 0x04   ; 4
    if (Bla4 & 0x8000) Blub |= 8;
  c2:   37 fd           sbrc    r19, 7
  c4:   88 60           ori r24, 0x08   ; 8
    if (Bla5 & 0x8000) Blub |= 16;
  c6:   f7 fd           sbrc    r31, 7
  c8:   80 61           ori r24, 0x10   ; 16

    target = Blub;
  ca:   89 83           std Y+1, r24    ; 0x01

Gruß,
Bernd

von AVR Anfänger (Gast)


Lesenswert?

Danke für die vielen Antworten, ihr gebt euch echt Mühe.
Nur leider habe ich unheimlich viele Variablen in meinem Programm.
Deshalb glaube ich nicht, das der Compiler die alle in Registern anlegen 
wird. Man könnte das dem Compiler vieleicht vorschlagen:
1
register unsigned short int Bla1;
2
register unsigned short int Bla2;
3
register unsigned short int Bla3;
4
register unsigned short int Bla4;
5
register unsigned short int Bla5;

Aber die "register" anweisung ist für den Compiler nicht wirklich 
bindend.
(Glaube ich mal irgendwo gelesen zu haben)

von AVR Anfänger (Gast)


Lesenswert?

ist "adc r24, r24" das selbe wie "rol r24" ?

von (prx) A. K. (prx)


Lesenswert?

Ja.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Un bist du sicher das diese "optimierung" an der richtigen Stelle ist?

von (prx) A. K. (prx)


Lesenswert?

AVR Anfänger schrieb:

> Aber die "register" anweisung ist für den Compiler nicht wirklich
> bindend. (Glaube ich mal irgendwo gelesen zu haben)

Korrekt.

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.