2.6.1. Direct loading with ADR and ADRL

The ADR and ADRL pseudo-instructions enable you to generate an address, within a certain range, without performing a data load. ADR and ADRL accept a program-relative expression, that is, a label with an optional offset where the address of the label is relative to the current PC.

Note

The label used with ADR or ADRL must be within the same code section. The assembler faults references to labels that are out of range in the same section. The linker faults references to labels that are out of range in other code sections.

In Thumb state, a 16-bit ADR instruction can generate word-aligned addresses only.

ADRL is not available in Thumb code. Use it only in ARM code.

ADR

The assembler converts an ADR rn,label pseudo-instruction by generating:

  • a single ADD or SUB instruction that loads the address, if it is in range

  • an error message if the address cannot be reached in a single instruction.

The available range depends on the instruction set:

ARM

±255 bytes to a byte or halfword-aligned address.

±1020 bytes to a word-aligned address.

32-bit Thumb-2

±4095 bytes to a byte, halfword, or word-aligned address.

16-bit Thumb

0 to 1020 bytes. label must be word-aligned. You can use the ALIGN directive to ensure this.

See ADR pseudo-instruction for details.

ADRL

The assembler converts an ADRL rn,label pseudo-instruction by generating:

  • two data processing instructions that load the address, if it is in range

  • an error message if the address cannot be constructed in two instructions.

The available range depends on the instruction set in use:

ARM

±64KB to a byte or halfword-aligned address.

±256KB bytes to a word-aligned address.

32-bit Thumb-2

±1MB bytes to a byte, halfword, or word-aligned address.

16-bit Thumb

ADRL is not available.

See Loading addresses with LDR Rd, =label for information on loading addresses that are outside the range of the ADRL pseudo-instruction.

Implementing a jump table with ADR

Example 2.5 shows ARM code that implements a jump table. Here the ADR pseudo-instruction loads the address of the jump table. It is supplied as jump.s in the main examples directory install_directory\RVDS\Examples. See Code examples for instructions on how to assemble, link, and execute the example.

Example 2.5. Implementing a jump table (ARM)

        AREA    Jump, CODE, READONLY     ; Name this block of code
        CODE32                           ; Following code is ARM code
num     EQU     2                        ; Number of entries in jump table
        ENTRY                            ; Mark first instruction to execute
start                                    ; First instruction to call
        MOV     r0, #0                   ; Set up the three parameters
        MOV     r1, #3
        MOV     r2, #2
        BL      arithfunc                ; Call the function
stop
        MOV     r0, #0x18                ; angel_SWIreason_ReportException
        LDR     r1, =0x20026             ; ADP_Stopped_ApplicationExit
        SWI     0x123456                 ; ARM semihosting SWI
arithfunc                                ; Label the function
        CMP     r0, #num                 ; Treat function code as unsigned integer
        BXHS    lr                       ; If code is >= num then simply return
        ADR     r3, JumpTable            ; Load address of jump table
        LDR     pc, [r3,r0,LSL#2]        ; Jump to the appropriate routine
JumpTable
        DCD     DoAdd
        DCD     DoSub

DoAdd
        ADD     r0, r1, r2               ; Operation 0
        BX      lr                       ; Return
DoSub
        SUB     r0, r1, r2               ; Operation 1
        BX      lr                       ; Return
        END                              ; Mark the end of this file

In Example 2.5, the function arithfunc takes three arguments and returns a result in r0. The first argument determines the operation to be carried out on the second and third arguments:

argument1=0

Result = argument2 + argument3.

argument1=1

Result = argument2 – argument3.

The jump table is implemented with the following instructions and assembler directives:

EQU

Is an assembler directive. It is used to give a value to a symbol. In Example 2.5 it assigns the value 2 to num. When num is used elsewhere in the code, the value 2 is substituted. Using EQU in this way is similar to using #define to define a constant in C.

DCD

Declares one or more words of store. In Example 2.5 each DCD stores the address of a routine that handles a particular clause of the jump table.

LDR

The LDR pc,[r3,r0,LSL#2] instruction loads the address of the required clause of the jump table into the PC. It:

  • multiplies the clause number in r0 by 4 to give a word offset

  • adds the result to the address of the jump table

  • loads the contents of the combined address into the PC.

Copyright © 2002-2005 ARM Limited. All rights reserved.ARM DUI 0204F
Non-Confidential