\input texinfo        @c                    -*- Texinfo -*-
@setfilename arm-interwork.info
@settitle ARM Interworking

@finalout
@setchapternewpage odd
@iftex
@raggedbottom
@global@parindent=0pt
@end iftex

@titlepage
@title ARM Interworking
@sp 4
@author Nick Clifton
@page

@ifinfo
@format
START-INFO-DIR-ENTRY
* ARM Interworking:              Arm/Thumb Interworking Notes
END-INFO-DIR-ENTRY
@end format
@end ifinfo

@vskip 0pt plus 1filll
Copyright @copyright{} 1998 Cygnus Solutions

Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by Cygnus Solutions.
@end titlepage

@ifinfo
@node Top
@top ARM Interworking
@end ifinfo

@c @lowersections

@c @chapter ARM Interworking

@menu
* Introduction::                Arm / Thumb Interworking
* Source Interworking::         Explicit interworking support for C and C++
* Assembler Interworking::      Explicit interworking support for assembler
* Super Interworking::          Support for old non-interworking aware code.
* DLL Interworking::            Interworking support in dlltool
* How Interworking Works::      How interworking support works
* Callee Super-interworking::   How caller-super-interworking support works
* Caller Super-interworking::   How callee-super-interworking support works
* How DLL Interworking Works::  How DLL interworking works
* Examples::                    Some examples of interworking
* Function Pointer Examples::   Some function pointer examples
* DLL Examples::                How to use dlltool to build ARM/Thumb DLLs
@end menu

@node Introduction
@chapter Arm / Thumb Interworking

The Cygnus GNU Pro Toolkit for the ARM7T processor supports function
calls between code compiled for the ARM instruction set and code
compiled for the Thumb instruction set and vice versa.  This document
describes how that interworking support operates and explains the
command line switches that should be used in order to produce working
programs.

Note:  The Cygnus GNU Pro Toolkit does not support switching between
compiling for the ARM instruction set and the Thumb instruction set
on anything other than a per file basis.  There are in fact two
completely separate compilers, one that produces ARM assembler
instructions and one that produces Thumb assembler instructions.  The
two compilers share the same assembler, linker and so on.


@node Source Interworking
@chapter Explicit interworking support for C and C++

By default, if a file is compiled without any special command line
switches then the code produced will not support interworking.
Provided that a program is made up entirely from object files and
libraries produced in this way and which contain either exclusively
ARM instructions or exclusively Thumb instructions then this will not
matter and a working executable will be created.  If an attempt is
made to link together mixed ARM and Thumb object files and libraries,
then warning messages will be produced by the linker and a non-working
executable will be created.

In order to produce code which does support interworking it should be
compiled with the @samp{-mthumb-interwork} command line option.
Provided that a program is made up entirely from object files and
libraries built with this command line switch a working executable will
be produced, even if both ARM and Thumb instructions are used by the
various components of the program.  (No warning messages will be
produced by the linker either). 

Note that specifying -mthumb-interwork does result in slightly larger,
slower code being produced.  This is why interworking support must be
specifically enabled by a switch.


@node Assembler Interworking
@chapter Explicit interworking support for assembler files

If assembler files are to be included into an interworking program
then the following rules must be obeyed:

@table @bullet

@item
Any externally visible functions must return by using the BX
instruction.

@item
Normal function calls can just use the BL instruction.  The
linker will automatically insert code to switch between ARM
and Thumb modes as necessary.

@item
Calls via function pointers should use the BX instruction if
the call is made in ARM mode:

@smallexample
		.code 32
		mov lr, pc
		bx  rX
@end smallexample

This code sequence will not work in Thumb mode however, since
the mov instruction will not set the bottom bit of the lr
register.  Instead a branch-and-link to the _call_via_rX
functions should be used instead:

@smallexample
		.code 16
		bl  _call_via_rX
@end smallexample

where rX is replaced by the name of the register containing
the function address.

@item
All externally visible functions which should be entered in
Thumb mode must have the .thumb_func pseudo op specified just
before their entry point.  eg:

@smallexample
		.code 16
		.global function
	       	.thumb_func
	function:
		...start of function....
@end smallexample

