10.5.6. Placing a Section at Different Load and Run Addresses

At times, you may want to load code into one area of memory and run it in another. For example, you may have performance-critical code in slow external memory. The code must be loaded into slow external memory, but it would run faster in fast external memory.

The linker provides a simple way to accomplish this. You can use the SECTIONS directive to direct the linker to allocate a section twice: once to set its load address and again to set its run address. For example:

.fir: load = SLOW_MEM, run = FAST_MEM

Use the load keyword for the load address and the run keyword for the run address.

See Run-Time Relocation for an overview on run-time relocation.

The application must copy the section from its load address to its run address; this does not happen automatically when you specify a separate run address. (The TABLE operator instructs the linker to produce a copy table; see The table() Operator.)

10.5.6.1. Specifying Load and Run Addresses

The load address determines where a loader places the raw data for the section. Any references to the section (such as labels in it) refer to its run address. See Load and Run Addresses for an overview of load and run addresses.

If you provide only one allocation (either load or run) for a section, the section is allocated only once and loads and runs at the same address. If you provide both allocations, the section is allocated as if it were two sections of the same size. This means that both allocations occupy space in the memory map and cannot overlay each other or other sections. (The UNION directive provides a way to overlay sections; see Overlaying Sections With the UNION Statement.)

If either the load or run address has additional parameters, such as alignment or blocking, list them after the appropriate keyword. Everything related to allocation after the keyword load affects the load address until the keyword run is seen, after which, everything affects the run address. The load and run allocations are completely independent, so any qualification of one (such as alignment) has no effect on the other. You can also specify run first, then load. Use parentheses to improve readability.

The examples that follow specify load and run addresses.

In this example, align applies only to load:

.data: load = SLOW_MEM, align = 32, run = FAST_MEM

The following example uses parentheses, but has effects that are identical to the previous example:

.data: load = (SLOW_MEM align 32), run = FAST_MEM

The following example aligns FAST_MEM to 32 bits for run allocations and aligns all load allocations to 16 bits:

.data: run  = FAST_MEM, align 32, load = align 16

For more information on run-time relocation see Run-Time Relocation.

Uninitialized sections (such as .bss) are not loaded, so their only significant address is the run address. The linker allocates uninitialized sections only once: if you specify both run and load addresses, the linker warns you and ignores the load address. Otherwise, if you specify only one address, the linker treats it as a run address, regardless of whether you call it load or run.

This example specifies load and run addresses for an uninitialized section:

.bss: load = 0x1000, run = FAST_MEM

A warning is issued, load is ignored, and space is allocated in FAST_MEM. All of the following examples have the same effect. The .bss section is allocated in FAST_MEM.

.dbss: load = FAST_MEM
.bss: run = FAST_MEM
.bss: > FAST_MEM

10.5.6.2. Referring to the Load Address by Using the .label Directive

Normally, any reference to a symbol refers to its run-time address. However, it may be necessary at run time to refer to a load-time address. Specifically, the code that copies a section from its load address to its run address must have access to the load address. The .label directive defines a special symbol that refers to the section’s load address. Thus, whereas normal symbols are relocated with respect to the run address, .label symbols are relocated with respect to the load address.

The following examples show assembly code that uses the .label directive to copy a section from its load address in SLOW_MEM to its run address in FAST_MEM. A linker command file to use with this assembly code is also provided. The figure that follows the examples illustrates the run-time execution of this code.

If you use the table operator, the .label directive is not needed. See The table() Operator.

;-----------------------------------------------------------
;    define a section to be copied from SLOW_MEM to FAST_MEM
;-----------------------------------------------------------
         .sect ".fir"
         .label fir_src      ; load address of section
fir:                         ; run address of section
         <code here>         ; code for section
        .label fir_end       ; load address of section end
;-----------------------------------------------------------
; copy .fir section from SLOW_MEM to FAST_MEM
;-----------------------------------------------------------
        .text

        LDR     r4, fir_s    ; get fir load address start
        LDR     r5, fir_e    ; get fir load address stop
        LDR     r3, fir_a    ; get fir run address
$1:     CMP     r4, r5
        LDRCC   r0, [r4], #4 ; copy fir routine to its
                             ; run address
        STRCC   r0, [r3], #4
        BCC     $1
;-----------------------------------------------------------
; jump to fir routine, now in FAST_MEM
;-----------------------------------------------------------
        B       fir
fir_a   .word   fir
fir_s   .word   fir_start
fir_e   .word   fir_end

The following linker command file is used with the code above:

/******************************************************/
/* PARTIAL LINKER COMMAND FILE FOR FIR EXAMPLE        */
/******************************************************/
MEMORY
{
    FAST_MEM : origin = 0x00001000, length = 0x00001000
    SLOW_MEM : origin = 0x10000000, length = 0x00001000
}

SECTIONS
{
    .text: load = FAST_MEM
    .fir: load = SLOW_MEM, run FAST_MEM
}

The following figure shows the run-time execution of the code in the assembly example above that moves a function from slow to fast memory.

../../../_images/runtime_exe_tdz075.png

See Using Linker Symbols in C/C++ Applications for information about referring to linker symbols in C/C++ code.