4.4.1. Assembly-only interworking using veneers

You can write assembly language ARM/Thumb interworking code to make use of interworking veneers generated by the linker. To do this, you write:

This is generally only necessary in ARMv4T, or if the caller and callee are widely separated or in different areas. In ARMv5T and later, if the caller and callee are sufficiently close together, no veneers are necessary.

Example of assembly language interworking using veneers

Example 4.6 shows the code to set registers r0 to r2 to the values 1, 2, and 3 respectively. Registers r0 and r2 are set by the ARM code. r1 is set by the Thumb code. Observe that:

  • the code must be assembled with the option --apcs /interwork

  • a BX lr instruction is used to return from the subroutine, instead of the usual MOV pc,lr.

Example 4.6. 

     ; *****
     ; arm.s
     ; *****


     AREA     Arm,CODE,READONLY   ; Name this block of code.	
     IMPORT     ThumbProg	
     ENTRY                        ; Mark 1st instruction to call.	
     MOV  r0,#1                   ; Set r0 to show in ARM code.	
     BL   ThumbProg               ; Call Thumb subroutine.		
     MOV  r2,#3                   ; Set r2 to show returned to ARM.	
                                  ; Terminate execution.	
     MOV  r0, #0x18               ; angel_SWIreason_ReportException	
     LDR  r1, =0x20026            ; ADP_Stopped_ApplicationExit	
     SVC 0x123456                 ; ARM semihosting (formerly SWI)

     ; *******
     ; thumb.s
     ; *******
     AREA  Thumb,CODE,READONLY	    ; Name this block of code.	
     THUMB                        ; Subsequent instructions are Thumb.	
     EXPORT ThumbProg	
     MOVS  r1, #2                 ; Set r1 to show reached Thumb code.	
     BX   lr                      ; Return to ARM subroutine.	
     END                          ; Mark end of this file.

Follow these steps to build and link the modules, and examine the interworking veneers:

  1. Type armasm -g arm.s to assemble the ARM code.

  2. Type armasm --thumb -g --apcs /interwork thumb.s to assemble the Thumb code.

  3. Type armlink arm.o thumb.o -o count to link the two object files.

  4. Run the image using a compatible debugger (for example, RealView Debugger or AXD) with an appropriate debug target.

You can see the interworking veneer that is inserted by the linker in the disassembled code shown in Example 4.7. The veneer is inserted on the next word boundary, and starts at address 0x0000801C.

Example 4.7. 

   00008000 E3A00001  MOV      r0,#1
   00008004 EB000004  BL       0x801c
   00008008 E3A02003  MOV      r2,#3
   0000800C E3A00018  MOV      r0,#0x18
   00008010 E59F1000  LDR      r1,0x8018
   00008014 EF123456  SVC      0x123456
   00008018 00020026  <Data> '&' 0x00 0x02 0x00
   0000801C E28FC001  ADR      r12,{pc}+9 ; #0x8025
   00008020 E12FFF1C  BX       r12
   00008024     2102  MOV      r1,#2
   00008026     4770  BX       r14

Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203G