thumb.c - add warning about PIC code not being supported just yet.
authorNick Clifton <nickc@cygnus.com>
Mon, 12 Oct 1998 10:53:08 +0000 (10:53 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Mon, 12 Oct 1998 10:53:08 +0000 (10:53 +0000)
arm.c - synchronised with devo
arm.md - synchronised with devo
README-interworking - sychronised with devo.

From-SVN: r23013

gcc/ChangeLog
gcc/config/arm/README-interworking
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/thumb.c

index 2cb1e09631de317ecfb2bd82d25d9cf64db632dc..f2868a6ae50e32451e2a7e8b29c0458fe258bcb4 100644 (file)
@@ -1,3 +1,8 @@
+Mon Oct 12 10:50:44 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * config/arm/thumb.c (thumb_override_options): Add warning about
+       PIC code not being supported just yet.
+
 Sun Oct 11 16:49:15 EDT 1998  John Wehle  (john@feith.com)
 
        * flow.c: Update comment.
index a0069a9ea80b57318998a7185fd1050a9900637d..46b76c9924251d6369ff8b7456515df7a4d23b89 100644 (file)
@@ -145,14 +145,14 @@ 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:
 
-       int function __attribute__((interfacearm))
+       int __attribute__((interfacearm)) function 
        {
                ... body of function ...
        }
 
 or
 
-       int function __declspec(interfacearm)
+       int __declspec(interfacearm) function
        {
                ... body of function ...
        }
@@ -162,8 +162,63 @@ or
 4. Interworking support in dlltool
 ==================================
 
-Currently there is no interworking support in dlltool.  This may be a
-future enhancement.
+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 `dlltool' program which supports the `--interwork'
+command line switch is needed, as well as the following special
+considerations when building programs and DLLs:
+
+*Use `-mthumb-interwork'*
+     When compiling files for a DLL or a program the `-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.
+
+*Use `-m thumb'*
+     If the exported functions from a DLL are all Thumb encoded then the
+     `-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 `-m thumb' switch should not be used.
+     Instead the Thumb functions in the DLL should be compiled with the
+     `-mcallee-super-interworking' switch, or with the `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.
+
+*Use `-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 `-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.
+
+*Link with `libgcc.a'*
+     When the dll is built it may have to be linked with the GCC
+     library (`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 *may* be present in the
+     application itself, but since they only take up 372 bytes this
+     should not be too much of a consideration.
+
+*Use `--support-old-code'*
+     When linking a program with an old DLL which does not support
+     interworking, the `--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.
 
 
 
@@ -363,191 +418,325 @@ be restored upon exit from the function.
 8. Some examples
 ================
 
-Given this test file:
+   Given these two test files:
+
+             int arm (void) { return 1 + thumb (); }
+
+             int thumb (void) { return 2 + arm (); }
+
+   The following pieces of assembler are produced by the ARM and Thumb
+version of GCC depending upon the command line options used:
+
+   `-O2':
+             .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}
+
+   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.
+
+   `-O2 -mthumb-interwork':
+
+             .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
+
+   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.
+
+   `-O2 -mcallee-super-interworking':
+
+             .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
+
+   The thumb function now has an ARM encoded prologue, and it no longer
+has the `.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 `--mcallee-super-interworking' automatically
+implies `-mthumb-interworking'.
+
+
+9. Some Function Pointer Examples
+=================================
 
-       int func (void) { return 1; }
+   Given this test file:
+
+       int func (void) { return 1; }
+     
+       int call (int (* ptr)(void)) { return ptr (); }
+
+   The following varying pieces of assembler are produced by the Thumb
+version of GCC depending upon the command line options used:
+
+   `-O2':
+               .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}
+
+   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 `-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.
+
+   `-O2 -mthumb-interwork':
+
+               .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
+
+   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.
+
+   `-O2 -mcaller-super-interworking':
+               .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}
+
+   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.
+
+   `-O2 -mcallee-super-interworking':
+
+               .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
+
+   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%.
 
-       int call (int (* ptr)(void)) { return ptr (); }
+   If a prototype for call() is added to the source code, and this
+prototype includes the `interfacearm' attribute:
+
+       int __attribute__((interfacearm)) call (int (* ptr)(void));
+
+   then this code is produced (with only -O2 specified on the command
+line):
+
+               .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
+
+   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.
+
+
+10. How to use dlltool to build ARM/Thumb DLLs
+==============================================
+   Given a program (`prog.c') like this:
 
-The following varying pieces of assembler are produced depending upon
-the command line options used:
+             extern int func_in_dll (void);
+     
+             int main (void) { return func_in_dll(); }
 
-no options:
+   And a DLL source file (`dll.c') like this:
 
-       @ Generated by gcc cygnus-2.91.07 980205 (gcc-2.8.0 release) for ARM/pe
-               .code   16
-               .text
-               .globl  _func
-               .thumb_func
-       _func:
-               mov     r0, #1
-               bx      lr
+             int func_in_dll (void) { return 1; }
 
-               .globl  _call
-               .thumb_func
-       _call:
-               push    {lr}
-               bl      __call_via_r0
-               pop     {pc}
+   Here is how to build the DLL and the program for a purely ARM based
+environment:
 
-Note how the two functions have different exit sequences.  In
-particular call() uses pop {pc} to return.  This would not work if the
-caller was in ARM mode.
+*Step One
+     Build a `.def' file describing the DLL:
 
-If -mthumb-interwork is specified on the command line:
+             ; example.def
+             ; This file describes the contents of the DLL
+             LIBRARY     example
+             HEAPSIZE    0x40000, 0x2000
+             EXPORTS
+                          func_in_dll  1
 
-       @ Generated by gcc cygnus-2.91.07 980205 (gcc-2.8.0 release) for ARM/pe
-               .code   16
-               .text
-               .globl  _func
-               .thumb_func
-       _func:
-               mov     r0, #1
-               bx      lr
+*Step Two
+     Compile the DLL source code:
 
-               .globl  _call
-               .thumb_func
-       _call:
-               push    {lr}
-               bl      __call_via_r0
-               pop     {r1}
-               bx      r1
+            arm-pe-gcc -O2 -c dll.c
 
-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 version that is not interworking enabled.
+*Step Three
+     Use `dlltool' to create an exports file and a library file:
 
-If -mcaller-super-interworking is specified:
+            dlltool --def example.def --output-exp example.o --output-lib example.a
 
-       @ Generated by gcc cygnus-2.91.07 980205 (gcc-2.8.0 release) for ARM/pe
-               .code   16
-               .text
-               .globl  _func
-               .thumb_func
-       _func:
-               mov     r0, #1
-               bx      lr
+*Step Four
+     Link together the complete DLL:
 
-               .globl  _call
-               .thumb_func
-       _call:
-               push    {lr}
-               bl      __interwork_call_via_r0
-               pop     {pc}
-
-Very similar to the first (non-interworking) version, except that a
-different stub is used to call via the function pointer.  Note that
-the assembly code for call() is not interworking aware, and so should
-not be called from ARM code.
-
-If -mcallee-super-interworking is specified:
-
-       @ Generated by gcc cygnus-2.91.07 980205 (gcc-2.8.0 release) for ARM/pe
-               .code   16
-               .text
-               .globl  _func
-               .code   32
-       _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
+            arm-pe-ld dll.o example.o -o example.dll
 
-               .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
+*Step Five
+     Compile the program's source code:
 
-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%.
+            arm-pe-gcc -O2 -c prog.c
 
-If the source code is slightly altered so that only the call function
-has an (interfacearm) attribute:
+*Step Six
+     Link together the program and the DLL's library file:
 
-       int func (void) { return 1; }
-       int call () __attribute__((interfacearm));
-       int call (int (* ptr)(void)) { return ptr (); }
-       int main (void) { return printf ("result: %d\n", call (func)); }
+            arm-pe-gcc prog.o example.a -o prog
 
-then this code is produced (with no command line switches):
+   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):
 
