Add thumb-pe support.
authorNick Clifton <nickc@cygnus.com>
Wed, 1 Apr 1998 17:19:01 +0000 (17:19 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Wed, 1 Apr 1998 17:19:01 +0000 (17:19 +0000)
Add super interworking.

From-SVN: r18935

15 files changed:
gcc/ChangeLog
gcc/config.sub
gcc/config/arm/README-interworking [new file with mode: 0644]
gcc/config/arm/lib1funcs.asm
gcc/config/arm/lib1thumb.asm
gcc/config/arm/t-pe [new file with mode: 0644]
gcc/config/arm/t-pe-thumb [new file with mode: 0644]
gcc/config/arm/t-semi
gcc/config/arm/t-thumb
gcc/config/arm/thumb.c
gcc/config/arm/thumb.h
gcc/config/arm/thumb.md
gcc/config/arm/tpe.h [new file with mode: 0644]
gcc/configure
gcc/configure.in

index 988ec23d8abd5ef320331a1c2800999734351929..8e821948519c9c79b1a3fdafaaaf611108bb753f 100644 (file)
@@ -1,3 +1,20 @@
+Wed Apr  1 17:06:19 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * config/arm/thumb.h: Add super interworking support.
+       * config/arm/thumb.c: Add super interworking support.
+       * config/arm/thumb.md: Add super interworking support.
+       * config/arm/tpe.h: New file.
+       * config/arm/lib1funcs.asm: Add interworking support.
+       * config/arm/lib1thumb.asm: Add super interworking support.
+       * config/arm/t-pe: New file.
+       * config/arm/t-semi: Add interworking support.
+       * config/arm/t-thumb: Add interworking support.
+       * config/arm/t-pe-thumb: New file.
+       * config/arm/README-interworking: New file.
+       * config.sub: Add thumb-pe target.
+       * configure.in: Add thumb-pe target.
+       * configure: Add thumb-pe target.
+       
 Wed Apr  1 14:38:10 1998  Jim Wilson  <wilson@cygnus.com>
 
        * config/mips/iris6.h (MD_EXEC_PREFIX): Set to /usr/bin/.
index dd52e87aee8565d3ac1de3e70807ed38513f2f6a..0271e3452bab083a3d7236271e0a6939e03b84a4 100755 (executable)
@@ -162,6 +162,10 @@ case $basic_machine in
        thumb | thumbel)
                basic_machine=$basic_machine-unknown
                ;;
+       thumb-pe) # CYGNUS LOCAL nickc/thumb-pe
+               basic_machine=$basic_machine-unknown
+               ;;
+       # END CYGNUS LOCAL nickc/thumb-pe
        # We use `pc' rather than `unknown'
        # because (1) that's what they normally are, and
        # (2) the word "unknown" tends to confuse beginning users.
diff --git a/gcc/config/arm/README-interworking b/gcc/config/arm/README-interworking
new file mode 100644 (file)
index 0000000..a0069a9
--- /dev/null
@@ -0,0 +1,553 @@
+               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.
+
+
+1. Explicit interworking support for C and C++ files
+====================================================
+
+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
+
+       -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.
+
+
+2. Explicit interworking support for assembler files
+====================================================
+
+If assembler files are to be included into an interworking program
+then the following rules must be obeyed:
+
+       * Any externally visible functions must return by using the BX
+       instruction.
+
+       * Normal function calls can just use the BL instruction.  The
+       linker will automatically insert code to switch between ARM
+       and Thumb modes as necessary.
+
+       * Calls via function pointers should use the BX instruction if
+       the call is made in ARM mode:
+
+               .code 32
+               mov lr, pc
+               bx  rX
+
+       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:
+
+               .code 16
+               bl  _call_via_rX
+
+       where rX is replaced by the name of the register containing
+       the function address.
+
+       * 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:
+
+                       .code 16
+                       .global function
+                       .thumb_func
+               function:
+                       ...start of function....
+
+       * All assembler files must be assembled with the switch
+       -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.) 
+
+
+3. 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
+
+       -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
+
+       -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:
+
+       int function __attribute__((interfacearm))
+       {
+               ... body of function ...
+       }
+
+or
+
+       int function __declspec(interfacearm)
+       {
+               ... body of function ...
+       }
+
+
+
+4. Interworking support in dlltool
+==================================
+
+Currently there is no interworking support in dlltool.  This may be a
+future enhancement.
+
+
+
+5. How interworking support works
+=================================
+
+Switching between the ARM and Thumb instruction sets is accomplished
+via the BX instruction which takes as an argument a register name.
+Control is transfered to the address held in this register (with the
+bottom bit masked out), and 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.  (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:
+
+       a. 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.
+
+       b. 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.
+
+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:
+
+       mov     lr, pc
+       bx      rX
+
+(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:
+
+       bl      _call_via_rX
+
+(again where rX is the name if the register containing the function
+pointer).  The special call_via_rX functions look like this:
+
+       .thumb_func
+_call_via_r0:
+       bx      r0
+       nop
+
+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.
+
+
+6. 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:
+
+       bl _interwork_call_via_r0
+
+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:
+
+       .code 16
+       .thumb_func
+_interwork_call_via_r0
+       bx      pc
+       nop
+       
+       .code 32
+       tst     r0, #1
+       stmeqdb r13!, {lr}
+       adreq   lr, _arm_return
+       bx      r0
+
+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.  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 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:
+
+       .code 32
+_arm_return:           
+       ldmia   r13!, {r12}
+       bx      r12
+       .code 16
+
+
+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.
+
+
+7. 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)):
+
+               .code 16
+               .thumb_func
+       function:
+               ... start of function ...
+
+  with __attribute__((interfacearm)):
+
+               .code 32
+       function:
+               orr     r12, pc, #1
+               bx      r12
+
+               .code 16
+                .thumb_func
+        .real_start_of_function:
+
+               ... start of function ...
+
+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
+outsside 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.
+
+
+8. Some examples
+================
+
+Given this test file:
+
+       int func (void) { return 1; }
+
+       int call (int (* ptr)(void)) { return ptr (); }
+
+The following varying pieces of assembler are produced depending upon
+the command line options used:
+
+no options:
+
+       @ 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
+
+               .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.  This would not work if the
+caller was in ARM mode.
+
+If -mthumb-interwork is specified on the command line:
+
+       @ 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
+
+               .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 version that is not interworking enabled.
+
+If -mcaller-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
+               .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.  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
+
+               .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
+
+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 the source code is slightly altered so that only the call function
+has an (interfacearm) attribute:
+
+       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)); }
+
+then this code is produced (with no command line switches):
+
+       @ 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
+
+               .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
+
+               .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}
+
index c2db824738feddda17ff46f8aac9f9fb38f2673d..aac0ce1977f264615f9d76e0a4a5d6a93c7145a5 100644 (file)
@@ -402,3 +402,120 @@ SYM (__div0):
        RET     pc, lr
 
 #endif /* L_divmodsi_tools */
