7.2.1. The Branch Exchange instruction

The BX instruction branches to the address contained in a specified register. The value of bit 0 of the branch address determines whether execution continues in ARM state or Thumb state.

Bit 0 of an address can be used in this way because:

The BX instruction is implemented on Thumb-capable ARM processors only.

Syntax

The syntax of BX is one of:

Thumb
BX Rn
ARM
BX{cond} Rn

where:

Rn

is a register in the range r0 to r15 that contains the address to branch to. The value of bit 0 in this register determines the processor state:

  • if bit 0 is set, the instruction at the branch address is executed in Thumb state

  • if bit 0 is clear, the instruction at the branch address is executed in ARM state.

cond

is an optional condition code. Only the ARM version of BX can be executed conditionally.

Usage

  • You can also use BX for branches that do not change state. You can use this to execute branches that are out of range of the normal branch instructions. Because BX takes a 32-bit register operand it can branch anywhere in 32-bit memory. The B and BL instructions are limited to:

    • 32 MB in ARM state, for both conditional and unconditional B and BL instructions

    • 4 MB in Thumb state, for unconditional B and BL instructions

    • -128 to +127 instructions in Thumb state, for the conditional B instruction.

Note

The BX instruction is only implemented on ARM processors that are Thumb-capable. If you use BX to execute long branches your code will fail on processors that are not Thumb-capable. The result of a BX instruction on a processor that is not Thumb-capable is unpredictable.

Changing the assembler mode

The ARM assembler can assemble both Thumb code and ARM code. By default, it assembles ARM code unless it is invoked with the -16 option.

Because all Thumb-capable ARM processors start in ARM state, you must use the BX instruction to branch and exchange to Thumb state, and then use the CODE16 directive to instruct the assembler to assemble Thumb instructions.

Refer to the ARM Software Development Toolkit Reference Guide for more information on these directives.

Example ARM header

Example 7.1 implements a short header section of ARM code that changes the processor to Thumb state.

The header code uses:

  • An ADR instruction to load the branch address and set the least significant bit. The ADR instruction generates the address by loading r2 with the value pc+offset. See Direct loading with ADR and ADRL for more information on the ADR instruction.

  • A BX (Branch exchange) instruction to branch to the Thumb code and change processor state.

The main body of the module is prefixed by a CODE16 directive that instructs the assembler to treat the following code as Thumb code. The Thumb code adds the contents of two registers together.

The code section labeled stop uses the Thumb Angel SWI to exit. The SWI reports an exception reason, specified in r1, to the debugger. In this case it is used to report normal application exit. Refer to Chapter 13 Angel for more information on Angel.

Note

The Thumb Angel semihosting SWI is, by default, a different number from the ARM semihosting SWI (0xAB rather than 0x123456).

Example 7.1. 

		AREA		AddReg,CODE,READONLY				
									; Name this block of code.
		ENTRY							; Mark first instruction to call.
main
		ADR	r2, ThumbProg + 1						; Generate branch target address 
									; and set bit 0, hence arrive
									; at target in Thumb state.
		BX	r2						; Branch exchange to ThumbProg.
		CODE16							; Subsequent instructions 
									; are Thumb.
ThumbProg
		MOV	r2, #2						; Load r2 with value 2.
		MOV	r3, #3						; Load r3 with value 3.
		ADD	r2, r2, r3						; r2 = r2 + r3
stop		MOV	r0, #0x18						; angel_SWIreason_ReportException
		LDR	r1, =0x20026						; ADP_Stopped_ApplicationExit
		SWI 	0xAB						; Angel semihosting Thumb SWI 
		END							; Mark end of this file.

Building the example

To build and execute the example:

  1. Enter the code using any text editor and save the file as addreg.s.

  2. Type asm -g addreg.s at the command prompt to assemble the source file.

  3. Type armlink addreg.o -o addreg to link the file.

  4. Type armsd addreg to load the module into the command-line debugger

  5. Type break @start at the armsd command prompt to set a breakpoint on the label start.

  6. Type go to execute the program.

  7. When the breakpoint is hit, type step to single step through the rest of the program. Type reg to display the registers after each step and watch the processor enter Thumb state. This is denoted by the T in the Current Program Status Register (cpsr) changing from a lowercase "t" to an uppercase "T".

Copyright © 1997, 1998 ARM Limited. All rights reserved.ARM DUI 0040D
Non-Confidential