# Using the Barrel Shifter

In this recipe you learn:

- how to index into an array efficiently in ARM assembler.
- how to use the barrel shifter in the main ARM instruction classes;

## Addressing an entry in a table of words

The following piece of code inefficiently calculates the address of an entry in a table of words and then loads the desired word:

``

    ; R0 holds the entry number [0,1,2,...]
        LDR  R1, =StartOfTable
        MOV  R3, #4
        MLA  R1, R0, R3, R1
        LDR  R2, [R1]
        ...
    StartOfTable
        DCD table data

Loading the desired table entry is performed by first loading the start address of the table, then moving the immediate constant "4" into a register, using the multiply and add instruction to calculate the address, and finally loading the entry. However, this operation can be performed by the barrel shifter more efficiently as follows:

``

    ; R0 holds the entry number [0,1,2,...]
        LDR  R1, =StartOfTable
        LDR  R2, [R1, R0, LSL #2]
        ...
    StartOfTable
        DCD table data

In this code the barrel shifter shifts R0 left 2 bits (ie. multiplying it by 4), this intermediate value is then used as the index for the LDR instruction. Thus a single instruction is used to perform the whole operation. Such significant savings can frequently be made by making good use of the barrel shifter.

## The ARM's Barrel Shifter

The ARM core contains a Barrel shifter which takes a value to be shifted or rotated, an amount to shift or rotate by and the type of shift or rotate. This can be used by various classes of ARM instructions to perform comparatively complex operations in a single instruction. On ARMs up to and including the ARM6 family, instructions take no longer to execute by making use of the barrel shifter, unless the amount to be shifted is specified by a register, in which case the instruction will take an extra cycle to complete.

The barrel shifter can perform the following types of operation:

    --------------------------------------------------------
    LSL  |shift left by n bits;
    --------------------------------------------------------
    LSR  |logical shift right by n bits;
    --------------------------------------------------------
    ASR  |arithmetic shift right by n bits (the bits fed
         |into the top end of the operand are copies of the
         |original top (or sign) bit);
    --------------------------------------------------------
    ROR  |rotate right by n bits;
    --------------------------------------------------------
    RRX  |rotate right extended by 1 bit.  This is a 33 bit
         |rotate, where the 33rd bit is the PSR C flag.
    --------------------------------------------------------

The barrel shifter can be used in several of the ARM's instruction classes. The options available in each case are described below.

## LDR/STR

The index can be a register shifted by any 5 bit constant. It may also be an unshifted 12 bit constant, for example:

``

    STR  R7, [R0], #24                                 ;Post-indexed
    LDR  R2, [R0], R4, ASR #4                          ;Post-indexed
    STR  R3, [R0, R5, LSL #3]                          ;Pre-indexed
    LDR  R6, [R0, R1, ROR #6]!                         ;Pre-indexed + Writeback

### Explanation

In all of the above instructions R0 is the base register.

In the pre-indexed instructions the offset is calculated and added to the base. This address is used for the transfer. If writeback is selected, then the transfer address is written back into the base register.

In the post-indexed instructions the offset is calculated and added to the base after the transfer. The base register is always updated by post-indexed instructions.

## Data processing operations

The last operand (the second for binary operations, and the first for unary operations) may be:

- an 8 bit constant rotated right through an even number of positions. eg.

`

        ADD R0, R1, #&C5, 10
        MOV R5, #&FC000003

`

- Note that in the second example the assembler is left to work out how to split the constant &FC000003 into an 8 bit constant and an even shift (in this case "#&FC000003" could be replaced by "#&FF, 6"). See Loading constants into registers for more information.

- a register (optionally) shifted or rotated either by a 5-bit constant or by another register. eg.

`

        ADD R0, R1, R2
        SUB R0, R1, R2, LSR #10
        CMP R1, R2, R1, ROR R5
        MVN R3, R2, RRX

`

## Program status register transfer instructions

For the precise format of these instructions see the appropriate datasheet.

## Related topics

For more examples which make good use of the barrel shifter see many of the recipes in Exploring ARM Assembly Language.

The following cover loading constants into registers, and explain how armasm can help out the assembly language programmer:

- MOV / MVN;
- LDR Rd, =numeric constant.