+
+#ifdef L_dvmd_lnx
+@ GNU/Linux division-by zero handler.  Used in place of L_dvmd_tls
+
+#include <asm/unistd.h>
+#define SIGFPE 8                       @ cant use <asm/signal.h> as it
+                                       @ contains too much C rubbish
+       .globl SYM (__div0)
+       .align 0
+SYM (__div0):
+       stmfd   sp!, {r1, lr}
+       swi     __NR_getpid
+       cmn     r0, #1000
+       ldmgefd sp!, {r1, pc}RETCOND    @ not much we can do
+       mov     r1, #SIGFPE
+       swi     __NR_kill
+       ldmfd   sp!, {r1, pc}RETCOND
+
+#endif /* L_dvmd_lnx */
+
+/* These next two sections are here despite the fact that they contain Thumb 
+   assembler because their presence allows interworked code to be linked even
+   when the GCC library is this one.  */
+               
+#ifdef L_call_via_rX
+
+/* These labels & instructions are used by the Arm/Thumb interworking code. 
+   The address of function to be called is loaded into a register and then 
+   one of these labels is called via a BL instruction.  This puts the 
+   return address into the link register with the bottom bit set, and the 
+   code here switches to the correct mode before executing the function.  */
+       
+       .text
+       .align 0
+       .code 16
+.macro call_via register
+       .globl  SYM (_call_via_\register)
+       .thumb_func
+SYM (_call_via_\register):
+       bx      \register
+       nop
+.endm
+
+       call_via r0
+       call_via r1
+       call_via r2
+       call_via r3
+       call_via r4
+       call_via r5
+       call_via r6
+       call_via r7
+       call_via r8
+       call_via r9
+       call_via sl
+       call_via fp
+       call_via ip
+       call_via sp
+       call_via lr
+
+#endif /* L_call_via_rX */
+
+#ifdef L_interwork_call_via_rX
+
+/* These labels & instructions are used by the Arm/Thumb interworking code,
+   when the target address is in an unknown instruction set.  The address 
+   of function to be called is loaded into a register and then one of these
+   labels is called via a BL instruction.  This puts the return address 
+   into the link register with the bottom bit set, and the code here 
+   switches to the correct mode before executing the function.  Unfortunately
+   the target code cannot be relied upon to return via a BX instruction, so
+   instead we have to store the resturn address on the stack and allow the
+   called function to return here instead.  Upon return we recover the real
+   return address and use a BX to get back to Thumb mode.  */
+       
+       .text
+       .align 0
+
+       .code   32
+_arm_return:           
+       ldmia   r13!, {r12}
+       bx      r12
+       .code   16
+
+.macro interwork register                                      
+       .code   16
+       .globl  SYM (_interwork_call_via_\register)
+       .thumb_func
+SYM (_interwork_call_via_\register):
+       bx      pc
+       nop
+       
+       .code   32
+       .globl .Lchange_\register
+.Lchange_\register:
+       tst     \register, #1
+       stmeqdb r13!, {lr}
+       adreq   lr, _arm_return
+       bx      \register
+.endm
+       
+       interwork r0
+       interwork r1
+       interwork r2
+       interwork r3
+       interwork r4
+       interwork r5
+       interwork r6
+       interwork r7
+       interwork r8
+       interwork r9
+       interwork sl
+       interwork fp
+       interwork ip
+       interwork sp
+       interwork lr
+               
+#endif /* L_interwork_call_via_rX */
index 8df1ae79e7d3ffedb805abd4a0e9190c1879f17e..d50d35d15f16ce1c941a4054a66072bbef9c4a99 100644 (file)
@@ -605,98 +605,91 @@ SYM (__div0):
    one of these labels is called via a BL instruction.  This puts the 
    return address into the link register with the bottom bit set, and the 
    code here switches to the correct mode before executing the function.  */
-
+       
        .text
        .align 0
-       
-       .globl  SYM (_call_via_r0)
-       .thumb_func
-SYM (_call_via_r0):
-       bx      r0 
-       nop
-
-       .globl  SYM (_call_via_r1)
-       .thumb_func
-SYM (_call_via_r1):
-       bx      r1
-       nop
-
-       .globl  SYM (_call_via_r2)
-       .thumb_func
-SYM (_call_via_r2):
-       bx      r2 
-       nop
-
-       .globl  SYM (_call_via_r3)
-       .thumb_func
-SYM (_call_via_r3):
-       bx      r3 
-       nop
-
-       .globl  SYM (_call_via_r4)
-       .thumb_func
-SYM (_call_via_r4):
-       bx      r4
-       nop
-
-       .globl  SYM (_call_via_r5)
-       .thumb_func
-SYM (_call_via_r5):
-       bx      r5
-       nop
-
-       .globl  SYM (_call_via_r6)
-       .thumb_func
-SYM (_call_via_r6):
-       bx      r6
-       nop
 
-       .globl  SYM (_call_via_r7)
+.macro call_via register
+       .globl  SYM (_call_via_\register)
        .thumb_func
-SYM (_call_via_r7):
-       bx      r7
+SYM (_call_via_\register):
+       bx      \register
        nop
+.endm
+
+       call_via r0
+       call_via r1
+       call_via r2
+       call_via r3
+       call_via r4
+       call_via r5
+       call_via r6
+       call_via r7
+       call_via r8
+       call_via r9
+       call_via sl
+       call_via fp
+       call_via ip
+       call_via sp
+       call_via lr
 
-       .globl  SYM (_call_via_r8)
-       .thumb_func
-SYM (_call_via_r8):
-       bx      r8
-       nop
-
-       .globl  SYM (_call_via_r9)
-       .thumb_func
-SYM (_call_via_r9):
-       bx      r9
-       nop
-
-       .globl  SYM (_call_via_sl)
-       .thumb_func
-SYM (_call_via_sl):
-       bx      sl 
-       nop
-
-       .globl  SYM (_call_via_fp)
-       .thumb_func
-SYM (_call_via_fp):
-       bx      fp 
-       nop
+#endif /* L_call_via_rX */
 
