Forum: Compiler & IDEs AVR_GCC: "lpm __temp_reg__, Z" wird durch "lpm __temp_reg__, Z+" ersetzt


von Leo B. (luigi)


Lesenswert?

Hey Leute,

1
[background]
2
ich möchte eine look-up-Table im Programmspeicher unterbringen. Nichts
3
besonderes. Jetzt möchte ich aber in einer Schleife mehrere Werte suchen.
4
Da das ganze schnell gehen muss (sind etwas über 4000 Werte und Zeit knapp) 
5
und der Compiler immer recht amüsant movw-Befehle eingefügt hat habe ich 
6
nun probiert den Code mit inline-Assembler etwas zu beschleunigen.
7
[/background]
Dabei habe ich nun aber festgestellt (und darum soll es eigentlich in 
diesem Thread gehen), dass der Compiler aus folgenden Quellcode-Zeilen
1
// äquivalent nur langsamer wegen sporadisch generierter, unnötiger mov-befehle:
2
// b0 = pgm_read_byte( &sBox[ b0 ] );
3
asm
4
(
5
  "ldi  %A[ptr], lo8(%[sBox])  \n\t"
6
  "ldi  %B[ptr], hi8(%[sBox])  \n\t"
7
  "add  %A[ptr], %[b0]         \n\t"
8
  "adc  %B[ptr], __zero_reg__  \n\t"
9
  "lpm %[b0], Z                \n\t"
10
  : [b0] "+r" (b)
11
  , [ptr] "=z" (b)  // b ist an dieser Stelle zwar falsch aber hat
12
                    // auch keine Auswirkung. Was hier korrekt wäre
13
                    // ist mir leider nicht klar.
14
  : [sBox] "i" (sBox)
15
);
folgenden code erzeugt:
1
 158:  e4 e3         ldi  r30, 0x34  ; 52
2
 15a:  f0 e0         ldi  r31, 0x00  ; 0
3
 15c:  e8 0f         add  r30, r24
4
 15e:  f1 1d         adc  r31, r1
5
 160:  84 91         lpm  r24, Z+

Nicht, dass das jetzt in diesem Falle stören würde, aber allgemein macht 
er aus dem "Z" (ohne post-increment) ein "Z+". Das ist mir auch schon an 
Stellen aufgefallen, wo es mich gestört hat und ich dann ein workaround 
finden musste.

Was ich mich nun Frage ist, ob das irgendwie mein Fehler oder ein Fehler 
des Compilers ist?

Danke schonmal fürs lesen
Liebe Grüße
Leo

von (prx) A. K. (prx)


Lesenswert?

84 91 ist LPM R24,Z
Riecht also nach einem Fehler im Disassembler.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Leo B. schrieb:

> Nicht, dass das jetzt in diesem Falle stören würde, aber allgemein macht
> er aus dem "Z" (ohne post-increment) ein "Z+".

Kein Fehler von dem ich je gehört hätte.  Lies mal den Assemblercode im 
mit -save-temps erzeugten s-File.

von (prx) A. K. (prx)


Lesenswert?


von Leo B. (luigi)


Lesenswert?

also im s-File steht noch
1
  ldi  r30, lo8(sBox)  
2
  ldi  r31, hi8(sBox)  
3
  add  r30, r24      
4
  adc  r31, __zero_reg__  
5
  lpm r24, Z

im hex-file an entsprechender Adresse steht dann
1
:1001600084918E2F880F10F43BE18327E4B984B982
2
         ^^^^

das enspricht der binären Folge
1
1000 0100 1001 0001

und im AVR "Instruction Set Nomenclature" steht, dass "LPM" wie folgt 
übersetzt wird:
1
(i)   LPM None, R0 implied PC ← PC + 1
2
(ii)  LPM Rd, Z 0 ≤ d ≤ 31 PC ← PC + 1
3
(iii) LPM Rd, Z+ 0 ≤ d ≤ 31 PC ← PC + 1
4
5
(i)   1001 0101 1100 1000
6
(ii)  1001 000d dddd 0100
7
(iii) 1001 000d dddd 0101

einzig sinnvolle Übersetzung ergibt sich, wenn man zuvor die Bytes 
tauscht. Das hat sicher was mit Big- und Little-Endian zu tun, aber 
damit halte ich mich jetzt mal nicht auf...

Ich vergleiche dann also:
1
     1001 0001 1000 0100
2
(ii) 1001 000d dddd 0100
=> d = 0b11000 = 24 (= r24, passt)
(ii) ist ohne "Post increment". Also scheints wirklich ein Fehler im 
Disassembler zu sein.

Danke
Gruß Leo

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ist aber nicht nur in Debian, sondern auch in "neueren" Versionen von 
WinAVR.

von Leo B. (luigi)


Lesenswert?

A. K. schrieb:
> http://sourceware.org/bugzilla/show_bug.cgi?id=10964

Jo da stehts dann wohl auch. so ähnlich.

Danke nochmal

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.