4.6.4 Accessing SFRs

The symbols for Special Function Registers (SFRs) are not automatically accessible from assembly code. The assembly header file <xc.inc> must be included into every module that needs access to these register definitions.

Include the header file using the assembler’s INCLUDE directive, (see 4.9.31 Include Directive) or use the C preprocessor’s #include directive. If you are using the latter method, make sure you name the assembly source file using a .S extension (upper case), or use the -xassembler-with-cpp option when you build (see 3.4.37 X: Specify Source Language Option).

An entire register can be accessed using the pre-defined symbol that has been equated to the register's address by the header. For example, the entire LATA register can be accessed via the symbol LATA. This symbol name is also made a preprocessor macro, defined to be a string that is the same as the register's name, allowing you to confirm that the register exists before accessing it. For example:
#ifdef LATA  // if this device has a PORTA latch register...
movf   LATA,w
movwf  savedState
#endif
Preproccessor macros are also defined for fields (often bits) within each register. These macros expand to be the address of the enclosing register followed by a comma and then the bit offset of that field within the register. This makes the symbol directly usable inside bit-orientated instructions, like bsf or btfsc etc. For example, bit #5 inside the PORTB register can be accessed using the symbol RB5. For example:
btfss  RB5
incf  count
Some devices have the same SFR field name used in more than one register. In these cases, no symbol will be defined for any of these fields. To access these fields, you must use the SFR name and a pre-defined macro that represent the field's bit position in the register. If required, this method of accessing fields within SFRs can be used with any field in any register. For example, some devices define more than one IPEN bit and so you would need to access IPEN with code similar to:
bsf BANKMASK(INTCON0),INTCON0_IPEN_POSN,c     ;set the IPEN bit in the INTCON0 register
Symbols are also not defined when the field name is a single letter, for example the carry bit in the STATUS register is called C, but there will be no symbol with this name defined. In some cases, there might be an alternate name provided, for example CARRY, but the field can always be access in a manner similar to that shown in the above example.
Note: The manual masking of addresses used as instruction operands (for example using the BANKMASK() or PAGEMASK() macros or ANDing the operand with a mask) is not necessary when using the -Wl,--fixupoverflow option and any of the ignore, warn, or lstwarn arguments.

The <xc.inc> header supplies a complete set of field-position equates representing the field's bit position in its register, size (in bits), and a bitmask that can be used to perform bitwise operations on the field. These equates have the form REGISTERNAME_FIELDNAME_SUFFIX, where SUFFIX can be POSITION or its alias POSN, SIZE or its alias LENGTH, or MASK. For example, the following are defined for the RA3 field in the PORTA register:PORTA_RA3_POSN and PORTA_RA3_POSITION, PORTA_RA3_SIZE and PORTA_RA3_LENGTH, and PORTA_RA3_MASK.