-       .globl  SYM (_call_via_ip)
-       .thumb_func
-SYM (_call_via_ip):
-       bx      ip
-       nop
+#ifdef L_interwork_call_via_rX
+
+/* These labels & instructions are used by the Arm/Thumb interworking code,
+   when the target address is in an unknown instruction set.  The address 
+   of function to be called is loaded into a register and then one of these
+   labels is called via a BL instruction.  This puts the return address 
+   into the link register with the bottom bit set, and the code here 
+   switches to the correct mode before executing the function.  Unfortunately
+   the target code cannot be relied upon to return via a BX instruction, so
+   instead we have to store the resturn address on the stack and allow the
+   called function to return here instead.  Upon return we recover the real
+   return address and use a BX to get back to Thumb mode.  */
+       
+       .text
+       .align 0
 
-       .globl  SYM (_call_via_sp)
-       .thumb_func
-SYM (_call_via_sp):
-       bx      sp 
-       nop
+       .code 32
+_arm_return:           
+       ldmia   r13!, {r12}
+       bx      r12
+       .code 16
 
-       .globl  SYM (_call_via_lr)
+.macro interwork register                                      
+       .globl  SYM (_interwork_call_via_\register)
        .thumb_func
-SYM (_call_via_lr):
-       bx      lr 
+SYM (_interwork_call_via_\register):
+       bx      pc
        nop
+       
+       .code 32
+       .globl .Lchange_\register
+.Lchange_\register:
+       tst     \register, #1
+       stmeqdb r13!, {lr}
+       adreq   lr, _arm_return
+       bx      \register
+       .code 16
+.endm
+       
+       interwork r0
+       interwork r1
+       interwork r2
+       interwork r3
+       interwork r4
+       interwork r5
+       interwork r6
+       interwork r7
+       interwork r8
+       interwork r9
+       interwork sl
+       interwork fp
+       interwork ip
+       interwork sp
+       interwork lr
+               
+#endif /* L_interwork_call_via_rX */
 
-#endif /* L_call_via_rX */
+       
diff --git a/gcc/config/arm/t-pe b/gcc/config/arm/t-pe
new file mode 100644 (file)
index 0000000..e68b3c9
--- /dev/null
@@ -0,0 +1,31 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = arm/lib1funcs.asm
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#define FLOAT' > fp-bit.c
+       echo '#ifndef __ARMEB__' >> fp-bit.c
+       echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+       echo '#endif' >> fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#ifndef __ARMEB__' > dp-bit.c
+       echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+       echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
+       echo '#endif' >> dp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+pe.o: $(srcdir)/config/arm/pe.c
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
+
+MULTILIB_OPTIONS = mhard-float
+MULTILIB_DIRNAMES = fpu
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/arm/t-pe-thumb b/gcc/config/arm/t-pe-thumb
new file mode 100644 (file)
index 0000000..253c814
--- /dev/null
@@ -0,0 +1,37 @@
+# Makefile fragment
+# Copyright (c) 1998 Free Software Foundation
+# CYGNUS LOCAL (entire file) nickc/thumb-pe
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = arm/lib1thumb.asm
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#define FLOAT' > fp-bit.c
+       echo '#ifndef __ARMEB__' >> fp-bit.c
+       echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+       echo '#endif' >> fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#ifndef __ARMEB__' > dp-bit.c
+       echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+       echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
+       echo '#endif' >> dp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+# Rule to build Psion specific GCC functions.
+pe.o: $(srcdir)/config/arm/pe.c
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
+
+# Avoid building a duplicate set of libraries for the default endian-ness.
+MULTILIB_OPTIONS = mthumb-interwork
+MULTILIB_DIRNAMES = interwork
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
index c14782a6d8916047b239a899b9bada956dee4260..74fdef49920e2ddaa37ff3986cad69485580254d 100644 (file)
@@ -11,7 +11,7 @@ LIBGCC1_TEST =
 
 CROSS_LIBGCC1 = libgcc1-asm.a
 LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX
 
 #Don't try to run fixproto
 STMP_FIXPROTO =
index 1701258e06f61cd3826b2cce2c7a110063503b0d..6b349e2fdf0c8b1681306c15ae39e844247135d1 100644 (file)
@@ -1,6 +1,6 @@
 CROSS_LIBGCC1 = libgcc1-asm.a
 LIB1ASMSRC = arm/lib1thumb.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX
 # adddi3/subdi3 added to machine description
 #LIB1ASMFUNCS = _adddi3 _subdi3 _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls
 
index 1a2eb18ff8dcff81793e493ee5cf04e74d8796b9..9f025f8dadcaf7ed555b57b19cab90efa11afe51 100644 (file)
@@ -540,6 +540,43 @@ thumb_reload_out_si (operands)
   abort ();
 }
 
+#ifdef THUMB_PE /* CYGNUS LOCAL nickc/thumb-pe */
+/* Return non-zero if FUNC is a naked function.  */
+
+static int
+arm_naked_function_p (func)
+     tree func;
+{
+  tree a;
+
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    abort ();
+
+  a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
+  return a != NULL_TREE;
+}
+#endif /* END CYGNUS LOCAL nickc/thumb-pe */
+
+/* CYGNUS LOCAL nickc/super-interworking */
+/* Return non-zero if FUNC must be entered in ARM mode.  */
+int
+is_called_in_ARM_mode (func)
+     tree func;
+{
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    abort ();
+
+  /* Ignore the problem about functions whoes address is taken.  */
+  if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
+    return TRUE;
+
+#ifdef THUMB_PE 
+  return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
+#else
+  return FALSE;
+#endif
+}
+/* END CYGNUS LOCAL */
 \f
 /* Routines for emitting code */
 
@@ -585,10 +622,9 @@ number_of_first_bit_set (mask)
 #define LINK_REGISTER  14
 #define PROGRAM_COUNTER 15
 
-/* Generate code to return from a thumb function.
-   If 'reg_containing_return_addr' is -1, then the
-   address is actually on the stack, at the stack
-   pointer.  */
+/* Generate code to return from a thumb function.  If
+   'reg_containing_return_addr' is -1, then the return address is
+   actually on the stack, at the stack pointer.  */
 
 static void
 thumb_exit (f, reg_containing_return_addr)
@@ -634,9 +670,15 @@ thumb_exit (f, reg_containing_return_addr)
     }
 
   /* Otherwise if we are not supporting interworking and we have not created
-     a backtrace structure then just pop the return address straight into the PC.  */
+     a backtrace structure and the function was not entered in ARM mode then
+     just pop the return address straight into the PC. */
   
