GCC-Inline-Assemblierung mit Anweisungen verwenden, die Sofortwerte annehmen

9

Das Problem

Ich arbeite an einem benutzerdefinierten Betriebssystem für einen ARM Cortex-M3-Prozessor. Um mit meinem Kernel zu interagieren, müssen Benutzer-Threads einen SuperVisor Call (SVC) -Befehl erzeugen (früher bekannt als SWI, für SoftWare Interrupt). Die Definition dieser Anweisung im ARM ARM lautet:

Dies bedeutet, dass die Anweisung ein sofortiges Argument und keinen Registerwert erfordert.

Dies erschwert es mir, meine Oberfläche lesbar zu gestalten. Es erfordert Code wie:

%Vor%

wenn ich etwas lieber bevorzuge

%Vor%

Ich bin jedoch nicht in der Lage, diese Funktion zu konstruieren, weil die SVC-Anweisung ein unmittelbares Argument benötigt und ich kann das nicht liefern, wenn der Wert über ein Register übergeben wird.

Der Kernel:

Für Hintergrund wird der SVC-Befehl wie folgt im Kernel decodiert:

%Vor%

Diese Fallaussage gerät schnell außer Kontrolle, aber ich sehe kein Problem. Irgendwelche Vorschläge sind willkommen.

Was ich versucht habe

SVC mit einem Registerargument

Ich habe zuerst überlegt

%Vor%

aber das funktioniert natürlich nicht, da SVC ein Registerargument benötigt.

Brute-Force

Der Brute-Force-Versuch, das Problem zu lösen, sieht so aus:

%Vor%

aber das hat einen üblen Code-Geruch. Sicherlich kann das besser gemacht werden.

Generierung der Befehlskodierung im laufenden Betrieb

Ein letzter Versuch bestand darin, die Anweisung im RAM zu generieren (der Rest des Codes läuft von einem schreibgeschützten Flash) und dann auszuführen:

%Vor%

aber das fühlt sich einfach nicht richtig an. Außerdem funktioniert es nicht - da ist etwas, was ich hier falsch mache; vielleicht ist meine Instruktion nicht richtig ausgerichtet oder ich habe den Prozessor nicht eingerichtet, um Code aus dem RAM an dieser Stelle laufen zu lassen.

Was soll ich tun?

Ich muss an der letzten Option arbeiten. Trotzdem fühlt es sich so an, als müsste ich etwas tun können wie:

%Vor%

aber ich finde keine solche Option in der Dokumentation und ich kann nicht erklären, wie ein solches Feature implementiert werden würde, also existiert es wahrscheinlich nicht. Wie soll ich das machen?

    
Kevin Vermeer 07.07.2012, 18:08
quelle

5 Antworten

19

Sie möchten eine Integritätsbedingung verwenden, um zu erzwingen, dass der Operand als 8-Bit-Sofortwert zugewiesen wird. Für ARM ist das die Einschränkung I . Du willst also

%Vor%

In der GCC-Dokumentation finden Sie eine Zusammenfassung dessen, was alle Constaints sind - Sie müssen sich die prozessorspezifischen Notizen ansehen, um die Einschränkungen für bestimmte Plattformen zu sehen. In einigen Fällen müssen Sie möglicherweise die Datei " .md " (Maschinenbeschreibung) für die Architektur in der gcc-Quelle nachsehen, um weitere Informationen zu erhalten.

Es gibt auch einige gute ARM-spezifische GCC-Dokumente hier . Ein paar Seiten weiter unten unter der Überschrift "Eingabe- und Ausgabeoperanden" gibt es eine Tabelle aller ARM-Einschränkungen

    
Chris Dodd 07.07.2012, 20:42
quelle
2

Was ist mit einem Makro:

%Vor%     
ouah 07.07.2012 18:15
quelle
1

Wie von Chris Dodd in den Kommentaren zu dem Makro bemerkt, funktioniert es nicht ganz, aber das tut:

%Vor%

Beachten Sie jedoch, dass es nicht funktioniert, wenn Sie ihm einen Aufzählungswert übergeben, nur einen #definierten Wert.

Daher ist die obige Antwort von Chris die beste, da sie einen unmittelbaren Wert verwendet, der für Daumenanweisungen mindestens erforderlich ist.

    
Anthony Wieser 06.06.2014 10:53
quelle
1

Meine Lösung ("Befehlscodierung während des Betriebs generieren"):

%Vor%

Es funktioniert und es ist viel besser als Switch-Case-Variante, die ~ 2kb ROM für 256 svc dauert. Diese Funktion muss nicht in den RAM-Bereich gestellt werden, FLASH ist in Ordnung. Sie können es verwenden, wenn svc_num eine Laufzeitvariable sein soll.

    
quelle
0

Wie in besprochen Diese Frage, der Operand von SVC ist fest, das heißt, er sollte dem Präprozessor bekannt sein und unterscheidet sich von unmittelbaren Datenverarbeitungsoperanden.

Das gcc-Handbuch liest

  

'I'- Integer, das als unmittelbarer Operand in einer Datenverarbeitungsinstruktion gilt. Das heißt, eine Ganzzahl im Bereich von 0 bis 255, die um ein Vielfaches von 2 gedreht ist.

Daher werden hier die Antworten bevorzugt, die ein Makro verwenden, und die Antwort von Chris Dodd funktioniert nicht garantiert, abhängig von der GCC-Version und der Optimierungsstufe. Siehe die Diskussion der anderen Frage.

    
Ruhollah Majdoddin 17.05.2016 11:07
quelle

Tags und Links