@item
All assembler files must be assembled with the switch
@samp{-mthumb-interwork} specified on the command line.  (If the file 
is assembled by calling gcc it will automatically pass on the
-mthumb-interwork switch to the assembler, provided that it
was specified on the gcc command line in the first place.) 

@end table


@node Super Interworking
@chapter Support for old non-interworking aware code.

If it is necessary to link together code produced by an older,
non-interworking aware compiler, or code produced by the new compiler
but without the -mthumb-interwork command line switch specified, then
there are two command line switches that can be used to support this.

The switch @samp{-mcaller-super-interworking} will allow calls via
function pointers in Thumb mode to work, regardless of whether the
function pointer points to old, non-interworking aware code or not.
Specifying this switch does produce slightly slower code however. 

Note:  There is no switch to allow calls via function pointers in ARM
mode to be handled specially.  Calls via function pointers from
interworking aware ARM code to non-interworking aware ARM code work
without any special considerations by the compiler.  Calls via
function pointers from interworking aware ARM code to non-interworking
aware Thumb code however will not work.  (Actually under some
circumstances they may work, but there are no guarantees).  This is
because only the new compiler is able to produce Thumb code, and this
compiler already has a command line switch to produce interworking
aware code.

The switch @samp{-mcallee-super-interworking} will allow
non-interworking aware ARM or Thumb code to call Thumb functions, either
directly or via function pointers.  Specifying this switch does produce
slightly larger, slower code however. 

Note:  There is no switch to allow non-interworking aware ARM or Thumb
code to call ARM functions.  There is no need for any special handling
of calls from non-interworking aware ARM code to interworking aware
ARM functions, they just work normally.  Calls from non-interworking
aware Thumb functions to ARM code however, will not work.  There is no
option to support this, since it is always possible to recompile the
Thumb code to be interworking aware.

As an alternative to the command line switch
-mcallee-super-interworking, which affects all externally visible
functions in a file, it is possible to specify an attribute or
declspec for individual functions, indicating that that particular
function should support being called by non-interworking aware code.
The function should be defined like this:

@smallexample
	int __attribute__((interfacearm)) 
        function ()
	@{
		... body of function ...
	@}
@end smallexample

or
@smallexample
	int __declspec(interfacearm) 
        function ()
	@{
		... body of function ...
	@}
@end smallexample


@node DLL Interworking
@chapter Interworking support in dlltool

It is possible to create DLLs containing mixed ARM and Thumb code.  It
is also possible to call Thumb code in a DLL from an ARM program and
vice versa.  It is even possible to call ARM DLLs that have been compiled
without interworking support (say by an older version of the compiler),
from Thumb programs and still have things work properly.

A version of the @samp{dlltool} program which supports the
@samp{--interwork} command line switch is needed, as well as the
following special considerations when building programs and DLLs:

@table @emph

@item Use @samp{-mthumb-interwork}
When compiling files for a DLL or a program the @samp{-mthumb-interwork}
command line switch should be specified if calling between ARM and Thumb
code can happen.  If a program is being compiled and the mode of the
DLLs that it uses is not known, then it should be assumed that
interworking might occur and the switch used.  

@item Use @samp{-m thumb}
If the exported functions from a DLL are all Thumb encoded then the
@samp{-m thumb} command line switch should be given to dlltool when
building the stubs.  This will make dlltool create Thumb encoded stubs, 
rather than its default of ARM encoded stubs.

If the DLL consists of both exported Thumb functions and exported ARM
functions then the @samp{-m thumb} switch should not be used.  Instead
the Thumb functions in the DLL should be compiled with the
@samp{-mcallee-super-interworking} switch, or with the 
@samp{interfacearm} attribute specified on their prototypes.  In this
way they will be given ARM encoded prologues, which will work with the
ARM encoded stubs produced by dlltool.

@item Use @samp{-mcaller-super-interworking}
If it is possible for Thumb functions in a DLL to call
non-interworking aware code via a function pointer, then the Thumb code
must be compiled with the @samp{-mcaller-super-interworking} command
line switch.  This will force the function pointer calls to use the
_interwork_call_via_rX stub functions which will correctly restore
Thumb mode upon return from the called function.

