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
call
andgoto
instructions, plus use the-Wl,--fixupoverflow=ignore|warn|lstwarn
option, 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
call
andgoto
instructions, as well as the-Wl,--fixupoverflow=error
option, 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
fcall
andljmp
pseudo 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.