Hi. Eine AES-Funktion, die ich einsetze, nutzt .balign 256, um Segmente im Flash anzuordnen. Das ist ja auch von Vorteil, wenn man einmal mit ldi ZH nur den High-Pointer einladen muss und dann nur noch ZL ändern muss, bevor man dann mit lpm das Byte einlädt. Und das passiert sehr oft im Loop, deshalb ist diese Optimierung durchaus legitim. Nun ist mir aufgefallen, dass diese Funktion mit -mrelax nicht mehr funktioniert. Im Code wird via .balign 256 der Block angeordnet. Dies ist auch so im Binary richtig platziert. Steht so im .lss-File. Allerdings wird jetzt der Pointer nicht mehr richtig eingeladen. Das (Pseudocode) ldi Z,0x3000 wurde zu ldi Z,0x297F. Kann mir da jemand helfen?
Dirty Assembler Hacks würde ich nicht mit C vermanschen, sondern in ein *.S auslagern.
Jan schrieb: > Eine AES-Funktion, die ich einsetze, nutzt .balign 256, um Segmente im > Flash anzuordnen. Das ist ja auch von Vorteil, wenn man einmal mit ldi > ZH nur den High-Pointer einladen muss und dann nur noch ZL ändern muss, > bevor man dann mit lpm das Byte einlädt. Mikro-Optimierung? Hast du mal gemessen, ob das überhaupt Einfluß auf die Laufzeit des Codes hat? > Nun ist mir aufgefallen, dass diese Funktion mit -mrelax nicht mehr > funktioniert. Das ist auch unklar. Hier beschreibst du den generierten Code: > Im Code wird via .balign 256 der Block angeordnet. Dies ist auch so im > Binary richtig platziert. Steht so im .lss-File. Allerdings wird jetzt > der Pointer nicht mehr richtig eingeladen. Das (Pseudocode) ldi Z,0x3000 > wurde zu ldi Z,0x297F. Aber du sagst nicht, ob der Code noch das richtige tut. Ist das nicht eigentlich das entscheidende? Wenn du gültigen C-Code hast, der ohne -mrelax das korrekte Verhalten, mit -mrelax jedoch inkorrektes Verhalten erzeugt, dann hast du einen Bug in der AVR Toolchain gefunden. Reporte ihn. Aber aus deinem Post werde ich nicht schlau. Und die Dokumentation von avr-gcc [1] zu -mrelax läßt den Zusammenhang mit dem gesagten zumindest unwahrscheinlich erscheinen. [1] https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
Axel S. schrieb: > Jan schrieb: > >> Eine AES-Funktion, die ich einsetze, nutzt .balign 256, um Segmente im >> Flash anzuordnen. Das ist ja auch von Vorteil, wenn man einmal mit ldi >> ZH nur den High-Pointer einladen muss und dann nur noch ZL ändern muss, >> bevor man dann mit lpm das Byte einlädt. > > Mikro-Optimierung? Hast du mal gemessen, ob das überhaupt Einfluß auf > die Laufzeit des Codes hat? Ja, macht gut 30% aus. Es handelt sich um diese Funktion: http://point-at-infinity.org/avraes/rijndaelfurious.asm.html >> Nun ist mir aufgefallen, dass diese Funktion mit -mrelax nicht mehr >> funktioniert. > > Das ist auch unklar. Hier beschreibst du den generierten Code: > >> Im Code wird via .balign 256 der Block angeordnet. Dies ist auch so im >> Binary richtig platziert. Steht so im .lss-File. Allerdings wird jetzt >> der Pointer nicht mehr richtig eingeladen. Das (Pseudocode) ldi Z,0x3000 >> wurde zu ldi Z,0x297F. > > Aber du sagst nicht, ob der Code noch das richtige tut. Ist das nicht > eigentlich das entscheidende? Der Code tut nur das richtige, wenn man -mrelax weglässt. Sobald man es aktiviert, wird im ldi ZH, high(sbox<<1) die falsche Adresse eingeladen. > Wenn du gültigen C-Code hast, der ohne -mrelax das korrekte Verhalten, > mit -mrelax jedoch inkorrektes Verhalten erzeugt, dann hast du einen Bug > in der AVR Toolchain gefunden. Reporte ihn. Wo? Habe sowas noch nie gemacht. Wird die avr toolchain überhaupt noch gepflegt? > Aber aus deinem Post werde ich nicht schlau. Und die Dokumentation von > avr-gcc [1] zu -mrelax läßt den Zusammenhang mit dem gesagten zumindest > unwahrscheinlich erscheinen. > > [1] https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html Ich liefere gerne Infos nach.
-mrelax veranlasst den Linker dazu "CALL n \ RET" durch "JMP n" ersetzt. Dabei reduziert er natürlich die Code-Größe und damit auch die Position von "hand-alignden" Adressen. Die Tabelle müßte in einem eigenen Segment stehen, daß Attribut "Alignment 256" hat. Dann würde der Linker das auch entsprechend ausrichten. Wahrscheinlich muß man das über ein passendes Linkerscript machen.
Gcc schrieb: > -mrelax veranlasst den Linker dazu "CALL n \ RET" durch "JMP n" > ersetzt. Dabei reduziert er natürlich die Code-Größe und damit auch die > Position von "hand-alignden" Adressen. Die Tabelle müßte in einem > eigenen Segment stehen, daß Attribut "Alignment 256" hat. Dann würde der > Linker das auch entsprechend ausrichten. Wahrscheinlich muß man das über > ein passendes Linkerscript machen. Ja, wenn es konsistent wäre, wäre das auch nachvollziehbar. Aber im .lss File sieht man, dass die Matrix weiterhin korrekt aligned wurde. Nur der ldi zeigt auf die optimierte (also falsche, da zu niedrige) Adresse.
Wie wäre es mit einem minimalen, compilierbaren Beispiel, das den Fehler reproduziert?
mh schrieb: > Wie wäre es mit einem minimalen, compilierbaren Beispiel, das den Fehler > reproduziert? Fände ich auch sinnvoll. Doku:
1 | -mrelax |
2 | Try to replace "CALL" resp. "JMP" instruction by the shorter |
3 | "RCALL" resp. "RJMP" instruction if applicable. Setting -mrelax |
4 | just adds the --mlink-relax option to the assembler's command line |
5 | and the --relax option to the linker's command line. |
6 | |
7 | Jump relaxing is performed by the linker because jump offsets are |
8 | not known before code is located. Therefore, the assembler code |
9 | generated by the compiler is the same, but the instructions in the |
10 | executable may differ from instructions in the assembler code. |
11 | |
12 | Relaxing must be turned on if linker stubs are needed, see the |
13 | section on "EIND" and linker stubs below. |
Ich denke, letzteres (linker stubs für AVRs > 128 KiB) war die wesentliche Motivation überhaupt für die Option.
Jan schrieb: >> Aber du sagst nicht, ob der Code noch das richtige tut. Ist das nicht >> eigentlich das entscheidende? > > Der Code tut nur das richtige, wenn man -mrelax weglässt. Sobald man es > aktiviert, wird im ldi ZH, high(sbox<<1) die falsche Adresse eingeladen. Das ist keine Antwort auf die Frage. Deswegen nochmal: "Tut der erzeugte Code, was er soll?" Sprich chiffriert und dechiffriert er ordungsgemäß? Wenn ja, dann ist die Toolchain nicht "buggy". Die Geschwindigkeit, mit der das Compilat läuft ist nicht entscheidend für Korrektheit. Natürlich kann es sein, das für dich die Geschwindigkeit auch wichtig ist (nach der Korrektheit natürlich). Aber dann muß ich erstmal die Frage stellen: warum -mrelax? Die Option nutzt nur RCALL/RJMP statt CALL/JMP, spart also gerade mal einen Cycle (und ein Byte) pro Funktionsaufruf. Der Riesen-Burner wird das also nicht sein. Zumal der Compiler, wenn man mit -O2 compiliert, Funktionen eher inlinen wird als sie aufzurufen.
Axel S. schrieb: > "Tut der erzeugte Code, was er soll?" > > Sprich chiffriert und dechiffriert er ordungsgemäß? Die Antwort sollte eigentlich selbstverständlich sein. Nein, tut er nicht. Was meinst du, wie ich sonst hätte dieses Problem mitbekommen sollen? Also nochmal deutlich: Mit -mrelax kommt nur noch Datenmüll raus, schalte ich -mrelax ab, funktioniert es.
Axel S. schrieb: > warum -mrelax? Weil ich ausschliesslich in Assembler programmiere und bei grossen Projekten switche ich dann alles auf call/jmp. Da soll der Compiler dann bitte selbst optimieren. Die Codegrösse (mit oder ohne mrelax) unterscheidet sich dabei gerne mal um 500 Bytes. Ich würde schon sagen, dass ich das gerne hätte, wenn es schonmal da ist. Bei den 8-Bittern sind 500 Bytes ja schon noch erwähnenswert.
Folgender Code reproduziert das Verhalten:
1 | .rept 300 |
2 | call test |
3 | .endr |
4 | |
5 | clr ZL |
6 | ldi ZH,hi8(matrix) |
7 | 1:rjmp 1b |
8 | |
9 | test: |
10 | ret |
11 | |
12 | .balign 256 |
13 | matrix: |
14 | .byte 1,2,3,4,5 |
.lss Ausschnitt:
1 | 250: 06 d0 rcall .+12 ; 0x25e <test> |
2 | 252: 05 d0 rcall .+10 ; 0x25e <test> |
3 | 254: 04 d0 rcall .+8 ; 0x25e <test> |
4 | 256: 03 d0 rcall .+6 ; 0x25e <test> |
5 | 258: ee 27 eor r30, r30 |
6 | 25a: f2 e0 ldi r31, 0x02 ; 2 |
7 | 25c: ff cf rjmp .-2 ; 0x25c <const_1s_max+0x1dd> |
8 | |
9 | 0000025e <test>: |
10 | 25e: 08 95 ret |
11 | ... |
12 | |
13 | 00000300 <matrix>: |
14 | 300: 01 02 muls r16, r17 |
15 | 302: 03 04 cpc r0, r3 |
16 | 304: 05 00 .word 0x0005 ; ???? |
Wie man sieht, lädt er 0x02 ein, richtig wäre aber 0x03. Kompiliert via: avr-gcc main.S -o main.elf -Wall -Wextra -std=gnu99 -mmcu=atxmega384c3 -nostartfiles -mrelax -Wl,--no-stubs -Wa,--no-pad-sections avr-objdump -DSg main.elf > main.lss
Falls jemand wissen will, was der Compiler in ZL einladen würde:
1 | 258: e8 ea ldi r30, 0xA8 ; 168 |
2 | 25a: f2 e0 ldi r31, 0x02 ; 2 |
Gut, dann hast du zumindest einen Testcase, damit kannst du bei den GNU Binutils einen Bugreport aufmachen. Den ganzen Zirkus -Wall -Wextra -std=gnu99 kannst du gern weglassen, wenn du eh keinen C-Code compilierst. Der interessiert nur den eigentlichen Compiler.
Jan schrieb: > Bei den 8-Bittern > sind 500 Bytes ja schon noch erwähnenswert. Nö. Call bedeutet, Du nimmst mindestens einen Mega16, d.h. die Einsparung ist bestenfalls nur 3%.
Peter D. schrieb: > Jan schrieb: >> Bei den 8-Bittern >> sind 500 Bytes ja schon noch erwähnenswert. > > Nö. > Call bedeutet, Du nimmst mindestens einen Mega16, d.h. die Einsparung > ist bestenfalls nur 3%. Und 3% findest du nicht erwähnenswert? Wow... Nope. Kann ich nicht nachvollziehen.
Jörg W. schrieb: > Gut, dann hast du zumindest einen Testcase, damit kannst du bei den GNU > Binutils einen Bugreport aufmachen. Wie gesagt, habe sowas noch nie gemacht. Wohin gehe ich da genau?
Jan schrieb: > Jörg W. schrieb: >> Gut, dann hast du zumindest einen Testcase, damit kannst du bei den GNU >> Binutils einen Bugreport aufmachen. > > Wie gesagt, habe sowas noch nie gemacht. Wohin gehe ich da genau? Mit nochmaligem drüber Nachdenken, vielleicht doch besser beim Compiler selbst: https://gcc.gnu.org/bugzilla/ statt bei den Binutils: https://www.sourceware.org/bugzilla/ Bin mir gerade nicht 100%ig sicher, wer genau was bei -mrelax macht. Jan schrieb: > War offensichtlich das falsche Forum für sowas. Na, du bist gut. Du brauchst einen Tag für dein Beispiel, und dann soll jeder hier springen und dir in 2 Stunden eine Antwort geliefert haben?
Jörg W. schrieb: > Mit nochmaligem drüber Nachdenken, vielleicht doch besser beim Compiler > selbst: > > https://gcc.gnu.org/bugzilla/ > > statt bei den Binutils: > > https://www.sourceware.org/bugzilla/ > > Bin mir gerade nicht 100%ig sicher, wer genau was bei -mrelax macht. Ich habe es erst anscheinend irrtümlich bei gcc eingereicht: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103673 Dort wurde er geschlossen. Eine Anmeldung bei binutils wurde geblockt. Anscheinend nehmen die grade einfach keine Anmeldungen an. Das wird mir jetzt auch alles zu viel. Ich persönlich habe schon seit gestern einen work-around zur Laufzeit, aber ich dachte, ich reiche den Bug mal ein, falls noch jemand drüber stoplert. Den zu finden alleine hat mich 2 Stunden gekostet.
Jörg W. schrieb: > Jan schrieb: >> War offensichtlich das falsche Forum für sowas. > > Na, du bist gut. Du brauchst einen Tag für dein Beispiel, und dann soll > jeder hier springen und dir in 2 Stunden eine Antwort geliefert haben? Es kam generell seit Eröffnung eher wenig Feedback. War keine Kritik, eher ne Feststellung.
Jan schrieb: > Eine Anmeldung bei binutils wurde geblockt. Gab's eine Begründung? Ansonsten kann ich das da für dich einreichen, aber ich brauche dazu deine Binutils-Version ("avr-ld -V"). Jan schrieb: > Es kam generell seit Eröffnung eher wenig Feedback. Ist ja auch ein reichlich spezieller Anwendungsfall. Wie ich schon schrieb, der wesentliche Grund, warum die Linker relaxations seinerzeit (durch Björn Haase, wenn ich mich recht entsinne) vorangetrieben worden sind für den AVR waren die jump trampolines / linker stubs für AVRs mit mehr als 128 KiB Flash. Alles jenseits dessen ist sicher eher sehr wenig getestetes Gelände. Kommt noch hinzu, die meisten, die einen AVR (ausgiebiger) in Assembler programmieren, werden das vermutlich mit Atmel/Microchips eigenem Assembler im Atmel/Microchip Studio tun. Der hat gleich gar keinen Linker. :-)
Jörg W. schrieb: > Mit nochmaligem drüber Nachdenken, vielleicht doch besser beim Compiler > selbst: > statt bei den Binutils: > Bin mir gerade nicht 100%ig sicher, wer genau was bei -mrelax macht. Wenn ich das richtig überblicke, dann macht auch der Assembler eher wenig dafür. Eigentlich ist das beim Linker angesiedelt, denn der macht ja die Relokation (und bei -relax noch ein paar Opcode-Ersetzungen zusätzlich). Andererseits ist Code (bzw. hier Daten) mit festem Placement (im Original) oder doch zumindest ungewöhnlichem Alignment (der Code des TE) in einer extra Flash-Sektion besser aufgehoben. Beim Mixen von Assembler und C-Code stößt man halt schneller an die Grenzen der Toolchain. Besonders, wenn es um Sachen geht, die über alle Phasen der Compilierung gehen. Für -flto erwarte ich auch spannende Effekte, wenn Assembler mit an Bord ist.
:
Bearbeitet durch User
Axel S. schrieb: > Für -flto erwarte ich auch spannende Effekte, wenn Assembler mit an Bord > ist. Ist die Frage, ob das dann überhaupt aktiviert wird. So wie ich das verstanden habe, wird da ja der Compiler nochmal angeworfen.
Jörg W. schrieb: > Jan schrieb: >> Eine Anmeldung bei binutils wurde geblockt. > > Gab's eine Begründung? Zitat, nach Eingabe der verlangten e-mail Adresse: "User account creation has been restricted. Contact your administrator or the maintainer (overseers@sourceware.org) for information about creating an account." > Ansonsten kann ich das da für dich einreichen, aber ich brauche dazu > deine Binutils-Version ("avr-ld -V"). Das wäre nett. Ich kenne mich mit der Toolchain gar nicht aus. Ich nutze nur den gas. Aber da ich das ja mit avr-gcc aufrufe, dachte ich halt, es gehört dazu... Naja ist alles ziermlich gross da.
1 | # avr-ld -V |
2 | GNU ld (GNU Binutils) 2.37 |
3 | Supported emulations: |
4 | avr2 |
5 | avr1 |
6 | avr25 |
7 | avr3 |
8 | avr31 |
9 | avr35 |
10 | avr4 |
11 | avr5 |
12 | avr51 |
13 | avr6 |
14 | avrxmega1 |
15 | avrxmega2 |
16 | avrxmega3 |
17 | avrxmega4 |
18 | avrxmega5 |
19 | avrxmega6 |
20 | avrxmega7 |
21 | avrtiny |
Plattform: FreeBSD 13.
@Jörg: Wenn du der Meinung bist, dass das Problem doch im gcc liegen könnte, könntest du ja hier mal ein deinen Kommentar hinzufügen. Der Bug ist jetzt halt "RESOLVED MOVED". Und ich kann da wirklich nicht mitdiskutieren. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103673
https://www.sourceware.org/bugzilla/show_bug.cgi?id=28686 Beim Eingeben tauchte Bug 20545 auf, der meiner Meinung nach etwas Ähnliches beschreibt. Da der aber als repariert markiert ist, habe ich einen neuen aufgemacht statt den alten wiederzubeleben. Deine Binutils-Version scheint ja recht aktuell zu sein, und damit ausreichend, dass Bug 20545 darin repariert ist. ps: Achso, wenn du mir deine Mailadresse zusendest (meine wirst du herausfinden können ;-), dann trage ich dich dort auf die Cc-Liste ein. pps: Ich habe mal den recht populären (u.a. durch Arduino) ATmega328 als Beispiel eingegeben statt deines eher exotischen Xmegas. Der Fehler tritt dafür genauso auf.
:
Bearbeitet durch Moderator
Jan schrieb: > Und 3% findest du nicht erwähnenswert? Wow... Nope. Kann ich nicht > nachvollziehen. Bei Deinem ATxmega384C3 sind es nur noch winzige 0,1%.
Jan schrieb: > Ja, macht gut 30% aus. Es wäre mal interessant, ob der Anwender die 30% überhaupt bemerken würde. Bei allen meinen Programmen würde der Benutzer nicht merken, wenn ich einen um 30% langsameren Quarz einsetze.
Jörg W. schrieb: > https://www.sourceware.org/bugzilla/show_bug.cgi?id=28686 Danke. Behalte ich im Auge. > ps: Achso, wenn du mir deine Mailadresse zusendest (meine wirst du > herausfinden können ;-), dann trage ich dich dort auf die Cc-Liste ein. Ja, steht ja alles auf sax.de ;) Man sieht, dass die Seite noch aus jungen Internetjahren stammt, wo die Leute noch nett zueinander waren. Aber du brauchst mich da nicht adden, ich habe den Bug auf der Watchlist und bekomme das mit, wenn sich da was tut. Die Aktivitäten dort scheinen aber generell eher zu ruhen. So ein bissl wie bei avrdude ;) Danke für deine Mithilfe.
Das ging ja schnell. Nick Clifton <nickc at redhat dot com> changed: What |Removed |Added ------------------------------------------------------------------------ ---- Resolution|--- |FIXED Status|ASSIGNED |RESOLVED --- Comment #3 from Nick Clifton <nickc at redhat dot com> --- Patch applied.
Oha.... gut, jetzt bin ich positiv überrascht. Ich weiss zwar nicht, wie lange es dauert, bis die gefixte Version es letztendlich in mein FreeBSD 13 schafft, aber immerhin fixed. Aber nagut, sowas ist ja auch einfacher zu fixen als ein double rjmp Hardware-bug in einem xmega E, der es damals bei Microchip nichtmal durch den 1st Level Support geschafft hat.
Jan schrieb: > Aber nagut, sowas ist ja auch einfacher zu fixen als ein double rjmp > Hardware-bug in einem xmega E, der es damals bei Microchip nichtmal > durch den 1st Level Support geschafft hat. Bei sowas musst du beim Firstlevel-Support hartnäckig bleiben. Sowie diese Leute zu der Überzeugung gekommen sind, dass es wirklich Hardware ist, dann können sie das ja an die Entwickler weiterreichen und der Fall ist für sie erledigt. Diese Leute werden mehr oder weniger nach "Durchsatz" evaluiert, und was sie folglich nicht an der Backe haben wollen, sind Bugs, die auf ihrer Liste ewig als offen herum lungern. Bezüglich FreeBSD: dafür braucht's natürlich erstmal einen binutils-Release. Aber bei FreeBSD hast du es einfach: installier dir den Ports-Tree, lege den Diff aus dem genannten commit in devel/binutils/files/bug28686.patch ab und bau dir die avr-binutils aus dem Port selbst.
Jörg W. schrieb: > Aber bei FreeBSD hast du es einfach: installier dir > den Ports-Tree, lege den Diff aus dem genannten commit in > devel/binutils/files/bug28686.patch ab und bau dir die avr-binutils aus > dem Port selbst. Danke für den Input. Das probiere ich dann mal aus. Derzeit läuft ein Offset-Hotfix beim Init auf dem µC. Ich dachte nicht, dass der Bug so schnell gefixt wird.
Jörg W. schrieb: > Bei sowas musst du beim Firstlevel-Support hartnäckig bleiben. Sowie > diese Leute zu der Überzeugung gekommen sind, dass es wirklich Hardware > ist, dann können sie das ja an die Entwickler weiterreichen und der Fall > ist für sie erledigt. Diese Leute werden mehr oder weniger nach > "Durchsatz" evaluiert, und was sie folglich nicht an der Backe haben > wollen, sind Bugs, die auf ihrer Liste ewig als offen herum lungern. Ja, mag sein, aber als Hobbybastler wird man nicht bezahlt. Wenn man angestellter Entwickler ist und der Chef sagt "Meld mal den Bug", dann investiert man halt die 20 Stunden dafür. So funktioniert ja Arbeit. Und für mich ist es da wesentlich schneller, das Problem einfach in meine Errata zu notieren. Ist vielleicht ein wenig egoistisch, aber deshalb habe ich den Bug ja wenigstens hier mal gemeldet, wenn auch vielleicht der Nickname etwas provokant gewählt war und es deshalb länger als nötig gedauert hat, bis hier die wenigen Leute, die wirklich was auf dem Kasten haben. die Sache ernst genommen haben. Das Thema wurde übrigens (leider, aber ehrlich gesagt wie erwartet) ohne Ergebnis geschlossen: Beitrag "XMEGA Hardware-Bug (Kritisch)"
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.