RETI Instructions

One Name, Many Meanings Across Microcontroller Architectures


            

If you spend enough time writing interrupt service routines in low-level embedded code, one tiny instruction shows up again and again: RETI. On paper it looks simple. It means RETurn from Interrupt. In practice, though, that small instruction exposes deep architectural differences between microcontroller families. On some CPUs RETI is a real instruction with distinct interrupt semantics. On others there is no RETI at all, even though the processor still performs an interrupt return. And on a few older or more exotic architectures, the return instruction also tells external interrupt hardware that service has completed.

This is what makes RETI interesting. It is not just a branch back to the interrupted code. It is a compact summary of how a CPU enters interrupts, what state it saves automatically, what state software must save manually, and how global interrupt enable is restored. Looking at RETI across AVR, STM32, Texas Instruments devices, and a few less mainstream architectures is a surprisingly good way to understand interrupt philosophy at the ISA level.

What RETI Really Means

A normal subroutine return only needs to restore the program counter. An interrupt return usually has to do more. Depending on the architecture, that may include restoring status flags, privilege level, interrupt masks, shadow registers, or even signaling an external interrupt controller. So while RETI often reads like a close relative of RET, it usually carries architectural side effects that a plain return does not.

That distinction matters because interrupt handlers are not ordinary functions. They are entered asynchronously, often with hardware-assisted context save, and they must leave the machine in a state where interrupt delivery can resume safely.

AVR: The Classic, Literal RETI

On classic AVR devices, RETI is exactly what many embedded developers first imagine when they hear the term. The CPU vectors into the interrupt, clears the global interrupt enable state on entry, runs the ISR, and RETI returns to the interrupted code while also restoring interrupt acceptance. In the simplest mental model, RETI is RET plus interrupt re-enable.

This makes AVR pleasantly explicit. You can often explain AVR interrupt control with just three ideas: the stack stores the return address, the I bit controls global interrupt enable, and RETI is the canonical way to end an ISR. That simplicity is one reason AVR assembly and low-level debugging remain so approachable.

There is one subtlety worth mentioning for newer AVR core variants. Not every modern AVR core treats RETI in exactly the same way as the oldest classic cores. On some newer core families, interrupt entry and the I bit handling differ, so RETI is not always the simple hardwired “set global interrupt enable” that old AVR folklore suggests. Even so, from the programmer’s point of view, RETI remains the proper architectural end of an ISR.

AVR Example

; AVR external interrupt example
; Toggle a flag or update a counter, then return with RETI

.org 0x0000
    rjmp reset

.org INT0addr
    rjmp isr_int0

reset:
    ; normal initialization here
main_loop:
    rjmp main_loop

isr_int0:
    push r16
    in   r16, SREG
    push r16

    ; ISR body goes here

    pop  r16
    out  SREG, r16
    pop  r16
    reti

That last line is the key. If you replaced RETI with RET in a real ISR, the program might resume execution, but the interrupt subsystem would not be restored correctly.

STM32: No RETI Instruction at All

STM32 microcontrollers, being based on Arm Cortex-M cores, take a very different approach. There is no RETI mnemonic in the instruction set. Instead, exception return is part of the Cortex-M exception mechanism. When an interrupt or exception occurs, hardware automatically stacks a register frame. The link register is loaded with a special EXC_RETURN value. When the handler finishes, a branch such as BX LR triggers exception return, and the core unstacks the saved machine state automatically.

This is a major conceptual difference from AVR. On AVR, RETI is a named ISA instruction. On STM32, interrupt return is more like a protocol implemented by the exception engine. The return operation is encoded through special values in LR and executed through ordinary branch mechanics. In other words, the semantic equivalent of RETI exists, but it is not spelled RETI.

This has important consequences. Cortex-M can restore multiple core registers automatically, distinguish between returning to thread mode or handler mode, and even return to different stack pointers depending on system configuration. It is a richer model, but it is less visible if you only ever write C.

STM32 Example

; Cortex-M / STM32 style interrupt return
; Hardware stacked the exception frame on entry.
; LR contains an EXC_RETURN value.

.thumb
.global EXTI0_IRQHandler
EXTI0_IRQHandler:
    push {r4, lr}

    ; ISR body goes here
    ; clear peripheral pending flag here

    pop  {r4, lr}
    bx   lr

That BX LR is not just a normal subroutine return when LR contains EXC_RETURN. It tells the Cortex-M exception logic to unstack context and resume interrupted execution. So in STM32 land, asking “where is RETI?” is really asking “how does exception return work on Cortex-M?”

