mret
lyszt.net covers mret and other RISC-V instructions in more detail.
Description
mret returns from a trap handler. A trap occurs when the processor stops the program it is running so a handler can take over. A handler is a routine at a fixed address. A device raises an interrupt, such as the button on the GPIO board, and that starts a trap. The name stands for machine-mode return.
mret
When a trap starts, the processor stores the address of the interrupted instruction in mepc, records the reason in mcause, clears the global interrupt enable bit of mstatus, and jumps to the handler address held in mtvec. mret undoes this. It loads the program counter with the address in mepc and restores the interrupt enable bit that mstatus saved at the start of the trap. The interrupted program then resumes at the instruction it was about to run.
mret takes no operands. Without it the processor continues past the end of the handler into whatever code follows.
An interrupt can arrive between any two instructions, and the interrupted program has made no preparation for it. A handler therefore saves every register it changes and restores them before mret.
A button handler also clears the button's pending bit before mret. If that bit stays set, the same interrupt fires again as soon as mret turns interrupts back on.
The example writes the address of target into mepc and runs mret, which jumps there. Outside a real trap this shows the jump on its own. See csrw for writing a CSR.
Example
la t0, target csrw mepc, t0 mret # pc = mepc, so execution continues at target target: nop
