Datum:
Hallo, in meinem PowerPC (56xx) Programmablauf kommt es nach gewisser Zeit zu einem falschen Programmablauf. Und zwar springt er zu Adresse 0x0. Die Ursache für diesen Sprung ist in diesen Zeilen zu finden:
.. .... lwzx r3,r3,r0 ; schreibe 0 nach r3 se_mtctr r3 ; schreibe r3 nach CTR (Count Register) se_bctr ; branch zu CTR |
Kann mir jemand sagen, was das für einen Sinn haben soll? An Adresse 0x0 steht das Reset Configuration Half Word (RCHW) = 0x015A0000. Da wird er wohl kaum hinspringen wollen. Ich glaube, dass r3 einfach nicht 0 sein darf - aber nur eine Vermutung. Wie die Null zu stande kommt sieht man wie folgt. Hier also der ganze Abschnitt:
; r0 = 0x0003A360
; r1 = 0x40003E2F
se_lhz r0,0x10(r1) ; nach diesem Schritt ist r0 gleich 0
se_cmpli r0,0x8
se_bgt 0x37A1E
e_lis r8,0x40000000
e_add16i r3,r8,0x1CD8
se_slwi r0,0x2
lwzx r3,r3,r0 ; schreibe 0 nach r3
se_mtctr r3 ; schreibe r3 nach CTR (Count Register)
se_bctr ; branch zu CTR
|
Ich verstehe hier nicht, wass der ASM mit se_lhz r0,0x10(r1) macht. Was bedeutet diese Zeile?
Datum:
Hi Udo, wenn ich mich richtig erinnere holt deine Zeile einen Wert aus der Speicherzelle, welche durch R1 plus 0x10 adressiert wird. In deinem Codeschnippsel steht darüber dass r1 = 0x40003E2F ist. Also wird der Wert aus dem RAM geholt. Entweder hast du vergessen eine Initfunktion aufzurufen. Oder es Mangelt an einer Routine zum Kopieren, der vorinitialisierten Variablen. Gruß, TManiac
Datum:
ok, er holt sich den Wert aus 0x40003E2F + 0x10 = 0x40003E3F. Dort steht 0x40 drin. Warum er denkt, es wäre 0, weis ich nicht :-( Ja, es wird aus dem RAM geholt. Warum meinst du, dass es falsch wäre? Deine Antwort klingt zumindest so.
Datum:
Habe nochmal geschaut. An der Stelle steht wirklich 0x00 drin. In dem Bereich liegt der Stack - ist also ein Stack Zugriff. Greift der falsch auf den Stack zu? Ist schon komisch, da es nur ab und zu dieses Verhalten bringt.
Datum:
Weitere Erkenntniss: der code oben ist der Assembler Code einer switch-case Anweisung. switch (value): >> code_oben case 0: break; case 1: break; ... case 7: break; Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch nicht ab. Für den Compiler gilt also ab 5 case Auswertungen eine andere Optimierung? Desweiteren habe ich die switch-case durch ein if-else-if ersetzt. Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code erzeugt wird. Welche Gründe gibt es denn hierfür?
Datum:
Udo schrieb: > Weitere Erkenntniss: > > der code oben ist der Assembler Code einer switch-case Anweisung. > > > switch (value): > >> _code_oben_ > > case 0: > break; > > case 1: > break; > > ... Sieht den Code wirklich so aus? also in etwa
int a; void foo (int i) { switch (i) { a = 1; case 2: a = 4; break; case 5: a = 7; break; } } |
Code im switch ohne case/default davor ist nicht wirklich prickelnd... > Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht > der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch > nicht ab. > > Für den Compiler gilt also ab 5 case Auswertungen eine andere > Optimierung? Ja. Ab 5 oder 4 (hängt wiederum von was anderem ab) case-Labels verwendet gcc Sprungtabellen, wenn die case-Werte "dicht" sind. Das müsste in deinem Code erkennbar sein, indem zB der Startwert der Sprungtabelle in ein Register geladen wird, etwas simple Arithmetimk darauf veranstaltet wird und dann indirekt darüber gesprungen wird. > Desweiteren habe ich die switch-case durch ein if-else-if ersetzt. > Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code > erzeugt wird. > > > Welche Gründe gibt es denn hierfür? Denkbar ist ein Compilerfehler. Um den Fehler nachvollziehbar zu machen empfiehlt sich ein Testfall, den andere übersetzen können. Hilfreich ist dann eine möglichst einfache/kurze Quelle zu haben. Leider ist das nicht immer möglich, wenn Änderungen "hier" einen Fehler "da" bewirken. PPC-Code ist für mich absolutes Kauderwelsch :-) Die Quelle mit -save-temps -dp -fverbose-asm zu übersetzen bringt aber lesbare Kommentare in der .s Datei (evtl. -dP).
Datum:
Also bei mir siehts so aus:
[c]
switch(actionId)
{
case 0:
foo0();
break;
case 1:
foo1();
break;
case 2:
foo2();
break;
case 3:
foo3();
break;
case 4:
foo4();
break;
case 5:
foo5();
break;
case 6:
foo6();
break;
case 7:
break;
}
[c]
Zwischen Switch und dem ersten case steht natürlich kein Code. Wollte
oben nur hindeuten dass an dieser Stelle der ASM von ganz oben steht.
Datum:
Ok. Dein compilierbarer Testfall ist also
void foo0(); void foo1(); void foo2(); void foo3(); void foo4(); void foo5(); void foo6(); void test (int actionId) { switch (actionId) { case 0: foo0(); break; case 1: foo1(); break; case 2: foo2(); break; case 3: foo3(); break; case 4: foo4(); break; case 5: foo5(); break; case 6: foo6(); break; case 7: break; } } |
für den falscher Code erzeugt wird -> Bugreport für gcc erstellen falls der Fehler nicht schon bekannt ist. Ohne konkreten Code ist da aber nix zu wollen, also Kommentare wie
// irgendein Code
|
werden vom Compiler wie Kommentare behandelt, es gibt keine Magie, die deine C-Quelle rät :-)
Datum:
Hallo Udo, Welchen Compiler nutzt du überhaupt? Es gibt nunmal für den PPC haufenweise Compiler. Und ehrlich bezweifle ich dass ein Bug im Compiler daran schuld ist. Wie sieht dein Linkerfile aus? Ist das aufgeräumt? Eine Sprungtabelle für switch anweisungen steht im Normalfall nicht im Stack oder RAM. Sprünge mit Adrressen aus dem RAM kommen nur bei berechneten Adressen vor, Also Zugriffen auf (größere) Arrays oder Strukturen. Sonderfall sind natürlich Rücksprünge aus einer Unterfunktion. Wenn du einen Debuger zur Verfügung hast, dann schau dir den Stack im Programmablauf genau an. Wird der Stack überhaupt bis zu der Adresse gefüllt? Wenn ja wann? Hast du nur einen Stack oder mehrere? Bei nur einem würde es mich noch mehr wundern wenn der Compiler eine Sprungadresse aus dem Stack herauskramt. Vorallem wie in deinem Fall mit einer festkodierten Arithmetik. Der Stack könnte je nach eingetroffener Interupte völlig anders aussehen. Wie gesagt, schau dir dein Linkerfile an. Wenn der Stack (unbeabsichtigt) beeinflusst wird, ist das nicht lustig man sucht Tage lang an den falschen Stellen nach Fehlern. Das hab ich erst letzte Woche durch (war aber kein selbstgeschriebener Code). Gruß, TManiac
Datum:
Ich würde auf einen amoklaufenden Pointer tippen, der den Stack zerhagelt. Du suchst vermutlich an der falschen Stelle. Aber mangels konkretem Code lässt sich das nicht verifizieren...
Datum:
Compiler ist Metrowerks 2.x. Habe zwei verschiedene Versionen probiert, gleiches Verhalten. Ich denke eigentlich auch nicht dass es der Compiler ist. Benutze nur 1 Stack. Im Linkerfile ist dieser auch separat wie alle andere Sektionen angegeben. Stack liegt als letztes im RAM. SRAM geht von 0x4000.0000 bis 0x4004.0000. Stack: Adress Length 0x4003.0000 0x0000.0FF0 STACK_START = ADDR(Stack)+LEN(Stack) STACK_END = ADDR(Stack) Ohje - amoklaufende Pointer. Da swill man nicht wirklich debuggen :-(
Datum:
Grundsätzlich erstmal die Fragen: - treten Exceptions auf bzw. werden diese gezielt abgefagen ? - sind Interrupts aktiviert ? (bei längeren Interruptroutinen reicht es nicht unbedingt aus die Register 0-12 zu sichern sondern 0-30) - wird ein Codewarrior defaultprojekt verwendet oder modifizierte Einstellungen (v.a. Linker file) ? (kann zur Folge haben das Variablen nicht initialisiert werden, Stichwort: Rom Image bei den Linker Einstellungen) Um welches MPC56xx device handelt es sich ? Evt. mal mit Book-E anstatt VLE compilieren.
Datum:
- Exceptions treten nachweisbar keine auf. IVxR Register sind programmiert. - Interrupts sind an. Das mit den r0..r30 werde ich nachsehen, Danke! - verwendet wird ein startup vom 55xx , sollte aber gehen. Linker File ist selbst erstellt. Das alles da das Device sehr neu ist. Ist ein 567x, mehr sollte ich denke ich nicht veröffentlichen. BookE werde ich auch mal probieren.