5.6 Register Usage
The assembly generated from C source code by the compiler will use certain registers in the PIC MCU register set. Most importantly, the compiler assumes that nothing other than code it generates can alter the contents of these registers.
The registers that are special and that are used by the compiler are listed in the following table.
Register name | Applicable devices |
---|---|
WREG | All 8-bit devices |
STATUS | All 8-bit devices |
PCLATH | All Mid-range devices |
PCL ,
PCLATH , PCLATU | All PIC18 devices |
BSR | Enhanced Mid-range and PIC18 devices |
FSR | Non-Enhanced Mid-range devices |
FSR0L ,
FSR0H , FSR1L ,
FSR1H | Enhanced Mid-range and PIC18 devices |
FSR2L ,
FSR2H | All PIC18 devices |
TBLPTRL ,
TBLPTRH , TBLPTRU ,
TABLAT | All PIC18 devices |
PRODL ,
PRODH | All PIC18 devices |
Dynamic working registers (btemps) | Enhanced Mid-range and PIC18 devices |
The dynamic working registers (btemps) are objects that the compiler treats like registers. These objects are saved and restored like any other register when used in interrupt code. They might be used (along with the software stack) when a function needs to be reentrant, especially when the register-optimized reentrant stack is being used, as described in Register-optimized Reentrant Stack.
WREG =
0;
were encoded using the clrf
instruction, the compiler would
not consider this as modifying the W register. Additionally, registers should not be
changed directly by in-line assembly code, as shown in the following example, which
modifies the ZERO
bit in the STATUS
register using the
macro defined by
<xc.h>
.#include <xc.h>
void getInput(void)
{
__asm("bcf " ZERO_bit); //do not write using inline assembly code
process(c);
}
If any of the applicable registers listed in the table are used by interrupt code, they will be saved and restored when an interrupt occurs, either in hardware or software (see Context Switching).
const
data defined by a
program. When building for PIC18 devices, the compiler can use this data to optimize
program memory access. For total const data sizes less than 64k and when the
mediumconst
psect is used to hold this data, the compiler positions the
mediumconst
psect so that the TBLPTRU register only needs to be
initialized at runtime startup and does not need to be modified during program execution.
For total sizes less than 256 bytes, the psect holding this data
(smallconst
) is positioned so that both the upper and high table
pointer registers (TBLPTRU and TBLPTRH) do not need to be changed and can be assumed to
hold the value assigned at runtime startup. As a consequence, any code that modifies the
table pointer registers without the compiler being "aware" of this operation could lead to
code failure.const array[] = { 0, 2, 4, 7};
// runtime startup sets TBLPTRU and TBLPTRH so that all smallconst psect is accessible
int main(void) {
...
data = array[idx]; // generated code only adjusts TBLPTRL to access array[]
TBLPTR = 0x2000; // code forces table pointer to change
...
data = array[idx]; // code fails, assuming TBLPTRU and TBLPTRH still point to smallconst
Corruption of the table pointers could even occur if the program dereferences a pointer assigned an address of an object outside of the general purpose flash program memory. Check the assembly list file if you are unsure if your code modified the table pointer, and the following code can be used to verify if any code failure is attributable to this situation.
#include <xc.h>
uint24_t saved_tblptr = TBLPTR;
// place code that manually modifies TBLPTR here
TBLPTR = saved_tblptr;