17.5.1 Context Save on Interrupt

The standard calling convention for C/C++ functions will already preserve zero, s0-s7, gp, sp, and fp. k0 and k1 are used by the compiler to access and preserve non-GPR context, but are always accessed atomically (that is, in sequences with global interrupts disabled), so they need not be preserved actively. A handler function will actively preserve the a0-a3, t0-t9, v0, v1 and ra registers in addition to the standard registers.

An interrupt handler function will also actively save processor status registers that are utilized by the handler function. Specifically, the EPC, SR, hi and lo registers are preserved as context. All available DSP accumulators are preserved as necessary.

In addition, if a DSP accumulator register is preserved, the DSP Control register is also preserved.

Handler functions may use a shadow register set to preserve the General Purpose Registers, enabling lower latency entry into the application code of the handler function. On some devices, the shadow register set is assigned to an interrupt priority level (IPL) using the device Configuration bit settings (for example, #pragma config FSRSSEL=PRIORITY_6). While on other devices, the shadow register set may be hard wired to IPL7. Consult the target device’s data sheet for more information on the shadow register set.

By default, the compiler saves the Floating-point Unit (FPU) general registers and the FCSR register on the stack as required for interrupt() attributed functions. This includes functions that use the __ISR(vector,priority) macro. As always, to minimize the required context saving for an ISR, avoid making calling functions from within the ISR so that the compiler generates code for only the registers used within the ISR.

The no_fpu function attribute can be used to suppress context saving of the FPU register. For example:
void __attribute__((interrupt(IPL7SRS),vector(_CORE_TIMER_VECTOR),no_fpu)) ct_isr(void)
{
  foo();
}
It also causes the compiler to disable the FPU in the ISR prologue, such that any use of the FPU from within the ISR context would result in a general exception. This means that any higher-priority ISR interrupting an ISR using the no_fpu attribute must re-enable the FPU if floating-point operations are required.