190075Sobrien		Arm / Thumb Interworking
290075Sobrien		========================
390075Sobrien
490075SobrienThe Cygnus GNU Pro Toolkit for the ARM7T processor supports function
590075Sobriencalls between code compiled for the ARM instruction set and code
690075Sobriencompiled for the Thumb instruction set and vice versa.  This document
790075Sobriendescribes how that interworking support operates and explains the
890075Sobriencommand line switches that should be used in order to produce working
990075Sobrienprograms.
1090075Sobrien
1190075SobrienNote:  The Cygnus GNU Pro Toolkit does not support switching between
1290075Sobriencompiling for the ARM instruction set and the Thumb instruction set
1390075Sobrienon anything other than a per file basis.  There are in fact two
1490075Sobriencompletely separate compilers, one that produces ARM assembler
1590075Sobrieninstructions and one that produces Thumb assembler instructions.  The
1690075Sobrientwo compilers share the same assembler, linker and so on.
1790075Sobrien
1890075Sobrien
1990075Sobrien1. Explicit interworking support for C and C++ files
2090075Sobrien====================================================
2190075Sobrien
2290075SobrienBy default if a file is compiled without any special command line
2390075Sobrienswitches then the code produced will not support interworking.
2490075SobrienProvided that a program is made up entirely from object files and
2590075Sobrienlibraries produced in this way and which contain either exclusively
2690075SobrienARM instructions or exclusively Thumb instructions then this will not
2790075Sobrienmatter and a working executable will be created.  If an attempt is
2890075Sobrienmade to link together mixed ARM and Thumb object files and libraries,
2990075Sobrienthen warning messages will be produced by the linker and a non-working
3090075Sobrienexecutable will be created.
3190075Sobrien
3290075SobrienIn order to produce code which does support interworking it should be
3390075Sobriencompiled with the
3490075Sobrien
3590075Sobrien	-mthumb-interwork
3690075Sobrien
3790075Sobriencommand line option.  Provided that a program is made up entirely from
3890075Sobrienobject files and libraries built with this command line switch a
3990075Sobrienworking executable will be produced, even if both ARM and Thumb
4090075Sobrieninstructions are used by the various components of the program.  (No
4190075Sobrienwarning messages will be produced by the linker either).
4290075Sobrien
4390075SobrienNote that specifying -mthumb-interwork does result in slightly larger,
4490075Sobrienslower code being produced.  This is why interworking support must be
4590075Sobrienspecifically enabled by a switch.
4690075Sobrien
4790075Sobrien
4890075Sobrien2. Explicit interworking support for assembler files
4990075Sobrien====================================================
5090075Sobrien
5190075SobrienIf assembler files are to be included into an interworking program
5290075Sobrienthen the following rules must be obeyed:
5390075Sobrien
5490075Sobrien	* Any externally visible functions must return by using the BX
5590075Sobrien	instruction.
5690075Sobrien
5790075Sobrien	* Normal function calls can just use the BL instruction.  The
5890075Sobrien	linker will automatically insert code to switch between ARM
5990075Sobrien	and Thumb modes as necessary.
6090075Sobrien
6190075Sobrien	* Calls via function pointers should use the BX instruction if
6290075Sobrien	the call is made in ARM mode:
6390075Sobrien
6490075Sobrien		.code 32
6590075Sobrien		mov lr, pc
6690075Sobrien		bx  rX
6790075Sobrien
6890075Sobrien	This code sequence will not work in Thumb mode however, since
6990075Sobrien	the mov instruction will not set the bottom bit of the lr
7090075Sobrien	register.  Instead a branch-and-link to the _call_via_rX
7190075Sobrien	functions should be used instead:
7290075Sobrien
7390075Sobrien		.code 16
7490075Sobrien		bl  _call_via_rX
7590075Sobrien
7690075Sobrien	where rX is replaced by the name of the register containing
7790075Sobrien	the function address.
7890075Sobrien
7990075Sobrien	* All externally visible functions which should be entered in
8090075Sobrien	Thumb mode must have the .thumb_func pseudo op specified just
81169689Skan	before their entry point.  e.g.:
8290075Sobrien
8390075Sobrien			.code 16
8490075Sobrien			.global function
8590075Sobrien			.thumb_func
8690075Sobrien		function:
8790075Sobrien			...start of function....
8890075Sobrien
8990075Sobrien	* All assembler files must be assembled with the switch
9090075Sobrien	-mthumb-interwork specified on the command line.  (If the file
9190075Sobrien	is assembled by calling gcc it will automatically pass on the
9290075Sobrien	-mthumb-interwork switch to the assembler, provided that it
9390075Sobrien	was specified on the gcc command line in the first place.) 
9490075Sobrien
9590075Sobrien
9690075Sobrien3. Support for old, non-interworking aware code.
9790075Sobrien================================================
9890075Sobrien
9990075SobrienIf it is necessary to link together code produced by an older,
10090075Sobriennon-interworking aware compiler, or code produced by the new compiler
10190075Sobrienbut without the -mthumb-interwork command line switch specified, then
10290075Sobrienthere are two command line switches that can be used to support this.
10390075Sobrien
10490075SobrienThe switch
10590075Sobrien
10690075Sobrien	-mcaller-super-interworking
10790075Sobrien
10890075Sobrienwill allow calls via function pointers in Thumb mode to work,
10990075Sobrienregardless of whether the function pointer points to old,
11090075Sobriennon-interworking aware code or not.  Specifying this switch does
11190075Sobrienproduce slightly slower code however.
11290075Sobrien
11390075SobrienNote:  There is no switch to allow calls via function pointers in ARM
11490075Sobrienmode to be handled specially.  Calls via function pointers from
11590075Sobrieninterworking aware ARM code to non-interworking aware ARM code work
11690075Sobrienwithout any special considerations by the compiler.  Calls via
11790075Sobrienfunction pointers from interworking aware ARM code to non-interworking
11890075Sobrienaware Thumb code however will not work.  (Actually under some
11990075Sobriencircumstances they may work, but there are no guarantees).  This is
12090075Sobrienbecause only the new compiler is able to produce Thumb code, and this
12190075Sobriencompiler already has a command line switch to produce interworking
12290075Sobrienaware code.
12390075Sobrien
12490075Sobrien
12590075SobrienThe switch
12690075Sobrien
12790075Sobrien	-mcallee-super-interworking
12890075Sobrien
12990075Sobrienwill allow non-interworking aware ARM or Thumb code to call Thumb
13090075Sobrienfunctions, either directly or via function pointers.  Specifying this
13190075Sobrienswitch does produce slightly larger, slower code however.
13290075Sobrien
13390075SobrienNote:  There is no switch to allow non-interworking aware ARM or Thumb
13490075Sobriencode to call ARM functions.  There is no need for any special handling
13590075Sobrienof calls from non-interworking aware ARM code to interworking aware
13690075SobrienARM functions, they just work normally.  Calls from non-interworking
13790075Sobrienaware Thumb functions to ARM code however, will not work.  There is no
13890075Sobrienoption to support this, since it is always possible to recompile the
13990075SobrienThumb code to be interworking aware.
14090075Sobrien
14190075SobrienAs an alternative to the command line switch
14290075Sobrien-mcallee-super-interworking, which affects all externally visible
14390075Sobrienfunctions in a file, it is possible to specify an attribute or
14490075Sobriendeclspec for individual functions, indicating that that particular
14590075Sobrienfunction should support being called by non-interworking aware code.
14690075SobrienThe function should be defined like this:
14790075Sobrien
14890075Sobrien	int __attribute__((interfacearm)) function 
14990075Sobrien	{
15090075Sobrien		... body of function ...
15190075Sobrien	}
15290075Sobrien
15390075Sobrienor
15490075Sobrien
15590075Sobrien	int __declspec(interfacearm) function
15690075Sobrien	{
15790075Sobrien		... body of function ...
15890075Sobrien	}
15990075Sobrien
16090075Sobrien
16190075Sobrien
16290075Sobrien4. Interworking support in dlltool
16390075Sobrien==================================
16490075Sobrien
16590075SobrienIt is possible to create DLLs containing mixed ARM and Thumb code.  It
16690075Sobrienis also possible to call Thumb code in a DLL from an ARM program and
16790075Sobrienvice versa.  It is even possible to call ARM DLLs that have been compiled
16890075Sobrienwithout interworking support (say by an older version of the compiler),
16990075Sobrienfrom Thumb programs and still have things work properly.
17090075Sobrien
17190075Sobrien   A version of the `dlltool' program which supports the `--interwork'
17290075Sobriencommand line switch is needed, as well as the following special
17390075Sobrienconsiderations when building programs and DLLs:
17490075Sobrien
17590075Sobrien*Use `-mthumb-interwork'*
17690075Sobrien     When compiling files for a DLL or a program the `-mthumb-interwork'
17790075Sobrien     command line switch should be specified if calling between ARM and
17890075Sobrien     Thumb code can happen.  If a program is being compiled and the
17990075Sobrien     mode of the DLLs that it uses is not known, then it should be
18090075Sobrien     assumed that interworking might occur and the switch used.
18190075Sobrien
18290075Sobrien*Use `-m thumb'*
18390075Sobrien     If the exported functions from a DLL are all Thumb encoded then the
18490075Sobrien     `-m thumb' command line switch should be given to dlltool when
18590075Sobrien     building the stubs.  This will make dlltool create Thumb encoded
18690075Sobrien     stubs, rather than its default of ARM encoded stubs.
18790075Sobrien
18890075Sobrien     If the DLL consists of both exported Thumb functions and exported
18990075Sobrien     ARM functions then the `-m thumb' switch should not be used.
19090075Sobrien     Instead the Thumb functions in the DLL should be compiled with the
19190075Sobrien     `-mcallee-super-interworking' switch, or with the `interfacearm'
19290075Sobrien     attribute specified on their prototypes.  In this way they will be
19390075Sobrien     given ARM encoded prologues, which will work with the ARM encoded
19490075Sobrien     stubs produced by dlltool.
19590075Sobrien
19690075Sobrien*Use `-mcaller-super-interworking'*
19790075Sobrien     If it is possible for Thumb functions in a DLL to call
19890075Sobrien     non-interworking aware code via a function pointer, then the Thumb
19990075Sobrien     code must be compiled with the `-mcaller-super-interworking'
20090075Sobrien     command line switch.  This will force the function pointer calls
20190075Sobrien     to use the _interwork_call_via_rX stub functions which will
20290075Sobrien     correctly restore Thumb mode upon return from the called function.
20390075Sobrien
20490075Sobrien*Link with `libgcc.a'*
20590075Sobrien     When the dll is built it may have to be linked with the GCC
20690075Sobrien     library (`libgcc.a') in order to extract the _call_via_rX functions
20790075Sobrien     or the _interwork_call_via_rX functions.  This represents a partial
20890075Sobrien     redundancy since the same functions *may* be present in the
20990075Sobrien     application itself, but since they only take up 372 bytes this
21090075Sobrien     should not be too much of a consideration.
21190075Sobrien
21290075Sobrien*Use `--support-old-code'*
21390075Sobrien     When linking a program with an old DLL which does not support
21490075Sobrien     interworking, the `--support-old-code' command line switch to the
21590075Sobrien     linker should be used.   This causes the linker to generate special
21690075Sobrien     interworking stubs which can cope with old, non-interworking aware
21790075Sobrien     ARM code, at the cost of generating bulkier code.  The linker will
21890075Sobrien     still generate a warning message along the lines of:
21990075Sobrien       "Warning: input file XXX does not support interworking, whereas YYY does."
22090075Sobrien     but this can now be ignored because the --support-old-code switch
22190075Sobrien     has been used.
22290075Sobrien
22390075Sobrien
22490075Sobrien
22590075Sobrien5. How interworking support works
22690075Sobrien=================================
22790075Sobrien
22890075SobrienSwitching between the ARM and Thumb instruction sets is accomplished
22990075Sobrienvia the BX instruction which takes as an argument a register name.
23090075SobrienControl is transfered to the address held in this register (with the
23190075Sobrienbottom bit masked out), and if the bottom bit is set, then Thumb
23290075Sobrieninstruction processing is enabled, otherwise ARM instruction
23390075Sobrienprocessing is enabled.
23490075Sobrien
23590075SobrienWhen the -mthumb-interwork command line switch is specified, gcc
23690075Sobrienarranges for all functions to return to their caller by using the BX
23790075Sobrieninstruction.  Thus provided that the return address has the bottom bit
238117395Skancorrectly initialized to indicate the instruction set of the caller,
23990075Sobriencorrect operation will ensue.
24090075Sobrien
24190075SobrienWhen a function is called explicitly (rather than via a function
24290075Sobrienpointer), the compiler generates a BL instruction to do this.  The
24390075SobrienThumb version of the BL instruction has the special property of
24490075Sobriensetting the bottom bit of the LR register after it has stored the
24590075Sobrienreturn address into it, so that a future BX instruction will correctly
24690075Sobrienreturn the instruction after the BL instruction, in Thumb mode.
24790075Sobrien
24890075SobrienThe BL instruction does not change modes itself however, so if an ARM
24990075Sobrienfunction is calling a Thumb function, or vice versa, it is necessary
25090075Sobriento generate some extra instructions to handle this.  This is done in
25190075Sobrienthe linker when it is storing the address of the referenced function
25290075Sobrieninto the BL instruction.  If the BL instruction is an ARM style BL
25390075Sobrieninstruction, but the referenced function is a Thumb function, then the
25490075Sobrienlinker automatically generates a calling stub that converts from ARM
25590075Sobrienmode to Thumb mode, puts the address of this stub into the BL
25690075Sobrieninstruction, and puts the address of the referenced function into the
25790075Sobrienstub.  Similarly if the BL instruction is a Thumb BL instruction, and
25890075Sobrienthe referenced function is an ARM function, the linker generates a
25990075Sobrienstub which converts from Thumb to ARM mode, puts the address of this
26090075Sobrienstub into the BL instruction, and the address of the referenced
26190075Sobrienfunction into the stub.
26290075Sobrien
26390075SobrienThis is why it is necessary to mark Thumb functions with the
26490075Sobrien.thumb_func pseudo op when creating assembler files.  This pseudo op
26590075Sobrienallows the assembler to distinguish between ARM functions and Thumb
26690075Sobrienfunctions.  (The Thumb version of GCC automatically generates these
26790075Sobrienpseudo ops for any Thumb functions that it generates).
26890075Sobrien
26990075SobrienCalls via function pointers work differently.  Whenever the address of
27090075Sobriena function is taken, the linker examines the type of the function
27190075Sobrienbeing referenced.  If the function is a Thumb function, then it sets
27290075Sobrienthe bottom bit of the address.  Technically this makes the address
27390075Sobrienincorrect, since it is now one byte into the start of the function,
27490075Sobrienbut this is never a problem because:
27590075Sobrien
27690075Sobrien	a. with interworking enabled all calls via function pointer
27790075Sobrien	   are done using the BX instruction and this ignores the
27890075Sobrien	   bottom bit when computing where to go to.
27990075Sobrien
28090075Sobrien	b. the linker will always set the bottom bit when the address
28190075Sobrien	   of the function is taken, so it is never possible to take
28290075Sobrien	   the address of the function in two different places and
28390075Sobrien	   then compare them and find that they are not equal.
28490075Sobrien
28590075SobrienAs already mentioned any call via a function pointer will use the BX
28690075Sobrieninstruction (provided that interworking is enabled).  The only problem
28790075Sobrienwith this is computing the return address for the return from the
28890075Sobriencalled function.  For ARM code this can easily be done by the code
28990075Sobriensequence:
29090075Sobrien
29190075Sobrien	mov	lr, pc
29290075Sobrien	bx	rX
29390075Sobrien
29490075Sobrien(where rX is the name of the register containing the function
29590075Sobrienpointer).  This code does not work for the Thumb instruction set,
29690075Sobriensince the MOV instruction will not set the bottom bit of the LR
29790075Sobrienregister, so that when the called function returns, it will return in
29890075SobrienARM mode not Thumb mode.  Instead the compiler generates this
29990075Sobriensequence:
30090075Sobrien
30190075Sobrien	bl	_call_via_rX
30290075Sobrien
30390075Sobrien(again where rX is the name if the register containing the function
30490075Sobrienpointer).  The special call_via_rX functions look like this:
30590075Sobrien
30690075Sobrien	.thumb_func
30790075Sobrien_call_via_r0:
30890075Sobrien	bx	r0
30990075Sobrien	nop
31090075Sobrien
31190075SobrienThe BL instruction ensures that the correct return address is stored
31290075Sobrienin the LR register and then the BX instruction jumps to the address
31390075Sobrienstored in the function pointer, switch modes if necessary.
31490075Sobrien
31590075Sobrien
31690075Sobrien6. How caller-super-interworking support works
31790075Sobrien==============================================
31890075Sobrien
31990075SobrienWhen the -mcaller-super-interworking command line switch is specified
32090075Sobrienit changes the code produced by the Thumb compiler so that all calls
32190075Sobrienvia function pointers (including virtual function calls) now go via a
32290075Sobriendifferent stub function.  The code to call via a function pointer now
32390075Sobrienlooks like this:
32490075Sobrien
32590075Sobrien	bl _interwork_call_via_r0
32690075Sobrien
32790075SobrienNote: The compiler does not insist that r0 be used to hold the
32890075Sobrienfunction address.  Any register will do, and there are a suite of stub
32990075Sobrienfunctions, one for each possible register.  The stub functions look
33090075Sobrienlike this:
33190075Sobrien
33290075Sobrien	.code 16
33390075Sobrien	.thumb_func
33490075Sobrien_interwork_call_via_r0
33590075Sobrien	bx 	pc
33690075Sobrien	nop
33790075Sobrien	
33890075Sobrien	.code 32
33990075Sobrien	tst	r0, #1
34090075Sobrien	stmeqdb	r13!, {lr}
34190075Sobrien	adreq	lr, _arm_return
34290075Sobrien	bx	r0
34390075Sobrien
34490075SobrienThe stub first switches to ARM mode, since it is a lot easier to
34590075Sobrienperform the necessary operations using ARM instructions.  It then
34690075Sobrientests the bottom bit of the register containing the address of the
34790075Sobrienfunction to be called.  If this bottom bit is set then the function
34890075Sobrienbeing called uses Thumb instructions and the BX instruction to come
34990075Sobrienwill switch back into Thumb mode before calling this function.  (Note
35090075Sobrienthat it does not matter how this called function chooses to return to
35190075Sobrienits caller, since the both the caller and callee are Thumb functions,
35290075Sobrienand mode switching is necessary).  If the function being called is an
35390075SobrienARM mode function however, the stub pushes the return address (with
35490075Sobrienits bottom bit set) onto the stack, replaces the return address with
35590075Sobrienthe address of the a piece of code called '_arm_return' and then
35690075Sobrienperforms a BX instruction to call the function.
35790075Sobrien
35890075SobrienThe '_arm_return' code looks like this:
35990075Sobrien
36090075Sobrien	.code 32
36190075Sobrien_arm_return:		
36290075Sobrien	ldmia 	r13!, {r12}
36390075Sobrien	bx 	r12
36490075Sobrien	.code 16
36590075Sobrien
36690075Sobrien
36790075SobrienIt simply retrieves the return address from the stack, and then
36890075Sobrienperforms a BX operation to return to the caller and switch back into
36990075SobrienThumb mode.
37090075Sobrien
37190075Sobrien
37290075Sobrien7. How callee-super-interworking support works
37390075Sobrien==============================================
37490075Sobrien
37590075SobrienWhen -mcallee-super-interworking is specified on the command line the
37690075SobrienThumb compiler behaves as if every externally visible function that it
37790075Sobriencompiles has had the (interfacearm) attribute specified for it.  What
37890075Sobrienthis attribute does is to put a special, ARM mode header onto the
37990075Sobrienfunction which forces a switch into Thumb mode:
38090075Sobrien
38190075Sobrien  without __attribute__((interfacearm)):
38290075Sobrien
38390075Sobrien		.code 16
38490075Sobrien		.thumb_func
38590075Sobrien	function:
38690075Sobrien		... start of function ...
38790075Sobrien
38890075Sobrien  with __attribute__((interfacearm)):
38990075Sobrien
39090075Sobrien		.code 32
39190075Sobrien	function:
39290075Sobrien		orr	r12, pc, #1
39390075Sobrien		bx	r12
39490075Sobrien
39590075Sobrien		.code 16
39690075Sobrien                .thumb_func
39790075Sobrien        .real_start_of_function:
39890075Sobrien
39990075Sobrien		... start of function ...
40090075Sobrien
40190075SobrienNote that since the function now expects to be entered in ARM mode, it
40290075Sobrienno longer has the .thumb_func pseudo op specified for its name.
40390075SobrienInstead the pseudo op is attached to a new label .real_start_of_<name>
40490075Sobrien(where <name> is the name of the function) which indicates the start
40590075Sobrienof the Thumb code.  This does have the interesting side effect in that
40690075Sobrienif this function is now called from a Thumb mode piece of code
407132718Skanoutside of the current file, the linker will generate a calling stub
40890075Sobriento switch from Thumb mode into ARM mode, and then this is immediately
40990075Sobrienoverridden by the function's header which switches back into Thumb
41090075Sobrienmode. 
41190075Sobrien
41290075SobrienIn addition the (interfacearm) attribute also forces the function to
41390075Sobrienreturn by using the BX instruction, even if has not been compiled with
41490075Sobrienthe -mthumb-interwork command line flag, so that the correct mode will
41590075Sobrienbe restored upon exit from the function.
41690075Sobrien
41790075Sobrien
41890075Sobrien8. Some examples
41990075Sobrien================
42090075Sobrien
42190075Sobrien   Given these two test files:
42290075Sobrien
42390075Sobrien             int arm (void) { return 1 + thumb (); }
42490075Sobrien
42590075Sobrien             int thumb (void) { return 2 + arm (); }
42690075Sobrien
42790075Sobrien   The following pieces of assembler are produced by the ARM and Thumb
42890075Sobrienversion of GCC depending upon the command line options used:
42990075Sobrien
43090075Sobrien   `-O2':
43190075Sobrien             .code 32                               .code 16
43290075Sobrien             .global _arm                           .global _thumb
43390075Sobrien                                                    .thumb_func
43490075Sobrien     _arm:                                    _thumb:
43590075Sobrien             mov     ip, sp
43690075Sobrien             stmfd   sp!, {fp, ip, lr, pc}          push    {lr}
43790075Sobrien             sub     fp, ip, #4
43890075Sobrien             bl      _thumb                          bl      _arm
43990075Sobrien             add     r0, r0, #1                      add     r0, r0, #2
44090075Sobrien             ldmea   fp, {fp, sp, pc}                pop     {pc}
44190075Sobrien
44290075Sobrien   Note how the functions return without using the BX instruction.  If
44390075Sobrienthese files were assembled and linked together they would fail to work
44490075Sobrienbecause they do not change mode when returning to their caller.
44590075Sobrien
44690075Sobrien   `-O2 -mthumb-interwork':
44790075Sobrien
44890075Sobrien             .code 32                               .code 16
44990075Sobrien             .global _arm                           .global _thumb
45090075Sobrien                                                    .thumb_func
45190075Sobrien     _arm:                                    _thumb:
45290075Sobrien             mov     ip, sp
45390075Sobrien             stmfd   sp!, {fp, ip, lr, pc}          push    {lr}
45490075Sobrien             sub     fp, ip, #4
45590075Sobrien             bl      _thumb                         bl       _arm
45690075Sobrien             add     r0, r0, #1                     add      r0, r0, #2
45790075Sobrien             ldmea   fp, {fp, sp, lr}               pop      {r1}
45890075Sobrien             bx      lr                             bx       r1
45990075Sobrien
46090075Sobrien   Now the functions use BX to return their caller.  They have grown by
46190075Sobrien4 and 2 bytes respectively, but they can now successfully be linked
46290075Sobrientogether and be expect to work.  The linker will replace the
46390075Sobriendestinations of the two BL instructions with the addresses of calling
46490075Sobrienstubs which convert to the correct mode before jumping to the called
46590075Sobrienfunction.
46690075Sobrien
46790075Sobrien   `-O2 -mcallee-super-interworking':
46890075Sobrien
46990075Sobrien             .code 32                               .code 32
47090075Sobrien             .global _arm                           .global _thumb
47190075Sobrien     _arm:                                    _thumb:
47290075Sobrien                                                    orr      r12, pc, #1
47390075Sobrien                                                    bx       r12
47490075Sobrien             mov     ip, sp                         .code 16
47590075Sobrien             stmfd   sp!, {fp, ip, lr, pc}          push     {lr}
47690075Sobrien             sub     fp, ip, #4
47790075Sobrien             bl      _thumb                         bl       _arm
47890075Sobrien             add     r0, r0, #1                     add      r0, r0, #2
47990075Sobrien             ldmea   fp, {fp, sp, lr}               pop      {r1}
48090075Sobrien             bx      lr                             bx       r1
48190075Sobrien
48290075Sobrien   The thumb function now has an ARM encoded prologue, and it no longer
48390075Sobrienhas the `.thumb-func' pseudo op attached to it.  The linker will not
48490075Sobriengenerate a calling stub for the call from arm() to thumb(), but it will
48590075Sobrienstill have to generate a stub for the call from thumb() to arm().  Also
48690075Sobriennote how specifying `--mcallee-super-interworking' automatically
48790075Sobrienimplies `-mthumb-interworking'.
48890075Sobrien
48990075Sobrien
49090075Sobrien9. Some Function Pointer Examples
49190075Sobrien=================================
49290075Sobrien
49390075Sobrien   Given this test file:
49490075Sobrien
49590075Sobrien     	int func (void) { return 1; }
49690075Sobrien     
49790075Sobrien     	int call (int (* ptr)(void)) { return ptr (); }
49890075Sobrien
49990075Sobrien   The following varying pieces of assembler are produced by the Thumb
50090075Sobrienversion of GCC depending upon the command line options used:
50190075Sobrien
50290075Sobrien   `-O2':
50390075Sobrien     		.code	16
50490075Sobrien     		.globl	_func
50590075Sobrien     		.thumb_func
50690075Sobrien     	_func:
50790075Sobrien     		mov	r0, #1
50890075Sobrien     		bx	lr
50990075Sobrien     
51090075Sobrien     		.globl	_call
51190075Sobrien     		.thumb_func
51290075Sobrien     	_call:
51390075Sobrien     		push	{lr}
51490075Sobrien     		bl	__call_via_r0
51590075Sobrien     		pop	{pc}
51690075Sobrien
51790075Sobrien   Note how the two functions have different exit sequences.  In
51890075Sobrienparticular call() uses pop {pc} to return, which would not work if the
51990075Sobriencaller was in ARM mode.  func() however, uses the BX instruction, even
52090075Sobrienthough `-mthumb-interwork' has not been specified, as this is the most
52190075Sobrienefficient way to exit a function when the return address is held in the
52290075Sobrienlink register.
52390075Sobrien
52490075Sobrien   `-O2 -mthumb-interwork':
52590075Sobrien
52690075Sobrien     		.code	16
52790075Sobrien     		.globl	_func
52890075Sobrien     		.thumb_func
52990075Sobrien     	_func:
53090075Sobrien     		mov	r0, #1
53190075Sobrien     		bx	lr
53290075Sobrien     
53390075Sobrien     		.globl	_call
53490075Sobrien     		.thumb_func
53590075Sobrien     	_call:
53690075Sobrien     		push	{lr}
53790075Sobrien     		bl	__call_via_r0
53890075Sobrien     		pop	{r1}
53990075Sobrien     		bx	r1
54090075Sobrien
54190075Sobrien   This time both functions return by using the BX instruction.  This
54290075Sobrienmeans that call() is now two bytes longer and several cycles slower
54390075Sobrienthan the previous version.
54490075Sobrien
54590075Sobrien   `-O2 -mcaller-super-interworking':
54690075Sobrien     		.code	16
54790075Sobrien     		.globl	_func
54890075Sobrien     		.thumb_func
54990075Sobrien     	_func:
55090075Sobrien     		mov	r0, #1
55190075Sobrien     		bx	lr
55290075Sobrien     
55390075Sobrien     		.globl	_call
55490075Sobrien     		.thumb_func
55590075Sobrien     	_call:
55690075Sobrien     		push	{lr}
55790075Sobrien     		bl	__interwork_call_via_r0
55890075Sobrien     		pop	{pc}
55990075Sobrien
56090075Sobrien   Very similar to the first (non-interworking) version, except that a
56190075Sobriendifferent stub is used to call via the function pointer.  This new stub
56290075Sobrienwill work even if the called function is not interworking aware, and
56390075Sobrientries to return to call() in ARM mode.  Note that the assembly code for
56490075Sobriencall() is still not interworking aware itself, and so should not be
56590075Sobriencalled from ARM code.
56690075Sobrien
56790075Sobrien   `-O2 -mcallee-super-interworking':
56890075Sobrien
56990075Sobrien     		.code	32
57090075Sobrien     		.globl	_func
57190075Sobrien     	_func:
57290075Sobrien     		orr	r12, pc, #1
57390075Sobrien     		bx	r12
57490075Sobrien     
57590075Sobrien     		.code	16
57690075Sobrien     		.globl .real_start_of_func
57790075Sobrien     		.thumb_func
57890075Sobrien     	.real_start_of_func:
57990075Sobrien     		mov	r0, #1
58090075Sobrien     		bx	lr
58190075Sobrien     
58290075Sobrien     		.code	32
58390075Sobrien     		.globl	_call
58490075Sobrien     	_call:
58590075Sobrien     		orr	r12, pc, #1
58690075Sobrien     		bx	r12
58790075Sobrien     
58890075Sobrien     		.code	16
58990075Sobrien     		.globl .real_start_of_call
59090075Sobrien     		.thumb_func
59190075Sobrien     	.real_start_of_call:
59290075Sobrien     		push	{lr}
59390075Sobrien     		bl	__call_via_r0
59490075Sobrien     		pop	{r1}
59590075Sobrien     		bx	r1
59690075Sobrien
59790075Sobrien   Now both functions have an ARM coded prologue, and both functions
59890075Sobrienreturn by using the BX instruction.  These functions are interworking
59990075Sobrienaware therefore and can safely be called from ARM code.  The code for
60090075Sobrienthe call() function is now 10 bytes longer than the original, non
60190075Sobrieninterworking aware version, an increase of over 200%.
60290075Sobrien
60390075Sobrien   If a prototype for call() is added to the source code, and this
60490075Sobrienprototype includes the `interfacearm' attribute:
60590075Sobrien
60690075Sobrien     	int __attribute__((interfacearm)) call (int (* ptr)(void));
60790075Sobrien
60890075Sobrien   then this code is produced (with only -O2 specified on the command
60990075Sobrienline):
61090075Sobrien
61190075Sobrien     		.code	16
61290075Sobrien     		.globl	_func
61390075Sobrien     		.thumb_func
61490075Sobrien     	_func:
61590075Sobrien     		mov	r0, #1
61690075Sobrien     		bx	lr
61790075Sobrien     
61890075Sobrien     		.globl	_call
61990075Sobrien     		.code	32
62090075Sobrien     	_call:
62190075Sobrien     		orr	r12, pc, #1
62290075Sobrien     		bx	r12
62390075Sobrien     
62490075Sobrien     		.code	16
62590075Sobrien     		.globl .real_start_of_call
62690075Sobrien     		.thumb_func
62790075Sobrien     	.real_start_of_call:
62890075Sobrien     		push	{lr}
62990075Sobrien     		bl	__call_via_r0
63090075Sobrien     		pop	{r1}
63190075Sobrien     		bx	r1
63290075Sobrien
63390075Sobrien   So now both call() and func() can be safely called via
63490075Sobriennon-interworking aware ARM code.  If, when such a file is assembled,
63590075Sobrienthe assembler detects the fact that call() is being called by another
63690075Sobrienfunction in the same file, it will automatically adjust the target of
63790075Sobrienthe BL instruction to point to .real_start_of_call.  In this way there
63890075Sobrienis no need for the linker to generate a Thumb-to-ARM calling stub so
63990075Sobrienthat call can be entered in ARM mode.
64090075Sobrien
64190075Sobrien
64290075Sobrien10. How to use dlltool to build ARM/Thumb DLLs
64390075Sobrien==============================================
64490075Sobrien   Given a program (`prog.c') like this:
64590075Sobrien
64690075Sobrien             extern int func_in_dll (void);
64790075Sobrien     
64890075Sobrien             int main (void) { return func_in_dll(); }
64990075Sobrien
65090075Sobrien   And a DLL source file (`dll.c') like this:
65190075Sobrien
65290075Sobrien             int func_in_dll (void) { return 1; }
65390075Sobrien
65490075Sobrien   Here is how to build the DLL and the program for a purely ARM based
65590075Sobrienenvironment:
65690075Sobrien
65790075Sobrien*Step One
65890075Sobrien     Build a `.def' file describing the DLL:
65990075Sobrien
66090075Sobrien             ; example.def
66190075Sobrien             ; This file describes the contents of the DLL
66290075Sobrien             LIBRARY     example
66390075Sobrien             HEAPSIZE    0x40000, 0x2000
66490075Sobrien             EXPORTS
66590075Sobrien                          func_in_dll  1
66690075Sobrien
66790075Sobrien*Step Two
66890075Sobrien     Compile the DLL source code:
66990075Sobrien
67090075Sobrien            arm-pe-gcc -O2 -c dll.c
67190075Sobrien
67290075Sobrien*Step Three
67390075Sobrien     Use `dlltool' to create an exports file and a library file:
67490075Sobrien
67590075Sobrien            dlltool --def example.def --output-exp example.o --output-lib example.a
67690075Sobrien
67790075Sobrien*Step Four
67890075Sobrien     Link together the complete DLL:
67990075Sobrien
68090075Sobrien            arm-pe-ld dll.o example.o -o example.dll
68190075Sobrien
68290075Sobrien*Step Five
68390075Sobrien     Compile the program's source code:
68490075Sobrien
68590075Sobrien            arm-pe-gcc -O2 -c prog.c
68690075Sobrien
68790075Sobrien*Step Six
68890075Sobrien     Link together the program and the DLL's library file:
68990075Sobrien
69090075Sobrien            arm-pe-gcc prog.o example.a -o prog
69190075Sobrien
69290075Sobrien   If instead this was a Thumb DLL being called from an ARM program, the
69390075Sobriensteps would look like this.  (To save space only those steps that are
69490075Sobriendifferent from the previous version are shown):
69590075Sobrien
69690075Sobrien*Step Two
69790075Sobrien     Compile the DLL source code (using the Thumb compiler):
69890075Sobrien
69990075Sobrien            thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
70090075Sobrien
70190075Sobrien*Step Three
70290075Sobrien     Build the exports and library files (and support interworking):
70390075Sobrien
70490075Sobrien            dlltool -d example.def -z example.o -l example.a --interwork -m thumb
70590075Sobrien
70690075Sobrien*Step Five
70790075Sobrien     Compile the program's source code (and support interworking):
70890075Sobrien
70990075Sobrien            arm-pe-gcc -O2 -c prog.c -mthumb-interwork
71090075Sobrien
71190075Sobrien   If instead, the DLL was an old, ARM DLL which does not support
71290075Sobrieninterworking, and which cannot be rebuilt, then these steps would be
71390075Sobrienused.
71490075Sobrien
71590075Sobrien*Step One
71690075Sobrien     Skip.  If you do not have access to the sources of a DLL, there is
71790075Sobrien     no point in building a `.def' file for it.
71890075Sobrien
71990075Sobrien*Step Two
72090075Sobrien     Skip.  With no DLL sources there is nothing to compile.
72190075Sobrien
72290075Sobrien*Step Three
72390075Sobrien     Skip.  Without a `.def' file you cannot use dlltool to build an
72490075Sobrien     exports file or a library file.
72590075Sobrien
72690075Sobrien*Step Four
72790075Sobrien     Skip.  Without a set of DLL object files you cannot build the DLL.
72890075Sobrien     Besides it has already been built for you by somebody else.
72990075Sobrien
73090075Sobrien*Step Five
73190075Sobrien     Compile the program's source code, this is the same as before:
73290075Sobrien
73390075Sobrien            arm-pe-gcc -O2 -c prog.c
73490075Sobrien
73590075Sobrien*Step Six
73690075Sobrien     Link together the program and the DLL's library file, passing the
73790075Sobrien     `--support-old-code' option to the linker:
73890075Sobrien
73990075Sobrien            arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
74090075Sobrien
74190075Sobrien     Ignore the warning message about the input file not supporting
74290075Sobrien     interworking as the --support-old-code switch has taken care if this.
743