@item Link with @samp{libgcc.a}
When the dll is built it may have to be linked with the GCC
library (@samp{libgcc.a}) in order to extract the _call_via_rX functions
or the _interwork_call_via_rX functions.  This represents a partial
redundancy since the same functions @emph{may} be present in the
application itself, but since they only take up 372 bytes this should
not be too much of a consideration.

@item Use @samp{--support-old-code}
When linking a program with an old DLL which does not support
interworking, the @samp{--support-old-code} command line switch to the
linker should be used.   This causes the linker to generate special 
interworking stubs which can cope with old, non-interworking aware ARM
code, at the cost of generating bulkier code.  The linker will still
generate a warning message along the lines of: 
  "Warning: input file XXX does not support interworking, whereas YYY does."
but this can now be ignored because the --support-old-code switch has
been used. 

@end table


@node How Interworking Works
@chapter How interworking support works

Switching between the ARM and Thumb instruction sets is accomplished
via the BX instruction.  This takes as an argument a register name and 
control is transfered to the address held in this register.  The bottom
bit of the register is ignored when determining where to go.  If the
bottom bit is set, then Thumb instruction processing is enabled,
otherwise ARM instruction processing is enabled.

When the -mthumb-interwork command line switch is specified, gcc
arranges for all functions to return to their caller by using the BX
instruction.  Thus provided that the return address has the bottom bit
correctly initialised to indicate the instruction set of the caller,
correct operation will ensue.

When a function is called explicitly (rather than via a function
pointer), the compiler generates a BL instruction to do this.  The
Thumb version of the BL instruction has the special property of
setting the bottom bit of the LR register after it has stored the
return address into it, so that a future BX instruction will correctly
return the instruction after the BL instruction, in Thumb mode.

The BL instruction does not change modes itself however, so if an ARM
function is calling a Thumb function, or vice versa, it is necessary
to generate some extra instructions to handle this.  This is done in
the linker when it is storing the address of the referenced function
into the BL instruction.  If the BL instruction is an ARM style BL
instruction, but the referenced function is a Thumb function, then the
linker automatically generates a calling stub that converts from ARM
mode to Thumb mode, puts the address of this stub into the BL
instruction, and puts the address of the referenced function into the
stub.  Similarly if the BL instruction is a Thumb BL instruction, and
the referenced function is an ARM function, the linker generates a
stub which converts from Thumb to ARM mode, puts the address of this
stub into the BL instruction, and the address of the referenced
function into the stub.

This is why it is necessary to mark Thumb functions with the
.thumb_func pseudo op when creating assembler files.  This pseudo op
allows the assembler to distinguish between ARM functions and Thumb
functions, and pass this information on to the linker.   (The Thumb
version of GCC automatically generates these pseudo ops for any Thumb
functions that it generates). 

Calls via function pointers work differently.  Whenever the address of
a function is taken, the linker examines the type of the function
being referenced.  If the function is a Thumb function, then it sets
the bottom bit of the address.  Technically this makes the address
incorrect, since it is now one byte into the start of the function,
but this is never a problem because:

@table @bullet
@item
with interworking enabled all calls via function pointer
are done using the BX instruction and this ignores the
bottom bit when computing where to go to.

@item
the linker will always set the bottom bit when the address
of the function is taken, so it is never possible to take
the address of the function in two different places and
then compare them and find that they are not equal.
@end table

As already mentioned any call via a function pointer will use the BX
instruction (provided that interworking is enabled).  The only problem
with this is computing the return address for the return from the
called function.  For ARM code this can easily be done by the code
sequence:

@smallexample
	mov	lr, pc
	bx	rX
@end smallexample

(where rX is the name of the register containing the function
pointer).  This code does not work for the Thumb instruction set,
since the MOV instruction will not set the bottom bit of the LR
register, so that when the called function returns, it will return in
ARM mode not Thumb mode.  Instead the compiler generates this
sequence:

@smallexample
	bl	_call_via_rX
@end smallexample

(again where rX is the name if the register containing the function
pointer).  The special call_via_rX functions look like this:

@smallexample
	.thumb_func
_call_via_r0:
	bx	r0
	nop
@end smallexample

The BL instruction ensures that the correct return address is stored
in the LR register and then the BX instruction jumps to the address
stored in the function pointer, switch modes if necessary.