Texas Instruments MSP430: RETI With a Different Flavor

Texas Instruments MSP430 does have a real RETI instruction, but it is not identical in spirit to AVR RETI. MSP430 interrupt entry pushes the status register and program counter onto the stack. RETI restores them in the reverse order. That means global interrupt enable is restored as part of the saved status register, not simply because RETI always forces interrupts on in a fixed way.

This is elegant and very MSP430-like. The architecture is compact, orthogonal, and extremely status-register-centric. On MSP430, RETI feels less like a special “magic enable interrupts now” instruction and more like a structured state restore from interrupt context.

From a firmware perspective, this gives MSP430 handlers a very clean mental model. The interrupt machinery preserves execution state, including interrupt enable state, through stack discipline. In practice, this is one reason MSP430 assembly often feels tidy and almost minimalistic.

MSP430 Example

; MSP430 timer interrupt example

            .text
timer_isr:
            push    r12

            ; ISR body goes here

            pop     r12
            reti

Compared with AVR, the visible source code looks similar. The architectural meaning is different. AVR programmers often think in terms of the I bit becoming active again at ISR end. MSP430 programmers think more naturally in terms of restoring the stacked SR and PC.

Texas Instruments C28x: Not RETI, But IRET

If we widen the TI view beyond MSP430, we immediately find another variation. TI C28x devices use IRET rather than RETI. That sounds like a cosmetic difference, but it reflects a different CPU lineage and different interrupt machinery. C28x devices use automatic context handling tied to their control and status model, and IRET is the canonical interrupt return instruction in that family.

This is a good reminder that “Texas Instruments” is not a single ISA story. TI has shipped multiple processor families with very different assembly languages, execution models, and interrupt semantics. So when comparing RETI behavior across vendors, the family name matters just as much as the vendor name.

C28x Example

; TI C28x style interrupt return

_my_isr:
    ; ISR body goes here
    IRET

PIC: RETFIE Instead of RETI

Microchip’s PIC families are a useful contrast because many developers assume all small microcontrollers use RETI. PIC does not. Classic PIC devices use RETFIE, which literally means return from interrupt. Functionally it fills the same architectural role as RETI, but the naming is different and the interrupt model is very much PIC’s own.

This matters because PIC interrupts have historically varied a lot across families. Some parts have a single vector, others support priority levels, and some PIC18 devices add fast return behavior using shadow registers. So while RETFIE is the PIC analog of RETI, it lives inside an ecosystem that is less uniform than AVR’s simpler classic interrupt story.

PIC Example

; PIC18 style interrupt return

my_isr:
    ; ISR body goes here
    retfie

On some PIC18 parts you may also encounter a fast form of RETFIE that restores shadowed registers, which is another sign that “return from interrupt” is often much more than just loading the PC.

8051: RETI as Interrupt-Controller Handshake

The 8051 family gives RETI a distinctly old-school flavor. Like AVR and MSP430, it has a real RETI instruction. But 8051 RETI does not automatically restore the program status word the way some newcomers might expect. More importantly, it restores the interrupt logic so the controller can accept further interrupts at the same priority level.

That is a subtle but important distinction. On 8051, RETI is not only about resuming execution. It also tells the interrupt subsystem that the current service sequence is complete. This makes RETI more tightly bound to interrupt control flow than an ordinary RET.

8051 Example

; 8051 external interrupt service routine

ORG 0003H
INT0_ISR:
    PUSH ACC

    ; ISR body goes here

    POP  ACC
    RETI

If you come from AVR, the mnemonic looks familiar. The machine-level meaning is related, but not identical.

Z80 and eZ80: RETI as a Bus-Level Signal

The Z80 family is one of the most interesting “exotic but still influential” cases. Z80 includes RETI and RETN. Internally, RETI behaves much like a return, but it also exists so daisy-chained interrupt peripherals can recognize that an interrupt acknowledge sequence has fully completed. In other words, RETI has meaning beyond the CPU core itself. It is part of a broader interrupt ecosystem involving external hardware.

This is a very different worldview from modern ARM microcontrollers, where interrupt control is mostly integrated into the core and NVIC. On Z80-style systems, RETI can serve as a form of hardware-visible interrupt completion signal. That makes it one of the clearest examples of how historical bus-oriented designs shaped instruction semantics.

Z80 Example

; Z80 interrupt service routine