-       @ Generated by gcc cygnus-2.91.07 980205 (gcc-2.8.0 release) for ARM/pe
-               .code   16
-               .text
-               .globl  _func
-               .thumb_func
-       _func:
-               mov     r0, #1
-               bx      lr
+*Step Two
+     Compile the DLL source code (using the Thumb compiler):
 
-               .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
+            thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
 
-               .globl  _main
-               .thumb_func
-       _main:
-               push    {r4, lr}
-               bl      ___gccmain
-               ldr     r4, .L4
-               ldr     r0, .L4+4
-               bl      _call
-               add     r1, r0, #0
-               add     r0, r4, #0
-               bl      _printf
-               pop     {r4, pc}
-       .L4:
-               .word   .LC0
-               .word   _func
-
-               .section .rdata
-       .LC0:
-               .ascii  "result: %d\n\000"
-
-So now only call() can be called via non-interworking aware ARM code.
-When this program is assembled, the assembler detects the fact that
-main() is calling call() in Thumb mode, and so automatically adjusts
-the BL instruction to point to the real start of call():
-
-       Disassembly of section .text:
-
-       00000028 <_main>:
-         28:   b530            b530    push    {r4, r5, lr}
-         2a:   fffef7ff        f7ff    bl      2a <_main+0x2>
-         2e:   4d06            4d06    ldr     r5, [pc, #24]   (48 <.L7>)
-         30:   ffe8f7ff        f7ff    bl      4 <_doit>
-         34:   1c04            1c04    add     r4, r0, #0
-         36:   4805            4805    ldr     r0, [pc, #20]   (4c <.L7+0x4>)
-         38:   fff0f7ff        f7ff    bl      1c <.real_start_of_call>
-         3c:   1824            1824    add     r4, r4, r0
-         3e:   1c28            1c28    add     r0, r5, #0
-         40:   1c21            1c21    add     r1, r4, #0
-         42:   fffef7ff        f7ff    bl      42 <_main+0x1a>
-         46:   bd30            bd30    pop     {r4, r5, pc}
+*Step Three
+     Build the exports and library files (and support interworking):
+
+            dlltool -d example.def -z example.o -l example.a --interwork -m thumb
+
+*Step Five
+     Compile the program's source code (and support interworking):
+
+            arm-pe-gcc -O2 -c prog.c -mthumb-interwork
+
+   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.
+
+*Step One
+     Skip.  If you do not have access to the sources of a DLL, there is
+     no point in building a `.def' file for it.
+
+*Step Two
+     Skip.  With no DLL sources there is nothing to compile.
+
+*Step Three
+     Skip.  Without a `.def' file you cannot use dlltool to build an
+     exports file or a library file.
+
+*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.
+
+*Step Five
+     Compile the program's source code, this is the same as before:
+
+            arm-pe-gcc -O2 -c prog.c
+
+*Step Six
+     Link together the program and the DLL's library file, passing the
+     `--support-old-code' option to the linker:
+
+            arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
 
+     Ignore the warning message about the input file not supporting
+     interworking as the --support-old-code switch has taken care if this.
index a4719c613791c58b4caba82b08188dbdb3dc044a..feaf7ba6d22870cc211aa23a648e240ee498b69a 100644 (file)
@@ -222,11 +222,14 @@ arm_override_options ()
   int arm_thumb_aware = 0;
   int flags = 0;
   unsigned i;
-  struct arm_cpu_select *ptr;
-  static struct cpu_default {
-    int cpu;
-    char *name;
-  } cpu_defaults[] = {
+  struct arm_cpu_select * ptr;
+  static struct cpu_default
+  {
+    int    cpu;
+    char * name;
+  }
+  cpu_defaults[] =
+  {
     { TARGET_CPU_arm2, "arm2" },
     { TARGET_CPU_arm6, "arm6" },
     { TARGET_CPU_arm610, "arm610" },
@@ -3642,7 +3645,7 @@ find_barrier (from, max_count)
       
       /* Walk back to be just before any jump.  */
       while (GET_CODE (from) == JUMP_INSN
-             || GET_CODE (from) == NOTE
+            || GET_CODE (from) == NOTE
             || GET_CODE (from) == CODE_LABEL)
        from = PREV_INSN (from);
       
@@ -4857,7 +4860,7 @@ output_return_instruction (operand, really_return, reverse)
   else if (really_return)
     {
       if (TARGET_THUMB_INTERWORK)
-       sprintf (instr, "bx%%?%%%s\t%%|lr", reverse ? "D" : "d");
+       sprintf (instr, "bx%%?%%%s0\t%%|lr", reverse ? "D" : "d");
       else
        sprintf (instr, "mov%%?%%%s0%s\t%%|pc, %%|lr",
                 reverse ? "D" : "d", TARGET_APCS_32 ? "" : "s");
@@ -5156,10 +5159,10 @@ output_func_epilogue (f, frame_size)
          /* And finally, go home */
          if (TARGET_THUMB_INTERWORK)
            fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX);
+         else if (TARGET_APCS_32)
+           fprintf (f, "\tmov\t%spc, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX );
          else
-           fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n"
-                        : "\tmovs\t%spc, %slr\n"),
-                    REGISTER_PREFIX, REGISTER_PREFIX, f);
+           fprintf (f, "\tmovs\t%spc, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX );
        }
     }
 
index 20b8d57b40ab2b61df24fbd87977e71cd6058f03..ffbff79aff85edf2dc45f4e3ffb2c970c4a89943 100644 (file)
   "sub%?s\\t%0, %1, #0"
 [(set_attr "conds" "set")])
 
-; Peepholes to spot possible load- and store-multiples.
+; Peepholes to spot possible load- and store-multiples, if the ordering is
+; reversed, check that the memory references aren't volatile.
 
 (define_peephole
   [(set (match_operand:SI 0 "s_register_operand" "=r")
index c7cc7a28e450ecff9cbba6e95c2ca0533ed73126..bd302a5966591639dc7ac11a5f86843ca4cabe2e 100644 (file)
@@ -1465,7 +1465,8 @@ thumb_unexpanded_epilogue ()
       if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
        thumb_exit (asm_out_file,
                    (had_to_push_lr
-                    && is_called_in_ARM_mode (current_function_decl)) ? -1 : LINK_REGISTER);
+                    && is_called_in_ARM_mode (current_function_decl)) ?
+                   -1 : LINK_REGISTER);
     }
   else
     {
@@ -1971,7 +1972,8 @@ thumb_return_in_memory (type)
   return 1;
 }
 
-void thumb_override_options()
+void
+thumb_override_options ()
 {
   if (structure_size_string != NULL)
     {
@@ -1982,4 +1984,10 @@ void thumb_override_options()
       else
        warning ("Structure size boundary can only be set to 8 or 32");
     }
+
+  if (flag_pic)
+    {
+      warning ("Position independent code not supported.  Ignored");
+      flag_pic = 0;
+    }
 }