AVR_GCC: "lpm __temp_reg__, Z" wird durch "lpm __temp_reg__, Z+" ersetzt

OP #3381267
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
OP #3381334
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

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.