2016-08-31 3 views
0

Es gibt ein seltsames Ergebnis beim Kompilieren von Interrupt Handler für ARM GIC mit Linaro GCC.ARM GIC Interrupt-Handler von Linaro GCC

Der Code ist:

void foo1(void) __attribute__((interrupt("IRQ"))); 
void foo2(void) __attribute__((interrupt("IRQ"))); 

void foo1() { 
    dummy(); 
    return; 
} 

void foo2() { 
    return; 
} 

Das Ergebnis Assemblercode:

foo1: 
     sub  lr, lr, #4 
     push {r0, r1, r2, r3, r4, fp, ip, lr} 
     add  fp, sp, #28 
     bl  dummy 
     nop 
     sub  sp, fp, #28 
     pop  {r0, r1, r2, r3, r4, fp, ip, pc}^ 

foo2: 
     str  fp, [sp, #-4]! 
     add  fp, sp, #0 
     nop 
     sub  sp, fp, #0 
     ldr  fp, [sp], #4 
     subs pc, lr, #4 

So wird SUBS verwendet, um Rückkehr von der Unterbrechung, wenn keine Subroutinen innerhalb Handler-Code und PUSH {lr}/POP { pc} wird verwendet, wenn ein Unterprogramm vorhanden ist.

Das Problem ist, dass SUBS automatisch von Prozessor IRQ-Modus in SVC-Modus wechseln, aber POP {pc} nicht. Also sollte SUBS verwendet werden und für foo1 ist es notwendig, einen externen SUBS-Befehl hinzuzufügen, um vom IRQ- zum SVC-Modus zu wechseln.

Ist es Feature oder Bug?

Gibt es eine Möglichkeit, Compiler zu zwingen, SUBS jedes Mal zu verwenden?

+0

Welche spezifische Linaro-Version? (FWIW Ich sehe kein Problem mit den knorrigen alten 13.11 arm-linux-gnueabihf Binaries zur Hand) Zweitens, welche Compiler/Assembler-Optionen gibst du weiter? Die Frage, wie sie aussieht, sieht wie ein einfaches Fehllesen der (korrekten) vom Compiler generierten Assembly aus, aber Ihre Kommentare zu der Antwort implizieren etwas anderes - bitte fügen Sie der Frage etwas mehr Detail hinzu, um zu klären, was genau hier vor sich geht. – Notlikethat

+0

arm-eabi-gcc-mfloat-abi = softfp -march = armv7-a-mcpu = Kortex-a9 -S-Funktionsabschnitte -fdata-Abschnitte arm-eabi-gcc (Linaro GCC 5.3-2016.02) 5.3.1 20160113 Der 'pop {r0, r1, r2, r3, r4, fp, ip, pc} ^' wird erzeugt, ist aber nicht korrekt. Es scheint, dass es sein sollte "ldm \t sp !, {r0, r1, r2, r3, r4, fp, ip, pc} ^' –

+0

Das Problem ist bekannt und in Zweig 6 https://gcc.gnu.org/ bugzilla/show_bug.cgi? id = 70830 –

Antwort

1

Ich kann die Referenz nicht finden, aber IIRC, pop {} entspricht LDM sp ...

Für LDM, die ARM ARM (A4.1.22 LDM (3)) heißt es:

^Für eine LDM Anweisung, die den PC lädt, zeigt dies, dass die SPSR des aktuellen Modus kopiert an den CPSR.

Aus diesem Grund stellt die generierte Pop-Anweisung das CPSR vom SPSR wieder her und kehrt damit in den vorherigen CPU-Modus zurück.

+0

Ja, das Problem ist lokalisiert. 'pop {r0, r1, r2, r3, r4, fp, ip, pc}' Anweisung ist 'e8bd981f'. 'pop {r0, r1, r2, r3, r4, fp, ip, pc} ^' Anweisung ist auch 'e8bd981f', sollte aber' e8fd981f' sein. –

+0

So wird generische LDM anstelle von LDM generiert (Ausnahme Rückgabe). Handelt es sich um einen Codegenerierungsfehler von GAS oder sollten einige zusätzliche Kompilierungsoptionen angegeben werden? –

Verwandte Themen