The #pragma Regsused Directive

The #pragma regsused directive allows the programmer to indicate register usage for functions that will not be “seen” by the code generator; for example, if they were written in assembly code. It has no effect when used with functions defined in C code, but in those cases the register usage of these functions can be accurately determined by the compiler and the pragma is not required. This pragma has no effect when used with devices that can save registers into shadow registers.

The general form of the pragma is:

#pragma regsused routineName registerList

where routineName is the C-equivalent name of the function or routine whose register usage is being defined, and registerList is a space-separated list of registers’ names, as shown in the Table 1 table.

Those registers that are not listed are assumed to be unused by the function or routine. The code generator can use any of these registers to hold values across a function call. If the routine does in fact use these registers, unreliable program execution can happen.

The register names are not case sensitive and a warning will be produced if the register name is not recognized. An empty register list indicates that the specified function or routine uses no registers. If this pragma is not used, the compiler will assume that the external function uses all registers.

For example, a routine called _search is written in PIC18 assembly code. In the C source, we can write:

extern void search(void);
#pragma regsused search wreg status fsr0

to indicate that this routine used the W register, STATUS and FSR0. Here, fsr0 expands to both FSR0L and FSR0H. These could be listed individually, if required.

The compiler can determine those registers and objects that need to be saved by an interrupt function, so this pragma could be used, for example, to allow you to customize the context switch code in cases where an interrupt routine calls an assembly routine.