3.4 Program Flow and Address Masking
On Baseline and Mid-range PIC devices, the call and goto flow
control instructions require the destination page of the call or jump to be preselected
and the upper bits of the destination address (referred to here as the page number)
removed to prevent build errors. There are three approaches you can follow to use flow
control instructions when using the PIC Assembler.
- Use a page selection sequence prior
to
callandgotoinstructions, plus use the-Wl,--fixupoverflow=ignore|warn|lstwarnoption, which will automatically truncate all instruction operands to the required size. This approach is the most compatible with MPASM code, but all instruction operands are truncated. - Use a page selection sequence prior
to
callandgotoinstructions, as well as the-Wl,--fixupoverflow=erroroption, then manually mask out the page values from destination operand addresses using thePAGEMASK()macro. This approach is efficient for new code and only truncates the addresses you specify. - Use the
fcallandljmppseudo instructions to have both page selection and address masking applied automatically. This approach is the easiest for new code but might not be the most efficient.
Note that on PIC18 devices, these same flow control instructions can reach any program memory destination specified with a valid label operand, and this section does not concern code written for such devices.
If you decide to follow the first approach when using Baseline or Mid-range devices, the
page of a routine can be preselected by using the PAGESEL directive.
The operation of this directive is identical in MPASM and the PIC Assembler.
It is first helpful to understand how PIC Assembler addresses are comprised. The value of
a label in program memory (for example the label associated with a routine) is always
the full address of where the label was positioned. The upper bits of such an address
come from the page value of the destination label (its page number, which is preloaded
into the PCLATH register by the PAGESEL directive) and the lower order
bits being the offset into that page. The flow control instructions require only the
offset within a page to be specified for the operand, so the upper bits of the address
operand, which indicate the page value, must be removed (zeroed). The PIC Assembler will
issue a fixup overflow error (for symbolic operands) or warning (for absolute operands)
should it detect that these instructions have an operand with superfluous page
information present.
The first approach has the linker automatically truncate all addresses to fit the
instruction. To do this, use the
-Wl,--fixupoverflow=action option and one of the
ignore, warn, or lstwarn action
arguments to prevent any fixup overflow errors from being issued. The
lstwarn argument is the default if the option not specified. See
the MPLAB® XC8 PIC® Assembler User's
Guide for full information on this feature.
ignore action argument. This will tell the linker to truncate
instruction operands with no warning, similar to how MPASM operates. Note, however, that
the linker will truncate all operands for all instructions in your
program. In some situations, an operand that is too large to fit the relevant field in
the instruction might indicate a flaw in the program design. It is recommended that you
select an action argument of warn or lstwarn, or both
(colon-separated), as these modes of operation will have the linker issue a warning when
it truncates a value so that you can confirm there is no potential for program failure.
If you are using this option with any of the warn,
lstwarn, or ignore action arguments, destination
labels can be used in instructions without modification, as shown in the following
comparison table, where example MPASM code and the equivalent PIC-AS code are
identical.| MPASM code | Equivalent PIC-AS code |
|---|---|
|
|
When using the second approach, page selection again takes place using the
PAGESEL directive.
PAGEMASK() macro, available once you include
<xc.inc>. This macro will perform the AND operation using the
correct mask value, based on the selected device and can be used with both
call and goto instructions. Next, specify the
-Wl,--fixupoverflow=error option, which will force the linker to
generate an error should it encounter any operand that has not had its page value
removed. Using the PAGEMASK() macro is the most portable way to
manually mask an address, and its use is shown in the following migration table.| MPASM code | Equivalent PIC-AS code |
|---|---|
|
|
The third approach is to again use the -Wl,--fixupoverflow=error option
but to use pseudo call and jump instructions supplied by the PIC Assembler to perform
both page selection and destination address masking for you. See the MPLAB® XC8 PIC® Assembler User's Guide for full
information on these instructions.
fcall pseudo instruction will expand into a regular
call instruction, and the ljmp pseudo instruction
will expand into a regular goto instruction, both with the destination
address correctly masked. Additionally, both pseudo instructions will insert a page
selection sequence prior to and after the call or jump to ensure that the correct
destination is reached and that the current page is selected afterward. Do not mask the
address operand of these pseudo instructions in any way; they use the full address to
determine the page of the destination.| MPASM code | Equivalent PIC-AS code |
|---|---|
|
|
Although this is the easiest way to write source code, it may result in page selection
instructions that are redundant, and hence increase code size. You should also remember
that these pseudo instructions can expand into more than one device instruction, and so
they should not be placed immediately after any test-and-skip instruction, like the
btfsc instruction, for example.
