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

#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
#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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren