7.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:

Example of assembly language interworking using veneers

Example 7.5 sets registers r0 to r2 to the values 1, 2, and 3 respectively. Registers r0 and r2 are set by the ARM code. Register r1 is set by the Thumb code. Note that:

  • the INTERWORK attribute is set in the area definition of thumb.s

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

Example 7.5. 

	; *****
	; arm.s
	; *****
	AREA		Arm,CODE,READONLY						; Name this block of code.
	IMPORT		ThumbProg
	ENTRY								; Mark 1st instruction to call.
ARMProg
	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
	SWI	0xAB							; Angel semihosting Thumb SWI 
	END
	; *******
	; thumb.s
	; *******
	AREA  Thumb,CODE,READONLY,INTERWORK
									; Name this block of code.
	CODE16								; Subsequent instructions are Thumb.
	EXPORT		ThumbProg
ThumbProg
	MOV   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 arm.s to assemble the ARM code.

  2. Type armasm -16 thumb.s to assemble the Thumb code.

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

  4. Type armsd count to load the code into the debugger.

  5. Type list 0x8000 at the armsd command prompt to list the code. Figure 7.5 shows an example.

    Figure 7.5. Example veneer


    armsd: list 0x8000
    Arm
    +0000 0x00008000: 0xe3a00001  .... : >  mov      r0,#1
    +0004 0x00008004: 0xeb000005  .... :    bl       0x8020  ; (ThumbProg + 0x4)
    +0008 0x00008008: 0xe3a02003  . .. :    mov      r2,#3
    +000c 0x0000800c: 0xe3a00018  .... :    mov      r0,#0x18
    +0010 0x00008010: 0xe59f1000  .... :    ldr      r1,0x00008018 ; = #0x00020026
    +0014 0x00008014: 0xef0000ab  .... :    swi      0xab
    +0018 0x00008018: 0x00020026  &... :    dcd      0x00020026  &...
    ThumbProg
    +0000 0x0000801c: 0x2102      .!   :    mov      r1,#2
    +0002 0x0000801e: 0x4770      pG   :    bx       r14
    +0004 0x00008020: 0xe59fc000  .... :    ldr      r12,0x00008028 
    ; = #ThumbProg+0x1
    +0008 0x00008024: 0xe12fff1c  ../. :    bx       r12
    +000c 0x00008028: 0x0000801d  .... :    andeq    r8,r0,r13,lsl r0
    _edata
    +0000 0x0000802c: 0xe800e800  .... :    stmda    r0,{r11,r13-pc}

    You can see that the linker has added the required ARM-to-Thumb interworking veneer. This is contained in locations 0x8020 to 0x8028. Location 0x8028 contains the address of the routine being branch-exchanged to, with bit 0 set.

Note

The addresses may vary depending on the version of the toolkit you are using.

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