mret
lyszt.net behandelt mret und andere RISC-V-Befehle ausführlicher.
Beschreibung
mret kehrt aus einem Trap-Handler zurück. Ein Trap tritt auf, wenn der Prozessor das laufende Programm anhält, damit ein Handler übernehmen kann. Ein Handler ist eine Routine an einer festen Adresse. Ein Gerät löst einen Interrupt aus, wie der Taster auf der GPIO-Platine, und das startet einen Trap. Der Name steht für Machine-Mode-Return.
mret
Wenn ein Trap startet, speichert der Prozessor die Adresse der unterbrochenen Anweisung in mepc, zeichnet den Grund in mcause auf, löscht das globale Interrupt-Enable-Bit von mstatus und springt zur Handler-Adresse in mtvec. mret macht dies rückgängig. Es lädt den Programmzähler mit der Adresse in mepc und stellt das Interrupt-Enable-Bit wieder her, das mstatus zu Beginn des Traps gesichert hat. Das unterbrochene Programm wird dann bei der Anweisung fortgesetzt, die es gerade ausführen wollte.
mret nimmt keine Operanden. Ohne es läuft der Prozessor über das Ende des Handlers hinaus in den darauf folgenden Code weiter.
Ein Interrupt kann zwischen zwei beliebigen Anweisungen eintreffen, und das unterbrochene Programm hat sich nicht darauf vorbereitet. Ein Handler sichert daher jedes Register, das er ändert, und stellt sie vor mret wieder her.
Ein Taster-Handler löscht außerdem das Pending-Bit des Tasters vor mret. Bleibt dieses Bit gesetzt, wird derselbe Interrupt erneut ausgelöst, sobald mret die Interrupts wieder einschaltet.
Das Beispiel schreibt die Adresse von target in mepc und führt mret aus, was dorthin springt. Außerhalb eines echten Traps zeigt dies den Sprung für sich allein. Siehe csrw zum Schreiben eines CSR.
Beispiel
la t0, target csrw mepc, t0 mret # pc = mepc, so execution continues at target target: nop