@node Caller Super-interworking
@chapter How caller-super-interworking support works

When the -mcaller-super-interworking command line switch is specified
it changes the code produced by the Thumb compiler so that all calls
via function pointers (including virtual function calls) now go via a
different stub function.  The code to call via a function pointer now
looks like this:

@smallexample
	bl _interwork_call_via_r0
@end smallexample

Note: The compiler does not insist that r0 be used to hold the
function address.  Any register will do, and there are a suite of stub
functions, one for each possible register.  The stub functions look
like this:

@smallexample
	.code   16
	.thumb_func
	.global _interwork_call_via_r0
_interwork_call_via_r0:
	bx 	pc
	nop
	
	.code   32
	tst	r0, #1
	stmeqdb	r13!, @{lr@}
	adreq	lr, _arm_return
	bx	r0
@end smallexample

The stub first switches to ARM mode, since it is a lot easier to
perform the necessary operations using ARM instructions.  It then
tests the bottom bit of the register containing the address of the
function to be called.  (Note: the tst instruction in the code above
will only set the Z flag if the address in r0 @samp{does not} have the
bottom bit set, so the EQ comparisons are only true if the address is an
ARM address, not a Thumb address).  If this bottom bit is set then the
function being called uses Thumb instructions and the BX instruction to
come will switch back into Thumb mode before calling this function.
(Note that it does not matter how this called function chooses to return
to its caller, since the both the caller and callee are Thumb functions,
and mode switching is not necessary).  If the function being called is
an ARM mode function however, the stub pushes the return address (with
its bottom bit set) onto the stack, replaces the return address with
the address of the a piece of code called '_arm_return' and then
performs a BX instruction to call the function.

The '_arm_return' code looks like this:

@smallexample
	.code   32
_arm_return:		
	ldmea 	r13!, @{r12@}
	bx 	r12
	.code   16
@end smallexample

It simply retrieves the return address from the stack, and then
performs a BX operation to return to the caller and switch back into
Thumb mode.


@node Callee Super-interworking
@chapter How callee-super-interworking support works

When -mcallee-super-interworking is specified on the command line the
Thumb compiler behaves as if every externally visible function that it
compiles has had the (interfacearm) attribute specified for it.  What
this attribute does is to put a special, ARM mode header onto the
function which forces a switch into Thumb mode:

  without __attribute__((interfacearm)):

@smallexample
		.code 16
		.thumb_func
	function:
		... start of function ...
@end smallexample

  with __attribute__((interfacearm)):

@smallexample
		.code 32
	function:
		orr	r12, pc, #1
		bx	r12

		.code 16
		.thumb_func
	.real_start_of_function:

		... start of function ...
@end smallexample

Note that since the function now expects to be entered in ARM mode, it
no longer has the .thumb_func pseudo op specified for its name.
Instead the pseudo op is attached to a new label .real_start_of_<name>
(where <name> is the name of the function) which indicates the start
of the Thumb code.  This does have the interesting side effect in that
if this function is now called from a Thumb mode piece of code
outside of the current file, the linker will generate a calling stub
to switch from Thumb mode into ARM mode, and then this is immediately
overridden by the function's header which switches back into Thumb
mode. 

In addition the (interfacearm) attribute also forces the function to
return by using the BX instruction, even if has not been compiled with
the -mthumb-interwork command line flag, so that the correct mode will
be restored upon exit from the function.

@node How DLL Interworking Works
@chapter How DLL interworking works

The only real issue with DLLs is the stubs used to call a DLL function
from a program.  By default dlltool will generate a stub that looks like
this:

@smallexample
        .text
        .arm
<name_of_DLL_function>:
        ldr     ip, .address
        ldr     pc, [ip]
.address:
        .long   __imp_<name_of_DLL_function>

        .idata5
__imp_<name_of_DLL_function>
        .long   0       @@ Loader inserts address of function here.
@end smallexample

So when the program calls the function <name_of_DLL_function> it
actually goes this piece of stub code.  This code loads the address of
the location in the .idata5 section that contains the address of the
real function in the DLL, and then loads the contents of that location
into the program counter.

