5.3 Linear Memory

The linear addressing mode is a means of accessing the banked data memory on Enhanced Mid-range devices as one contiguous and linear block. Your device data sheet will indicate if this memory is implemented on your device and contain further operational details.

Linear memory is typically used for objects that are too large to fit into a single memory bank, but it is important to remember that linear memory is not present in addition to a device's regular banked memory; it is simply an alternate way to access that banked memory. You have to define objects larger than a bank in a different way to ordinary objects that are placed into banked memory.

This chapter's example code defines an object that is larger than a bank using the DLABS directive, shown here.
;define NUM_TO_READ bytes of linear memory, at banked address 0x120
DLABS  1,0x120,NUM_TO_READ,levels

This directive takes several arguments. The first is the address space in which the memory will be defined. This should be the value 1 for objects to be placed in data memory. The second argument is the starting address for the storage. This can be specified as either a linear or banked address. The equivalent linear address for the banked address 0x120, as used above, is 0x20A0, for example. The following argument is the number of bytes that is to be reserved. In this case, a preprocessor macro has been used to represent the array size. This macro has been defined in the build options, as shown in section Building the Example. The final argument is a symbol. This is optional and creates a label for the object at the indicated address.

Unlike most directives, the DLABS directive does not produce output that is part of the current psect, so it can appear at any location in the source file. This also means that there should not be a label placed immediately before the directive. If a label is required for the object you are defining, then specify it as the last argument of the directive, as shown above.

In this example, the compiler will reserve storage for the levels object in banks 2 and 3, as specified by the address used with the directive. While it is possible to access this memory using the ordinary file register instructions, such access can become problematic if the offset into the array is not known, as it is not clear which bank needs to be selected beforehand. The Enhanced Mid-range devices, however, allow you to use the FSR register to indirectly read and write data memory using a linear address and without banking. Accessing levels indirectly is shown in the example and is repeated here.
storeLevel:
	movwf     tmp                 ;store the parameter
	movf      count,w             ;add the count index to...
	addlw     low(levels)         ;the linear base address of the array...
	movwf     FSR1L               ;storing the result in FSR1
	movlw     high(levels)
	clrf      FSR1H
	addwfc    FSR1H
	movf      tmp,w               ;retrieve the parameter
	movwf     INDF1               ;access levels using linear memory

Since it was defined using the DLABS directive, the symbol levels will always represent a linear address. This is still true even if a banked address was used as the second argument to this directive. Such an address can be loaded directly into an FSR register when linear access is required. The linear address value of the symbol can be found in the assembly list file and also in the map file if the symbol was made globally accessible using the GLOBAL directive.