-  else if (! TARGET_THUMB_INTERWORK && ! TARGET_BACKTRACE)
+  else if (   ! TARGET_THUMB_INTERWORK
+          && ! TARGET_BACKTRACE
+/* CYGNUS LOCAL nickc/super-interworking */
+          && ! is_called_in_ARM_mode (current_function_decl)
+/* END CYGNUS LOCAL */
+             )
     {
       asm_fprintf (f, "\tpop\t{pc}\n" );
 
@@ -926,7 +968,7 @@ thumb_pushpop (f, mask, push)
       if (mask & 0xFF)
        asm_fprintf (f, ", ");
       
-      asm_fprintf (f, "%s", reg_names[14]);
+      asm_fprintf (f, reg_names[14]);
     }
   else if (!push && (mask & (1 << 15)))
     {
@@ -948,7 +990,7 @@ thumb_pushpop (f, mask, push)
          if (mask & 0xFF)
            asm_fprintf (f, ", ");
          
-         asm_fprintf (f, "%s", reg_names[15]);
+         asm_fprintf (f, reg_names[15]);
        }
     }
        
@@ -995,7 +1037,12 @@ output_return ()
        {
          thumb_exit (asm_out_file, 14);              
        }
-      else if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
+      else if (   TARGET_THUMB_INTERWORK
+              || TARGET_BACKTRACE
+/* CYGNUS LOCAL nickc/super-interworking */
+              || is_called_in_ARM_mode (current_function_decl)
+/* END CYGNUS LOCAL */           
+                 )
        {
          thumb_exit (asm_out_file, -1);
        }
@@ -1014,7 +1061,12 @@ output_return ()
                asm_fprintf (asm_out_file, ", ");
          }
 
-      if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
+      if (   TARGET_THUMB_INTERWORK
+         || TARGET_BACKTRACE
+/* CYGNUS LOCAL nickc/super-interworking */
+         || is_called_in_ARM_mode (current_function_decl)
+/* END CYGNUS LOCAL */
+            )
        {
          asm_fprintf (asm_out_file, "}\n");
          thumb_exit (asm_out_file, -1);
@@ -1037,6 +1089,43 @@ thumb_function_prologue (f, frame_size)
   int store_arg_regs = 0;
   int regno;
 
+#ifdef THUMB_PE   /* CYGNUS LOCAL nickc/thumb-pe */
+  if (arm_naked_function_p (current_function_decl))
+    return;
+#endif /* CYGNUS LOCAL nickc/thumb-pe */
+
+/* CYGNUS LOCAL nickc/super-interworking */
+  if (is_called_in_ARM_mode (current_function_decl))
+    {
+      char * name;
+      if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
+       abort();
+      if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
+       abort();
+      name = XSTR  (XEXP (DECL_RTL (current_function_decl), 0), 0);
+      
+      /* Generate code sequence to switch us into Thumb mode.  */
+      /* The .code 32 directive has already been emitted by
+        ASM_DECLARE_FUNCITON_NAME */
+      asm_fprintf (f, "\torr\tr12, pc, #1\n");
+      asm_fprintf (f, "\tbx\tr12\n");
+
+      /* Generate a label, so that the debugger will notice the
+        change in instruction sets.  This label is also used by
+        the assembler to bypass the ARM code when this function
+        is called from a Thumb encoded function elsewhere in the
+        same file.  Hence the definition of STUB_NAME here must
+        agree with the definition in gas/config/tc-arm.c  */
+      
+#define STUB_NAME ".real_start_of"
+      
+      asm_fprintf (f, "\t.code\t16\n");
+      asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
+      asm_fprintf (f, "\t.thumb_func\n");
+      asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
+    }
+/* END CYGNUS LOCAL nickc/super-interworking */
+    
   if (current_function_anonymous_args && current_function_pretend_args_size)
     store_arg_regs = 1;
 
@@ -1318,7 +1407,7 @@ thumb_unexpanded_epilogue ()
   int high_regs_pushed = 0;
   int leaf_function = leaf_function_p ();
   int had_to_push_lr;
-  
+
   if (return_used_this_function)
     return "";
 
@@ -1329,7 +1418,7 @@ thumb_unexpanded_epilogue ()
   for (regno = 8; regno < 13; regno++)
     {
       if (regs_ever_live[regno] && ! call_used_regs[regno])
-       high_regs_pushed++;
+       high_regs_pushed ++;
     }
 
   /* The prolog may have pushed some high registers to use as
@@ -1385,7 +1474,6 @@ thumb_unexpanded_epilogue ()
       while (high_regs_pushed)
        {
          /* Find low register(s) into which the high register(s) can be popped.  */
-         
          for (regno = 0; regno < 8; regno++)
            {
              if (mask & (1 << regno))
@@ -1397,11 +1485,9 @@ thumb_unexpanded_epilogue ()
          mask &= (2 << regno) - 1;     /* A noop if regno == 8 */
 
          /* Pop the values into the low register(s). */
-         
          thumb_pushpop (asm_out_file, mask, 0);
 
          /* Move the value(s) into the high registers.  */
-         
          for (regno = 0; regno < 8; regno++)
            {
              if (mask & (1 << regno))
@@ -1419,11 +1505,6 @@ thumb_unexpanded_epilogue ()
 
   had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
   
-  if (had_to_push_lr)
-    {
-      live_regs_mask |= 1 << PROGRAM_COUNTER;
-    }
-
   if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
     {
       /* The stack backtrace structure creation code had to
@@ -1435,6 +1516,13 @@ thumb_unexpanded_epilogue ()
   
   if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
     {
+      if (had_to_push_lr
+/* CYGNUS LOCAL nickc/super-interworking */
+         && ! is_called_in_ARM_mode (current_function_decl)
+/* END CYGNUS LOCAL nickc/super-interworking */
+         )
+       live_regs_mask |= 1 << PROGRAM_COUNTER;
+
       /* Either no argument registers were pushed or a backtrace
         structure was created which includes an adjusted stack
         pointer, so just pop everything.  */
@@ -1443,15 +1531,23 @@ thumb_unexpanded_epilogue ()
        thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
       
       /* We have either just popped the return address into the
-        PC or it is was kept in LR for the entire function.  */
+        PC or it is was kept in LR for the entire function or
+        it is still on the stack because we do not want to
+        return by doing a pop {pc}.  */
       
-      if (! had_to_push_lr)
-       thumb_exit (asm_out_file, LINK_REGISTER);
+      if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
+       thumb_exit (asm_out_file,
+                   (
+                    had_to_push_lr
+/* CYGNUS LOCAL nickc/super-interworking */
+                    && is_called_in_ARM_mode (current_function_decl)
+/* END CYGNUS LOCAL */
+                    ) ? -1 : LINK_REGISTER
+                   );
     }
   else
     {
       /* Pop everything but the return address.  */
-      
       live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
       
       if (live_regs_mask)
@@ -1460,15 +1556,13 @@ thumb_unexpanded_epilogue ()
       if (had_to_push_lr)
        {
          /* Get the return address into a temporary register.  */
-      
          thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
        }
       
       /* Remove the argument registers that were pushed onto the stack.  */
-      
       asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
-                  reg_names[STACK_POINTER],
-                  reg_names[STACK_POINTER],
+                  reg_names [STACK_POINTER],
+                  reg_names [STACK_POINTER],
                   current_function_pretend_args_size);
       
       thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
@@ -1963,3 +2057,36 @@ void thumb_override_options()
        warning ("Structure size boundary can only be set to 8 or 32");
     }
 }