There are two problems with this stub function.  Firstly this is an ARM
encoded stub, and it does not use the BX instruction to call the code in
the DLL, so that code will always be entered in ARM mode.  This problem
can be avoid in two ways.  Either the code in DLL can be built so that
its exported functions always have ARM encoded prologues, even if the
rest of the code uses Thumb instructions.  The
@samp{-mcaller-super-interworking} command line switch to gcc does
this.  The other alternative is to specify @samp{-m thumb} when using
dlltool to build the stubs.  This will result in dlltool building Thumb
encoded stubs that look like this:

@smallexample
        .text
        .thumb
<name_of_DLL_function>:
        push    @{r6, r7@}
        ldr     r6, .address
        ldr     r6, [r6]
        str     r6, [sp, #4]
        pop     @{r6, pc@}
        nop
.address:
        .long   __imp_<name_of_DLL_function>

        .idata5
__imp_<name_of_DLL_function>
        .long   0       @@ Loader inserts address of function here.
@end smallexample

Note that this stub always enters the DLL in thumb mode, so it cannot be
used if the code in the DLL expects to be entered in ARM mode.

The second problem with DLL interworking is how the code in the DLL
returns to its caller.  If the code in the DLL has been compiled to be
interworking aware, then it will use the BX instruction, and since the
stubs produced by dlltool (either form), do not alter the return
address, the correct mode - ARM or Thumb - will be selected upon return
from the DLL.

If the code in the DLL is non-interworking aware, then the BX
instruction will not be used, and the DLL will always return in ARM
mode.  (This assumes that there will never be non-interworking aware
Thumb code.  It is possible to build such code, but since the Thumb
compiler and the dlltool with interworking support are being released at
approximately the same time, there should not be any need to support
@emph{legacy} Thumb code that is non interworking aware and for which
the sources for recompilation do not exist). 

This is where the @samp{--support-old-code} switch to the linker comes
in.  With this switch specified the linker will generate Thumb-to-ARM
stubs, (to call the DLL stubs), that can cope with non-interworking
aware code.  The linker generated stub looks like this:

@smallexample
        .text
        .thumb
<name_of_DLL_function>_from_thumb:
        push    @{r6, lr@}
        ldr     r6, .address
        mov     lr, pc
        bx      r6

        .arm
<name_of_DLL_function>_back_from_arm:
        ldmea   sp!, @{r6, lr@}
        bx      lr
.address:
        .long   <name_of_DLL_function>

@end smallexample

So the program, instead of calling the stub generated by dlltool
directly, goes via this piece of stub code first.  This code saves the
return address on the stack, and then replaces it with an address of its
own.  It then uses the BX instruction to jump to the dlltool generated
stub and switch to ARM mode at the same time.  When the DLL function
returns it will return in ARM mode to this stub, which has an ARM
encoded piece of assembler ready and waiting to retrieve the real return
address off the stack and then jump back to the real caller, switching
back to Thumb mode at the same time.


@node Examples
@chapter Some examples of interworking

Given these two test files:

@smallexample
        int arm (void) @{ return 1 + thumb (); @}
@end smallexample

@smallexample
        int thumb (void) @{ return 2 + arm (); @}
@end smallexample

The following pieces of assembler are produced by the ARM and Thumb
version of GCC depending upon the command line options used:

@samp{-O2}:
@smallexample
        .code 32                               .code 16
        .global _arm                           .global _thumb
                                               .thumb_func
_arm:                                    _thumb:
        mov     ip, sp	                        
        stmfd   sp!, @{fp, ip, lr, pc@}          push    @{lr@}
        sub     fp, ip, #4			
        bl      _thumb                          bl      _arm
        add     r0, r0, #1                      add     r0, r0, #2
        ldmea   fp, @{fp, sp, pc@}                pop     @{pc@}
@end smallexample

Note how the functions return without using the BX instruction.  If
these files were assembled and linked together they would fail to work
because they do not change mode when returning to their caller.

@samp{-O2 -mthumb-interwork}:

@smallexample
        .code 32                               .code 16
        .global _arm                           .global _thumb
                                               .thumb_func
_arm:                                    _thumb:
        mov     ip, sp                         
        stmfd   sp!, @{fp, ip, lr, pc@}          push    @{lr@}
        sub     fp, ip, #4
        bl      _thumb                         bl       _arm
        add     r0, r0, #1                     add      r0, r0, #2
        ldmea   fp, @{fp, sp, lr@}               pop      @{r1@}
        bx      lr                             bx       r1
@end smallexample

Now the functions use BX to return their caller.  They have grown by 4
and 2 bytes respectively, but they can now successfully be linked
together and be expect to work.  The linker will replace the
destinations of the two BL instructions with the addresses of calling
stubs which convert to the correct mode before jumping to the called
function. 

@samp{-O2 -mcallee-super-interworking}:

@smallexample
        .code 32                               .code 32
        .global _arm                           .global _thumb
_arm:                                    _thumb:
                                               orr      r12, pc, #1
                                               bx       r12
        mov     ip, sp                         .code 16
        stmfd   sp!, @{fp, ip, lr, pc@}          push     @{lr@}
        sub     fp, ip, #4                    
        bl      _thumb                         bl       _arm
        add     r0, r0, #1                     add      r0, r0, #2
        ldmea   fp, @{fp, sp, lr@}               pop      @{r1@}
        bx      lr                             bx       r1
@end smallexample

The thumb function now has an ARM encoded prologue, and it no longer has
the @samp{.thumb-func} pseudo op attached to it.  The linker will not
generate a calling stub for the call from arm() to thumb(), but it will
still have to generate a stub for the call from thumb() to arm().  Also
note how specifying @samp{--mcallee-super-interworking} automatically
implies @samp{-mthumb-interworking}.


@node Function Pointer Examples
@chapter Some function pointer examples

Given this test file:

@smallexample
	int func (void) @{ return 1; @}

	int call (int (* ptr)(void)) @{ return ptr (); @}
@end smallexample

The following varying pieces of assembler are produced by the Thumb
version of GCC depending upon the command line options used:

@samp{-O2}:
@smallexample
		.code	16
		.globl	_func
		.thumb_func
	_func:
		mov	r0, #1
		bx	lr

		.globl	_call
		.thumb_func
	_call:
		push	@{lr@}
		bl	__call_via_r0
		pop	@{pc@}
@end smallexample

Note how the two functions have different exit sequences.  In
particular call() uses pop @{pc@} to return, which would not work if the
caller was in ARM mode.  func() however, uses the BX instruction, even
though @samp{-mthumb-interwork} has not been specified, as this is the
most efficient way to exit a function when the return address is held in
the link register.

@samp{-O2 -mthumb-interwork}:

@smallexample
		.code	16
		.globl	_func
		.thumb_func
	_func:
		mov	r0, #1
		bx	lr

		.globl	_call
		.thumb_func
	_call:
		push	@{lr@}
		bl	__call_via_r0
		pop	@{r1@}
		bx	r1
@end smallexample

This time both functions return by using the BX instruction.  This
means that call() is now two bytes longer and several cycles slower
than the previous version.

@samp{-O2 -mcaller-super-interworking}:
@smallexample
		.code	16
		.globl	_func
		.thumb_func
	_func:
		mov	r0, #1
		bx	lr

		.globl	_call
		.thumb_func
	_call:
		push	@{lr@}
		bl	__interwork_call_via_r0
		pop	@{pc@}
@end smallexample

Very similar to the first (non-interworking) version, except that a
different stub is used to call via the function pointer.  This new stub
will work even if the called function is not interworking aware, and
tries to return to call() in ARM mode.  Note that the assembly code for
call() is still not interworking aware itself, and so should not be
called from ARM code.

@samp{-O2 -mcallee-super-interworking}:

@smallexample
		.code	32
		.globl	_func
	_func:
		orr	r12, pc, #1
		bx	r12

		.code	16
		.globl .real_start_of_func
		.thumb_func
	.real_start_of_func:
		mov	r0, #1
		bx	lr

		.code	32
		.globl	_call
	_call:
		orr	r12, pc, #1
		bx	r12

		.code	16
		.globl .real_start_of_call
		.thumb_func
	.real_start_of_call:
		push	@{lr@}
		bl	__call_via_r0
		pop	@{r1@}
		bx	r1
@end smallexample

Now both functions have an ARM coded prologue, and both functions
return by using the BX instruction.  These functions are interworking
aware therefore and can safely be called from ARM code.  The code for
the call() function is now 10 bytes longer than the original, non
interworking aware version, an increase of over 200%.

If a prototype for call() is added to the source code, and this
prototype includes the @samp{interfacearm} attribute:

@smallexample
	int __attribute__((interfacearm)) call (int (* ptr)(void));
@end smallexample

then this code is produced (with only -O2 specified on the command
line): 

@smallexample
		.code	16
		.globl	_func
		.thumb_func
	_func:
		mov	r0, #1
		bx	lr

		.globl	_call
		.code	32
	_call:
		orr	r12, pc, #1
		bx	r12

		.code	16
		.globl .real_start_of_call
		.thumb_func
	.real_start_of_call:
		push	@{lr@}
		bl	__call_via_r0
		pop	@{r1@}
		bx	r1
@end smallexample

So now both call() and func() can be safely called via non-interworking
aware ARM code.  If, when such a file is assembled, the assembler
detects the fact that call() is being called by another function in the
same file, it will automatically adjust the target of the BL instruction
to point to .real_start_of_call.  In this way there is no need for
the linker to generate a Thumb-to-ARM calling stub so that call can be
entered in ARM mode.


@node DLL Examples
@chapter How to use dlltool to build ARM/Thumb DLLs

Given a program (@samp{prog.c}) like this:

@smallexample
        extern int func_in_dll (void);

        int main (void) @{ return func_in_dll(); @}
@end smallexample

And a DLL source file (@samp{dll.c}) like this:

@smallexample
        int func_in_dll (void) @{ return 1; @}
@end smallexample

Here is how to build the DLL and the program for a purely ARM based
environment: 

@table @bullet

@item Step One
Build a @samp{.def} file describing the DLL:

@smallexample
   ; example.def
   ; This file describes the contents of the DLL
   LIBRARY     example
   HEAPSIZE    0x40000, 0x2000
   EXPORTS
                func_in_dll @ 1
@end smallexample

@item Step Two
Compile the DLL source code:

@smallexample
  arm-pe-gcc -O2 -c dll.c
@end smallexample

@item Step Three
Use @samp{dlltool} to create an exports file and a library file:

@smallexample
  dlltool --def example.def --output-exp example.o --output-lib example.a
@end smallexample

@item Step Four
Link together the complete DLL:

@smallexample
  arm-pe-ld dll.o example.o -o example.dll
@end smallexample

@item Step Five
Compile the program's source code:

@smallexample
  arm-pe-gcc -O2 -c prog.c
@end smallexample

@item Step Six
Link together the program and the DLL's library file:

@smallexample
  arm-pe-gcc prog.o example.a -o prog
@end smallexample

@end table

If instead this was a Thumb DLL being called from an ARM program, the
steps would look like this.  (To save space only those steps that are
different from the previous version are shown):

@table @bullet

@item Step Two
Compile the DLL source code (using the Thumb compiler):

@smallexample
  thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
@end smallexample

@item Step Three
Build the exports and library files (and support interworking):

@smallexample
  dlltool -d example.def -e example.o -l example.a --interwork -m thumb
@end smallexample

@item Step Five
Compile the program's source code (and support interworking):

@smallexample
  arm-pe-gcc -O2 -c prog.c -mthumb-interwork
@end smallexample

@end table

If instead, the DLL was an old, ARM DLL which does not support
interworking, and which cannot be rebuilt, then these steps would be
used.

@table @bullet
@item Step One
Skip.  If you do not have access to the sources of a DLL, there is no
point in building a @samp{.def} file for it.

@item Step Two
Skip.  With no DLL sources there is nothing to compile.

@item Step Three
Skip.  Without a @samp{.def} file you cannot use dlltool to build an
exports file or a library file.

@item Step Four
Skip.  Without a set of DLL object files you cannot build the DLL.
Besides it has already been built for you by somebody else.

@item Step Five
Compile the program's source code, this is the same as before:

@smallexample
  arm-pe-gcc -O2 -c prog.c 
@end smallexample

@item Step Six
Link together the program and the DLL's library file, passing the
@samp{--support-old-code} option to the linker:

@smallexample
  arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
@end smallexample

Ignore the warning message about the input file not supporting
interworking as the --support-old-code switch has taken care if this.

@end table
@contents
@bye

