Hab mich gewundert, warum die ISR so lahm ist (bin bissi knapp bei
Resourcen). Im List kam dann raus:
1
128: 1f 92 push r1
2
12a: 0f 92 push r0
3
12c: 0f b6 in r0, 0x3f ; 63
4
12e: 0f 92 push r0
5
130: 11 24 eor r1, r1
6
132: 8f 93 push r24
7
/* Turn off display */
8
PORTD = 255;
9
134: 8f ef ldi r24, 0xFF ; 255
10
136: 82 bb out 0x12, r24 ; 18
11
138: 8f 91 pop r24
12
13a: 0f 90 pop r0
13
13c: 0f be out 0x3f, r0 ; 63
14
13e: 0f 90 pop r0
15
140: 1f 90 pop r1
16
142: 18 95 reti
Und da dacht ich mir, das kann doch wohl nicht wahr sein?! Übersetzt
wurde mit -Os.
Der Schnipsel hier hätte doch genau dieselben Wirkungen und
Nebenwirkungen:
1
push r16
2
ldi r16, 255
3
out 0x12, r16
4
pop r16
Vorallen Dingen, was zum Geier hat "eor r1, r1" oben zu suchen?
Kann man dem GCC das irgendwie verständlich machen? Ich mein, dass der
mir ab drei Variablen sowieso fast das ganze Registerfile pusht, daran
hab ich mich ja gewöhnt, aber sowas?
Vielen Dank und viele Grüße,
Sven
Hi
Wenn die ISR wirklich so extrem zeitkritisch und simpel ist implementier
sie doch in einer .s Datei in Assembler und link sie deinem Projekt
dazu.
Matthias
Hi
das muss er halt machen da er über den Code in der ISR recht wenig weiß
bzw. noch niemand den Compiler in diese Richtung optimiert hat.
eor r1, r1 setzt dabei das Zero-Register auf 0 da der Compiler ja nicht
wissen kann ob eben jenes irgendwo mal nicht 0 war.
Auch der restliche Code hat durchaus seine Bedeutung. Wenn dir das also
zu viel ist -> .s oder Inline-ASM.
Matthias
Ich denke in r0 wird das Status-Register gesichert (keine Ahnung, ob das
stimmt - loisch wärs aber - man müsste mal das Datenblatt ansehen, was
der da reinholt) r1 wird auf 0 gesetzt, weil er das Statusregister als
16-Bit int verwaltet (auch nur Vermutung). Dann nutzt er r24 für das
ldi.
Alles in allem unschön, aber dennoch nachvollziehbar.
Dein Schnipsel hätte halt wesentlich mehr Nebenwirkungen, wie du es
nennst, weil du das Statusregister nicht sicherst. Gefährlich!! ;-)
MFG
@Albi: Joa, soweit warn wir schon, schätze mal, wir ham gleichzeitig
getippselt...:-)
Der Albi wrote:
> Ich denke in r0 wird das Status-Register gesichert (keine Ahnung, ob das> stimmt - loisch wärs aber - man müsste mal das Datenblatt ansehen, was> der da reinholt)
Er benutzt r0 als temporäres Register, um damit das Statusregister aufn
Stack zu pushen, jo.
> r1 wird auf 0 gesetzt, weil er das Statusregister als> 16-Bit int verwaltet (auch nur Vermutung).
Nö; r1 ist per Definition immer als "Nullregister" gedacht. Deshalb
setzt er es auf Null-.
> Dann nutzt er r24 für das ldi.> Alles in allem unschön, aber dennoch nachvollziehbar.
Jubb.
> Dein Schnipsel hätte halt wesentlich mehr Nebenwirkungen, wie du es> nennst, weil du das Statusregister nicht sicherst. Gefährlich!! ;-)
Hätte er nicht. Weder LDI noch OUT noch PUSH noch POP verändern das
Statusregister. Daran habe ich schon gedacht...
Ja, schön und gut. Das "Problem" ist bekannt und wie gesagt hat in der
Hinsicht noch keiner Hand angelegt am AVR-GCC. Sprich: Es gibt einfach
keine Optimierungsroutine an dieser Stelle, die überprüft ob das
Nullregister überhaupt gebraucht wird oder ob das SREG überhaupt
verändert wird.
Und für die 10 (über den Daumen gepeilt) Takte wird sich da so leicht
wahrscheinlich auch niemand für begeistern lassen.
Man sollte auch nicht ausschließen, dass vielleicht irgendwelche Normen
im C-Compilerbau bestimmte Sachen einfach verbieten. Dazu müsste sich
aber einer der Compiler-Freaks hier mal zu Wort melden ;)
PS: Was spricht gegen eine naked-ISR und einem kleinen C-Kommentar an
der Stelle, dass es legitim ist?
Simon K. wrote:
> Sprich: Es gibt einfach keine Optimierungsroutine an dieser Stelle,> die überprüft ob das Nullregister überhaupt gebraucht wird oder ob> das SREG überhaupt verändert wird.
Der Haken ist, dass die Änderungen im avr-gcc weit über "diese Stelle"
hinausgingen.
In r1 steht in avr-gcc immer die 0. Dies geschieht jedoch komplett
implizit, d.h. gcc hat keine Vorstellung davon. Das ist auch der Grund,
warum Instruktionen (insns), welche r1 verändern (zB mul) r1 immer
wieder von Hand herstellen müssen und r1 nicht in der
Register-Allokierung teilnimmt.
Ich wüsst auch garnicht, wie das gcc beizubringen wäre, d.h welches RTL
das ausdrücken könnte. Dazu müsste man nämlich sagen können, dass in
einem bestimmten GPR ein bestimmter Wert vorhanden sein muss. Evrl
könnte man in jedem Prolog ein (set (reg) (const_int 0)) emittieren und
mit (use (reg)) die Verwendung anzeigen. Allerdings führt das an anderen
Stellen zu Problemen, die ohne weiteres nicht zu beheben sind.
Mit SREG sieht's da schon einfacher aus, weil avr-gcc den CC (Condition
Code) implementiert und jede Insn enstprechend attribuiert.
Also los Jungs, wenn ne hausbackene naked-ISR zu viel Arbeit ist, ihr
wisst wo die Quelle ist ... feel free to improve and contribute to
GCC...