Forum: Compiler & IDEs WinAVR 20070525 Optimierung


von m4444x (Gast)


Lesenswert?

Hallo!

Gibt's beim Upgrade von WinAVR irgendwas zu beachten? Ich hatte bis vor 
kurzem WinAVR 2006 installiert. Jetzt hab ich auf WinAVR 2007 upgedated 
und meinen Webserver neucompiliert. Leider funktioniert nun die 
Checksummenberechnung nicht mehr.
1
WORD checksum( BYTE * buffer, WORD count )
2
{
3
  WORD sum;
4
  asm volatile (
5
    "clr %A0               \n\t"
6
    "clr %B0               \n\t"
7
    
8
    "sbiw %A2, 1           \n\t"
9
    "brcs 2f               \n\t"
10
    
11
    "1:                    \n\t"
12
    
13
    "ld __tmp_reg__, %a1+  \n\t"
14
    "add %A0, __tmp_reg__  \n\t"
15
    "adc %B0, __zero_reg__ \n\t"
16
    "adc %A0, __zero_reg__ \n\t"
17
    
18
    "sbiw %A2, 1           \n\t"
19
    "brcs 2f               \n\t"
20
    
21
    "ld __tmp_reg__, %a1+  \n\t"
22
    "add %B0, __tmp_reg__  \n\t"
23
    "adc %A0, __zero_reg__ \n\t"
24
    "adc %B0, __zero_reg__ \n\t"
25
    
26
    "sbiw %A2, 1           \n\t"
27
    "brcc 1b               \n\t"
28
    
29
    "2:                    \n\t"
30
    : "=r" (sum) : "e" (buffer), "w" (count)
31
  );
32
  return sum;
33
}

Daraus macht der neue WinAVR (mit -Os):
1
    20c0:  fe 01         movw  r30, r28
2
    20c2:  39 96         adiw  r30, 0x09  ; 9
3
    20c4:  8c e0         ldi  r24, 0x0C  ; 12
4
    20c6:  90 e0         ldi  r25, 0x00  ; 0
5
    20c8:  ee 27         eor  r30, r30
6
    20ca:  ff 27         eor  r31, r31
7
    20cc:  01 97         sbiw  r24, 0x01  ; 1
8
    20ce:  60 f0         brcs  .+24       ; 0x20e8 <pushUDP+0xa2>
9
    20d0:  01 90         ld  r0, Z+
10
    20d2:  e0 0d         add  r30, r0
11
    20d4:  f1 1d         adc  r31, r1
12
    20d6:  e1 1d         adc  r30, r1
13
    20d8:  01 97         sbiw  r24, 0x01  ; 1
14
    20da:  30 f0         brcs  .+12       ; 0x20e8 <pushUDP+0xa2>
15
    20dc:  01 90         ld  r0, Z+
16
    20de:  f0 0d         add  r31, r0
17
    20e0:  e1 1d         adc  r30, r1
18
    20e2:  f1 1d         adc  r31, r1
19
    20e4:  01 97         sbiw  r24, 0x01  ; 1
20
    20e6:  a0 f7         brcc  .-24       ; 0x20d0 <pushUDP+0x8a>
21
    20e8:  f8 87         std  Y+8, r31  ; 0x08
22
    20ea:  ef 83         std  Y+7, r30  ; 0x07

Sieht so aus als ob die Funktion in 'inline' umgewandelt wird. Aber 
warum tut er R31:R30 doppelt belegen?!?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

m4444x wrote:

> Sieht so aus als ob die Funktion in 'inline' umgewandelt wird.

Ja.  Der Compiler hat keine Ahnung, dass dein inline asm statement
ziemlich länglich ist.  Für ihn ist es ein einzelnes statement (insn),
und das lohnt es sich allemal zu inlinen.

Du kannst das ggf. mit __attribute__((noinline)) verhindern.

> Aber warum tut er R31:R30 doppelt belegen?!?

Hast du mal ein aufs Minimum zusammengestrichenes Codeschnipsel, damit
man es selbst durch den Compiler schieben kann?

von m4444x (Gast)


Angehängte Dateien:

Lesenswert?

1
int main(void)
2
{
3
  char data[123]
4
  return checksum( data, 123 );
5
}

Das scheint schon zu reichen, um den Fehler zu reproduzieren.

Danke für den Tip mit dem noinline. Aber ich werd' wohl erstmal wieder 
mit dem alten gcc compilieren.

von Andreas K. (a-k)


Lesenswert?

Den Regeln von GCC entsprechend dürfen Input- und Output-Operand im 
gleichen Register landen, sofern das nicht ausdrücklich verboten wurde. 
Das ist also nicht das Problem des Compilers, sondern wie üblich des 
Programmierers, der die Doku nicht genau genug gelesen hat:

"Unless an output operand has the `&' constraint modifier, GCC may 
allocate it in the same register as an unrelated input operand, on the 
assumption the inputs are consumed before the outputs are produced. This 
assumption may be false if the assembler code actually consists of more 
than one instruction. In such a case, use `&' for each output operand 
that may not overlap an input."

von m4444x (Gast)


Lesenswert?

Achso, also doch bloß der gute alte "did you forget the & ?"

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.