+\f
+#ifdef THUMB_PE /* CYGNUS LOCAL nickc/thumb-pe */
+/* Return nonzero if ATTR is a valid attribute for DECL.
+   ATTRIBUTES are any existing attributes and ARGS are the arguments
+   supplied with ATTR.
+
+   Supported attributes:
+
+   naked: don't output any prologue or epilogue code, the user is assumed
+   to do the right thing.
+
+   interfacearm: Always assume that this function will be entered in ARM
+   mode, not Thumb mode, and that the caller wishes to be returned to in
+   ARM mode.  */
+int
+arm_valid_machine_decl_attribute (decl, attributes, attr, args)
+     tree decl;
+     tree attributes;
+     tree attr;
+     tree args;
+{
+  if (args != NULL_TREE)
+    return 0;
+
+  if (is_attribute_p ("naked", attr))
+    return TREE_CODE (decl) == FUNCTION_DECL;
+  
+  if (is_attribute_p ("interfacearm", attr))
+    return TREE_CODE (decl) == FUNCTION_DECL;
+  
+  return 0;
+}
+#endif /* END CYGNUS LOCAL nickc/thumb-pe */
index 61218661b7e30a3b9727880d72a503009b1e9206..a847c5659a4f21322f9027c2f488c99345be0328 100644 (file)
@@ -55,36 +55,63 @@ Boston, MA 02111-1307, USA.  */
 #define TARGET_VERSION  fputs (" (ARM/THUMB:generic)", stderr);
 
 /* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1.  */
-#define THUMB_FLAG_BIG_END             (0x0001)
-#define THUMB_FLAG_BACKTRACE           (0x0002)
-#define THUMB_FLAG_LEAF_BACKTRACE      (0x0004)
-#define ARM_FLAG_THUMB                 (0x1000)        /* same as in arm.h */
+#define THUMB_FLAG_BIG_END                     0x0001
+#define THUMB_FLAG_BACKTRACE                   0x0002
+#define THUMB_FLAG_LEAF_BACKTRACE              0x0004
+#define ARM_FLAG_THUMB                         0x1000  /* same as in arm.h */
+#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING   0x40000 /* CYGNUS LOCAL nickc */
+#define THUMB_FLAG_CALLER_SUPER_INTERWORKING   0x80000 /* CYGNUS LOCAL nickc */
+
 
 /* Run-time compilation parameters selecting different hardware/software subsets.  */
 extern int target_flags;
 #define TARGET_DEFAULT          0 /* ARM_FLAG_THUMB */
 #define TARGET_BIG_END          (target_flags & THUMB_FLAG_BIG_END)
 #define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-#define TARGET_BACKTRACE       (leaf_function_p()                              \
-                                ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE)   \
+#define TARGET_BACKTRACE       (leaf_function_p()                            \
+                                ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
                                 : (target_flags & THUMB_FLAG_BACKTRACE))
 
