7.3.2. Compiling code for Interworking

The -apcs /interwork compiler option enables all ARM and Thumb C and C++ compilers to compile modules containing routines that can be called by routines compiled for the other processor state:

tcc -apcs /interwork
armcc -apcs /interwork
tcpp -apcs /interwork
armcpp -apcs /interwork

Modules that are compiled for interworking generate slightly (typically 2%) larger code for Thumb and marginally larger code for ARM.

For a leaf function, (that is, a function whose body contains no function calls), the only change in the code generated by the compiler is to replace MOV pc,lr with BX lr. For non-leaf functions, the Thumb compiler must replace, for example, the single instruction:

	POP	{r4,r5,pc}

with the sequence:

	POP	{r4,r5}
	POP	{r3}
	BX	r3

This has a correspondingly small effect on performance. It is not necessary to compile all source modules for interworking, only those that contain subroutines called through interworking calls.

In addition, the -apcs /interwork option sets the interwork attribute for the code area into which the modules are compiled. The linker detects this attribute and inserts the appropriate veneer. The sizes of the veneers are:


ARM code compiled for interworking cannot be used on ARM processors that are not Thumb-capable because these processors do not implement the BX instruction.

Use the armlink -info total option to find the amount of space taken by the veneers. The interworking veneers are included in the const data column of the object totals. See Figure 7.1 for an example.

Figure 7.1. Total code sizes

                    code   inline   inline  'const'       RW   0-Init    debug
                    size     data  strings     data     data     data     data
Object totals         32        0       92       20        0        0        0
Library totals      6924     1516      532        4      264     1104     2224
Grand totals        6956     1516      624       24      264     1104     2224
Debug Area Optimization Statistics
Input debug total(excluding low level debug areas)      2224 (2.17Kb)
Output debug total                                      2224 (2.17Kb)
% reduction                                             0.00%

Use the armlink -info size option to see more detail. The space taken by the veneers is displayed as an <anon> row entry at the top of the table. See Figure 7.2 for an example.

Figure 7.2. Interworking veneer sizes

object file        code   inline   inline  'const'       RW   0-Init    debug
                   size     data  strings     data     data     data     data
arm.o                 8        0       36        0        0        0        0
thumb.o              24        0       56        0        0        0        0
<anon>                0        0        0       20        0        0        0

Simple C interworking example

The two modules in Example 7.4 can be built to produce an application where main() is a Thumb routine that carries out an interworking call to an ARM subroutine. The subroutine call itself makes an interworking call to the Thumb library routine, printf().

Example 7.4. 

	*       thumb.c      *
	#include <stdio.h>
	extern void arm_function(void);
	int main(void)
		printf("Hello from Thumb World\n");
		printf("And goodbye from Thumb World\n");
		return (0);
	*        arm.c       *
	#include <stdio.h>
	void arm_function(void)
		printf("Hello and Goodbye from ARM world\n");

To compile and link these modules:

  1. Type tcc -c -apcs /interwork -o thumb.o thumb.c at the system prompt to compile the Thumb code for interworking.

  2. Type armcc -c -apcs /interwork -o arm.o arm.c to compile the ARM code for interworking.

  3. Type armlink -o hello thumb.o to link the object files.

    Alternatively, type armlink -info size thumb.o arm.o to view the size of the interworking veneers in the <anon> column (see Figure 7.2).

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