Home | History | Annotate | Line # | Download | only in arm
      1   1.1  mrg 		Arm / Thumb Interworking
      2   1.1  mrg 		========================
      3   1.1  mrg 
      4   1.1  mrg The Cygnus GNU Pro Toolkit for the ARM7T processor supports function
      5   1.1  mrg calls between code compiled for the ARM instruction set and code
      6   1.1  mrg compiled for the Thumb instruction set and vice versa.  This document
      7   1.1  mrg describes how that interworking support operates and explains the
      8   1.1  mrg command line switches that should be used in order to produce working
      9   1.1  mrg programs.
     10   1.1  mrg 
     11   1.1  mrg Note:  The Cygnus GNU Pro Toolkit does not support switching between
     12   1.1  mrg compiling for the ARM instruction set and the Thumb instruction set
     13   1.1  mrg on anything other than a per file basis.  There are in fact two
     14   1.1  mrg completely separate compilers, one that produces ARM assembler
     15   1.1  mrg instructions and one that produces Thumb assembler instructions.  The
     16   1.1  mrg two compilers share the same assembler, linker and so on.
     17   1.1  mrg 
     18   1.1  mrg 
     19   1.1  mrg 1. Explicit interworking support for C and C++ files
     20   1.1  mrg ====================================================
     21   1.1  mrg 
     22   1.1  mrg By default if a file is compiled without any special command line
     23   1.1  mrg switches then the code produced will not support interworking.
     24   1.1  mrg Provided that a program is made up entirely from object files and
     25   1.1  mrg libraries produced in this way and which contain either exclusively
     26   1.1  mrg ARM instructions or exclusively Thumb instructions then this will not
     27   1.1  mrg matter and a working executable will be created.  If an attempt is
     28   1.1  mrg made to link together mixed ARM and Thumb object files and libraries,
     29   1.1  mrg then warning messages will be produced by the linker and a non-working
     30   1.1  mrg executable will be created.
     31   1.1  mrg 
     32   1.1  mrg In order to produce code which does support interworking it should be
     33   1.1  mrg compiled with the
     34   1.1  mrg 
     35   1.1  mrg 	-mthumb-interwork
     36   1.1  mrg 
     37   1.1  mrg command line option.  Provided that a program is made up entirely from
     38   1.1  mrg object files and libraries built with this command line switch a
     39   1.1  mrg working executable will be produced, even if both ARM and Thumb
     40   1.1  mrg instructions are used by the various components of the program.  (No
     41   1.1  mrg warning messages will be produced by the linker either).
     42   1.1  mrg 
     43   1.1  mrg Note that specifying -mthumb-interwork does result in slightly larger,
     44   1.1  mrg slower code being produced.  This is why interworking support must be
     45   1.1  mrg specifically enabled by a switch.
     46   1.1  mrg 
     47   1.1  mrg 
     48   1.1  mrg 2. Explicit interworking support for assembler files
     49   1.1  mrg ====================================================
     50   1.1  mrg 
     51   1.1  mrg If assembler files are to be included into an interworking program
     52   1.1  mrg then the following rules must be obeyed:
     53   1.1  mrg 
     54   1.1  mrg 	* Any externally visible functions must return by using the BX
     55   1.1  mrg 	instruction.
     56   1.1  mrg 
     57   1.1  mrg 	* Normal function calls can just use the BL instruction.  The
     58   1.1  mrg 	linker will automatically insert code to switch between ARM
     59   1.1  mrg 	and Thumb modes as necessary.
     60   1.1  mrg 
     61   1.1  mrg 	* Calls via function pointers should use the BX instruction if
     62   1.1  mrg 	the call is made in ARM mode:
     63   1.1  mrg 
     64   1.1  mrg 		.code 32
     65   1.1  mrg 		mov lr, pc
     66   1.1  mrg 		bx  rX
     67   1.1  mrg 
     68   1.1  mrg 	This code sequence will not work in Thumb mode however, since
     69   1.1  mrg 	the mov instruction will not set the bottom bit of the lr
     70   1.1  mrg 	register.  Instead a branch-and-link to the _call_via_rX
     71   1.1  mrg 	functions should be used instead:
     72   1.1  mrg 
     73   1.1  mrg 		.code 16
     74   1.1  mrg 		bl  _call_via_rX
     75   1.1  mrg 
     76   1.1  mrg 	where rX is replaced by the name of the register containing
     77   1.1  mrg 	the function address.
     78   1.1  mrg 
     79   1.1  mrg 	* All externally visible functions which should be entered in
     80   1.1  mrg 	Thumb mode must have the .thumb_func pseudo op specified just
     81   1.1  mrg 	before their entry point.  e.g.:
     82   1.1  mrg 
     83   1.1  mrg 			.code 16
     84   1.1  mrg 			.global function
     85   1.1  mrg 			.thumb_func
     86   1.1  mrg 		function:
     87   1.1  mrg 			...start of function....
     88   1.1  mrg 
     89   1.1  mrg 	* All assembler files must be assembled with the switch
     90   1.1  mrg 	-mthumb-interwork specified on the command line.  (If the file
     91   1.1  mrg 	is assembled by calling gcc it will automatically pass on the
     92   1.1  mrg 	-mthumb-interwork switch to the assembler, provided that it
     93   1.1  mrg 	was specified on the gcc command line in the first place.) 
     94   1.1  mrg 
     95   1.1  mrg 
     96   1.1  mrg 3. Support for old, non-interworking aware code.
     97   1.1  mrg ================================================
     98   1.1  mrg 
     99   1.1  mrg If it is necessary to link together code produced by an older,
    100   1.1  mrg non-interworking aware compiler, or code produced by the new compiler
    101   1.1  mrg but without the -mthumb-interwork command line switch specified, then
    102   1.1  mrg there are two command line switches that can be used to support this.
    103   1.1  mrg 
    104   1.1  mrg The switch
    105   1.1  mrg 
    106   1.1  mrg 	-mcaller-super-interworking
    107   1.1  mrg 
    108   1.1  mrg will allow calls via function pointers in Thumb mode to work,
    109   1.1  mrg regardless of whether the function pointer points to old,
    110   1.1  mrg non-interworking aware code or not.  Specifying this switch does
    111   1.1  mrg produce slightly slower code however.
    112   1.1  mrg 
    113   1.1  mrg Note:  There is no switch to allow calls via function pointers in ARM
    114   1.1  mrg mode to be handled specially.  Calls via function pointers from
    115   1.1  mrg interworking aware ARM code to non-interworking aware ARM code work
    116   1.1  mrg without any special considerations by the compiler.  Calls via
    117   1.1  mrg function pointers from interworking aware ARM code to non-interworking
    118   1.1  mrg aware Thumb code however will not work.  (Actually under some
    119   1.1  mrg circumstances they may work, but there are no guarantees).  This is
    120   1.1  mrg because only the new compiler is able to produce Thumb code, and this
    121   1.1  mrg compiler already has a command line switch to produce interworking
    122   1.1  mrg aware code.
    123   1.1  mrg 
    124   1.1  mrg 
    125   1.1  mrg The switch
    126   1.1  mrg 
    127   1.1  mrg 	-mcallee-super-interworking
    128   1.1  mrg 
    129   1.1  mrg will allow non-interworking aware ARM or Thumb code to call Thumb
    130   1.1  mrg functions, either directly or via function pointers.  Specifying this
    131   1.1  mrg switch does produce slightly larger, slower code however.
    132   1.1  mrg 
    133   1.1  mrg Note:  There is no switch to allow non-interworking aware ARM or Thumb
    134   1.1  mrg code to call ARM functions.  There is no need for any special handling
    135   1.1  mrg of calls from non-interworking aware ARM code to interworking aware
    136   1.1  mrg ARM functions, they just work normally.  Calls from non-interworking
    137   1.1  mrg aware Thumb functions to ARM code however, will not work.  There is no
    138   1.1  mrg option to support this, since it is always possible to recompile the
    139   1.1  mrg Thumb code to be interworking aware.
    140   1.1  mrg 
    141   1.1  mrg As an alternative to the command line switch
    142   1.1  mrg -mcallee-super-interworking, which affects all externally visible
    143   1.1  mrg functions in a file, it is possible to specify an attribute or
    144   1.1  mrg declspec for individual functions, indicating that that particular
    145   1.1  mrg function should support being called by non-interworking aware code.
    146   1.1  mrg The function should be defined like this:
    147   1.1  mrg 
    148   1.1  mrg 	int __attribute__((interfacearm)) function 
    149   1.1  mrg 	{
    150   1.1  mrg 		... body of function ...
    151   1.1  mrg 	}
    152   1.1  mrg 
    153   1.1  mrg or
    154   1.1  mrg 
    155   1.1  mrg 	int __declspec(interfacearm) function
    156   1.1  mrg 	{
    157   1.1  mrg 		... body of function ...
    158   1.1  mrg 	}
    159   1.1  mrg 
    160   1.1  mrg 
    161   1.1  mrg 
    162   1.1  mrg 4. Interworking support in dlltool
    163   1.1  mrg ==================================
    164   1.1  mrg 
    165   1.1  mrg It is possible to create DLLs containing mixed ARM and Thumb code.  It
    166   1.1  mrg is also possible to call Thumb code in a DLL from an ARM program and
    167   1.1  mrg vice versa.  It is even possible to call ARM DLLs that have been compiled
    168   1.1  mrg without interworking support (say by an older version of the compiler),
    169   1.1  mrg from Thumb programs and still have things work properly.
    170   1.1  mrg 
    171   1.1  mrg    A version of the `dlltool' program which supports the `--interwork'
    172   1.1  mrg command line switch is needed, as well as the following special
    173   1.1  mrg considerations when building programs and DLLs:
    174   1.1  mrg 
    175   1.1  mrg *Use `-mthumb-interwork'*
    176   1.1  mrg      When compiling files for a DLL or a program the `-mthumb-interwork'
    177   1.1  mrg      command line switch should be specified if calling between ARM and
    178   1.1  mrg      Thumb code can happen.  If a program is being compiled and the
    179   1.1  mrg      mode of the DLLs that it uses is not known, then it should be
    180   1.1  mrg      assumed that interworking might occur and the switch used.
    181   1.1  mrg 
    182   1.1  mrg *Use `-m thumb'*
    183   1.1  mrg      If the exported functions from a DLL are all Thumb encoded then the
    184   1.1  mrg      `-m thumb' command line switch should be given to dlltool when
    185   1.1  mrg      building the stubs.  This will make dlltool create Thumb encoded
    186   1.1  mrg      stubs, rather than its default of ARM encoded stubs.
    187   1.1  mrg 
    188   1.1  mrg      If the DLL consists of both exported Thumb functions and exported
    189   1.1  mrg      ARM functions then the `-m thumb' switch should not be used.
    190   1.1  mrg      Instead the Thumb functions in the DLL should be compiled with the
    191   1.1  mrg      `-mcallee-super-interworking' switch, or with the `interfacearm'
    192   1.1  mrg      attribute specified on their prototypes.  In this way they will be
    193   1.1  mrg      given ARM encoded prologues, which will work with the ARM encoded
    194   1.1  mrg      stubs produced by dlltool.
    195   1.1  mrg 
    196   1.1  mrg *Use `-mcaller-super-interworking'*
    197   1.1  mrg      If it is possible for Thumb functions in a DLL to call
    198   1.1  mrg      non-interworking aware code via a function pointer, then the Thumb
    199   1.1  mrg      code must be compiled with the `-mcaller-super-interworking'
    200   1.1  mrg      command line switch.  This will force the function pointer calls
    201   1.1  mrg      to use the _interwork_call_via_rX stub functions which will
    202   1.1  mrg      correctly restore Thumb mode upon return from the called function.
    203   1.1  mrg 
    204   1.1  mrg *Link with `libgcc.a'*
    205   1.1  mrg      When the dll is built it may have to be linked with the GCC
    206   1.1  mrg      library (`libgcc.a') in order to extract the _call_via_rX functions
    207   1.1  mrg      or the _interwork_call_via_rX functions.  This represents a partial
    208   1.1  mrg      redundancy since the same functions *may* be present in the
    209   1.1  mrg      application itself, but since they only take up 372 bytes this
    210   1.1  mrg      should not be too much of a consideration.
    211   1.1  mrg 
    212   1.1  mrg *Use `--support-old-code'*
    213   1.1  mrg      When linking a program with an old DLL which does not support
    214   1.1  mrg      interworking, the `--support-old-code' command line switch to the
    215   1.1  mrg      linker should be used.   This causes the linker to generate special
    216   1.1  mrg      interworking stubs which can cope with old, non-interworking aware
    217   1.1  mrg      ARM code, at the cost of generating bulkier code.  The linker will
    218   1.1  mrg      still generate a warning message along the lines of:
    219   1.1  mrg        "Warning: input file XXX does not support interworking, whereas YYY does."
    220   1.1  mrg      but this can now be ignored because the --support-old-code switch
    221   1.1  mrg      has been used.
    222   1.1  mrg 
    223   1.1  mrg 
    224   1.1  mrg 
    225   1.1  mrg 5. How interworking support works
    226   1.1  mrg =================================
    227   1.1  mrg 
    228   1.1  mrg Switching between the ARM and Thumb instruction sets is accomplished
    229   1.1  mrg via the BX instruction which takes as an argument a register name.
    230   1.3  mrg Control is transferred to the address held in this register (with the
    231   1.1  mrg bottom bit masked out), and if the bottom bit is set, then Thumb
    232   1.1  mrg instruction processing is enabled, otherwise ARM instruction
    233   1.1  mrg processing is enabled.
    234   1.1  mrg 
    235   1.1  mrg When the -mthumb-interwork command line switch is specified, gcc
    236   1.1  mrg arranges for all functions to return to their caller by using the BX
    237   1.1  mrg instruction.  Thus provided that the return address has the bottom bit
    238   1.1  mrg correctly initialized to indicate the instruction set of the caller,
    239   1.1  mrg correct operation will ensue.
    240   1.1  mrg 
    241   1.1  mrg When a function is called explicitly (rather than via a function
    242   1.1  mrg pointer), the compiler generates a BL instruction to do this.  The
    243   1.1  mrg Thumb version of the BL instruction has the special property of
    244   1.1  mrg setting the bottom bit of the LR register after it has stored the
    245   1.1  mrg return address into it, so that a future BX instruction will correctly
    246   1.1  mrg return the instruction after the BL instruction, in Thumb mode.
    247   1.1  mrg 
    248   1.1  mrg The BL instruction does not change modes itself however, so if an ARM
    249   1.1  mrg function is calling a Thumb function, or vice versa, it is necessary
    250   1.1  mrg to generate some extra instructions to handle this.  This is done in
    251   1.1  mrg the linker when it is storing the address of the referenced function
    252   1.1  mrg into the BL instruction.  If the BL instruction is an ARM style BL
    253   1.1  mrg instruction, but the referenced function is a Thumb function, then the
    254   1.1  mrg linker automatically generates a calling stub that converts from ARM
    255   1.1  mrg mode to Thumb mode, puts the address of this stub into the BL
    256   1.1  mrg instruction, and puts the address of the referenced function into the
    257   1.1  mrg stub.  Similarly if the BL instruction is a Thumb BL instruction, and
    258   1.1  mrg the referenced function is an ARM function, the linker generates a
    259   1.1  mrg stub which converts from Thumb to ARM mode, puts the address of this
    260   1.1  mrg stub into the BL instruction, and the address of the referenced
    261   1.1  mrg function into the stub.
    262   1.1  mrg 
    263   1.1  mrg This is why it is necessary to mark Thumb functions with the
    264   1.1  mrg .thumb_func pseudo op when creating assembler files.  This pseudo op
    265   1.1  mrg allows the assembler to distinguish between ARM functions and Thumb
    266   1.1  mrg functions.  (The Thumb version of GCC automatically generates these
    267   1.1  mrg pseudo ops for any Thumb functions that it generates).
    268   1.1  mrg 
    269   1.1  mrg Calls via function pointers work differently.  Whenever the address of
    270   1.1  mrg a function is taken, the linker examines the type of the function
    271   1.1  mrg being referenced.  If the function is a Thumb function, then it sets
    272   1.1  mrg the bottom bit of the address.  Technically this makes the address
    273   1.1  mrg incorrect, since it is now one byte into the start of the function,
    274   1.1  mrg but this is never a problem because:
    275   1.1  mrg 
    276   1.1  mrg 	a. with interworking enabled all calls via function pointer
    277   1.1  mrg 	   are done using the BX instruction and this ignores the
    278   1.1  mrg 	   bottom bit when computing where to go to.
    279   1.1  mrg 
    280   1.1  mrg 	b. the linker will always set the bottom bit when the address
    281   1.1  mrg 	   of the function is taken, so it is never possible to take
    282   1.1  mrg 	   the address of the function in two different places and
    283   1.1  mrg 	   then compare them and find that they are not equal.
    284   1.1  mrg 
    285   1.1  mrg As already mentioned any call via a function pointer will use the BX
    286   1.1  mrg instruction (provided that interworking is enabled).  The only problem
    287   1.1  mrg with this is computing the return address for the return from the
    288   1.1  mrg called function.  For ARM code this can easily be done by the code
    289   1.1  mrg sequence:
    290   1.1  mrg 
    291   1.1  mrg 	mov	lr, pc
    292   1.1  mrg 	bx	rX
    293   1.1  mrg 
    294   1.1  mrg (where rX is the name of the register containing the function
    295   1.1  mrg pointer).  This code does not work for the Thumb instruction set,
    296   1.1  mrg since the MOV instruction will not set the bottom bit of the LR
    297   1.1  mrg register, so that when the called function returns, it will return in
    298   1.1  mrg ARM mode not Thumb mode.  Instead the compiler generates this
    299   1.1  mrg sequence:
    300   1.1  mrg 
    301   1.1  mrg 	bl	_call_via_rX
    302   1.1  mrg 
    303   1.1  mrg (again where rX is the name if the register containing the function
    304   1.1  mrg pointer).  The special call_via_rX functions look like this:
    305   1.1  mrg 
    306   1.1  mrg 	.thumb_func
    307   1.1  mrg _call_via_r0:
    308   1.1  mrg 	bx	r0
    309   1.1  mrg 	nop
    310   1.1  mrg 
    311   1.1  mrg The BL instruction ensures that the correct return address is stored
    312   1.1  mrg in the LR register and then the BX instruction jumps to the address
    313   1.1  mrg stored in the function pointer, switch modes if necessary.
    314   1.1  mrg 
    315   1.1  mrg 
    316   1.1  mrg 6. How caller-super-interworking support works
    317   1.1  mrg ==============================================
    318   1.1  mrg 
    319   1.1  mrg When the -mcaller-super-interworking command line switch is specified
    320   1.1  mrg it changes the code produced by the Thumb compiler so that all calls
    321   1.1  mrg via function pointers (including virtual function calls) now go via a
    322   1.1  mrg different stub function.  The code to call via a function pointer now
    323   1.1  mrg looks like this:
    324   1.1  mrg 
    325   1.1  mrg 	bl _interwork_call_via_r0
    326   1.1  mrg 
    327   1.1  mrg Note: The compiler does not insist that r0 be used to hold the
    328   1.1  mrg function address.  Any register will do, and there are a suite of stub
    329   1.1  mrg functions, one for each possible register.  The stub functions look
    330   1.1  mrg like this:
    331   1.1  mrg 
    332   1.1  mrg 	.code 16
    333   1.1  mrg 	.thumb_func
    334   1.1  mrg _interwork_call_via_r0
    335   1.1  mrg 	bx 	pc
    336   1.1  mrg 	nop
    337   1.1  mrg 	
    338   1.1  mrg 	.code 32
    339   1.1  mrg 	tst	r0, #1
    340   1.1  mrg 	stmeqdb	r13!, {lr}
    341   1.1  mrg 	adreq	lr, _arm_return
    342   1.1  mrg 	bx	r0
    343   1.1  mrg 
    344   1.1  mrg The stub first switches to ARM mode, since it is a lot easier to
    345   1.1  mrg perform the necessary operations using ARM instructions.  It then
    346   1.1  mrg tests the bottom bit of the register containing the address of the
    347   1.1  mrg function to be called.  If this bottom bit is set then the function
    348   1.1  mrg being called uses Thumb instructions and the BX instruction to come
    349   1.1  mrg will switch back into Thumb mode before calling this function.  (Note
    350   1.1  mrg that it does not matter how this called function chooses to return to
    351   1.1  mrg its caller, since the both the caller and callee are Thumb functions,
    352   1.1  mrg and mode switching is necessary).  If the function being called is an
    353   1.1  mrg ARM mode function however, the stub pushes the return address (with
    354   1.1  mrg its bottom bit set) onto the stack, replaces the return address with
    355   1.1  mrg the address of the a piece of code called '_arm_return' and then
    356   1.1  mrg performs a BX instruction to call the function.
    357   1.1  mrg 
    358   1.1  mrg The '_arm_return' code looks like this:
    359   1.1  mrg 
    360   1.1  mrg 	.code 32
    361   1.1  mrg _arm_return:		
    362   1.1  mrg 	ldmia 	r13!, {r12}
    363   1.1  mrg 	bx 	r12
    364   1.1  mrg 	.code 16
    365   1.1  mrg 
    366   1.1  mrg 
    367   1.1  mrg It simply retrieves the return address from the stack, and then
    368   1.1  mrg performs a BX operation to return to the caller and switch back into
    369   1.1  mrg Thumb mode.
    370   1.1  mrg 
    371   1.1  mrg 
    372   1.1  mrg 7. How callee-super-interworking support works
    373   1.1  mrg ==============================================
    374   1.1  mrg 
    375   1.1  mrg When -mcallee-super-interworking is specified on the command line the
    376   1.1  mrg Thumb compiler behaves as if every externally visible function that it
    377   1.1  mrg compiles has had the (interfacearm) attribute specified for it.  What
    378   1.1  mrg this attribute does is to put a special, ARM mode header onto the
    379   1.1  mrg function which forces a switch into Thumb mode:
    380   1.1  mrg 
    381   1.1  mrg   without __attribute__((interfacearm)):
    382   1.1  mrg 
    383   1.1  mrg 		.code 16
    384   1.1  mrg 		.thumb_func
    385   1.1  mrg 	function:
    386   1.1  mrg 		... start of function ...
    387   1.1  mrg 
    388   1.1  mrg   with __attribute__((interfacearm)):
    389   1.1  mrg 
    390   1.1  mrg 		.code 32
    391   1.1  mrg 	function:
    392   1.1  mrg 		orr	r12, pc, #1
    393   1.1  mrg 		bx	r12
    394   1.1  mrg 
    395   1.1  mrg 		.code 16
    396   1.1  mrg                 .thumb_func
    397   1.1  mrg         .real_start_of_function:
    398   1.1  mrg 
    399   1.1  mrg 		... start of function ...
    400   1.1  mrg 
    401   1.1  mrg Note that since the function now expects to be entered in ARM mode, it
    402   1.1  mrg no longer has the .thumb_func pseudo op specified for its name.
    403   1.1  mrg Instead the pseudo op is attached to a new label .real_start_of_<name>
    404   1.1  mrg (where <name> is the name of the function) which indicates the start
    405   1.1  mrg of the Thumb code.  This does have the interesting side effect in that
    406   1.1  mrg if this function is now called from a Thumb mode piece of code
    407   1.1  mrg outside of the current file, the linker will generate a calling stub
    408   1.1  mrg to switch from Thumb mode into ARM mode, and then this is immediately
    409   1.1  mrg overridden by the function's header which switches back into Thumb
    410   1.1  mrg mode. 
    411   1.1  mrg 
    412   1.1  mrg In addition the (interfacearm) attribute also forces the function to
    413   1.1  mrg return by using the BX instruction, even if has not been compiled with
    414   1.1  mrg the -mthumb-interwork command line flag, so that the correct mode will
    415   1.1  mrg be restored upon exit from the function.
    416   1.1  mrg 
    417   1.1  mrg 
    418   1.1  mrg 8. Some examples
    419   1.1  mrg ================
    420   1.1  mrg 
    421   1.1  mrg    Given these two test files:
    422   1.1  mrg 
    423   1.1  mrg              int arm (void) { return 1 + thumb (); }
    424   1.1  mrg 
    425   1.1  mrg              int thumb (void) { return 2 + arm (); }
    426   1.1  mrg 
    427   1.1  mrg    The following pieces of assembler are produced by the ARM and Thumb
    428   1.1  mrg version of GCC depending upon the command line options used:
    429   1.1  mrg 
    430   1.1  mrg    `-O2':
    431   1.1  mrg              .code 32                               .code 16
    432   1.1  mrg              .global _arm                           .global _thumb
    433   1.1  mrg                                                     .thumb_func
    434   1.1  mrg      _arm:                                    _thumb:
    435   1.1  mrg              mov     ip, sp
    436   1.1  mrg              stmfd   sp!, {fp, ip, lr, pc}          push    {lr}
    437   1.1  mrg              sub     fp, ip, #4
    438   1.1  mrg              bl      _thumb                          bl      _arm
    439   1.1  mrg              add     r0, r0, #1                      add     r0, r0, #2
    440   1.1  mrg              ldmea   fp, {fp, sp, pc}                pop     {pc}
    441   1.1  mrg 
    442   1.1  mrg    Note how the functions return without using the BX instruction.  If
    443   1.1  mrg these files were assembled and linked together they would fail to work
    444   1.1  mrg because they do not change mode when returning to their caller.
    445   1.1  mrg 
    446   1.1  mrg    `-O2 -mthumb-interwork':
    447   1.1  mrg 
    448   1.1  mrg              .code 32                               .code 16
    449   1.1  mrg              .global _arm                           .global _thumb
    450   1.1  mrg                                                     .thumb_func
    451   1.1  mrg      _arm:                                    _thumb:
    452   1.1  mrg              mov     ip, sp
    453   1.1  mrg              stmfd   sp!, {fp, ip, lr, pc}          push    {lr}
    454   1.1  mrg              sub     fp, ip, #4
    455   1.1  mrg              bl      _thumb                         bl       _arm
    456   1.1  mrg              add     r0, r0, #1                     add      r0, r0, #2
    457   1.1  mrg              ldmea   fp, {fp, sp, lr}               pop      {r1}
    458   1.1  mrg              bx      lr                             bx       r1
    459   1.1  mrg 
    460   1.1  mrg    Now the functions use BX to return their caller.  They have grown by
    461   1.1  mrg 4 and 2 bytes respectively, but they can now successfully be linked
    462   1.1  mrg together and be expect to work.  The linker will replace the
    463   1.1  mrg destinations of the two BL instructions with the addresses of calling
    464   1.1  mrg stubs which convert to the correct mode before jumping to the called
    465   1.1  mrg function.
    466   1.1  mrg 
    467   1.1  mrg    `-O2 -mcallee-super-interworking':
    468   1.1  mrg 
    469   1.1  mrg              .code 32                               .code 32
    470   1.1  mrg              .global _arm                           .global _thumb
    471   1.1  mrg      _arm:                                    _thumb:
    472   1.1  mrg                                                     orr      r12, pc, #1
    473   1.1  mrg                                                     bx       r12
    474   1.1  mrg              mov     ip, sp                         .code 16
    475   1.1  mrg              stmfd   sp!, {fp, ip, lr, pc}          push     {lr}
    476   1.1  mrg              sub     fp, ip, #4
    477   1.1  mrg              bl      _thumb                         bl       _arm
    478   1.1  mrg              add     r0, r0, #1                     add      r0, r0, #2
    479   1.1  mrg              ldmea   fp, {fp, sp, lr}               pop      {r1}
    480   1.1  mrg              bx      lr                             bx       r1
    481   1.1  mrg 
    482   1.1  mrg    The thumb function now has an ARM encoded prologue, and it no longer
    483   1.1  mrg has the `.thumb-func' pseudo op attached to it.  The linker will not
    484   1.1  mrg generate a calling stub for the call from arm() to thumb(), but it will
    485   1.1  mrg still have to generate a stub for the call from thumb() to arm().  Also
    486   1.1  mrg note how specifying `--mcallee-super-interworking' automatically
    487   1.1  mrg implies `-mthumb-interworking'.
    488   1.1  mrg 
    489   1.1  mrg 
    490   1.1  mrg 9. Some Function Pointer Examples
    491   1.1  mrg =================================
    492   1.1  mrg 
    493   1.1  mrg    Given this test file:
    494   1.1  mrg 
    495   1.1  mrg      	int func (void) { return 1; }
    496   1.1  mrg      
    497   1.1  mrg      	int call (int (* ptr)(void)) { return ptr (); }
    498   1.1  mrg 
    499   1.1  mrg    The following varying pieces of assembler are produced by the Thumb
    500   1.1  mrg version of GCC depending upon the command line options used:
    501   1.1  mrg 
    502   1.1  mrg    `-O2':
    503   1.1  mrg      		.code	16
    504   1.1  mrg      		.globl	_func
    505   1.1  mrg      		.thumb_func
    506   1.1  mrg      	_func:
    507   1.1  mrg      		mov	r0, #1
    508   1.1  mrg      		bx	lr
    509   1.1  mrg      
    510   1.1  mrg      		.globl	_call
    511   1.1  mrg      		.thumb_func
    512   1.1  mrg      	_call:
    513   1.1  mrg      		push	{lr}
    514   1.1  mrg      		bl	__call_via_r0
    515   1.1  mrg      		pop	{pc}
    516   1.1  mrg 
    517   1.1  mrg    Note how the two functions have different exit sequences.  In
    518   1.1  mrg particular call() uses pop {pc} to return, which would not work if the
    519   1.1  mrg caller was in ARM mode.  func() however, uses the BX instruction, even
    520   1.1  mrg though `-mthumb-interwork' has not been specified, as this is the most
    521   1.1  mrg efficient way to exit a function when the return address is held in the
    522   1.1  mrg link register.
    523   1.1  mrg 
    524   1.1  mrg    `-O2 -mthumb-interwork':
    525   1.1  mrg 
    526   1.1  mrg      		.code	16
    527   1.1  mrg      		.globl	_func
    528   1.1  mrg      		.thumb_func
    529   1.1  mrg      	_func:
    530   1.1  mrg      		mov	r0, #1
    531   1.1  mrg      		bx	lr
    532   1.1  mrg      
    533   1.1  mrg      		.globl	_call
    534   1.1  mrg      		.thumb_func
    535   1.1  mrg      	_call:
    536   1.1  mrg      		push	{lr}
    537   1.1  mrg      		bl	__call_via_r0
    538   1.1  mrg      		pop	{r1}
    539   1.1  mrg      		bx	r1
    540   1.1  mrg 
    541   1.1  mrg    This time both functions return by using the BX instruction.  This
    542   1.1  mrg means that call() is now two bytes longer and several cycles slower
    543   1.1  mrg than the previous version.
    544   1.1  mrg 
    545   1.1  mrg    `-O2 -mcaller-super-interworking':
    546   1.1  mrg      		.code	16
    547   1.1  mrg      		.globl	_func
    548   1.1  mrg      		.thumb_func
    549   1.1  mrg      	_func:
    550   1.1  mrg      		mov	r0, #1
    551   1.1  mrg      		bx	lr
    552   1.1  mrg      
    553   1.1  mrg      		.globl	_call
    554   1.1  mrg      		.thumb_func
    555   1.1  mrg      	_call:
    556   1.1  mrg      		push	{lr}
    557   1.1  mrg      		bl	__interwork_call_via_r0
    558   1.1  mrg      		pop	{pc}
    559   1.1  mrg 
    560   1.1  mrg    Very similar to the first (non-interworking) version, except that a
    561   1.1  mrg different stub is used to call via the function pointer.  This new stub
    562   1.1  mrg will work even if the called function is not interworking aware, and
    563   1.1  mrg tries to return to call() in ARM mode.  Note that the assembly code for
    564   1.1  mrg call() is still not interworking aware itself, and so should not be
    565   1.1  mrg called from ARM code.
    566   1.1  mrg 
    567   1.1  mrg    `-O2 -mcallee-super-interworking':
    568   1.1  mrg 
    569   1.1  mrg      		.code	32
    570   1.1  mrg      		.globl	_func
    571   1.1  mrg      	_func:
    572   1.1  mrg      		orr	r12, pc, #1
    573   1.1  mrg      		bx	r12
    574   1.1  mrg      
    575   1.1  mrg      		.code	16
    576   1.1  mrg      		.globl .real_start_of_func
    577   1.1  mrg      		.thumb_func
    578   1.1  mrg      	.real_start_of_func:
    579   1.1  mrg      		mov	r0, #1
    580   1.1  mrg      		bx	lr
    581   1.1  mrg      
    582   1.1  mrg      		.code	32
    583   1.1  mrg      		.globl	_call
    584   1.1  mrg      	_call:
    585   1.1  mrg      		orr	r12, pc, #1
    586   1.1  mrg      		bx	r12
    587   1.1  mrg      
    588   1.1  mrg      		.code	16
    589   1.1  mrg      		.globl .real_start_of_call
    590   1.1  mrg      		.thumb_func
    591   1.1  mrg      	.real_start_of_call:
    592   1.1  mrg      		push	{lr}
    593   1.1  mrg      		bl	__call_via_r0
    594   1.1  mrg      		pop	{r1}
    595   1.1  mrg      		bx	r1
    596   1.1  mrg 
    597   1.1  mrg    Now both functions have an ARM coded prologue, and both functions
    598   1.1  mrg return by using the BX instruction.  These functions are interworking
    599   1.1  mrg aware therefore and can safely be called from ARM code.  The code for
    600   1.1  mrg the call() function is now 10 bytes longer than the original, non
    601   1.1  mrg interworking aware version, an increase of over 200%.
    602   1.1  mrg 
    603   1.1  mrg    If a prototype for call() is added to the source code, and this
    604   1.1  mrg prototype includes the `interfacearm' attribute:
    605   1.1  mrg 
    606   1.1  mrg      	int __attribute__((interfacearm)) call (int (* ptr)(void));
    607   1.1  mrg 
    608   1.1  mrg    then this code is produced (with only -O2 specified on the command
    609   1.1  mrg line):
    610   1.1  mrg 
    611   1.1  mrg      		.code	16
    612   1.1  mrg      		.globl	_func
    613   1.1  mrg      		.thumb_func
    614   1.1  mrg      	_func:
    615   1.1  mrg      		mov	r0, #1
    616   1.1  mrg      		bx	lr
    617   1.1  mrg      
    618   1.1  mrg      		.globl	_call
    619   1.1  mrg      		.code	32
    620   1.1  mrg      	_call:
    621   1.1  mrg      		orr	r12, pc, #1
    622   1.1  mrg      		bx	r12
    623   1.1  mrg      
    624   1.1  mrg      		.code	16
    625   1.1  mrg      		.globl .real_start_of_call
    626   1.1  mrg      		.thumb_func
    627   1.1  mrg      	.real_start_of_call:
    628   1.1  mrg      		push	{lr}
    629   1.1  mrg      		bl	__call_via_r0
    630   1.1  mrg      		pop	{r1}
    631   1.1  mrg      		bx	r1
    632   1.1  mrg 
    633   1.1  mrg    So now both call() and func() can be safely called via
    634   1.1  mrg non-interworking aware ARM code.  If, when such a file is assembled,
    635   1.1  mrg the assembler detects the fact that call() is being called by another
    636   1.1  mrg function in the same file, it will automatically adjust the target of
    637   1.1  mrg the BL instruction to point to .real_start_of_call.  In this way there
    638   1.1  mrg is no need for the linker to generate a Thumb-to-ARM calling stub so
    639   1.1  mrg that call can be entered in ARM mode.
    640   1.1  mrg 
    641   1.1  mrg 
    642   1.1  mrg 10. How to use dlltool to build ARM/Thumb DLLs
    643   1.1  mrg ==============================================
    644   1.1  mrg    Given a program (`prog.c') like this:
    645   1.1  mrg 
    646   1.1  mrg              extern int func_in_dll (void);
    647   1.1  mrg      
    648   1.1  mrg              int main (void) { return func_in_dll(); }
    649   1.1  mrg 
    650   1.1  mrg    And a DLL source file (`dll.c') like this:
    651   1.1  mrg 
    652   1.1  mrg              int func_in_dll (void) { return 1; }
    653   1.1  mrg 
    654   1.1  mrg    Here is how to build the DLL and the program for a purely ARM based
    655   1.1  mrg environment:
    656   1.1  mrg 
    657   1.1  mrg *Step One
    658   1.1  mrg      Build a `.def' file describing the DLL:
    659   1.1  mrg 
    660   1.1  mrg              ; example.def
    661   1.1  mrg              ; This file describes the contents of the DLL
    662   1.1  mrg              LIBRARY     example
    663   1.1  mrg              HEAPSIZE    0x40000, 0x2000
    664   1.1  mrg              EXPORTS
    665   1.1  mrg                           func_in_dll  1
    666   1.1  mrg 
    667   1.1  mrg *Step Two
    668   1.1  mrg      Compile the DLL source code:
    669   1.1  mrg 
    670   1.1  mrg             arm-pe-gcc -O2 -c dll.c
    671   1.1  mrg 
    672   1.1  mrg *Step Three
    673   1.1  mrg      Use `dlltool' to create an exports file and a library file:
    674   1.1  mrg 
    675   1.1  mrg             dlltool --def example.def --output-exp example.o --output-lib example.a
    676   1.1  mrg 
    677   1.1  mrg *Step Four
    678   1.1  mrg      Link together the complete DLL:
    679   1.1  mrg 
    680   1.1  mrg             arm-pe-ld dll.o example.o -o example.dll
    681   1.1  mrg 
    682   1.1  mrg *Step Five
    683   1.1  mrg      Compile the program's source code:
    684   1.1  mrg 
    685   1.1  mrg             arm-pe-gcc -O2 -c prog.c
    686   1.1  mrg 
    687   1.1  mrg *Step Six
    688   1.1  mrg      Link together the program and the DLL's library file:
    689   1.1  mrg 
    690   1.1  mrg             arm-pe-gcc prog.o example.a -o prog
    691   1.1  mrg 
    692   1.1  mrg    If instead this was a Thumb DLL being called from an ARM program, the
    693   1.1  mrg steps would look like this.  (To save space only those steps that are
    694   1.1  mrg different from the previous version are shown):
    695   1.1  mrg 
    696   1.1  mrg *Step Two
    697   1.1  mrg      Compile the DLL source code (using the Thumb compiler):
    698   1.1  mrg 
    699   1.1  mrg             thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
    700   1.1  mrg 
    701   1.1  mrg *Step Three
    702   1.1  mrg      Build the exports and library files (and support interworking):
    703   1.1  mrg 
    704   1.1  mrg             dlltool -d example.def -z example.o -l example.a --interwork -m thumb
    705   1.1  mrg 
    706   1.1  mrg *Step Five
    707   1.1  mrg      Compile the program's source code (and support interworking):
    708   1.1  mrg 
    709   1.1  mrg             arm-pe-gcc -O2 -c prog.c -mthumb-interwork
    710   1.1  mrg 
    711   1.1  mrg    If instead, the DLL was an old, ARM DLL which does not support
    712   1.1  mrg interworking, and which cannot be rebuilt, then these steps would be
    713   1.1  mrg used.
    714   1.1  mrg 
    715   1.1  mrg *Step One
    716   1.1  mrg      Skip.  If you do not have access to the sources of a DLL, there is
    717   1.1  mrg      no point in building a `.def' file for it.
    718   1.1  mrg 
    719   1.1  mrg *Step Two
    720   1.1  mrg      Skip.  With no DLL sources there is nothing to compile.
    721   1.1  mrg 
    722   1.1  mrg *Step Three
    723   1.1  mrg      Skip.  Without a `.def' file you cannot use dlltool to build an
    724   1.1  mrg      exports file or a library file.
    725   1.1  mrg 
    726   1.1  mrg *Step Four
    727   1.1  mrg      Skip.  Without a set of DLL object files you cannot build the DLL.
    728   1.1  mrg      Besides it has already been built for you by somebody else.
    729   1.1  mrg 
    730   1.1  mrg *Step Five
    731   1.1  mrg      Compile the program's source code, this is the same as before:
    732   1.1  mrg 
    733   1.1  mrg             arm-pe-gcc -O2 -c prog.c
    734   1.1  mrg 
    735   1.1  mrg *Step Six
    736   1.1  mrg      Link together the program and the DLL's library file, passing the
    737   1.1  mrg      `--support-old-code' option to the linker:
    738   1.1  mrg 
    739   1.1  mrg             arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
    740   1.1  mrg 
    741   1.1  mrg      Ignore the warning message about the input file not supporting
    742   1.1  mrg      interworking as the --support-old-code switch has taken care if this.
    743   1.1  mrg 
    744   1.1  mrg 
    746   1.1  mrg Copyright (C) 1998-2022 Free Software Foundation, Inc.
    747   1.1  mrg 
    748   1.1  mrg Copying and distribution of this file, with or without modification,
    749   1.1  mrg are permitted in any medium without royalty provided the copyright
    750            notice and this notice are preserved.
    751