my_isr:
    push af

    ; ISR body goes here

    pop  af
    reti

RISC-V: MRET and SRET Instead of RETI

RISC-V takes yet another path. It does not define a simple RETI instruction for machine-mode interrupt handlers. Instead, privileged code returns from traps with MRET or SRET, depending on privilege level. These instructions restore privilege state and interrupt-enable state from dedicated control bits. This is conceptually closer to a modern exception-return mechanism than to the small-MCU “single global interrupt bit plus RETI” model.

For embedded developers, this is a useful bridge between the bare-metal and operating-system worlds. RISC-V trap return is designed to scale from small microcontrollers to more complex systems with multiple privilege levels. So while MRET plays the role of interrupt return, it belongs to a much more formal privilege architecture.

RISC-V Example

; RISC-V machine-mode trap handler ending

trap_handler:
    addi sp, sp, -16
    sw   ra, 12(sp)

    ; handler body goes here

    lw   ra, 12(sp)
    addi sp, sp, 16
    mret

That mret is doing more than “return to where I came from.” It also restores architectural interrupt and privilege state according to the trap CSRs.

Renesas RX: RTE and Fast Interrupt Variants

Renesas RX is another good example of an architecture that solves the same problem with different naming and slightly different machinery. Most exception handlers return with RTE, while fast interrupts may use RTFI. Again, the pattern is familiar even when the mnemonic is not: interrupt return is special, and the ISA treats it as special.

This is why comparing interrupt returns across architectures is so valuable. Even when the opcode name changes, the design question stays the same: what hidden processor state must be reconstituted so normal execution can continue safely?

Renesas RX Example

; Renesas RX exception return style

_excep_handler:
    ; handler body goes here
    RTE

So Which Architecture Has the “Real” RETI?

If by real RETI we mean a literal instruction named RETI, then AVR, MSP430, 8051, and Z80 all qualify. But even among those families, the exact semantics differ. AVR ties RETI strongly to global interrupt re-enable behavior. MSP430 uses RETI as a restoration of stacked machine state including the status register. 8051 uses RETI to restore PC and signal the interrupt controller logic. Z80 uses RETI in a way that can matter to external daisy-chain hardware.

If by real RETI we mean “the architectural mechanism that returns from interrupt context correctly,” then STM32 absolutely has one, even though the mnemonic is not RETI. On Cortex-M, exception return is simply implemented through EXC_RETURN and BX LR rather than through a dedicated instruction spelling.

That is the most useful takeaway for embedded work: the spelling is less important than the semantics. The real question is what state was saved on interrupt entry, and what operation reestablishes that state at ISR exit.

Practical Takeaways for Embedded Developers

First, never assume RETI means the same thing on every architecture. The mnemonic may be identical while the side effects differ.

Second, do not force assembly intuitions from one family onto another. AVR habits do not map directly onto STM32, and 8051 assumptions do not map cleanly onto MSP430.

Third, when writing naked handlers, startup code, RTOS ports, or context-switch code, always check exactly what the architecture saves automatically on exception entry and exactly what the interrupt return operation restores.

Finally, remember that interrupt return instructions often reveal the age and philosophy of an architecture. Simpler 8-bit MCUs often expose the mechanism directly. More modern cores hide more of it in exception hardware. Older bus-oriented CPUs may use RETI partly as a signal to the outside world.

Conclusion

RETI is one of those tiny instructions that opens a door into much bigger architectural ideas. On AVR it is direct and iconic. On STM32 it disappears into the Cortex-M exception engine. On TI MSP430 it restores stacked status cleanly, while TI C28x uses a related but different IRET model. PIC calls the same idea RETFIE. 8051 and Z80 preserve older interrupt-controller traditions. RISC-V scales the concept into privilege-aware trap return, and Renesas RX adds its own exception-return vocabulary.

So the next time you see RETI in a datasheet or disassembly, it is worth slowing down for a moment. That one instruction is rarely just “return from interrupt.” It is the architecture telling you how it thinks about control flow, privilege, state, and time-critical events.

Ufff ! That was long.

Happy coding.

73

PetaLinux: Linux flavor for Arty Z7 ARM9 cores

AMD Xilinx PetaLinux is not a normal Linux distribution like Ubuntu or Debian. It is a set of tools used to build a custom embedded Linux distribution targeting Xilinx/AMD FPGA SoCs, such as the Zynq-7000 SoC used on the Digilent Arty Z7. Think of it as a build system and configuration environment, not the OS […]

Comments are closed.