-#define TARGET_SWITCHES                                 \
-{                                                       \
-  {"big-endian",               THUMB_FLAG_BIG_END},    \
-  {"little-endian",           -THUMB_FLAG_BIG_END},    \
-  {"thumb-interwork",          ARM_FLAG_THUMB},        \
-  {"no-thumb-interwork",       -ARM_FLAG_THUMB},       \
-  {"tpcs-frame",               THUMB_FLAG_BACKTRACE},  \
-  {"no-tpcs-frame",            -THUMB_FLAG_BACKTRACE}, \
-  {"tpcs-leaf-frame",          THUMB_FLAG_LEAF_BACKTRACE},     \
-  {"no-tpcs-leaf-frame",       -THUMB_FLAG_LEAF_BACKTRACE},    \
-  {"",                          TARGET_DEFAULT}         \
+/* CYGNUS LOCAL nickc/super-interworking */
+/* Set if externally visable functions should assume that they
+   might be called in ARM mode, from a non-thumb aware code.  */
+#define TARGET_CALLEE_INTERWORKING     \
+     (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
+
+/* Set if calls via function pointers should assume that their
+   destination is non-Thumb aware.  */
+#define TARGET_CALLER_INTERWORKING     \
+     (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
+/* END CYGNUS LOCAL */
+
+/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
+#ifndef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES
+#endif
+
+#define TARGET_SWITCHES                                        \
+{                                                              \
+  {"big-endian",                   THUMB_FLAG_BIG_END},        \
+  {"little-endian",               -THUMB_FLAG_BIG_END},        \
+  {"thumb-interwork",              ARM_FLAG_THUMB},            \
+  {"no-thumb-interwork",           -ARM_FLAG_THUMB},           \
+  {"tpcs-frame",                   THUMB_FLAG_BACKTRACE},      \
+  {"no-tpcs-frame",                -THUMB_FLAG_BACKTRACE},     \
+  {"tpcs-leaf-frame",              THUMB_FLAG_LEAF_BACKTRACE}, \
+  {"no-tpcs-leaf-frame",           -THUMB_FLAG_LEAF_BACKTRACE},        \
+  /* CYGNUS LOCAL nickc/super-interworking */ \
+  {"callee-super-interworking",            THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
+  {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
+  {"caller-super-interworking",            THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
+  {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
+  /* END CYGNUS LOCAL */ \
+  SUBTARGET_SWITCHES                                           \
+  {"",                          TARGET_DEFAULT}                \
 }
 
-#define TARGET_OPTIONS                                 \
-{                                                      \
-  { "structure-size-boundary=", & structure_size_string }, \
+#define TARGET_OPTIONS                                         \
+{                                                              \
+  { "structure-size-boundary=", & structure_size_string },     \
 }
 
 #define REGISTER_PREFIX ""
@@ -1026,7 +1053,12 @@ int thumb_shiftable_const ();
 /* Emit a special directive when defining a function name.
    This is used by the assembler to assit with interworking.  */
 #define ASM_DECLARE_FUNCTION_NAME(file, name, decl)             \
-  fprintf (file, ".thumb_func\n") ;                            \
+/* CYGNUS LOCAL nickc/supr-interworking */ \
+  if (! is_called_in_ARM_mode (decl))                  \
+    fprintf (file, "\t.thumb_func\n") ;                        \
+  else                                                 \
+    fprintf (file, "\t.code\t32\n") ;                  \
+/* END CYGNUS LOCAL */ \
   ASM_OUTPUT_LABEL (file, name)
 
 #define ASM_OUTPUT_REG_PUSH(STREAM,REGNO)                      \
@@ -1095,8 +1127,10 @@ int thumb_shiftable_const ();
 int thumb_trivial_epilogue ();
 #define USE_RETURN (reload_completed && thumb_trivial_epilogue ())
 
-extern char *thumb_unexpanded_epilogue ();
-extern char *output_move_mem_multiple ();
-extern char *thumb_load_double_from_address ();
-extern char *output_return ();
-extern int   far_jump_used_p();
+extern char * thumb_unexpanded_epilogue ();
+extern char * output_move_mem_multiple ();
+extern char * thumb_load_double_from_address ();
+extern char * output_return ();
+extern int    far_jump_used_p();
+extern int    is_called_in_ARM_mode (); /* CYGNUS LOCAL */
+
index 1e0ee38051d01d07b720f7e2b7a29d21e29535b1..2334aa1b10c501a2e882cf0ddb4672d37e66713e 100644 (file)
 (define_insn "*call_indirect"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
         (match_operand 1 "" ""))]
-  "TARGET_THUMB_INTERWORK"
+  "! TARGET_CALLER_INTERWORKING"
   "bl\\t__call_via_%0"
 [(set_attr "length" "4")])
+;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
+;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
+;; the bottom bit of lr so that a function return (using bx)
+;; would switch back into ARM mode...
 
-
-(define_insn "*call_indirect"
+(define_insn "*call_indirect_interwork"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
         (match_operand 1 "" ""))]
-  "! TARGET_THUMB_INTERWORK"
-  "bl\\t__call_via_%0"
+  "TARGET_CALLER_INTERWORKING"
+  "bl\\t__interwork_call_via_%0"
 [(set_attr "length" "4")])
-;; used to be: "mov\\tlr,pc\;bx\\t%0"
-;; but this does not set bottom bit of lr
 
 (define_expand "call_value"
   [(set (match_operand 0 "" "")
   [(set (match_operand 0 "" "=l")
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
              (match_operand 2 "" "")))]
-  "TARGET_THUMB_INTERWORK"
+  "! TARGET_CALLER_INTERWORKING"
   "bl\\t__call_via_%1"
 [(set_attr "length" "4")])
+;; See comment for call_indirect pattern
 
-(define_insn "*call_value_indirect"
+(define_insn "*call_value_indirect_interwork"
   [(set (match_operand 0 "" "=l")
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
              (match_operand 2 "" "")))]
-  "! TARGET_THUMB_INTERWORK"
-  "bl\\t__call_via_%1"
+  "TARGET_CALLER_INTERWORKING"
+  "bl\\t__interwork_call_via_%1"
 [(set_attr "length" "4")])
-;; used to be  "mov\\tlr,pc\;bx\\t%1"
-;; but this does not set bottom bit of lr
+
 
 (define_insn "*call_insn"
   [(call (mem:SI (match_operand:SI 0 "" "i"))
diff --git a/gcc/config/arm/tpe.h b/gcc/config/arm/tpe.h
new file mode 100644 (file)
index 0000000..375a84c
--- /dev/null
@@ -0,0 +1,420 @@
+/* CYGNUS LOCAL (entire file) nickc/thumb-pe */
+/* Definitions of target machine for GNU compiler,
+   for Thumb with PE object format.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Derived from arm/coff.h and arm/pe.h originally by Doug Evans (evans@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "arm/thumb.h"
+\f
+#define THUMB_PE 1
+
+/* Run-time Target Specification.  */
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (Thumb/pe)", stderr)
+\f
+/* Support the __declspec keyword by turning them into attributes.
+   We currently only support: naked, dllimport, and dllexport.
+   Note that the current way we do this may result in a collision with
+   predefined attributes later on.  This can be solved by using one attribute,
+   say __declspec__, and passing args to it.  The problem with that approach
+   is that args are not accumulated: each new appearance would clobber any
+   existing args.  */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "\
+-Dthumb -D__thumb -D__pe__ -Acpu(arm) -Amachine(arm) \
+-D__declspec(x)=__attribute__((x)) \
+"
+
+/* Experimental addition for pr 7885.
+   Ignore dllimport for functions.  */
+#define ARM_FLAG_NOP_FUN_IMPORT                0x20000
+#define TARGET_NOP_FUN_DLLIMPORT (target_flags & ARM_FLAG_NOP_FUN_IMPORT)
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+{ "nop-fun-dllimport",           ARM_FLAG_NOP_FUN_IMPORT }, \
+{ "no-nop-fun-dllimport",       -ARM_FLAG_NOP_FUN_IMPORT }, 
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT ARM_FLAG_NOP_FUN_IMPORT
+\f
+/* Setting this to 32 produces more efficient code, but the value set in previous
+   versions of this toolchain was 8, which produces more compact structures. The
+   command line option -mstructure_size_boundary=<n> can be used to change this
+   value.  */
+#undef STRUCTURE_SIZE_BOUNDARY
+#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
+
+extern int arm_structure_size_boundary;
+\f
+/* This is COFF, but prefer stabs.  */
+#define SDB_DEBUGGING_INFO
+
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#include "dbxcoff.h"
+\f
+/* Note - it is important that these definitions match those in semi.h for the ARM port.  */
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+/* A C statement to output assembler commands which will identify the
+   object file as having been compiled with GNU CC (or another GNU
+   compiler).  */
+#define ASM_IDENTIFY_GCC(STREAM)                               \
+     fprintf (STREAM, "%sgcc2_compiled.:\n%s", LOCAL_LABEL_PREFIX, ASM_APP_OFF )
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(STREAM) \
+do {                                                           \
+  extern char *version_string;                                 \
+  fprintf ((STREAM), "%s Generated by gcc %s for Thumb/coff\n", \
+          ASM_COMMENT_START, version_string);                  \
+  fprintf ((STREAM), ASM_APP_OFF);                              \
+} while (0)
+
+/* A C statement to output something to the assembler file to switch to section
+   NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
+   NULL_TREE.  Some target formats do not support arbitrary sections.  Do not
+   define this macro in such cases.  */
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+do {                                                           \
+  if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL)             \
+    fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME));         \
+  else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC))      \
+    fprintf (STREAM, "\t.section %s,\"\"\n", (NAME));          \
+  else                                                         \
+    fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME));         \
+} while (0)
+\f
+/* Support the ctors/dtors and other sections.  */
+
+#undef INIT_SECTION_ASM_OP
+
+/* Define this macro if jump tables (for `tablejump' insns) should be
+   output in the text section, along with the assembler instructions.
+   Otherwise, the readonly data section is used.  */
+#define JUMP_TABLES_IN_TEXT_SECTION
+
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION  rdata_section
+#undef RDATA_SECTION_ASM_OP
+#define RDATA_SECTION_ASM_OP   "\t.section .rdata"
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP   "\t.section .ctors,\"x\""
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP   "\t.section .dtors,\"x\""
+
+/* A list of other sections which the compiler might be "in" at any
+   given time.  */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata, in_ctors, in_dtors
+
+#define SUBTARGET_EXTRA_SECTIONS
+
+/* A list of extra section function definitions.  */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+  RDATA_SECTION_FUNCTION       \
+  CTORS_SECTION_FUNCTION       \
+  DTORS_SECTION_FUNCTION       \
+  SUBTARGET_EXTRA_SECTION_FUNCTIONS
+
+#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
+
+#define RDATA_SECTION_FUNCTION \
+void                                                                   \
+rdata_section ()                                                       \
+{                                                                      \
+  if (in_section != in_rdata)                                          \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP);            \
+      in_section = in_rdata;                                           \
+    }                                                                  \
+}
+
+#define CTORS_SECTION_FUNCTION \
+void                                                                   \
+ctors_section ()                                                       \
+{                                                                      \
+  if (in_section != in_ctors)                                          \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP);            \
+      in_section = in_ctors;                                           \
+    }                                                                  \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void                                                                   \
+dtors_section ()                                                       \
+{                                                                      \
+  if (in_section != in_dtors)                                          \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP);            \
+      in_section = in_dtors;                                           \
+    }                                                                  \
+}
+\f
+/* Support the ctors/dtors sections for g++.  */
+
+#define INT_ASM_OP ".word"
+
+/* A C statement (sans semicolon) to output an element in the table of
+   global constructors.  */
+#undef ASM_OUTPUT_CONSTRUCTOR
+#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
+do {                                           \
+  ctors_section ();                            \
+  fprintf (STREAM, "\t%s\t ", INT_ASM_OP);     \
+  assemble_name (STREAM, NAME);                        \
+  fprintf (STREAM, "\n");                      \
+} while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+   global destructors.  */
+#undef ASM_OUTPUT_DESTRUCTOR
+#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
+do {                                           \
+  dtors_section ();                            \
+  fprintf (STREAM, "\t%s\t ", INT_ASM_OP);     \
+  assemble_name (STREAM, NAME);                \
+  fprintf (STREAM, "\n");                      \
+} while (0)
+
+/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script.  */
+#define CTOR_LISTS_DEFINED_EXTERNALLY
+
+#undef DO_GLOBAL_CTORS_BODY
+#undef DO_GLOBAL_DTORS_BODY
+
+/* The ARM development system has atexit and doesn't have _exit,
+   so define this for now.  */
+#define HAVE_ATEXIT
+
+/* The ARM development system defines __main.  */
+#define NAME__MAIN "__gccmain"
+#define SYMBOL__MAIN __gccmain
+\f
+/* This is to better conform to the ARM PCS.
+   Richard Earnshaw hasn't put this into FSF sources yet so it's here.  */
+#undef RETURN_IN_MEMORY
+#define RETURN_IN_MEMORY(TYPE)                                                 \
+  ((TYPE_MODE ((TYPE)) == BLKmode && ! TYPE_NO_FORCE_BLK (TYPE))       \
+   || (AGGREGATE_TYPE_P ((TYPE)) && arm_pe_return_in_memory ((TYPE))))
+\f
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+   is a valid machine specific attribute for DECL.
+   The attributes in ATTRIBUTES have previously been assigned to DECL.  */
+extern int arm_pe_valid_machine_decl_attribute ();
+extern int arm_valid_machine_decl_attribute ();
+#undef VALID_MACHINE_DECL_ATTRIBUTE
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+  arm_pe_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+extern union tree_node * arm_pe_merge_machine_decl_attributes ();
+#define MERGE_MACHINE_DECL_ATTRIBUTES(OLD, NEW) \
+  arm_pe_merge_machine_decl_attributes ((OLD), (NEW))
+
+/* In addition to the stuff done in arm.h, we must mark dll symbols specially.
+   Definitions of dllexport'd objects install some info in the .drectve
+   section.  References to dllimport'd objects are fetched indirectly via
+   __imp_.  If both are declared, dllexport overrides.
+   This is also needed to implement one-only vtables: they go into their own
+   section and we need to set DECL_SECTION_NAME so we do that here.
+   Note that we can be called twice on the same decl.  */
+extern void arm_pe_encode_section_info ();
+#undef ENCODE_SECTION_INFO
+#define ENCODE_SECTION_INFO(DECL) \
+  arm_pe_encode_section_info (DECL)
+
+     /* Utility used only in this file.  */
+#define ARM_STRIP_NAME_ENCODING(SYM_NAME) \
+((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
+
+/* Strip any text from SYM_NAME added by ENCODE_SECTION_INFO and store
+   the result in VAR.  */
+#undef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR, SYM_NAME) \
+(VAR) = ARM_STRIP_NAME_ENCODING (SYM_NAME)
+
+/* Define this macro if in some cases global symbols from one translation
+   unit may not be bound to undefined symbols in another translation unit
+   without user intervention.  For instance, under Microsoft Windows
+   symbols must be explicitly imported from shared libraries (DLLs).  */
+#define MULTIPLE_SYMBOL_SPACES
+
+#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
+extern void arm_pe_unique_section ();
+#define UNIQUE_SECTION(DECL,RELOC) arm_pe_unique_section (DECL, RELOC)
+
+#define SUPPORTS_ONE_ONLY 1
+
+/* A C statement to output something to the assembler file to switch to section
+   NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
+   NULL_TREE.  Some target formats do not support arbitrary sections.  Do not
+   define this macro in such cases.  */
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC)     \
+do {                                                           \
+  if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL)             \
+    fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME));         \
+  else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC))      \
+    fprintf (STREAM, "\t.section %s,\"\"\n", (NAME));          \
+  else                                                         \
+    fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME));         \
+  /* Functions may have been compiled at various levels of     \
+     optimization so we can't use `same_size' here.  Instead,  \
+     have the linker pick one.  */                             \
+  if ((DECL) && DECL_ONE_ONLY (DECL))                          \
+    fprintf (STREAM, "\t.linkonce %s\n",                       \
+            TREE_CODE (DECL) == FUNCTION_DECL                  \
+            ? "discard" : "same_size");                        \
+} while (0)
+\f
+/* This outputs a lot of .req's to define alias for various registers.
+   Let's try to avoid this.  */
+#undef ASM_FILE_START
+#define ASM_FILE_START(STREAM) \
+do {                                                           \
+  extern char *version_string;                                 \
+  fprintf (STREAM, "%s Generated by gcc %s for ARM/pe\n",      \
+          ASM_COMMENT_START, version_string);                  \
+  output_file_directive ((STREAM), main_input_filename);       \
+} while (0)
+
+/* Output a reference to a label.  */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME)  \
+fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, ARM_STRIP_NAME_ENCODING (NAME))
+
+/* Output a function definition label.  */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
+do {                                                   \
+  if (arm_dllexport_name_p (NAME))                     \
+    {                                                  \
+      drectve_section ();                              \
+      fprintf (STREAM, "\t.ascii \" -export:%s\"\n",   \
+              ARM_STRIP_NAME_ENCODING (NAME));         \
+      function_section (DECL);                         \
+    }                                                  \
+  if (! is_called_in_ARM_mode (decl))                  \
+    fprintf (STREAM, "\t.thumb_func\n") ;              \
+  else                                                 \
+    fprintf (STREAM, "\t.code\t32\n") ;                        \
+  ASM_OUTPUT_LABEL ((STREAM), (NAME));                 \
+} while (0)
+
+/* Output a common block.  */
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
+do {                                                   \
+  if (arm_dllexport_name_p (NAME))                     \
+    {                                                  \
+      drectve_section ();                              \
+      fprintf ((STREAM), "\t.ascii \" -export:%s\"\n", \
+              ARM_STRIP_NAME_ENCODING (NAME));         \
+    }                                                  \
+  if (! arm_dllimport_name_p (NAME))                   \
+    {                                                  \
+      fprintf ((STREAM), "\t.comm\t");                         \
+      assemble_name ((STREAM), (NAME));                        \
+      fprintf ((STREAM), ", %d\t%s %d\n",              \
+              (ROUNDED), ASM_COMMENT_START, (SIZE));   \
+    }                                                  \
+} while (0)
+
+/* Output the label for an initialized variable.  */
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
+do {                                                   \
+  if (arm_dllexport_name_p (NAME))                     \
+    {                                                  \
+      enum in_section save_section = in_section;       \
+      drectve_section ();                              \
+      fprintf (STREAM, "\t.ascii \" -export:%s\"\n",   \
+              ARM_STRIP_NAME_ENCODING (NAME));         \
+      switch_to_section (save_section, (DECL));                \
+    }                                                  \
+  ASM_OUTPUT_LABEL ((STREAM), (NAME));                 \
+} while (0)
+\f
+/* Support the ctors/dtors and other sections.  */
+
+#define DRECTVE_SECTION_ASM_OP "\t.section .drectve"
+
+/* A list of other sections which the compiler might be "in" at any
+   given time.  */
+
+#undef SUBTARGET_EXTRA_SECTIONS
+#define SUBTARGET_EXTRA_SECTIONS in_drectve,
+
+/* A list of extra section function definitions.  */
+
+#undef SUBTARGET_EXTRA_SECTION_FUNCTIONS
+#define SUBTARGET_EXTRA_SECTION_FUNCTIONS \
+  DRECTVE_SECTION_FUNCTION     \
+  SWITCH_TO_SECTION_FUNCTION
+
+#define DRECTVE_SECTION_FUNCTION \
+void                                                                   \
+drectve_section ()                                                     \
+{                                                                      \
+  if (in_section != in_drectve)                                                \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", DRECTVE_SECTION_ASM_OP);          \
+      in_section = in_drectve;                                         \
+    }                                                                  \
+}
+
+/* Switch to SECTION (an `enum in_section').
+
+   ??? This facility should be provided by GCC proper.
+   The problem is that we want to temporarily switch sections in
+   ASM_DECLARE_OBJECT_NAME and then switch back to the original section
+   afterwards.  */
+#define SWITCH_TO_SECTION_FUNCTION \
+void \
+switch_to_section (section, decl) \
+     enum in_section section; \
+     tree decl; \
+{ \
+  switch (section) \
+    { \
+      case in_text: text_section (); break; \
+      case in_data: data_section (); break; \
+      case in_named: named_section (decl, NULL, 0); break; \
+      case in_rdata: rdata_section (); break; \
+      case in_ctors: ctors_section (); break; \
+      case in_dtors: dtors_section (); break; \
+      case in_drectve: drectve_section (); break; \
+      default: abort (); break; \
+    } \
+}
+
+
+\f
+extern int thumb_pe_valid_machine_decl_attribute ();
index 90b43098d6242df7f44bda35dabebed5635cd8dd..7b010b5ab09069a8ff842662bdcf7be6ea2b49aa 100755 (executable)
@@ -4175,6 +4175,16 @@ for machine in $build $host $target; do
                md_file=arm/thumb.md
                tmake_file=arm/t-thumb
                ;;
+       # CYGNUS LOCAL thumb-pe/nickc
+       thumb-*-pe)
+               tm_file=arm/tpe.h
+               out_file=arm/thumb.c
+               xm_file=arm/xm-thumb.h
+               md_file=arm/thumb.md
+               tmake_file=arm/t-pe-thumb
+               extra_objs=pe.o
+               ;;
+       # END CYGNUS LOCAL
 # This hasn't been upgraded to GCC 2.
 #      tron-*-*)
 #              cpu_type=gmicro
index 0a0fc4100f1f3bf82127536813d7b78d26d93d46..70a13735fbf61eff71cbb548f82007a8aa5e8196 100644 (file)
@@ -2492,6 +2492,16 @@ for machine in $build $host $target; do
                md_file=arm/thumb.md
                tmake_file=arm/t-thumb
                ;;
+       # CYGNUS LOCAL thumb-pe/nickc
+       thumb-*-pe)
+               tm_file=arm/tpe.h
+               out_file=arm/thumb.c
+               xm_file=arm/xm-thumb.h
+               md_file=arm/thumb.md
+               tmake_file=arm/t-pe-thumb
+               extra_objs=pe.o
+               ;;
+       # END CYGNUS LOCAL
 # This hasn't been upgraded to GCC 2.
 #      tron-*-*)
 #              cpu_type=gmicro