OSDN Git Service

update PowerPC support
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Nov 1995 20:02:16 +0000 (20:02 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Nov 1995 20:02:16 +0000 (20:02 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@10648 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/config/rs6000/aix3newas.h
gcc/config/rs6000/aix41.h
gcc/config/rs6000/eabi.asm
gcc/config/rs6000/eabi.h
gcc/config/rs6000/eabiaix.h
gcc/config/rs6000/eabile.h
gcc/config/rs6000/eabilesim.h
gcc/config/rs6000/eabisim.h
gcc/config/rs6000/mach.h
gcc/config/rs6000/netware.h
gcc/config/rs6000/powerpc.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h
gcc/config/rs6000/sysv4le.h
gcc/config/rs6000/t-ppc
gcc/config/rs6000/t-ppcgas

index 31c0fd3..2d9b653 100644 (file)
@@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=403: -mppc} \
 %{mcpu=601: -m601} \
 %{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
 %{mcpu=604: -mppc}"
 
 /* Define the options for the binder: Start text at 512, align all segments
@@ -65,10 +66,17 @@ Boston, MA 02111-1307, USA.  */
    as per README.RS6000.  */
 
 #undef LINK_SPEC
+#ifndef CROSS_COMPILE
 #define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
    %{static:-bnso -bI:/lib/syscalls.exp} \
    %{mcpu=common: milli.exp%s} \
    %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
+#else
+#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
+   %{static:-bnso} \
+   %{mcpu=common: milli.exp%s} \
+   %{shared:-bM:SRE}"
+#endif
 
 /* These are not necessary when we pass -u to the assembler, and undefining
    them saves a great deal of space in object files.  */
index caf1a8b..a35b3fa 100644 (file)
@@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=403: -mppc} \
 %{mcpu=601: -m601} \
 %{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
 %{mcpu=604: -mppc}"
 
 /* These are not necessary when we pass -u to the assembler, and undefining
@@ -65,6 +66,13 @@ Boston, MA 02111-1307, USA.  */
 }
 
 #undef LINK_SPEC
+#ifndef CROSS_COMPILE
 #define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
    %{static:-bnso -bI:/lib/syscalls.exp} %{g*:-bexport:/usr/lib/libg.exp}\
    %{shared:-bM:SRE}"
+#else
+#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
+   %{static:-bnso} \
+   %{shared:-bM:SRE}"
+#endif
+
index 38674dd..b5cf5c5 100644 (file)
-# File to either setup register 2 to point to the GOT, or to adjust the
-# pointers in the .got2 section to point to their new addresses.
+/* Do any initializations needed for the eabi environment */
 
        .file   "eabi.asm"
        .section ".text"
-       .globl   __eabi
+       #include "ppc-asm.h"
 
         .section ".got2","aw"
-.LCTOC1 = . # +32768
+.LCTOC1 = . /* +32768 */
 
-# Table of addresses
+/* Table of addresses */
 .Ltable = .-.LCTOC1
-       .long   .LCTOC1                         # address we are really at
+       .long   .LCTOC1                         /* address we are really at */
 
 .Lgot = .-.LCTOC1
-       .long   _GLOBAL_OFFSET_TABLE_           # normal GOT address
+       .long   _GLOBAL_OFFSET_TABLE_           /* normal GOT address */
 
 .Lgots = .-.LCTOC1
-       .long   _GOT_START_                     # start of .got section
+       .long   _GOT_START_                     /* start of .got section */
 
 .Lgote = .-.LCTOC1
-       .long   _GOT_END_                       # end of .got section
+       .long   _GOT_END_                       /* end of .got section */
 
 .Lgot2s = .-.LCTOC1
-       .long   _GOT2_START_                    # -mrelocatable GOT pointers start
+       .long   _GOT2_START_                    /* -mrelocatable GOT pointers start */
 
 .Lgot2e = .-.LCTOC1
-       .long   _GOT2_END_                      # -mrelocatable GOT pointers end
+       .long   _GOT2_END_                      /* -mrelocatable GOT pointers end */
 
 .Lfixups = .-.LCTOC1
-       .long   _FIXUP_START_                   # start of .fixup section
+       .long   _FIXUP_START_                   /* start of .fixup section */
 
 .Lfixupe = .-.LCTOC1
-       .long   _FIXUP_END_                     # end of .fixup section
+       .long   _FIXUP_END_                     /* end of .fixup section */
 
        .text
 .Lptr:
-       .long   .LCTOC1-.Laddr                  # PC relative pointer to .got2
-       .long   0x4000                          # traceback table
+       .long   .LCTOC1-.Laddr                  /* PC relative pointer to .got2 */
 
-__eabi:        mflr    0
-       bl      .Laddr                          # get current address
+FUNC_START(__eabi)
+       mflr    0
+       bl      .Laddr                          /* get current address */
 .Laddr:
-       mflr    12                              # real address of .Laddr
-       lwz     11,(.Lptr-.Laddr)(12)           # linker generated address of .LCTOC1
-       add     11,11,12                        # correct to real pointer
-       lwz     12,.Ltable(11)                  # get linker's idea of where .Laddr is
-       subf.   12,12,11                        # calculate difference
-       mtlr    0                               # restore link register
-       bc      4,2,.Lreloc                     # skip if we need to relocate
-
-# Only load up register 2 if there is a .got section
-
-       lwz     3,.Lgots(11)                    # start of .got section
-       lwz     4,.Lgote(11)                    # end of .got section
-       cmpw    1,3,4                           # .got section non-empty?
+       mflr    12                              /* real address of .Laddr */
+       lwz     11,(.Lptr-.Laddr)(12)           /* linker generated address of .LCTOC1 */
+       add     11,11,12                        /* correct to real pointer */
+       lwz     12,.Ltable(11)                  /* get linker's idea of where .Laddr is */
+       subf.   12,12,11                        /* calculate difference */
+       mtlr    0                               /* restore link register */
+       bc      4,2,.Lreloc                     /* skip if we need to relocate */
+
+/* Only load up register 2 if there is a .got section */
+
+       lwz     3,.Lgots(11)                    /* start of .got section */
+       lwz     4,.Lgote(11)                    /* end of .got section */
+       cmpw    1,3,4                           /* .got section non-empty? */
        bc      12,6,.Ldone
 
-# Normal program, load up register 2
+/* Normal program, load up register 2 */
 
-       lwz     2,.Lgot(11)                     # normal GOT address (obsolete in register 2)
-       mr      13,2                            # also same as _SDA_BASE_ (V.4 small data ptr)
-       b       __do_global_ctors               # do any C++ global constructors (which returns to caller)
+       lwz     2,.Lgot(11)                     /* normal GOT address (obsolete in register 2) */
+       mr      13,2                            /* also same as _SDA_BASE_ (V.4 small data ptr) */
+       b       FUNC_NAME(__do_global_ctors)    /* do any C++ global constructors (which returns to caller) */
 
-# We need to relocate the .got2 pointers.  Don't load register 2
+/* We need to relocate the .got2 pointers.  Don't load register 2 */
 
 .Lreloc:
-       lwz     3,.Lgot2s(11)                   # GOT pointers start
-       lwz     4,.Lgot2e(11)                   # GOT pointers end
-       add     3,12,3                          # adjust pointers
+       lwz     3,.Lgot2s(11)                   /* GOT pointers start */
+       lwz     4,.Lgot2e(11)                   /* GOT pointers end */
+       add     3,12,3                          /* adjust pointers */
        add     4,12,4
 
-       cmpw    1,3,4                           # any pointers to adjust
+       cmpw    1,3,4                           /* any pointers to adjust */
        bc      12,6,.Lfix
 
 .Lloop:
-       lwz     5,0(3)                          # next pointer
-       add     5,5,12                          # adjust
+       lwz     5,0(3)                          /* next pointer */
+       add     5,5,12                          /* adjust */
        stw     5,0(3)
-       addi    3,3,4                           # bump to next word
-       cmpw    1,3,4                           # more pointers to adjust?
+       addi    3,3,4                           /* bump to next word */
+       cmpw    1,3,4                           /* more pointers to adjust? */
        bc      4,6,.Lloop
 
-# Fixup any user initialized pointers now (the compiler drops pointers to
-# each of the relocs that it does in the .fixup section).  Note, the pointers
-# themselves have already been fixed up by the previous loop.
+/* Fixup any user initialized pointers now (the compiler drops pointers to */
+/* each of the relocs that it does in the .fixup section).  Note, the pointers */
+/* themselves have already been fixed up by the previous loop. */
 
 .Lfix:
-       lwz     3,.Lfixups(11)                  # fixup pointers start
-       lwz     4,.Lfixupe(11)                  # fixup pointers end
+       lwz     3,.Lfixups(11)                  /* fixup pointers start */
+       lwz     4,.Lfixupe(11)                  /* fixup pointers end */
 
-       cmpw    1,3,4                           # any user pointers to adjust
+       cmpw    1,3,4                           /* any user pointers to adjust */
        bc      12,6,.Ldone
 
 .Lfloop:
-       lwz     5,0(3)                          # next pointer
-       lwz     6,0(5)                          # get the pointer it points to
-       add     6,6,12                          # adjust
+       lwz     5,0(3)                          /* next pointer */
+       lwz     6,0(5)                          /* get the pointer it points to */
+       add     6,6,12                          /* adjust */
        stw     6,0(5)
-       addi    3,3,4                           # bump to next word
-       cmpw    1,3,4                           # more pointers to adjust?
+       addi    3,3,4                           /* bump to next word */
+       cmpw    1,3,4                           /* more pointers to adjust? */
        bc      4,6,.Lfloop
 
-# Done adjusting pointers, return
+/* Done adjusting pointers, return */
 
 .Ldone:
-       b       __do_global_ctors               # do any C++ global constructors (which returns to caller)
-
-# Routines for saving floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-
-       .globl  _savefpr_14
-       .globl  _savefpr_15
-       .globl  _savefpr_16
-       .globl  _savefpr_17
-       .globl  _savefpr_18
-       .globl  _savefpr_19
-       .globl  _savefpr_20
-       .globl  _savefpr_21
-       .globl  _savefpr_22
-       .globl  _savefpr_23
-       .globl  _savefpr_24
-       .globl  _savefpr_25
-       .globl  _savefpr_26
-       .globl  _savefpr_27
-       .globl  _savefpr_28
-       .globl  _savefpr_29
-       .globl  _savefpr_30
-       .globl  _savefpr_31
-
-               .long   0x00400000      # traceback tag
-_savefpr_14:   stfd    14,-144(11)     # save fp registers
-_savefpr_15:   stfd    15,-136(11)
-_savefpr_16:   stfd    16,-128(11)
-_savefpr_17:   stfd    17,-120(11)
-_savefpr_18:   stfd    18,-112(11)
-_savefpr_19:   stfd    19,-104(11)
-_savefpr_20:   stfd    20,-96(11)
-_savefpr_21:   stfd    21,-88(11)
-_savefpr_22:   stfd    22,-80(11)
-_savefpr_23:   stfd    23,-72(11)
-_savefpr_24:   stfd    24,-64(11)
-_savefpr_25:   stfd    25,-56(11)
-_savefpr_26:   stfd    26,-48(11)
-_savefpr_27:   stfd    27,-40(11)
-_savefpr_28:   stfd    28,-32(11)
-_savefpr_29:   stfd    29,-24(11)
-_savefpr_30:   stfd    30,-16(11)
-_savefpr_31:   stfd    31,-8(11)
-               blr
-
-# Routines for saving integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer save area.
-
-       .globl  _savegpr_14
-       .globl  _savegpr_15
-       .globl  _savegpr_16
-       .globl  _savegpr_17
-       .globl  _savegpr_18
-       .globl  _savegpr_19
-       .globl  _savegpr_20
-       .globl  _savegpr_21
-       .globl  _savegpr_22
-       .globl  _savegpr_23
-       .globl  _savegpr_24
-       .globl  _savegpr_25
-       .globl  _savegpr_26
-       .globl  _savegpr_27
-       .globl  _savegpr_28
-       .globl  _savegpr_29
-       .globl  _savegpr_30
-       .globl  _savegpr_31
-
-               .long   0x00400000      # traceback tag
-_savegpr_14:   stw     14,-72(11)      # save gp registers
-_savegpr_15:   stw     15,-68(11)
-_savegpr_16:   stw     16,-64(11)
-_savegpr_17:   stw     17,-60(11)
-_savegpr_18:   stw     18,-56(11)
-_savegpr_19:   stw     19,-52(11)
-_savegpr_20:   stw     20,-48(11)
-_savegpr_21:   stw     21,-44(11)
-_savegpr_22:   stw     22,-40(11)
-_savegpr_23:   stw     23,-36(11)
-_savegpr_24:   stw     24,-32(11)
-_savegpr_25:   stw     25,-28(11)
-_savegpr_26:   stw     26,-24(11)
-_savegpr_27:   stw     27,-20(11)
-_savegpr_28:   stw     28,-16(11)
-_savegpr_29:   stw     29,-12(11)
-_savegpr_30:   stw     30,-8(11)
-_savegpr_31:   stw     31,-4(11)
-               blr
-
-# Routines for restoring floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-
-       .globl  _restfpr_14
-       .globl  _restfpr_15
-       .globl  _restfpr_16
-       .globl  _restfpr_17
-       .globl  _restfpr_18
-       .globl  _restfpr_19
-       .globl  _restfpr_20
-       .globl  _restfpr_21
-       .globl  _restfpr_22
-       .globl  _restfpr_23
-       .globl  _restfpr_24
-       .globl  _restfpr_25
-       .globl  _restfpr_26
-       .globl  _restfpr_27
-       .globl  _restfpr_28
-       .globl  _restfpr_29
-       .globl  _restfpr_30
-       .globl  _restfpr_31
-
-               .long   0x00600000      # traceback tag
-_restfpr_14:   lfd     14,-144(11)     # restore fp registers
-_restfpr_15:   lfd     15,-136(11)
-_restfpr_16:   lfd     16,-128(11)
-_restfpr_17:   lfd     17,-120(11)
-_restfpr_18:   lfd     18,-112(11)
-_restfpr_19:   lfd     19,-104(11)
-_restfpr_20:   lfd     20,-96(11)
-_restfpr_21:   lfd     21,-88(11)
-_restfpr_22:   lfd     22,-80(11)
-_restfpr_23:   lfd     23,-72(11)
-_restfpr_24:   lfd     24,-64(11)
-_restfpr_25:   lfd     25,-56(11)
-_restfpr_26:   lfd     26,-48(11)
-_restfpr_27:   lfd     27,-40(11)
-_restfpr_28:   lfd     28,-32(11)
-_restfpr_29:   lfd     29,-24(11)
-_restfpr_30:   lfd     30,-16(11)
-_restfpr_31:   lfd     31,-8(11)
-               blr
-
-# Routines for restoring integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer restore area.
-
-       .globl  _restgpr_14
-       .globl  _restgpr_15
-       .globl  _restgpr_16
-       .globl  _restgpr_17
-       .globl  _restgpr_18
-       .globl  _restgpr_19
-       .globl  _restgpr_20
-       .globl  _restgpr_21
-       .globl  _restgpr_22
-       .globl  _restgpr_23
-       .globl  _restgpr_24
-       .globl  _restgpr_25
-       .globl  _restgpr_26
-       .globl  _restgpr_27
-       .globl  _restgpr_28
-       .globl  _restgpr_29
-       .globl  _restgpr_30
-       .globl  _restgpr_31
-
-               .long   0x00600000      # traceback tag
-_restgpr_14:   lwz     14,-72(11)      # rest gp registers
-_restgpr_15:   lwz     15,-68(11)
-_restgpr_16:   lwz     16,-64(11)
-_restgpr_17:   lwz     17,-60(11)
-_restgpr_18:   lwz     18,-56(11)
-_restgpr_19:   lwz     19,-52(11)
-_restgpr_20:   lwz     20,-48(11)
-_restgpr_21:   lwz     21,-44(11)
-_restgpr_22:   lwz     22,-40(11)
-_restgpr_23:   lwz     23,-36(11)
-_restgpr_24:   lwz     24,-32(11)
-_restgpr_25:   lwz     25,-28(11)
-_restgpr_26:   lwz     26,-24(11)
-_restgpr_27:   lwz     27,-20(11)
-_restgpr_28:   lwz     28,-16(11)
-_restgpr_29:   lwz     29,-12(11)
-_restgpr_30:   lwz     30,-8(11)
-_restgpr_31:   lwz     31,-4(11)
-               blr
-
-# Routines for restoring floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-# In addition to restoring the fp registers, it will return to the caller's
-# caller
-
-       .globl  _restfpr_14_x
-       .globl  _restfpr_15_x
-       .globl  _restfpr_16_x
-       .globl  _restfpr_17_x
-       .globl  _restfpr_18_x
-       .globl  _restfpr_19_x
-       .globl  _restfpr_20_x
-       .globl  _restfpr_21_x
-       .globl  _restfpr_22_x
-       .globl  _restfpr_23_x
-       .globl  _restfpr_24_x
-       .globl  _restfpr_25_x
-       .globl  _restfpr_26_x
-       .globl  _restfpr_27_x
-       .globl  _restfpr_28_x
-       .globl  _restfpr_29_x
-       .globl  _restfpr_30_x
-       .globl  _restfpr_31_x
-
-               .long   0x00600000      # traceback tag
-_restfpr_14_x: lfd     14,-144(11)     # restore fp registers
-_restfpr_15_x: lfd     15,-136(11)
-_restfpr_16_x: lfd     16,-128(11)
-_restfpr_17_x: lfd     17,-120(11)
-_restfpr_18_x: lfd     18,-112(11)
-_restfpr_19_x: lfd     19,-104(11)
-_restfpr_20_x: lfd     20,-96(11)
-_restfpr_21_x: lfd     21,-88(11)
-_restfpr_22_x: lfd     22,-80(11)
-_restfpr_23_x: lfd     23,-72(11)
-_restfpr_24_x: lfd     24,-64(11)
-_restfpr_25_x: lfd     25,-56(11)
-_restfpr_26_x: lfd     26,-48(11)
-_restfpr_27_x: lfd     27,-40(11)
-_restfpr_28_x: lfd     28,-32(11)
-_restfpr_29_x: lfd     29,-24(11)
-_restfpr_30_x: lfd     30,-16(11)
-_restfpr_31_x: lwz     0,4(11)
-               lfd     31,-8(11)
-               mtlr    0
-               mr      1,11
-               blr
-
-# Routines for restoring integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer restore area.
-
-       .globl  _restgpr_14_x
-       .globl  _restgpr_15_x
-       .globl  _restgpr_16_x
-       .globl  _restgpr_17_x
-       .globl  _restgpr_18_x
-       .globl  _restgpr_19_x
-       .globl  _restgpr_20_x
-       .globl  _restgpr_21_x
-       .globl  _restgpr_22_x
-       .globl  _restgpr_23_x
-       .globl  _restgpr_24_x
-       .globl  _restgpr_25_x
-       .globl  _restgpr_26_x
-       .globl  _restgpr_27_x
-       .globl  _restgpr_28_x
-       .globl  _restgpr_29_x
-       .globl  _restgpr_30_x
-       .globl  _restgpr_31_x
-
-               .long   0x00600000      # traceback tag
-_restgpr_14_x: lwz     14,-72(11)      # rest gp registers
-_restgpr_15_x: lwz     15,-68(11)
-_restgpr_16_x: lwz     16,-64(11)
-_restgpr_17_x: lwz     17,-60(11)
-_restgpr_18_x: lwz     18,-56(11)
-_restgpr_19_x: lwz     19,-52(11)
-_restgpr_20_x: lwz     20,-48(11)
-_restgpr_21_x: lwz     21,-44(11)
-_restgpr_22_x: lwz     22,-40(11)
-_restgpr_23_x: lwz     23,-36(11)
-_restgpr_24_x: lwz     24,-32(11)
-_restgpr_25_x: lwz     25,-28(11)
-_restgpr_26_x: lwz     26,-24(11)
-_restgpr_27_x: lwz     27,-20(11)
-_restgpr_28_x: lwz     28,-16(11)
-_restgpr_29_x: lwz     29,-12(11)
-_restgpr_30_x: lwz     30,-8(11)
-_restgpr_31_x: lwz     0,4(11)
-               lwz     31,-4(11)
-               mtlr    0
-               mr      1,11
-               blr
+       b       FUNC_NAME(__do_global_ctors)    /* do any C++ global constructors (which returns to caller) */
+FUNC_END(__eabi)
+
+/* Routines for saving floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+
+FUNC_START(_savefpr_14)        stfd    14,-144(11)     /* save fp registers */
+FUNC_START(_savefpr_15)        stfd    15,-136(11)
+FUNC_START(_savefpr_16)        stfd    16,-128(11)
+FUNC_START(_savefpr_17)        stfd    17,-120(11)
+FUNC_START(_savefpr_18)        stfd    18,-112(11)
+FUNC_START(_savefpr_19)        stfd    19,-104(11)
+FUNC_START(_savefpr_20)        stfd    20,-96(11)
+FUNC_START(_savefpr_21)        stfd    21,-88(11)
+FUNC_START(_savefpr_22)        stfd    22,-80(11)
+FUNC_START(_savefpr_23)        stfd    23,-72(11)
+FUNC_START(_savefpr_24)        stfd    24,-64(11)
+FUNC_START(_savefpr_25)        stfd    25,-56(11)
+FUNC_START(_savefpr_26)        stfd    26,-48(11)
+FUNC_START(_savefpr_27)        stfd    27,-40(11)
+FUNC_START(_savefpr_28)        stfd    28,-32(11)
+FUNC_START(_savefpr_29)        stfd    29,-24(11)
+FUNC_START(_savefpr_30)        stfd    30,-16(11)
+FUNC_START(_savefpr_31)        stfd    31,-8(11)
+                       blr
+FUNC_END(_savefpr_31)
+FUNC_END(_savefpr_30)
+FUNC_END(_savefpr_29)
+FUNC_END(_savefpr_28)
+FUNC_END(_savefpr_27)
+FUNC_END(_savefpr_26)
+FUNC_END(_savefpr_25)
+FUNC_END(_savefpr_24)
+FUNC_END(_savefpr_23)
+FUNC_END(_savefpr_22)
+FUNC_END(_savefpr_21)
+FUNC_END(_savefpr_20)
+FUNC_END(_savefpr_19)
+FUNC_END(_savefpr_18)
+FUNC_END(_savefpr_17)
+FUNC_END(_savefpr_16)
+FUNC_END(_savefpr_15)
+FUNC_END(_savefpr_14)
+
+/* Routines for saving integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer save area. */
+
+FUNC_START(_savegpr_14)        stw     14,-72(11)      /* save gp registers */
+FUNC_START(_savegpr_15)        stw     15,-68(11)
+FUNC_START(_savegpr_16)        stw     16,-64(11)
+FUNC_START(_savegpr_17)        stw     17,-60(11)
+FUNC_START(_savegpr_18)        stw     18,-56(11)
+FUNC_START(_savegpr_19)        stw     19,-52(11)
+FUNC_START(_savegpr_20)        stw     20,-48(11)
+FUNC_START(_savegpr_21)        stw     21,-44(11)
+FUNC_START(_savegpr_22)        stw     22,-40(11)
+FUNC_START(_savegpr_23)        stw     23,-36(11)
+FUNC_START(_savegpr_24)        stw     24,-32(11)
+FUNC_START(_savegpr_25)        stw     25,-28(11)
+FUNC_START(_savegpr_26)        stw     26,-24(11)
+FUNC_START(_savegpr_27)        stw     27,-20(11)
+FUNC_START(_savegpr_28)        stw     28,-16(11)
+FUNC_START(_savegpr_29)        stw     29,-12(11)
+FUNC_START(_savegpr_30)        stw     30,-8(11)
+FUNC_START(_savegpr_31)        stw     31,-4(11)
+                       blr
+FUNC_END(_savegpr_31)
+FUNC_END(_savegpr_30)
+FUNC_END(_savegpr_29)
+FUNC_END(_savegpr_28)
+FUNC_END(_savegpr_27)
+FUNC_END(_savegpr_26)
+FUNC_END(_savegpr_25)
+FUNC_END(_savegpr_24)
+FUNC_END(_savegpr_23)
+FUNC_END(_savegpr_22)
+FUNC_END(_savegpr_21)
+FUNC_END(_savegpr_20)
+FUNC_END(_savegpr_19)
+FUNC_END(_savegpr_18)
+FUNC_END(_savegpr_17)
+FUNC_END(_savegpr_16)
+FUNC_END(_savegpr_15)
+FUNC_END(_savegpr_14)
+
+/* Routines for restoring floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+
+FUNC_START(_restfpr_14)        lfd     14,-144(11)     /* restore fp registers */
+FUNC_START(_restfpr_15)        lfd     15,-136(11)
+FUNC_START(_restfpr_16)        lfd     16,-128(11)
+FUNC_START(_restfpr_17)        lfd     17,-120(11)
+FUNC_START(_restfpr_18)        lfd     18,-112(11)
+FUNC_START(_restfpr_19)        lfd     19,-104(11)
+FUNC_START(_restfpr_20)        lfd     20,-96(11)
+FUNC_START(_restfpr_21)        lfd     21,-88(11)
+FUNC_START(_restfpr_22)        lfd     22,-80(11)
+FUNC_START(_restfpr_23)        lfd     23,-72(11)
+FUNC_START(_restfpr_24)        lfd     24,-64(11)
+FUNC_START(_restfpr_25)        lfd     25,-56(11)
+FUNC_START(_restfpr_26)        lfd     26,-48(11)
+FUNC_START(_restfpr_27)        lfd     27,-40(11)
+FUNC_START(_restfpr_28)        lfd     28,-32(11)
+FUNC_START(_restfpr_29)        lfd     29,-24(11)
+FUNC_START(_restfpr_30)        lfd     30,-16(11)
+FUNC_START(_restfpr_31)        lfd     31,-8(11)
+                       blr
+FUNC_END(_restfpr_31)
+FUNC_END(_restfpr_30)
+FUNC_END(_restfpr_29)
+FUNC_END(_restfpr_28)
+FUNC_END(_restfpr_27)
+FUNC_END(_restfpr_26)
+FUNC_END(_restfpr_25)
+FUNC_END(_restfpr_24)
+FUNC_END(_restfpr_23)
+FUNC_END(_restfpr_22)
+FUNC_END(_restfpr_21)
+FUNC_END(_restfpr_20)
+FUNC_END(_restfpr_19)
+FUNC_END(_restfpr_18)
+FUNC_END(_restfpr_17)
+FUNC_END(_restfpr_16)
+FUNC_END(_restfpr_15)
+FUNC_END(_restfpr_14)
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+FUNC_START(_restgpr_14)        lwz     14,-72(11)      /* restore gp registers */
+FUNC_START(_restgpr_15)        lwz     15,-68(11)
+FUNC_START(_restgpr_16)        lwz     16,-64(11)
+FUNC_START(_restgpr_17)        lwz     17,-60(11)
+FUNC_START(_restgpr_18)        lwz     18,-56(11)
+FUNC_START(_restgpr_19)        lwz     19,-52(11)
+FUNC_START(_restgpr_20)        lwz     20,-48(11)
+FUNC_START(_restgpr_21)        lwz     21,-44(11)
+FUNC_START(_restgpr_22)        lwz     22,-40(11)
+FUNC_START(_restgpr_23)        lwz     23,-36(11)
+FUNC_START(_restgpr_24)        lwz     24,-32(11)
+FUNC_START(_restgpr_25)        lwz     25,-28(11)
+FUNC_START(_restgpr_26)        lwz     26,-24(11)
+FUNC_START(_restgpr_27)        lwz     27,-20(11)
+FUNC_START(_restgpr_28)        lwz     28,-16(11)
+FUNC_START(_restgpr_29)        lwz     29,-12(11)
+FUNC_START(_restgpr_30)        lwz     30,-8(11)
+FUNC_START(_restgpr_31)        lwz     31,-4(11)
+                       blr
+FUNC_END(_restgpr_31)
+FUNC_END(_restgpr_30)
+FUNC_END(_restgpr_29)
+FUNC_END(_restgpr_28)
+FUNC_END(_restgpr_27)
+FUNC_END(_restgpr_26)
+FUNC_END(_restgpr_25)
+FUNC_END(_restgpr_24)
+FUNC_END(_restgpr_23)
+FUNC_END(_restgpr_22)
+FUNC_END(_restgpr_21)
+FUNC_END(_restgpr_20)
+FUNC_END(_restgpr_19)
+FUNC_END(_restgpr_18)
+FUNC_END(_restgpr_17)
+FUNC_END(_restgpr_16)
+FUNC_END(_restgpr_15)
+FUNC_END(_restgpr_14)
+
+/* Routines for restoring floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+/* In addition to restoring the fp registers, it will return to the caller's */
+/* caller */
+
+FUNC_START(_restfpr_14_x)      lfd     14,-144(11)     /* restore fp registers */
+FUNC_START(_restfpr_15_x)      lfd     15,-136(11)
+FUNC_START(_restfpr_16_x)      lfd     16,-128(11)
+FUNC_START(_restfpr_17_x)      lfd     17,-120(11)
+FUNC_START(_restfpr_18_x)      lfd     18,-112(11)
+FUNC_START(_restfpr_19_x)      lfd     19,-104(11)
+FUNC_START(_restfpr_20_x)      lfd     20,-96(11)
+FUNC_START(_restfpr_21_x)      lfd     21,-88(11)
+FUNC_START(_restfpr_22_x)      lfd     22,-80(11)
+FUNC_START(_restfpr_23_x)      lfd     23,-72(11)
+FUNC_START(_restfpr_24_x)      lfd     24,-64(11)
+FUNC_START(_restfpr_25_x)      lfd     25,-56(11)
+FUNC_START(_restfpr_26_x)      lfd     26,-48(11)
+FUNC_START(_restfpr_27_x)      lfd     27,-40(11)
+FUNC_START(_restfpr_28_x)      lfd     28,-32(11)
+FUNC_START(_restfpr_29_x)      lfd     29,-24(11)
+FUNC_START(_restfpr_30_x)      lfd     30,-16(11)
+FUNC_START(_restfpr_31_x)      lwz     0,4(11)
+                               lfd     31,-8(11)
+                               mtlr    0
+                               mr      1,11
+                               blr
+FUNC_END(_restfpr_31_x)
+FUNC_END(_restfpr_30_x)
+FUNC_END(_restfpr_29_x)
+FUNC_END(_restfpr_28_x)
+FUNC_END(_restfpr_27_x)
+FUNC_END(_restfpr_26_x)
+FUNC_END(_restfpr_25_x)
+FUNC_END(_restfpr_24_x)
+FUNC_END(_restfpr_23_x)
+FUNC_END(_restfpr_22_x)
+FUNC_END(_restfpr_21_x)
+FUNC_END(_restfpr_20_x)
+FUNC_END(_restfpr_19_x)
+FUNC_END(_restfpr_18_x)
+FUNC_END(_restfpr_17_x)
+FUNC_END(_restfpr_16_x)
+FUNC_END(_restfpr_15_x)
+FUNC_END(_restfpr_14_x)
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+FUNC_START(_restgpr_14_x)      lwz     14,-72(11)      /* restore gp registers */
+FUNC_START(_restgpr_15_x)      lwz     15,-68(11)
+FUNC_START(_restgpr_16_x)      lwz     16,-64(11)
+FUNC_START(_restgpr_17_x)      lwz     17,-60(11)
+FUNC_START(_restgpr_18_x)      lwz     18,-56(11)
+FUNC_START(_restgpr_19_x)      lwz     19,-52(11)
+FUNC_START(_restgpr_20_x)      lwz     20,-48(11)
+FUNC_START(_restgpr_21_x)      lwz     21,-44(11)
+FUNC_START(_restgpr_22_x)      lwz     22,-40(11)
+FUNC_START(_restgpr_23_x)      lwz     23,-36(11)
+FUNC_START(_restgpr_24_x)      lwz     24,-32(11)
+FUNC_START(_restgpr_25_x)      lwz     25,-28(11)
+FUNC_START(_restgpr_26_x)      lwz     26,-24(11)
+FUNC_START(_restgpr_27_x)      lwz     27,-20(11)
+FUNC_START(_restgpr_28_x)      lwz     28,-16(11)
+FUNC_START(_restgpr_29_x)      lwz     29,-12(11)
+FUNC_START(_restgpr_30_x)      lwz     30,-8(11)
+FUNC_START(_restgpr_31_x)      lwz     0,4(11)
+                               lwz     31,-4(11)
+                               mtlr    0
+                               mr      1,11
+                               blr
+FUNC_END(_restgpr_31_x)
+FUNC_END(_restgpr_30_x)
+FUNC_END(_restgpr_29_x)
+FUNC_END(_restgpr_28_x)
+FUNC_END(_restgpr_27_x)
+FUNC_END(_restgpr_26_x)
+FUNC_END(_restgpr_25_x)
+FUNC_END(_restgpr_24_x)
+FUNC_END(_restgpr_23_x)
+FUNC_END(_restgpr_22_x)
+FUNC_END(_restgpr_21_x)
+FUNC_END(_restgpr_20_x)
+FUNC_END(_restgpr_19_x)
+FUNC_END(_restgpr_18_x)
+FUNC_END(_restgpr_17_x)
+FUNC_END(_restgpr_16_x)
+FUNC_END(_restgpr_15_x)
+FUNC_END(_restgpr_14_x)
index 0f8bdb5..6044be7 100644 (file)
@@ -60,7 +60,6 @@ Boston, MA 02111-1307, USA.  */
 
 /* Invoke an initializer function to set up the GOT */
 #define NAME__MAIN "__eabi"
-#define INVOKE__main 1
 
 #undef TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)");
@@ -69,57 +68,19 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_PREDEFINES \
   "-DPPC -D__embedded__ -Asystem(embedded) -Acpu(powerpc) -Amachine(powerpc)"
 
-/* Don't use startfiles or libraries except for libgcc.a */
+/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */
 #undef  STARTFILE_SPEC
-#define        STARTFILE_SPEC ""
+#define        STARTFILE_SPEC "\
+%{mmvme: mvme-crt0.o%s} \
+%{msim:  sim-crt0.o%s}"
 
 #undef LIB_SPEC
-#define        LIB_SPEC ""
+#define        LIB_SPEC "\
+%{mmvme: -lmvme -lc -lmvme} \
+%{msim: -lsim -lc -lsim}"
 
 #undef LIBGCC_SPEC
 #define        LIBGCC_SPEC "libgcc.a%s"
 
 #undef ENDFILE_SPEC
 #define        ENDFILE_SPEC ""
-
-/* This is how to output an assembler line defining an `int' constant.
-   For -mrelocatable, we mark all addresses that need to be fixed up
-   in the .fixup section.  */
-#undef ASM_OUTPUT_INT
-#define ASM_OUTPUT_INT(FILE,VALUE)                                     \
-do {                                                                   \
-  static int recurse = 0;                                              \
-  if (TARGET_RELOCATABLE                                               \
-      && in_section != in_toc                                          \
-      && in_section != in_text                                         \
-      && in_section != in_ctors                                                \
-      && in_section != in_dtors                                                \
-      && !recurse                                                      \
-      && GET_CODE (VALUE) != CONST_INT                                 \
-      && GET_CODE (VALUE) != CONST_DOUBLE                              \
-      && CONSTANT_P (VALUE))                                           \
-    {                                                                  \
-      static int labelno = 0;                                          \
-      char buf[256], *p;                                               \
-                                                                       \
-      recurse = 1;                                                     \
-      ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++);             \
-      STRIP_NAME_ENCODING (p, buf);                                    \
-      fprintf (FILE, "%s:\n", p);                                      \
-      fprintf (FILE, "\t.long (");                                     \
-      output_addr_const (FILE, (VALUE));                               \
-      fprintf (FILE, ")@fixup\n");                                     \
-      fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n");               \
-      ASM_OUTPUT_ALIGN (FILE, 2);                                      \
-      fprintf (FILE, "\t.long\t%s\n", p);                              \
-      fprintf (FILE, "\t.previous\n");                                 \
-      recurse = 0;                                                     \
-    }                                                                  \
-  else                                                                 \
-    {                                                                  \
-      fprintf (FILE, "\t.long ");                                      \
-      output_addr_const (FILE, (VALUE));                               \
-      fprintf (FILE, "\n");                                            \
-    }                                                                  \
-} while (0)
-
index 6e92d17..c07f6d6 100644 (file)
@@ -28,7 +28,9 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_SPEC "\
 %{posix: -D_POSIX_SOURCE} \
 %{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_AIX}} \
+%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
+%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
+%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_AIX}}}} \
 %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
 %{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
 %{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
@@ -49,5 +51,20 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef MULTILIB_DEFAULTS
+#define        MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-aix" }
index 11ff65e..430660b 100644 (file)
@@ -29,7 +29,9 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_SPEC "\
 %{posix: -D_POSIX_SOURCE} \
 %{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
+%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
+%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
+%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \
 %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
 %{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
 %{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
@@ -50,5 +52,20 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef MULTILIB_DEFAULTS
+#define        MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" }
index afc8565..4df32f7 100644 (file)
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include "rs6000/eabile.h"
 
-/* Right now, the simulator doesn't handle floating point, so disable it
-   by default.  */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN | MASK_SOFT_FLOAT)
-
 #undef TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
 
@@ -34,40 +29,16 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_PREDEFINES \
   "-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)"
 
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{!mhard-float: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
-%{!mcpu*: \
-  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
-  %{mpower2: -D_ARCH_PWR2} \
-  %{mpowerpc*: -D_ARCH_PPC} \
-  %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
-  %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
-
-/* Use the simulator crt0 and libgloss/newlib libraries */
+/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */
 #undef  STARTFILE_SPEC
-#define        STARTFILE_SPEC "sim-crt0.o%s"
+#define        STARTFILE_SPEC "\
+%{mmvme: mvme-crt0.o%s} \
+%{!mmvme: sim-crt0.o%s}"
 
 #undef LIB_SPEC
-#define        LIB_SPEC "-lsim -lc -lsim"
+#define        LIB_SPEC "\
+%{mmvme: -lmvme -lc -lmvme} \
+%{!mmvme: -lsim -lc -lsim}"
 
 #undef LIBGCC_SPEC
 #define        LIBGCC_SPEC "libgcc.a%s"
index 98c9f0e..826801c 100644 (file)
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include "rs6000/eabi.h"
 
-/* Right now, the simulator doesn't handle floating point, so disable it
-   by default.  */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_SOFT_FLOAT)
-
 #undef TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
 
@@ -34,40 +29,16 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_PREDEFINES \
   "-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)"
 
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{!mhard-float: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
-%{!mcpu*: \
-  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
-  %{mpower2: -D_ARCH_PWR2} \
-  %{mpowerpc*: -D_ARCH_PPC} \
-  %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
-  %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
-
-/* Use the simulator crt0 and libgloss/newlib libraries */
+/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */
 #undef  STARTFILE_SPEC
-#define        STARTFILE_SPEC "sim-crt0.o%s"
+#define        STARTFILE_SPEC "\
+%{mmvme: mvme-crt0.o%s} \
+%{!mmvme: sim-crt0.o%s}"
 
 #undef LIB_SPEC
-#define        LIB_SPEC "-lsim -lc -lsim"
+#define        LIB_SPEC "\
+%{mmvme: -lmvme -lc -lmvme} \
+%{!mmvme: -lsim -lc -lsim}"
 
 #undef LIBGCC_SPEC
 #define        LIBGCC_SPEC "libgcc.a%s"
index c812c6b..bb4e8b4 100644 (file)
@@ -20,6 +20,7 @@ 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.  */
 
+#define TARGET_AIX 0
 
 #include "rs6000/rs6000.h"
 
index 8e86a34..7d5bbaa 100644 (file)
@@ -19,6 +19,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#define TARGET_AIX 0
+
 #include "rs6000/powerpc.h"
 
 /* Don't generate XCOFF debugging information.  */
@@ -32,8 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* The XCOFF support uses weird symbol suffixes, which we don't want
    for ELF.  */
 
-#undef RS6000_OUTPUT_BASENAME
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME)
+#undef STRIP_NAME_ENCODING
 
 /* Don't bother to output .extern pseudo-ops.  They are not needed by
    ELF assemblers.  */
index e8f6a17..96e15d7 100644 (file)
@@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=403: -mppc} \
 %{mcpu=601: -m601} \
 %{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
 %{mcpu=604: -mppc}"
 
 #undef CPP_PREDEFINES
@@ -68,8 +69,11 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
 
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
index 08ebd4e..a28bd5c 100644 (file)
@@ -74,6 +74,12 @@ int rs6000_pic_labelno;
 /* Whether a System V.4 varargs area was created.  */
 int rs6000_sysv_varargs_p;
 
+/* Whether we need to save the TOC register.  */
+int rs6000_save_toc_p;
+
+/* ABI enumeration available for subtarget to use.  */
+enum rs6000_abi rs6000_current_abi;
+
 /* Temporary memory used to convert integer -> float */
 static rtx stack_temps[NUM_MACHINE_MODES];
 
@@ -223,11 +229,20 @@ rs6000_override_options ()
         {"601", PROCESSOR_PPC601,
            MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_MULTIPLE | MASK_STRING,
            MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64},
+        {"602", PROCESSOR_PPC602,
+           MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS,
+           MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64},
         {"603", PROCESSOR_PPC603,
            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+        {"603e", PROCESSOR_PPC603,
+           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
+           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
         {"604", PROCESSOR_PPC604,
            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
+           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+        {"620", PROCESSOR_PPC620,
+           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}};
 
   int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
@@ -350,6 +365,23 @@ any_operand (op, mode)
   return 1;
 }
 
+/* Returns 1 if op is the count register */
+int count_register_operand(op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (GET_CODE (op) != REG)
+    return 0;
+
+  if (REGNO (op) == COUNT_REGISTER_REGNUM)
+    return 1;
+
+  if (REGNO (op) > FIRST_PSEUDO_REGISTER)
+    return 1;
+
+  return 0;
+}
+
 /* Return 1 if OP is a constant that can fit in a D field.  */
 
 int
@@ -476,6 +508,10 @@ easy_fp_constant (op, mode)
       || GET_MODE_CLASS (mode) != MODE_FLOAT)
     return 0;
 
+  /* Consider all constants with -msoft-float to be easy */
+  if (TARGET_SOFT_FLOAT)
+    return 1;
+
   high = operand_subword (op, 0, 0, mode);
   low = operand_subword (op, 1, 0, mode);
 
@@ -486,6 +522,34 @@ easy_fp_constant (op, mode)
          || (low != 0 && input_operand (low, word_mode)));
 }
 
+/* Return 1 if the operand is in volatile memory.  Note that during the
+   RTL generation phase, memory_operand does not return TRUE for
+   volatile memory references.  So this function allows us to
+   recognize volatile references where its safe.  */
+
+int
+volatile_mem_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (GET_CODE (op) != MEM)
+    return 0;
+
+  if (!MEM_VOLATILE_P (op))
+    return 0;
+
+  if (mode != GET_MODE (op))
+    return 0;
+
+  if (reload_completed)
+    return memory_operand (op, mode);
+
+  if (reload_in_progress)
+    return strict_memory_address_p (mode, XEXP (op, 0));
+
+  return memory_address_p (mode, XEXP (op, 0));
+}
+
 /* Return 1 if the operand is an offsettable memory address.  */
 
 int
@@ -506,6 +570,7 @@ fp_reg_or_mem_operand (op, mode)
      enum machine_mode mode;
 {
   return (memory_operand (op, mode)
+         || volatile_mem_operand (op, mode)
          || (register_operand (op, mode)
              && (GET_CODE (op) != REG
                  || REGNO (op) >= FIRST_PSEUDO_REGISTER
@@ -640,7 +705,9 @@ reg_or_mem_operand (op, mode)
      register rtx op;
      register enum machine_mode mode;
 {
-  return gpc_reg_operand (op, mode) || memory_operand (op, mode);
+  return (gpc_reg_operand (op, mode)
+         || memory_operand (op, mode)
+         || volatile_mem_operand (op, mode));
 }
 
 /* Return 1 if the operand is a general register or memory operand without
@@ -732,6 +799,12 @@ input_operand (op, mode)
   if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))
     return 1;
 
+  /* Windows NT allows SYMBOL_REFs and LABEL_REFs against the TOC
+     directly in the instruction stream */
+  if (DEFAULT_ABI == ABI_NT
+      && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF))
+    return 1;
+
   /* Otherwise, we will be doing this SET with an add, so anything valid
      for an add will be valid.  */
   return add_operand (op, mode);
@@ -796,6 +869,26 @@ init_cumulative_args (cum, fntype, libname, incoming)
     }
 }
 \f
+/* If defined, a C expression that gives the alignment boundary, in bits,
+   of an argument with the specified mode and type.  If it is not defined, 
+   PARM_BOUNDARY is used for all arguments.
+   
+   Windows NT wants anything >= 8 bytes to be double word aligned.  */
+
+int
+function_arg_boundary (mode, type)
+     enum machine_mode mode;
+     tree type;
+{
+  if (DEFAULT_ABI != ABI_NT || TARGET_64BIT)
+    return PARM_BOUNDARY;
+
+  if (mode != BLKmode)
+    return (GET_MODE_SIZE (mode)) >= 8 ? 64 : 32;
+
+  return (int_size_in_bytes (type) >= 8) ? 64 : 32;
+}
+\f
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
    (TYPE is null for libcalls where that information may not be available.)  */
@@ -807,6 +900,8 @@ function_arg_advance (cum, mode, type, named)
      tree type;
      int named;
 {
+  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
+  cum->words += align;
   cum->nargs_prototype--;
 
 #ifdef TARGET_V4_CALLS
@@ -846,8 +941,8 @@ function_arg_advance (cum, mode, type, named)
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
-            "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n",
-            cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named);
+            "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+            cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
 }
 \f
 /* Determine where to put an argument to a function.
@@ -880,10 +975,13 @@ function_arg (cum, mode, type, named)
      tree type;
      int named;
 {
+  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
+  int align_words = cum->words + align;
+
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
-            "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n",
-            cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named);
+            "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",
+            cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);
 
   /* Return a marker to indicate whether CR1 needs to set or clear the bit that V.4
      uses to say fp args were passed in registers.  Assume that we don't need the
@@ -920,8 +1018,8 @@ function_arg (cum, mode, type, named)
        return gen_rtx (REG, mode, cum->fregno);
 
       return gen_rtx (EXPR_LIST, VOIDmode,
-                     ((cum->words < GP_ARG_NUM_REG)
-                      ? gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words)
+                     ((align_words < GP_ARG_NUM_REG)
+                      ? gen_rtx (REG, mode, GP_ARG_MIN_REG + align_words)
                       : NULL_RTX),
                      gen_rtx (REG, mode, cum->fregno));
     }
@@ -929,14 +1027,14 @@ function_arg (cum, mode, type, named)
 #ifdef TARGET_V4_CALLS
   /* Long longs won't be split between register and stack */
   else if (TARGET_V4_CALLS &&
-          cum->words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)
+          align_words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)
     {
       return NULL_RTX;
     }
 #endif
 
-  else if (cum->words < GP_ARG_NUM_REG)
-    return gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words);
+  else if (align_words < GP_ARG_NUM_REG)
+    return gen_rtx (REG, mode, GP_ARG_MIN_REG + align_words);
 
   return NULL_RTX;
 }
@@ -1164,8 +1262,13 @@ expand_block_move_mem (mode, addr, orig_mem)
      rtx orig_mem;
 {
   rtx mem = gen_rtx (MEM, mode, addr);
+
+  RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (orig_mem);
   MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
   MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (orig_mem);
+#ifdef MEM_UNALIGNED_P
+  MEM_UNALIGNED_P (mem) = MEM_UNALIGNED_P (orig_mem);
+#endif
   return mem;
 }
 
@@ -1183,6 +1286,8 @@ int
 expand_block_move (operands)
      rtx operands[];
 {
+  rtx orig_dest = operands[0];
+  rtx orig_src = operands[1];
   rtx bytes_rtx        = operands[2];
   rtx align_rtx = operands[3];
   int constp   = (GET_CODE (bytes_rtx) == CONST_INT);
@@ -1224,8 +1329,8 @@ expand_block_move (operands)
     return 0;
 
   /* Move the address into scratch registers.  */
-  dest_reg = copy_addr_to_reg (XEXP (operands[0], 0));
-  src_reg  = copy_addr_to_reg (XEXP (operands[1], 0));
+  dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0));
+  src_reg  = copy_addr_to_reg (XEXP (orig_src,  0));
 
   if (TARGET_STRING)   /* string instructions are available */
     {
@@ -1242,8 +1347,8 @@ expand_block_move (operands)
              && !fixed_regs[12])
            {
              move_bytes = (bytes > 32) ? 32 : bytes;
-             emit_insn (gen_movstrsi_8reg (dest_reg,
-                                           src_reg,
+             emit_insn (gen_movstrsi_8reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest),
+                                           expand_block_move_mem (BLKmode, src_reg, orig_src),
                                            GEN_INT ((move_bytes == 32) ? 0 : move_bytes),
                                            align_rtx));
            }
@@ -1256,8 +1361,8 @@ expand_block_move (operands)
                   && !fixed_regs[12])
            {
              move_bytes = (bytes > 24) ? 24 : bytes;
-             emit_insn (gen_movstrsi_6reg (dest_reg,
-                                           src_reg,
+             emit_insn (gen_movstrsi_6reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest),
+                                           expand_block_move_mem (BLKmode, src_reg, orig_src),
                                            GEN_INT (move_bytes),
                                            align_rtx));
            }
@@ -1268,16 +1373,16 @@ expand_block_move (operands)
                   && !fixed_regs[12])
            {
              move_bytes = (bytes > 16) ? 16 : bytes;
-             emit_insn (gen_movstrsi_4reg (dest_reg,
-                                           src_reg,
+             emit_insn (gen_movstrsi_4reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest),
+                                           expand_block_move_mem (BLKmode, src_reg, orig_src),
                                            GEN_INT (move_bytes),
                                            align_rtx));
            }
          else if (bytes > 4 && !TARGET_64BIT)
            {                   /* move up to 8 bytes at a time */
              move_bytes = (bytes > 8) ? 8 : bytes;
-             emit_insn (gen_movstrsi_2reg (dest_reg,
-                                           src_reg,
+             emit_insn (gen_movstrsi_2reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest),
+                                           expand_block_move_mem (BLKmode, src_reg, orig_src),
                                            GEN_INT (move_bytes),
                                            align_rtx));
            }
@@ -1285,28 +1390,28 @@ expand_block_move (operands)
            {                   /* move 4 bytes */
              move_bytes = 4;
              tmp_reg = gen_reg_rtx (SImode);
-             emit_move_insn (tmp_reg, gen_rtx (MEM, SImode, src_reg));
-             emit_move_insn (gen_rtx (MEM, SImode, dest_reg), tmp_reg);
+             emit_move_insn (tmp_reg, expand_block_move_mem (SImode, src_reg, orig_src));
+             emit_move_insn (expand_block_move_mem (SImode, dest_reg, orig_dest), tmp_reg);
            }
          else if (bytes == 2 && (align >= 2 || !STRICT_ALIGNMENT))
            {                   /* move 2 bytes */
              move_bytes = 2;
              tmp_reg = gen_reg_rtx (HImode);
-             emit_move_insn (tmp_reg, gen_rtx (MEM, HImode, src_reg));
-             emit_move_insn (gen_rtx (MEM, HImode, dest_reg), tmp_reg);
+             emit_move_insn (tmp_reg, expand_block_move_mem (HImode, src_reg, orig_src));
+             emit_move_insn (expand_block_move_mem (HImode, dest_reg, orig_dest), tmp_reg);
            }
          else if (bytes == 1)  /* move 1 byte */
            {
              move_bytes = 1;
              tmp_reg = gen_reg_rtx (QImode);
-             emit_move_insn (tmp_reg, gen_rtx (MEM, QImode, src_reg));
-             emit_move_insn (gen_rtx (MEM, QImode, dest_reg), tmp_reg);
+             emit_move_insn (tmp_reg, expand_block_move_mem (QImode, src_reg, orig_src));
+             emit_move_insn (expand_block_move_mem (QImode, dest_reg, orig_dest), tmp_reg);
            }
          else
            {                   /* move up to 4 bytes at a time */
              move_bytes = (bytes > 4) ? 4 : bytes;
-             emit_insn (gen_movstrsi_1reg (dest_reg,
-                                           src_reg,
+             emit_insn (gen_movstrsi_1reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest),
+                                           expand_block_move_mem (BLKmode, src_reg, orig_src),
                                            GEN_INT (move_bytes),
                                            align_rtx));
            }
@@ -1337,26 +1442,33 @@ expand_block_move (operands)
            }
 
          /* Generate the appropriate load and store, saving the stores for later */
-         if (bytes >= 4 && (align >= 4 || !STRICT_ALIGNMENT))
+         if (bytes >= 8 && TARGET_64BIT && (align >= 8 || !STRICT_ALIGNMENT))
+           {
+             move_bytes = 8;
+             tmp_reg = gen_reg_rtx (DImode);
+             emit_insn (gen_movdi (tmp_reg, expand_block_move_mem (DImode, src_addr, orig_src)));
+             stores[ num_reg++ ] = gen_movdi (expand_block_move_mem (DImode, dest_addr, orig_dest), tmp_reg);
+           }
+         else if (bytes >= 4 && (align >= 4 || !STRICT_ALIGNMENT))
            {
              move_bytes = 4;
              tmp_reg = gen_reg_rtx (SImode);
-             emit_insn (gen_movsi (tmp_reg, gen_rtx (MEM, SImode, src_addr)));
-             stores[ num_reg++ ] = gen_movsi (gen_rtx (MEM, SImode, dest_addr), tmp_reg);
+             emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (SImode, src_addr, orig_src)));
+             stores[ num_reg++ ] = gen_movsi (expand_block_move_mem (SImode, dest_addr, orig_dest), tmp_reg);
            }
          else if (bytes >= 2 && (align >= 2 || !STRICT_ALIGNMENT))
            {
              move_bytes = 2;
              tmp_reg = gen_reg_rtx (HImode);
-             emit_insn (gen_movhi (tmp_reg, gen_rtx (MEM, HImode, src_addr)));
-             stores[ num_reg++ ] = gen_movhi (gen_rtx (MEM, HImode, dest_addr), tmp_reg);
+             emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (HImode, src_addr, orig_src)));
+             stores[ num_reg++ ] = gen_movhi (expand_block_move_mem (HImode, dest_addr, orig_dest), tmp_reg);
            }
          else
            {
              move_bytes = 1;
              tmp_reg = gen_reg_rtx (QImode);
-             emit_insn (gen_movqi (tmp_reg, gen_rtx (MEM, QImode, src_addr)));
-             stores[ num_reg++ ] = gen_movqi (gen_rtx (MEM, QImode, dest_addr), tmp_reg);
+             emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (QImode, src_addr, orig_src)));
+             stores[ num_reg++ ] = gen_movqi (expand_block_move_mem (QImode, dest_addr, orig_dest), tmp_reg);
            }
 
          if (num_reg >= MAX_MOVE_REG)
@@ -1367,11 +1479,8 @@ expand_block_move (operands)
            }
        }
 
-      if (num_reg > 0)
-       {
-         for (i = 0; i < num_reg; i++)
-           emit_insn (stores[i]);
-       }
+      for (i = 0; i < num_reg; i++)
+       emit_insn (stores[i]);
     }
 
   return 1;
@@ -2127,9 +2236,26 @@ print_operand (file, x, code)
       if (GET_CODE (x) != SYMBOL_REF)
        abort ();
 
-#ifndef USING_SVR4_H
-      putc ('.', file);
-#endif
+      if (XSTR (x, 0)[0] != '.')
+       {
+         switch (DEFAULT_ABI)
+           {
+           default:
+             abort ();
+
+           case ABI_AIX:
+             putc ('.', file);
+             break;
+
+           case ABI_V4:
+           case ABI_AIX_NODESC:
+             break;
+
+           case ABI_NT:
+             fputs ("..", file);
+             break;
+           }
+       }
       RS6000_OUTPUT_BASENAME (file, XSTR (x, 0));
       return;
 
@@ -2235,11 +2361,9 @@ first_reg_to_save ()
      to 23 to do this.  Don't use the frame pointer in reg 31.
 
      For now, save enough room for all of the parameter registers.  */
-#ifndef USING_SVR4_H
-  if (profile_flag)
+  if (DEFAULT_ABI == ABI_AIX && profile_flag)
     if (first_reg > 23)
       first_reg = 23;
-#endif
 
   return first_reg;
 }
@@ -2333,7 +2457,49 @@ rs6000_makes_calls ()
                +---------------------------------------+
        old SP->| back chain to caller's caller         |
                +---------------------------------------+
-*/
+
+
+   A PowerPC Windows/NT frame looks like:
+
+       SP----> +---------------------------------------+
+               | back chain to caller                  | 0
+               +---------------------------------------+
+               | reserved                              | 4
+               +---------------------------------------+
+               | reserved                              | 8
+               +---------------------------------------+
+               | reserved                              | 12
+               +---------------------------------------+
+               | reserved                              | 16
+               +---------------------------------------+
+               | reserved                              | 20
+               +---------------------------------------+
+               | Parameter save area (P)               | 24
+               +---------------------------------------+
+               | Alloca space (A)                      | 24+P
+               +---------------------------------------+
+               | Local variable space (L)              | 24+P+A
+               +---------------------------------------+
+               | Save area for FP registers (F)        | 24+P+A+L
+               +---------------------------------------+
+               | Possible alignment area (X)           | 24+P+A+L+F
+               +---------------------------------------+
+               | Save area for GP registers (G)        | 24+P+A+L+F+X
+               +---------------------------------------+
+               | Save area for CR (C)                  | 24+P+A+L+F+X+G
+               +---------------------------------------+
+               | Save area for TOC (T)                 | 24+P+A+L+F+X+G+C
+               +---------------------------------------+
+               | Save area for LR (R)                  | 24+P+A+L+F+X+G+C+T
+               +---------------------------------------+
+       old SP->| back chain to caller's caller         |
+               +---------------------------------------+
+
+   For NT, there is no specific order to save the registers, but in
+   order to support __builtin_return_address, the save area for the
+   link register needs to be in a known place, so we use -4 off of the
+   old SP.  To support calls through pointers, we also allocate a
+   fixed slot to store the TOC, -8 off the old SP.  */
 
 rs6000_stack_t *
 rs6000_stack_info ()
@@ -2342,19 +2508,13 @@ rs6000_stack_info ()
   rs6000_stack_t *info_ptr = &info;
   int reg_size = TARGET_64BIT ? 8 : 4;
   enum rs6000_abi abi;
+  int total_raw_size;
 
   /* Zero all fields portably */
   info = zero_info;
 
   /* Select which calling sequence */
-#ifdef TARGET_V4_CALLS
-  if (TARGET_V4_CALLS)
-    abi = ABI_V4;
-  else
-#endif
-    abi = ABI_AIX;
-
-  info_ptr->abi = abi;
+  info_ptr->abi = abi = DEFAULT_ABI;
 
   /* Calculate which registers need to be saved & save area size */
   info_ptr->first_gp_reg_save = first_reg_to_save ();
@@ -2366,6 +2526,39 @@ rs6000_stack_info ()
   /* Does this function call anything? */
   info_ptr->calls_p = rs6000_makes_calls ();
 
+  /* Do we need to allocate space to save the toc? */
+  if (rs6000_save_toc_p)
+    {
+      info_ptr->toc_save_p = 1;
+      info_ptr->toc_size = reg_size;
+    }
+
+  /* If this is main and we need to call a function to set things up,
+     save main's arguments around the call.  */
+  if (strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), "main") == 0)
+    {
+      info_ptr->main_p = 1;
+
+#ifdef NAME__MAIN
+      if (DECL_ARGUMENTS (current_function_decl))
+       {
+         int i;
+         tree arg;
+
+         info_ptr->main_save_p = 1;
+         info_ptr->main_size = 0;
+         info_ptr->calls_p = 1;
+
+         for ((i = 0), (arg = DECL_ARGUMENTS (current_function_decl));
+              arg != NULL_TREE && i < 8;
+              (arg = TREE_CHAIN (arg)), i++)
+           {
+             info_ptr->main_size += reg_size;
+           }
+       }
+#endif
+    }
+
   /* Determine if we need to save the link register */
   if (regs_ever_live[65] || profile_flag
 #ifdef TARGET_RELOCATABLE
@@ -2378,13 +2571,15 @@ rs6000_stack_info ()
     {
       info_ptr->lr_save_p = 1;
       regs_ever_live[65] = 1;
+      if (abi == ABI_NT)
+       info_ptr->lr_size = reg_size;
     }
 
   /* Determine if we need to save the condition code registers */
   if (regs_ever_live[70] || regs_ever_live[71] || regs_ever_live[72])
     {
       info_ptr->cr_save_p = 1;
-      if (abi == ABI_V4)
+      if (abi == ABI_V4 || abi == ABI_NT)
        info_ptr->cr_size = reg_size;
     }
 
@@ -2394,12 +2589,20 @@ rs6000_stack_info ()
   info_ptr->varargs_size = RS6000_VARARGS_AREA;
   info_ptr->vars_size    = ALIGN (get_frame_size (), 8);
   info_ptr->parm_size    = ALIGN (current_function_outgoing_args_size, 8);
-  info_ptr->save_size    = ALIGN (info_ptr->fp_size + info_ptr->gp_size + info_ptr->cr_size, 8);
-  info_ptr->total_size   = ALIGN (info_ptr->vars_size
-                                 + info_ptr->parm_size
-                                 + info_ptr->save_size
-                                 + info_ptr->varargs_size
-                                 + info_ptr->fixed_size, STACK_BOUNDARY / BITS_PER_UNIT);
+  info_ptr->save_size    = ALIGN (info_ptr->fp_size
+                                 + info_ptr->gp_size
+                                 + info_ptr->cr_size
+                                 + info_ptr->lr_size
+                                 + info_ptr->toc_size
+                                 + info_ptr->main_size, 8);
+
+  total_raw_size        = (info_ptr->vars_size
+                           + info_ptr->parm_size
+                           + info_ptr->save_size
+                           + info_ptr->varargs_size
+                           + info_ptr->fixed_size);
+
+  info_ptr->total_size   = ALIGN (total_raw_size, STACK_BOUNDARY / BITS_PER_UNIT);
 
   /* Determine if we need to allocate any stack frame.
      For AIX We need to push the stack if a frame pointer is needed (because
@@ -2412,8 +2615,8 @@ rs6000_stack_info ()
   if (info_ptr->calls_p)
     info_ptr->push_p = 1;
 
-  else if (abi == ABI_V4)
-    info_ptr->push_p = (info_ptr->total_size > info_ptr->fixed_size
+  else if (abi == ABI_V4 || abi == ABI_NT)
+    info_ptr->push_p = (total_raw_size > info_ptr->fixed_size
                        || info_ptr->lr_save_p);
 
   else
@@ -2422,18 +2625,40 @@ rs6000_stack_info ()
                        || info_ptr->total_size > 220);
 
   /* Calculate the offsets */
-  info_ptr->fp_save_offset = - info_ptr->fp_size;
-  info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
   switch (abi)
     {
+    case ABI_NONE:
     default:
-      info_ptr->cr_save_offset = 4;
-      info_ptr->lr_save_offset = 8;
+      abort ();
+
+    case ABI_AIX:
+    case ABI_AIX_NODESC:
+      info_ptr->fp_save_offset   = - info_ptr->fp_size;
+      info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
+      info_ptr->main_save_offset = info_ptr->gp_save_offset - info_ptr->main_size;
+      info_ptr->cr_save_offset   = 4;
+      info_ptr->lr_save_offset   = 8;
       break;
 
     case ABI_V4:
-      info_ptr->cr_save_offset = info_ptr->gp_save_offset - reg_size;
-      info_ptr->lr_save_offset = reg_size;
+      info_ptr->fp_save_offset   = - info_ptr->fp_size;
+      info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
+      info_ptr->cr_save_offset   = info_ptr->gp_save_offset - reg_size;
+      info_ptr->toc_save_offset  = info_ptr->cr_save_offset - info_ptr->cr_size;
+      info_ptr->main_save_offset = info_ptr->toc_save_offset - info_ptr->toc_size;
+      info_ptr->lr_save_offset   = reg_size;
+      break;
+
+    case ABI_NT:
+      info_ptr->lr_save_offset    = -4;
+      info_ptr->toc_save_offset   = info_ptr->lr_save_offset - info_ptr->lr_size;
+      info_ptr->cr_save_offset    = info_ptr->toc_save_offset - info_ptr->toc_size;
+      info_ptr->gp_save_offset    = info_ptr->cr_save_offset - info_ptr->cr_size - info_ptr->gp_size + reg_size;
+      info_ptr->fp_save_offset    = info_ptr->gp_save_offset - info_ptr->fp_size;
+      if (info_ptr->fp_size && ((- info_ptr->fp_save_offset) % 8) != 0)
+       info_ptr->fp_save_offset -= 4;
+
+      info_ptr->main_save_offset = info_ptr->fp_save_offset - info_ptr->main_size;
       break;
     }
 
@@ -2450,6 +2675,12 @@ rs6000_stack_info ()
   if (!info_ptr->cr_save_p)
     info_ptr->cr_save_offset = 0;
 
+  if (!info_ptr->toc_save_p)
+    info_ptr->toc_save_offset = 0;
+
+  if (!info_ptr->main_save_p)
+    info_ptr->main_save_offset = 0;
+
   return info_ptr;
 }
 
@@ -2469,10 +2700,12 @@ debug_stack_info (info)
 
   switch (info->abi)
     {
-    default:      abi_string = "Unknown";      break;
-    case ABI_NONE: abi_string = "NONE";                break;
-    case ABI_AIX:  abi_string = "AIX";         break;
-    case ABI_V4:   abi_string = "V.4";         break;
+    default:            abi_string = "Unknown";        break;
+    case ABI_NONE:      abi_string = "NONE";           break;
+    case ABI_AIX:       abi_string = "AIX";            break;
+    case ABI_AIX_NODESC: abi_string = "AIX";           break;
+    case ABI_V4:        abi_string = "V.4";            break;
+    case ABI_NT:        abi_string = "NT";             break;
     }
 
   fprintf (stderr, "\tABI                 = %5s\n", abi_string);
@@ -2489,12 +2722,21 @@ debug_stack_info (info)
   if (info->cr_save_p)
     fprintf (stderr, "\tcr_save_p           = %5d\n", info->cr_save_p);
 
+  if (info->toc_save_p)
+    fprintf (stderr, "\ttoc_save_p          = %5d\n", info->toc_save_p);
+
   if (info->push_p)
     fprintf (stderr, "\tpush_p              = %5d\n", info->push_p);
 
   if (info->calls_p)
     fprintf (stderr, "\tcalls_p             = %5d\n", info->calls_p);
 
+  if (info->main_p)
+    fprintf (stderr, "\tmain_p              = %5d\n", info->main_p);
+
+  if (info->main_save_p)
+    fprintf (stderr, "\tmain_save_p         = %5d\n", info->main_save_p);
+
   if (info->gp_save_offset)
     fprintf (stderr, "\tgp_save_offset      = %5d\n", info->gp_save_offset);
 
@@ -2507,9 +2749,15 @@ debug_stack_info (info)
   if (info->cr_save_offset)
     fprintf (stderr, "\tcr_save_offset      = %5d\n", info->cr_save_offset);
 
+  if (info->toc_save_offset)
+    fprintf (stderr, "\ttoc_save_offset     = %5d\n", info->toc_save_offset);
+
   if (info->varargs_save_offset)
     fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
 
+  if (info->main_save_offset)
+    fprintf (stderr, "\tmain_save_offset    = %5d\n", info->main_save_offset);
+
   if (info->total_size)
     fprintf (stderr, "\ttotal_size          = %5d\n", info->total_size);
 
@@ -2531,9 +2779,18 @@ debug_stack_info (info)
   if (info->fp_size)
     fprintf (stderr, "\tfp_size             = %5d\n", info->fp_size);
 
+ if (info->lr_size)
+    fprintf (stderr, "\tlr_size             = %5d\n", info->cr_size);
+
   if (info->cr_size)
     fprintf (stderr, "\tcr_size             = %5d\n", info->cr_size);
 
+ if (info->toc_size)
+    fprintf (stderr, "\ttoc_size            = %5d\n", info->toc_size);
+
+ if (info->main_size)
+    fprintf (stderr, "\tmain_size           = %5d\n", info->main_size);
+
   if (info->save_size)
     fprintf (stderr, "\tsave_size           = %5d\n", info->save_size);
 
@@ -2544,65 +2801,6 @@ debug_stack_info (info)
 }
 
 \f
-
-#ifdef USING_SVR4_H
-/* Write out a System V.4 style traceback table before the prologue
-
-   At present, only emit the basic tag table (ie, do not emit tag_types other
-   than 0, which might use more than 1 tag word).
-
-   The first tag word looks like:
-
-    0                  1                   2                   3
-    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |         0 |ver| tag |e|s| alloca  | # fprs  | # gprs  |s|l|c|f|
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-*/
-
-void
-svr4_traceback (file, name, decl)
-     FILE *file;
-     tree name, decl;
-{
-  rs6000_stack_t *info = rs6000_stack_info ();
-  long tag;
-  long version         = 0;                            /* version number */
-  long tag_type                = 0;                            /* function type */
-  long extended_tag    = 0;                            /* additional tag words needed */
-  long spare           = 0;                            /* reserved for future use */
-  long fpscr_max       = 0;                            /* 1 if the function has a FPSCR save word */
-  long fpr_max         = 64 - info->first_fp_reg_save; /* # of floating point registers saved */
-  long gpr_max         = 32 - info->first_gp_reg_save; /* # of general purpose registers saved */
-  long alloca_reg;                                     /* stack/frame register */
-
-  if (frame_pointer_needed)
-    alloca_reg = 31;
-
-  else if (info->push_p != 0)
-    alloca_reg = 1;
-
-  else
-    alloca_reg = 0;
-
-  tag = ((version << 24)
-        | (tag_type << 21)
-        | (extended_tag << 20)
-        | (spare << 19)
-        | (alloca_reg << 14)
-        | (fpr_max << 9)
-        | (gpr_max << 4)
-        | (info->push_p << 3)
-        | (info->lr_save_p << 2)
-        | (info->cr_save_p << 1)
-        | (fpscr_max << 0));
-          
-  fprintf (file, "\t.long 0x%lx\n", tag);
-}
-
-#endif /* USING_SVR4_H */
-\f
 /* Write function prologue.  */
 void
 output_prolog (file, size)
@@ -2610,19 +2808,30 @@ output_prolog (file, size)
      int size;
 {
   rs6000_stack_t *info = rs6000_stack_info ();
-  char *store_reg = (TARGET_64BIT) ? "\tstd %s,%d(%s)" : "\t{st|stw} %s,%d(%s)\n";
+  int reg_size = info->reg_size;
+  char *store_reg;
+  char *load_reg;
+
+  if (TARGET_64BIT)
+    {
+      store_reg = "\tstd %s,%d(%s)";
+      load_reg = "\tlld %s,%d(%s)";
+    }
+  else
+    {
+      store_reg = "\t{st|stw} %s,%d(%s)\n";
+      load_reg = "\t{l|lwz} %s,%d(%s)\n";
+    }
 
   if (TARGET_DEBUG_STACK)
     debug_stack_info (info);
 
   /* Write .extern for any function we will call to save and restore fp
      values.  */
-#ifndef USING_SVR4_H
-  if (info->first_fp_reg_save < 62)
+  if (info->first_fp_reg_save < 64 && !FP_SAVE_INLINE (info->first_fp_reg_save))
     fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
             SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
             RESTORE_FP_PREFIX, info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
-#endif
 
   /* Write .extern for truncation routines, if needed.  */
   if (rs6000_trunc_used && ! trunc_defined)
@@ -2672,7 +2881,6 @@ output_prolog (file, size)
     {
       int regno    = info->first_gp_reg_save;
       int loc      = info->gp_save_offset;
-      int reg_size = (TARGET_64BIT) ? 8 : 4;
 
       for ( ; regno < 32; regno++, loc += reg_size)
        asm_fprintf (file, store_reg, reg_names[regno], loc, reg_names[1]);
@@ -2684,6 +2892,19 @@ output_prolog (file, size)
                 info->gp_save_offset,
                 reg_names[1]);
 
+  /* Save main's arguments if we need to call a function */
+#ifdef NAME__MAIN
+  if (info->main_save_p)
+    {
+      int regno;
+      int loc = info->main_save_offset;
+      int size = info->main_size;
+
+      for (regno = 3; size > 0; regno++, loc -= reg_size, size -= reg_size)
+       asm_fprintf (file, store_reg, reg_names[regno], loc, reg_names[1]);
+    }
+#endif
+
   /* Save lr if we used it.  */
   if (info->lr_save_p)
     asm_fprintf (file, store_reg, reg_names[0], info->lr_save_offset, reg_names[1]);
@@ -2692,6 +2913,9 @@ output_prolog (file, size)
   if (info->cr_save_p)
     asm_fprintf (file, store_reg, reg_names[12], info->cr_save_offset, reg_names[1]);
 
+  if (info->toc_save_p)
+    asm_fprintf (file, store_reg, reg_names[2], info->toc_save_offset, reg_names[1]);
+
   /* Update stack and set back pointer.  */
   if (info->push_p)
     {
@@ -2715,13 +2939,62 @@ output_prolog (file, size)
   if (frame_pointer_needed)
     asm_fprintf (file, "\tmr %s,%s\n", reg_names[31], reg_names[1]);
 
+#ifdef NAME__MAIN
+  /* If we need to call a function to set things up for main, do so now
+     before dealing with the TOC.  */
+  if (info->main_p)
+    {
+      char *prefix = "";
+
+      switch (DEFAULT_ABI)
+       {
+       case ABI_AIX:   prefix = ".";   break;
+       case ABI_NT:    prefix = "..";  break;
+       }
+
+      fprintf (file, "\tbl %s%s\n", prefix, NAME__MAIN);
+#ifdef RS6000_CALL_GLUE2
+      fprintf (file, "\t%s%s%s\n", RS6000_CALL_GLUE2, prefix, NAME_MAIN);
+#else
+#ifdef RS6000_CALL_GLUE
+      if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
+       fprintf (file, "\t%s\n", RS6000_CALL_GLUE);
+#endif
+#endif
+
+      if (info->main_save_p)
+       {
+         int regno;
+         int loc;
+         int size = info->main_size;
+
+         if (info->total_size < 32767)
+           {
+             loc = info->total_size + info->main_save_offset;
+             for (regno = 3; size > 0; regno++, size -= reg_size, loc -= reg_size)
+               asm_fprintf (file, load_reg, reg_names[regno], loc, reg_names[1]);
+           }
+         else
+           {                   /* for large frames, reg 0 above contains -frame size */
+             loc = info->main_save_offset;
+             asm_fprintf (file, "\t{sf|subf} %s,%s,%s\n", reg_names[0], reg_names[0],
+                          reg_names[1]);
+
+             for (regno = 3; size > 0; regno++, size -= reg_size, loc -= reg_size)
+               asm_fprintf (file, load_reg, reg_names[regno], loc, reg_names[0]);
+           }
+       }
+    }
+#endif
+
+
   /* If TARGET_MINIMAL_TOC, and the constant pool is needed, then load the
      TOC_TABLE address into register 30.  */
   if (TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
     {
       char buf[256];
 
-#ifdef USING_SVR4_H
+#ifdef TARGET_RELOCATABLE
       if (TARGET_RELOCATABLE)
        {
          ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
@@ -2732,13 +3005,7 @@ output_prolog (file, size)
          ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno);
          fprintf (file, "\tmflr %s\n", reg_names[30]);
 
-         if (TARGET_POWERPC64)
-           fprintf (file, "\tld");
-         else if (TARGET_NEW_MNEMONICS)
-           fprintf (file, "\tlwz");
-         else
-           fprintf (file, "\tl");
-
+         asm_fprintf (file, TARGET_64BIT ? "\tld" : "\t{l|lwz}");
          fprintf (file, " %s,(", reg_names[0]);
          ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
          assemble_name (file, buf);
@@ -2750,34 +3017,51 @@ output_prolog (file, size)
                       reg_names[30], reg_names[0], reg_names[30]);
          rs6000_pic_labelno++;
        }
-      else if (!TARGET_64BIT)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
-         asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]);
+      else
+#endif
+
+       switch (DEFAULT_ABI)
+         {
+         case ABI_V4:
+         case ABI_AIX_NODESC:
+           if (!TARGET_64BIT)
+             {
+               ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
+               asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]);
+               assemble_name (file, buf);
+               asm_fprintf (file, "@ha\n");
+               if (TARGET_NEW_MNEMONICS)
+                 {
+                   asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]);
+                   assemble_name (file, buf);
+                   asm_fprintf (file, "@l\n");
+                 }
+               else
+                 {
+                   asm_fprintf (file, "\tcal %s,", reg_names[30]);
+                   assemble_name (file, buf);
+                   asm_fprintf (file, "@l(%s)\n", reg_names[30]);
+                 }
+             }
+           else
+             abort ();
+
+         break;
+
+       case ABI_NT:
+       case ABI_AIX:
+         ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
+         asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
          assemble_name (file, buf);
-         asm_fprintf (file, "@ha\n");
-         if (TARGET_NEW_MNEMONICS)
-           {
-             asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]);
-             assemble_name (file, buf);
-             asm_fprintf (file, "@l\n");
-           }
-         else
-           {
-             asm_fprintf (file, "\tcal %s,", reg_names[30]);
-             assemble_name (file, buf);
-             asm_fprintf (file, "@l(%s)\n", reg_names[30]);
-           }
+         asm_fprintf (file, "(%s)\n", reg_names[2]);
+         break;
        }
-      else
-       abort ();
+    }
 
-#else  /* !USING_SVR4_H */
-      ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
-      asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
-      assemble_name (file, buf);
-      asm_fprintf (file, "(%s)\n", reg_names[2]);
-#endif /* USING_SVR4_H */
+  if (DEFAULT_ABI == ABI_NT)
+    {
+      assemble_name (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+      fputs (".b:\n", file);
     }
 }
 
@@ -2886,14 +3170,16 @@ output_epilog (file, size)
      traceback table itself.
 
      System V.4 Powerpc's (and the embedded ABI derived from it) use a
-     different traceback table located before the prologue.  */
-#ifndef USING_SVR4_H
-  if (! flag_inhibit_size_directive)
+     different traceback table.  */
+  if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive)
     {
       char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
       int fixed_parms, float_parms, parm_info;
       int i;
 
+      while (*fname == '.')    /* V.4 encodes . in the name */
+       fname++;
+
       /* Need label immediately before tbtab, so we can compute its offset
         from the function start.  */
       if (*fname == '*')
@@ -3065,10 +3351,18 @@ output_epilog (file, size)
       if (frame_pointer_needed)
        fprintf (file, "\t.byte 31\n");
     }
-#endif /* !USING_SVR4_H */
 
-  /* Reset varargs indicator */
+  /* Reset varargs and save TOC indicator */
   rs6000_sysv_varargs_p = 0;
+  rs6000_save_toc_p = 0;
+
+  if (DEFAULT_ABI == ABI_NT)
+    {
+      RS6000_OUTPUT_BASENAME (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+      fputs (".e:\nFE_MOT_RESVD..", file);
+      RS6000_OUTPUT_BASENAME (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+      fputs (":\n", file);
+    }
 }
 \f
 /* Output a TOC entry.  We derive the entry name from what is
@@ -3082,6 +3376,7 @@ output_toc (file, x, labelno)
 {
   char buf[256];
   char *name = buf;
+  char *real_name;
   rtx base = x;
   int offset = 0;
 
@@ -3098,8 +3393,7 @@ output_toc (file, x, labelno)
   }
 
 
-#ifdef USING_SVR4_H
-  if (TARGET_MINIMAL_TOC)
+  if (TARGET_ELF && TARGET_MINIMAL_TOC)
     {
       ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
       fprintf (file, "%d = .-", labelno);
@@ -3107,7 +3401,6 @@ output_toc (file, x, labelno)
       fprintf (file, "1\n");
     }
   else
-#endif /* USING_SVR4_H */
     ASM_OUTPUT_INTERNAL_LABEL (file, "LC", labelno);
 
   /* Handle FP constants specially.  Note that if we have a minimal
@@ -3163,8 +3456,8 @@ output_toc (file, x, labelno)
     fprintf (file, "\t.long ");
   else
     {
-      fprintf (file, "\t.tc ");
-      RS6000_OUTPUT_BASENAME (file, name);
+      STRIP_NAME_ENCODING (real_name, name);
+      fprintf (file, "\t.tc %s", real_name);
 
       if (offset < 0)
        fprintf (file, ".N%d", - offset);
@@ -3309,14 +3602,14 @@ output_function_profiler (file, labelno)
   FILE *file;
   int labelno;
 {
-#ifdef USING_SVR4_H
-  abort ();
-#else
   /* The last used parameter register.  */
   int last_parm_reg;
   int i, j;
   char buf[100];
 
+  if (DEFAULT_ABI != ABI_AIX)
+    abort ();
+
   /* Set up a TOC entry for the profiler label.  */
   toc_section ();
   ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno);
@@ -3363,7 +3656,6 @@ output_function_profiler (file, labelno)
 
   for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
     fprintf (file, "\tai %d,%d,0\n", i, j);
-#endif
 }
 
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
@@ -3399,3 +3691,275 @@ rs6000_adjust_cost (insn, link, dep_insn, cost)
 
   return cost;
 }
+
+/* Return how many instructions the machine can issue per cycle */
+int get_issue_rate()
+{
+  switch (rs6000_cpu_attr) {
+  case CPU_RIOS1:
+    return 3;       /* ? */
+  case CPU_RIOS2:
+    return 4;
+  case CPU_PPC601:
+    return 3;       /* ? */
+  case CPU_PPC602:
+    return 1; 
+  case CPU_PPC603:
+    return 2; 
+  case CPU_PPC604:
+    return 4;
+  case CPU_PPC620:
+    return 4;
+  default:
+    return 1;
+  }
+}
+
+\f
+/* Output insns to flush the {data|instruction} caches after building a
+   trampoline. */
+
+static void
+rs6000_sync_trampoline (addr)
+     rtx addr;
+{
+  enum machine_mode pmode = Pmode;
+  rtx reg = gen_reg_rtx (pmode);
+  rtx mem2;
+  rtx mem1;
+  int size = rs6000_trampoline_size ();
+  rtx (*sub_fcn) PROTO ((rtx, rtx, rtx));
+  rtx (*cmp_fcn) PROTO ((rtx, rtx));
+  rtx label;
+
+  if (TARGET_64BIT)
+    {
+      abort ();                        /* no cmpdi function yet */
+    }
+  else
+    {
+      sub_fcn = gen_subsi3;
+      cmp_fcn = gen_cmpsi;
+    }
+
+  addr = force_reg (pmode, addr);
+  mem2 = gen_rtx (MEM, pmode, gen_rtx (PLUS, pmode, addr, reg));
+  mem1 = gen_rtx (MEM, pmode, addr);
+
+  /* Issue a loop of dcbst's to flush the data cache */
+  emit_move_insn (reg, GEN_INT (size-4));
+  label = gen_label_rtx ();
+  emit_label (label);
+  emit_insn (gen_dcbst (mem2, addr, reg));
+  emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4)));
+  emit_insn ((*cmp_fcn) (reg, const0_rtx));
+  emit_jump_insn (gen_bgt (label));
+
+  /* Issue a sync after the dcbst's to let things settle down */
+  emit_insn (gen_sync (mem1));
+
+  /* Issue a loop of icbi's to flush the instruction cache */
+  emit_move_insn (reg, GEN_INT (size-4));
+  label = gen_label_rtx ();
+  emit_label (label);
+  emit_insn (gen_icbi (mem2, addr, reg));
+  emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4)));
+  emit_insn ((*cmp_fcn) (reg, const0_rtx));
+  emit_jump_insn (gen_bgt (label));
+
+  /* Issue a sync after the icbi's to let things settle down */
+  emit_insn (gen_sync (mem1));
+
+  /* Finally issue an isync to synchronize the icache */
+  emit_insn (gen_isync (mem1));
+}
+
+\f
+/* Output assembler code for a block containing the constant parts
+   of a trampoline, leaving space for the variable parts.
+
+   The trampoline should set the static chain pointer to value placed
+   into the trampoline and should branch to the specified routine.  */
+
+void
+rs6000_trampoline_template (file)
+     FILE *file;
+{
+  char *sc = reg_names[STATIC_CHAIN_REGNUM];
+  char *r0 = reg_names[0];
+
+  switch (DEFAULT_ABI)
+    {
+    default:
+      abort ();
+
+    /* Under AIX, this is not code at all, but merely a data area,
+       since that is the way all functions are called.  The first word is
+       the address of the function, the second word is the TOC pointer (r2),
+       and the third word is the static chain value.  */
+    case ABI_AIX:
+      fprintf (file, "\t.long %s\n", (TARGET_64BIT) ? "0,0,0,0,0,0" : "0,0,0");
+      break;
+
+
+    /* V.4/eabi function pointers are just a single pointer, so we need to
+       do the full gory code to load up the static chain.  */
+    case ABI_V4:
+    case ABI_AIX_NODESC:
+      if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS)
+       abort ();
+
+      if (TARGET_64BIT)
+       {
+         fprintf (file, "\tmflr %s\n", r0);            /* offset  0 */
+         fprintf (file, "\tbl .LTRAMP1\n");            /* offset  4 */
+         fprintf (file, "\t.long 0,0,0,0\n");          /* offset  8 */
+         fprintf (file, ".LTRAMP1:\n");
+         fprintf (file, "\tmflr %s\n", sc);            /* offset 28 */
+         fprintf (file, "\tmtlr %s\n", r0);            /* offset 32 */
+         fprintf (file, "\tld %s,0(%s)\n", r0, sc);    /* offset 36 */
+         fprintf (file, "\tld %s,8(%s)\n", sc, sc);    /* offset 40 */
+         fprintf (file, "\tmtctr %s\n", r0);           /* offset 44 */
+         fprintf (file, "\tbctr\n");                   /* offset 48 */
+       }
+      else
+       {
+         fprintf (file, "\tmflr %s\n", r0);            /* offset  0 */
+         fprintf (file, "\tbl .LTRAMP1\n");            /* offset  4 */
+         fprintf (file, "\t.long 0,0\n");              /* offset  8 */
+         fprintf (file, ".LTRAMP1:\n");
+         fprintf (file, "\tmflr %s\n", sc);            /* offset 20 */
+         fprintf (file, "\tmtlr %s\n", r0);            /* offset 24 */
+         fprintf (file, "\tlwz %s,0(%s)\n", r0, sc);   /* offset 28 */
+         fprintf (file, "\tlwz %s,4(%s)\n", sc, sc);   /* offset 32 */
+         fprintf (file, "\tmtctr %s\n", r0);           /* offset 36 */
+         fprintf (file, "\tbctr\n");                   /* offset 40 */
+       }
+      break;
+
+  /* NT function pointers point to a two word area (real address, TOC)
+     which unfortunately does not include a static chain field.  So we
+     need to have a 2 word area followed by the code to load up the
+     static chain.  */
+    case ABI_NT:
+      if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS || TARGET_64BIT)
+       abort ();
+
+      fprintf (file, "\t.ualong 0,0\n");               /* offset  0 */
+      fprintf (file, "\tmflr %s\n", r0);               /* offset  8 */
+      fprintf (file, "\tbl .LTRAMP1\n");               /* offset 12 */
+      fprintf (file, "\t.ualong 0,0\n");               /* offset 16 */
+      fprintf (file, ".LTRAMP1:\n");
+      fprintf (file, "\tmflr %s\n", sc);               /* offset 28 */
+      fprintf (file, "\tmtlr %s\n", r0);               /* offset 32 */
+      fprintf (file, "\tlwz %s,0(%s)\n", r0, sc);      /* offset 36 */
+      fprintf (file, "\tlwz %s,4(%s)\n", sc, sc);      /* offset 40 */
+      fprintf (file, "\tmtctr %s\n", r0);              /* offset 44 */
+      fprintf (file, "\tbctr\n");                      /* offset 48 */
+      break;
+    }
+
+  return;
+}
+
+/* Length in units of the trampoline for entering a nested function.  */
+
+int
+rs6000_trampoline_size ()
+{
+  int ret = 0;
+
+  switch (DEFAULT_ABI)
+    {
+    default:
+      abort ();
+
+    case ABI_AIX:
+      ret = (TARGET_64BIT) ? 24 : 12;
+      break;
+
+    case ABI_V4:
+    case ABI_AIX_NODESC:
+      ret = (TARGET_64BIT ? 48 : 40);
+      break;
+
+    case ABI_NT:
+      ret = 52;
+      break;
+    }
+
+  return ret;
+}
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+   FNADDR is an RTX for the address of the function's pure code.
+   CXT is an RTX for the static chain value for the function.  */
+
+void
+rs6000_initialize_trampoline (addr, fnaddr, cxt)
+     rtx addr;
+     rtx fnaddr;
+     rtx cxt;
+{
+  rtx reg, reg2, reg3;
+
+  switch (DEFAULT_ABI)
+    {
+    default:
+      abort ();
+
+    /* Under AIX, just build the 3 word function descriptor */
+    case ABI_AIX:
+      emit_move_insn (gen_rtx (MEM, SImode,
+                              memory_address (SImode, (addr))),
+                     gen_rtx (MEM, SImode,
+                              memory_address (SImode, (fnaddr))));
+      emit_move_insn (gen_rtx (MEM, SImode,
+                              memory_address (SImode,
+                                              plus_constant ((addr), 4))),
+                     gen_rtx (MEM, SImode,
+                              memory_address (SImode,
+                                              plus_constant ((fnaddr), 4))));
+      emit_move_insn (gen_rtx (MEM, SImode,
+                              memory_address (SImode,
+                                              plus_constant ((addr), 8))),
+                     force_reg (SImode, (cxt)));
+      break;
+
+    /* Under V.4/eabi, update the two words after the bl to have the real
+       function address and the static chain.  */
+    case ABI_V4:
+    case ABI_AIX_NODESC:
+      reg = gen_reg_rtx (Pmode);
+
+      emit_move_insn (reg, fnaddr);
+      emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 8)), reg);
+      emit_move_insn (gen_rtx (MEM, Pmode,
+                              plus_constant (addr, (TARGET_64BIT ? 16 : 12))),
+                     cxt);
+
+      rs6000_sync_trampoline (addr);
+      break;
+
+    /* Under NT, update the first 2 words to look like a normal descriptor, and
+       then fill in the fields with the function address and static chain after
+       the bl instruction.  */
+    case ABI_NT:
+      reg  = gen_reg_rtx (Pmode);
+      reg2 = gen_reg_rtx (Pmode);
+      reg3 = gen_reg_rtx (Pmode);
+
+      emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 4)),
+                     gen_rtx (REG, Pmode, 2));
+      emit_move_insn (reg, fnaddr);
+      emit_move_insn (reg2, gen_rtx (MEM, Pmode, reg));
+      emit_move_insn (reg3, plus_constant (addr, 8));
+      emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 16)), reg);
+      emit_move_insn (gen_rtx (MEM, Pmode, addr), reg3);
+      emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 20)), cxt);
+      rs6000_sync_trampoline (addr);
+      break;
+    }
+
+  return;
+}
index 7cb08fe..f52a381 100644 (file)
@@ -63,8 +63,11 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
 
 /* Define the options for the binder: Start text at 512, align all segments
    to 512 bytes, and warn if there is text relocation.
@@ -80,9 +83,15 @@ Boston, MA 02111-1307, USA.  */
    that to actually build a shared library you will also need to specify an
    export list with the -Wl,-bE option.  */
 
+#ifndef CROSS_COMPILE
+#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
+   %{static:-bnso} \
+   %{shared:-bM:SRE}"
+#else
 #define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
    %{static:-bnso -bI:/lib/syscalls.exp} \
    %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
+#endif
 
 /* Profiled library versions are used by linking with special directories.  */
 #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
@@ -187,6 +196,25 @@ extern int target_flags;
 #define        TARGET_TOC              1
 #endif
 
+/* Pseudo target to say whether this is Windows NT */
+#ifndef        TARGET_WINDOWS_NT
+#define        TARGET_WINDOWS_NT 0
+#endif
+
+/* Pseudo target to say whether this is MAC */
+#ifndef        TARGET_MACOS
+#define        TARGET_MACOS 0
+#endif
+
+/* Pseudo target to say whether this is AIX */
+#ifndef TARGET_AIX
+#if (TARGET_ELF || TARGET_WINDOWS_NT || TARGET_MACOS)
+#define TARGET_AIX 0
+#else
+#define TARGET_AIX 1
+#endif
+#endif
+
 /* Run-time compilation parameters selecting different hardware subsets.
 
    Macro to define tables used to set the flags.
@@ -246,6 +274,7 @@ enum processor_type
   PROCESSOR_RIOS2,
   PROCESSOR_PPC403,
   PROCESSOR_PPC601,
+  PROCESSOR_PPC602,
   PROCESSOR_PPC603,
   PROCESSOR_PPC604,
   PROCESSOR_PPC620};
@@ -256,7 +285,7 @@ extern enum processor_type rs6000_cpu;
 #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu)
 
 /* Define generic processor types based upon current deployment.  */
-#define PROCESSOR_COMMON  PROCESSOR_PPC601
+#define PROCESSOR_COMMON  PROCESSOR_PPC604
 #define PROCESSOR_POWER   PROCESSOR_RIOS1
 #define PROCESSOR_POWERPC PROCESSOR_PPC601
 
@@ -284,8 +313,16 @@ extern enum processor_type rs6000_cpu;
        extern char *m88k_short_data;
        #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } }  */
 
-#define TARGET_OPTIONS         \
-{ {"cpu=", &rs6000_cpu_string}}
+/* This is meant to be overriden in target specific files.  */
+#ifndef SUBTARGET_OPTIONS
+#define        SUBTARGET_OPTIONS
+#endif
+
+#define TARGET_OPTIONS                 \
+{                                      \
+   {"cpu=", &rs6000_cpu_string}                \
+   SUBTARGET_OPTIONS                   \
+}
 
 extern char *rs6000_cpu_string;
 
@@ -670,6 +707,9 @@ extern char *rs6000_cpu_string;
 /* Place to put static chain when calling a function that requires it.  */
 #define STATIC_CHAIN_REGNUM 11
 
+/* count register number for special purposes */
+#define COUNT_REGISTER_REGNUM 66
+
 /* Place that structure value return address is placed.
 
    On the RS/6000, it is passed as an extra parameter.  */
@@ -802,12 +842,16 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
 
 /* Optional extra constraints for this machine.
 
-   For the RS/6000, `Q' means that this is a memory operand that is just
-   an offset from a register.  */
+   'Q' means that is a memory operand that is just an offset from a reg.
+   'R' is for AIX TOC entries.
+   'S' is for Windows NT SYMBOL_REFs
+   'T' is for Windows NT LABEL_REFs.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                                \
   ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
    : (C) == 'R' ? LEGITIMATE_CONSTANT_POOL_ADDRESS_P (OP)              \
+   : (C) == 'S' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == SYMBOL_REF)\
+   : (C) == 'T' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == LABEL_REF) \
    : 0)
 
 /* Given an rtx X being reloaded into a reg required to be
@@ -857,32 +901,49 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
 enum rs6000_abi {
   ABI_NONE,
   ABI_AIX,                     /* IBM's AIX */
-  ABI_V4                       /* System V.4/eabi */
+  ABI_AIX_NODESC,              /* AIX calling sequence minus function descriptors */
+  ABI_V4,                      /* System V.4/eabi */
+  ABI_NT                       /* Windows/NT */
 };
 
+extern enum rs6000_abi rs6000_current_abi;     /* available for use by subtarget */
+
+/* Default ABI to compile code for */
+#ifndef DEFAULT_ABI
+#define DEFAULT_ABI ABI_AIX
+#endif
+
 /* Structure used to define the rs6000 stack */
 typedef struct rs6000_stack {
   int first_gp_reg_save;       /* first callee saved GP register used */
   int first_fp_reg_save;       /* first callee saved FP register used */
   int lr_save_p;               /* true if the link reg needs to be saved */
   int cr_save_p;               /* true if the CR reg needs to be saved */
+  int toc_save_p;              /* true if the TOC needs to be saved */
   int push_p;                  /* true if we need to allocate stack space */
   int calls_p;                 /* true if the function makes any calls */
+  int main_p;                  /* true if this is main */
+  int main_save_p;             /* true if this is main and we need to save args */
   enum rs6000_abi abi;         /* which ABI to use */
   int gp_save_offset;          /* offset to save GP regs from initial SP */
   int fp_save_offset;          /* offset to save FP regs from initial SP */
   int lr_save_offset;          /* offset to save LR from initial SP */
   int cr_save_offset;          /* offset to save CR from initial SP */
+  int toc_save_offset;         /* offset to save the TOC pointer */
   int varargs_save_offset;     /* offset to save the varargs registers */
+  int main_save_offset;                /* offset to save main's args */
   int reg_size;                        /* register size (4 or 8) */
   int varargs_size;            /* size to hold V.4 args passed in regs */
   int vars_size;               /* variable save area size */
   int parm_size;               /* outgoing parameter size */
+  int main_size;               /* size to hold saving main's args */
   int save_size;               /* save area size */
   int fixed_size;              /* fixed size of stack frame */
   int gp_size;                 /* size of saved GP registers */
   int fp_size;                 /* size of saved FP registers */
   int cr_size;                 /* size to hold CR if not in save_size */
+  int lr_size;                 /* size to hold LR if not in save_size */
+  int toc_size;                        /* size to hold TOC if not in save_size */
   int total_size;              /* total bytes allocated for stack */
 } rs6000_stack_t;
 
@@ -905,6 +966,12 @@ typedef struct rs6000_stack {
 /* Size of the fixed area on the stack */
 #define RS6000_SAVE_AREA (TARGET_64BIT ? 48 : 24)
 
+/* Address to save the TOC register */
+#define RS6000_SAVE_TOC plus_constant (stack_pointer_rtx, 20)
+
+/* Whether a separate TOC save area is needed */
+extern int rs6000_save_toc_p;
+
 /* Size of the V.4 varargs area if needed */
 #define RS6000_VARARGS_AREA 0
 
@@ -1130,6 +1197,13 @@ typedef struct rs6000_args
 #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
   function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED)
 
+/* If defined, a C expression that gives the alignment boundary, in bits,
+   of an argument with the specified mode and type.  If it is not defined, 
+   PARM_BOUNDARY is used for all arguments.  */
+
+#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
+  function_arg_boundary (MODE, TYPE)
+
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments. 
 
@@ -1202,40 +1276,19 @@ typedef struct rs6000_args
    of a trampoline, leaving space for the variable parts.
 
    The trampoline should set the static chain pointer to value placed
-   into the trampoline and should branch to the specified routine.
-
-   On the RS/6000, this is not code at all, but merely a data area,
-   since that is the way all functions are called.  The first word is
-   the address of the function, the second word is the TOC pointer (r2),
-   and the third word is the static chain value.  */
-
-#define TRAMPOLINE_TEMPLATE(FILE) { fprintf (FILE, "\t.long 0, 0, 0\n"); }
+   into the trampoline and should branch to the specified routine.  */
+#define TRAMPOLINE_TEMPLATE(FILE) rs6000_trampoline_template (FILE)
 
 /* Length in units of the trampoline for entering a nested function.  */
 
-#define TRAMPOLINE_SIZE    12
+#define TRAMPOLINE_SIZE rs6000_trampoline_size ()
 
 /* Emit RTL insns to initialize the variable parts of a trampoline.
    FNADDR is an RTX for the address of the function's pure code.
    CXT is an RTX for the static chain value for the function.  */
 
 #define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT)               \
-{                                                              \
-  emit_move_insn (gen_rtx (MEM, SImode,                                \
-                          memory_address (SImode, (ADDR))),    \
-                 gen_rtx (MEM, SImode,                         \
-                          memory_address (SImode, (FNADDR)))); \
-  emit_move_insn (gen_rtx (MEM, SImode,                                \
-                          memory_address (SImode,              \
-                                          plus_constant ((ADDR), 4))), \
-                 gen_rtx (MEM, SImode,                         \
-                          memory_address (SImode,              \
-                                          plus_constant ((FNADDR), 4)))); \
-  emit_move_insn (gen_rtx (MEM, SImode,                                \
-                          memory_address (SImode,              \
-                                          plus_constant ((ADDR), 8))), \
-                 force_reg (SImode, (CXT)));                   \
-}
+  rs6000_initialize_trampoline (ADDR, FNADDR, CXT)
 \f
 /* Definitions for __builtin_return_address and __builtin_frame_address.
    __builtin_return_address (0) should give link register (65), enable
@@ -1247,13 +1300,15 @@ typedef struct rs6000_args
    (mrs) */
 /* #define RETURN_ADDR_IN_PREVIOUS_FRAME */
 
-/* Number of bytes into the frame return addresses can be found.  */
-#ifndef TARGET_V4_CALLS
-#define RETURN_ADDRESS_OFFSET 8
-#else
-#define RETURN_ADDRESS_OFFSET \
- ((TARGET_V4_CALLS) ?  (TARGET_64BIT ? 8 : 4) : 8)
-#endif
+/* Number of bytes into the frame return addresses can be found.  See
+   rs6000_stack_info in rs6000.c for more information on how the different
+   abi's store the return address.  */
+#define RETURN_ADDRESS_OFFSET                                          \
+ ((DEFAULT_ABI == ABI_AIX                                              \
+   || DEFAULT_ABI == ABI_AIX_NODESC)   ? 8 :                           \
+  (DEFAULT_ABI == ABI_V4)              ? (TARGET_64BIT ? 8 : 4) :      \
+  (DEFAULT_ABI == ABI_NT)              ? -4 :                          \
+  (fatal ("RETURN_ADDRESS_OFFSET not supported"), 0))
 
 /* The current return address is in link register (65).  The return address
    of anything farther back is accessed normally at an offset of 8 from the
@@ -1638,8 +1693,13 @@ typedef struct rs6000_args
    .stabs in cc1plus.  */
    
 #define FASCIST_ASSEMBLER
+
+#ifndef ASM_OUTPUT_CONSTRUCTOR
 #define ASM_OUTPUT_CONSTRUCTOR(file, name)
+#endif
+#ifndef ASM_OUTPUT_DESTRUCTOR
 #define ASM_OUTPUT_DESTRUCTOR(file, name)
+#endif
 
 /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
    is done just by pretending it is already truncated.  */
@@ -2106,19 +2166,17 @@ toc_section ()                                          \
   do                                                                   \
     {                                                                  \
       char *_name = (NAME);                                            \
+      int _len;                                                                \
       if (_name[0] == '*')                                             \
-       (VAR) = _name+1;                                                \
+       _name++;                                                        \
+      _len = strlen (_name);                                           \
+      if (_name[_len - 1] != ']')                                      \
+       (VAR) = _name;                                                  \
       else                                                             \
        {                                                               \
-         int _len = strlen (_name);                                    \
-         if (_name[_len - 1] != ']')                                   \
-           (VAR) = _name;                                              \
-         else                                                          \
-           {                                                           \
-             (VAR) = (char *) alloca (_len + 1);                       \
-             strcpy ((VAR), _name);                                    \
-             (VAR)[_len - 4] = '\0';                                   \
-           }                                                           \
+         (VAR) = (char *) alloca (_len + 1);                           \
+         strcpy ((VAR), _name);                                        \
+         (VAR)[_len - 4] = '\0';                                       \
        }                                                               \
     }                                                                  \
   while (0)
@@ -2468,6 +2526,7 @@ do {                                                                      \
   {"easy_fp_constant", {CONST_DOUBLE}},                                \
   {"reg_or_mem_operand", {SUBREG, MEM, REG}},                  \
   {"lwa_operand", {SUBREG, MEM, REG}},                         \
+  {"volatile_mem_operand", {MEM}},                             \
   {"offsettable_addr_operand", {REG, SUBREG, PLUS}},           \
   {"fp_reg_or_mem_operand", {SUBREG, MEM, REG}},               \
   {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}},  \
@@ -2478,6 +2537,7 @@ do {                                                                      \
   {"logical_operand", {SUBREG, REG, CONST_INT}},               \
   {"non_logical_cint_operand", {CONST_INT}},                   \
   {"mask_operand", {CONST_INT}},                               \
+  {"count_register_operand", {REG}},                           \
   {"call_operand", {SYMBOL_REF, REG}},                         \
   {"current_file_function_operand", {SYMBOL_REF}},             \
   {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}},        \
@@ -2488,6 +2548,16 @@ do {                                                                     \
   {"scc_comparison_operator", {EQ, NE, LE, LT, GE,             \
                               GT, LEU, LTU, GEU, GTU}},
 
+
+/* uncomment for disabling the corresponding default options */
+/* #define  MACHINE_no_sched_interblock */
+/* #define  MACHINE_no_sched_speculative */
+/* #define  MACHINE_no_sched_speculative_load */
+
+/* indicate that issue rate is defined for this machine
+   (no need to use the default) */
+#define MACHINE_issue_rate
+
 /* Declare functions in rs6000.c */
 extern void output_options ();
 extern void rs6000_override_options ();
@@ -2524,6 +2594,7 @@ extern int current_file_function_operand ();
 extern int input_operand ();
 extern void init_cumulative_args ();
 extern void function_arg_advance ();
+extern int function_arg_boundary ();
 extern struct rtx_def *function_arg ();
 extern int function_arg_partial_nregs ();
 extern int function_arg_pass_by_reference ();
@@ -2555,3 +2626,6 @@ extern void output_ascii ();
 extern void rs6000_gen_section_name ();
 extern void output_function_profiler ();
 extern int rs6000_adjust_cost ();
+extern void rs6000_trampoline_template ();
+extern int rs6000_trampoline_size ();
+extern void rs6000_initialize_trampoline ();
index 3a975ab..3a46ecc 100644 (file)
@@ -40,7 +40,7 @@
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,ppc403,ppc601,ppc603,ppc604,ppc620"
+(define_attr "cpu" "rios1,rios2,ppc403,ppc601,ppc602,ppc603,ppc604,ppc620"
   (const (symbol_ref "rs6000_cpu_attr")))
 
 ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
 ; (POWER and 601 use Integer Unit)
 (define_function_unit "lsu" 1 0
   (and (eq_attr "type" "load")
-       (eq_attr "cpu" "rios2,ppc603,ppc604,ppc620"))
-  2 0)
+       (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620"))
+  2 1)
 
 (define_function_unit "lsu" 1 0
   (and (eq_attr "type" "fpload")
-       (eq_attr "cpu" "rios2,ppc603,ppc604,ppc620"))
-  2 0)
+       (eq_attr "cpu" "ppc604,ppc620"))
+  3 1)
+
+(define_function_unit "lsu" 1 0
+  (and (eq_attr "type" "fpload")
+       (eq_attr "cpu" "ppc602,ppc603"))
+  2 1)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "load")
-       (eq_attr "cpu" "rios1,ppc403,ppc601"))
-  2 0)
+       (eq_attr "cpu" "rios1,ppc601"))
+  2 1)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "fpload")
        (eq_attr "cpu" "rios1,ppc601"))
-  3 0)
+  2 0)
 
 ; Integer Unit (RIOS1, PPC601, PPC603)
 ; Trivial operations take one cycle which need not be listed here.
 (define_function_unit "iu" 1 0
-  (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "rios1"))
-  3 3)
+  (and (eq_attr "type" "integer")
+       (eq_attr "cpu" "rios1,ppc601"))
+  1 1)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "ppc403"))
-  4 4)
+       (eq_attr "cpu" "rios1"))
+  3 3)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "ppc601,ppc603"))
+       (eq_attr "cpu" "ppc601,ppc602,ppc603"))
   5 5)
 
 (define_function_unit "iu" 1 0
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "ppc403"))
-  33 33)
-
-(define_function_unit "iu" 1 0
-  (and (eq_attr "type" "idiv")
        (eq_attr "cpu" "ppc601"))
   36 36)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "ppc603"))
+       (eq_attr "cpu" "ppc602,ppc603"))
   37 36)
 
 ; RIOS2 has two integer units: a primary one which can perform all
 ; operations and a secondary one which is fed in lock step with the first
-; and can perform "simple" integer operations.
+; and can perform "simple" integer operations.  
+; To catch this we define a 'dummy' imuldiv-unit that is also needed
+; for the complex insns. 
 (define_function_unit "iu2" 2 0
   (and (eq_attr "type" "integer")
        (eq_attr "cpu" "rios2"))
-  1 0
-  [(eq_attr "type" "imul,idiv")])
+  1 0)
+
+(define_function_unit "iu2" 2 0
+  (and (eq_attr "type" "imul")
+       (eq_attr "cpu" "rios2"))
+  2 2)
+
+(define_function_unit "iu2" 2 0
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "rios2"))
+  13 13)
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "imul")
        (eq_attr "cpu" "rios2"))
-  2 2
-  [(eq_attr "type" "integer")])
+  2 2)
+
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "idiv")
        (eq_attr "cpu" "rios2"))
-  13 13
-  [(eq_attr "type" "integer")])
+  13 13)
 
-; PPC604 has three integer units: one primary and two secondary.
-(define_function_unit "iu3" 3 0
+; PPC604 has two units that perform integer operations
+; and one unit for divide/multiply operations (and move
+; from/to spr).
+(define_function_unit "iu2" 2 0
   (and (eq_attr "type" "integer")
        (eq_attr "cpu" "ppc604,ppc620"))
-  1 0
+  1 1
   [(eq_attr "type" "imul,idiv")])
 
 (define_function_unit "imuldiv" 1 0
   20 19
   [(eq_attr "type" "integer")])
 
-; Branch Processing Unit
-(define_function_unit "bpu" 1 0
-  (eq_attr "type" "compare")
-  4 0)
+; compare is done on integer unit, but feeds insns which
+; execute on the branch unit.  Ready-delay of the compare 
+; on the branch unit is large (3-5 cycles).  On the iu/fpu
+; it is 1.  One drawback is that the compare will also be 
+; assigned to the bpu, but this inaccuracy is worth for being
+; able to fill the compare-branch delay, with insns on iu/fpu.
+(define_function_unit "iu" 1 0   
+  (and (eq_attr "type" "compare")
+       (eq_attr "cpu" "rios1,ppc601"))
+  1 1)
+
+(define_function_unit "iu2" 2 0   
+  (and (eq_attr "type" "compare")
+       (eq_attr "cpu" "rios2"))
+  1 1)
+
+(define_function_unit "bpu" 1 0   
+  (and (eq_attr "type" "compare")
+       (eq_attr "cpu" "rios1,rios2,ppc601"))
+  4 1)
+
+; different machines have different compare timings
+; in ppc604, compare is done on the one of the two
+; main integer units.
+(define_function_unit "iu2" 2 0
+  (and (eq_attr "type" "compare")
+       (eq_attr "cpu" "ppc604,ppc620"))
+  1 1)
 
 (define_function_unit "bpu" 1 0
   (eq_attr "type" "delayed_compare")
   5 0)
 
-(define_function_unit "bpu" 1 0
+; fp compare uses fp unit
+(define_function_unit "fpu" 1 0
   (and (eq_attr "type" "fpcompare")
-       (eq_attr "cpu" "rios1,rios2"))
-  8 0)
+       (eq_attr "cpu" "rios1"))
+  8 1)
 
-(define_function_unit "bpu" 1 0
+; rios1 and rios2 have different fpcompare delays
+(define_function_unit "fpu2" 2 0
   (and (eq_attr "type" "fpcompare")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  4 0)
+       (eq_attr "cpu" "rios2"))
+  5 1)
+
+; on ppc601 and ppc603, fpcompare takes also 2 cycles from
+; the integer unit
+; here we do not define delays, just occupy the unit. The dependencies
+; will be signed by the fpcompare definition in the fpu.
+(define_function_unit "iu" 1 0
+  (and (eq_attr "type" "fpcompare")
+       (eq_attr "cpu" "ppc601,ppc602,ppc603"))
+  0 2)
+
+; fp compare uses fp unit
+(define_function_unit "fpu" 1 0
+  (and (eq_attr "type" "fpcompare")
+       (eq_attr "cpu" "ppc601,ppc602,ppc603,ppc604,ppc620"))
+  5 1)
 
 (define_function_unit "bpu" 1 0
   (and (eq_attr "type" "mtjmpr")
 
 (define_function_unit "bpu" 1 0
   (and (eq_attr "type" "mtjmpr")
-       (eq_attr "cpu" "ppc403,ppc601,ppc603,ppc604,ppc620"))
+       (eq_attr "cpu" "ppc601,ppc602,ppc603,ppc604,ppc620"))
   4 0)
 
+; all jumps/branches are executing on the bpu, in 1 cycle, for all machines.
+(define_function_unit "bpu" 1 0
+  (eq_attr "type" "jmpreg")
+  1 0)
+
+(define_function_unit "bpu" 1 0
+  (eq_attr "type" "branch")
+  1 0)
+
 ; Floating Point Unit (RIOS1, PPC601, PPC603, PPC604).
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "fp,dmul")
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "fp")
-       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
-  3 0)
+       (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620"))
+  3 1)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dmul")
        (eq_attr "cpu" "ppc601"))
-  5 5)
+  5 2)
 
+; is this true?
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dmul")
-       (eq_attr "cpu" "ppc603"))
+       (eq_attr "cpu" "ppc602,ppc603"))
   4 2)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dmul")
        (eq_attr "cpu" "ppc604,ppc620"))
-  3 0)
+  3 1)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "sdiv,ddiv")
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "sdiv")
-       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
+       (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620"))
   18 18)
 
 (define_function_unit "fpu" 1 0
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "ddiv")
-       (eq_attr "cpu" "ppc603"))
+       (eq_attr "cpu" "ppc602,ppc603"))
   33 33)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "ssqrt,dsqrt")
        (eq_attr "cpu" "rios2"))
   26 26)
+
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
   if (GET_CODE (operands[2]) == CONST_INT
       && exact_log2 (INTVAL (operands[2])) >= 0)
     ;
-  else if (TARGET_POWER && ! TARGET_POWERPC)
+  else if (TARGET_POWERPC)
+    operands[2] = force_reg (SImode, operands[2]);
+  else if (TARGET_POWER)
     FAIL;
   else
-    operands[2] = force_reg (SImode, operands[2]);
-
-  if (! TARGET_POWER && ! TARGET_POWERPC)
     {
       emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
       emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
       rtx target = (reload_completed || reload_in_progress)
                        ? operands[0] : gen_reg_rtx (SImode);
 
+      /* If this is a function address on -mcall-aixdesc or -mcall-nt,
+        convert it to the address of the descriptor.  */
+      if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
+         && GET_CODE (operands[1]) == SYMBOL_REF
+         && XSTR (operands[1], 0)[0] == '.')
+       {
+         char *name = XSTR (operands[1], 0);
+         rtx new_ref;
+         while (*name == '.')
+           name++;
+         new_ref = gen_rtx (SYMBOL_REF, Pmode, name);
+         CONSTANT_POOL_ADDRESS_P (new_ref) = CONSTANT_POOL_ADDRESS_P (operands[1]);
+         SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
+         SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
+         operands[1] = new_ref;
+       }
+
       emit_insn (gen_elf_high (target, operands[1]));
       emit_insn (gen_elf_low (operands[0], target, operands[1]));
       DONE;
     }
 
-  if (CONSTANT_P (operands[1])
+  if (GET_CODE (operands[1]) == CONST
+      && DEFAULT_ABI == ABI_NT
+      && !side_effects_p (operands[0]))
+    {
+      rtx const_term = const0_rtx;
+      rtx sym = eliminate_constant_term (XEXP (operands[1], 0), &const_term);
+      if (sym && GET_CODE (const_term) == CONST_INT
+         && (GET_CODE (sym) == SYMBOL_REF || GET_CODE (sym) == LABEL_REF))
+       {
+         emit_insn (gen_movsi (operands[0], sym));
+         if (INTVAL (const_term) != 0)
+           {
+             unsigned HOST_WIDE_INT value = INTVAL (const_term);
+             if (value + 0x8000 < 0x10000)
+               emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (value)));
+             else
+               {
+                 emit_insn (gen_addsi3 (operands[0], operands[0],
+                                        GEN_INT ((value >> 16) + ((value >> 15) & 1))));
+
+                 if ((value & 0xffff) != 0)
+                   emit_insn (gen_addsi3 (operands[0], operands[0],
+                                          GEN_INT (value & 0xffff)));
+               }
+           }
+         DONE;
+       }
+      else
+       fatal_insn (\"bad address\", operands[1]);
+    }
+
+  if ((!TARGET_WINDOWS_NT || DEFAULT_ABI != ABI_NT)
+      && CONSTANT_P (operands[1])
       && GET_CODE (operands[1]) != CONST_INT
       && GET_CODE (operands[1]) != HIGH
       && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1]))
 }")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*q,*c*l,*h")
-       (match_operand:SI 1 "input_operand" "r,m,r,I,J,R,*h,r,r,0"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,r,r,r,r,*q,*c*l,*h")
+       (match_operand:SI 1 "input_operand" "r,S,T,m,r,I,J,R,*h,r,r,0"))]
   "gpc_reg_operand (operands[0], SImode)
    || gpc_reg_operand (operands[1], SImode)"
   "@
    mr %0,%1
+   {l|lwz} %0,[toc]%1(2)
+   {l|lwz} %0,[toc]%l1(2)
    {l%U1%X1|lwz%U1%X1} %0,%1
    {st%U0%X0|stw%U0%X0} %1,%0
    {lil|li} %0,%1
    mt%0 %1
    mt%0 %1
    cror 0,0,0"
-  [(set_attr "type" "*,load,*,*,*,*,*,*,mtjmpr,*")])
+  [(set_attr "type" "*,load,load,load,*,*,*,*,*,*,mtjmpr,*")])
 
 ;; Split a load of a large constant into the appropriate two-insn
 ;; sequence.
 ;; Argument 3 is the alignment
 
 (define_expand "movstrsi"
-  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
-                  (match_operand:BLK 1 "memory_operand" ""))
-             (use (match_operand:SI 2 "general_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))])]
+  [(parallel [(set (match_operand:BLK 0 "" "")
+                  (match_operand:BLK 1 "" ""))
+             (use (match_operand:SI 2 "" ""))
+             (use (match_operand:SI 3 "" ""))])]
   ""
   "
 {
 ;; Move up to 32 bytes at a time.  The fixed registers are needed because the
 ;; register allocator doesn't have a clue about allocating 8 word registers
 (define_expand "movstrsi_8reg"
-  [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" ""))
-                  (mem:BLK (match_operand:SI 1 "register_operand" "")))
-             (use (match_operand:SI 2 "immediate_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))
+  [(parallel [(set (match_operand 0 "" "")
+                  (match_operand 1 "" ""))
+             (use (match_operand 2 "" ""))
+             (use (match_operand 3 "" ""))
              (clobber (reg:SI  5))
              (clobber (reg:SI  6))
              (clobber (reg:SI  7))
 ;; Move up to 24 bytes at a time.  The fixed registers are needed because the
 ;; register allocator doesn't have a clue about allocating 6 word registers
 (define_expand "movstrsi_6reg"
-  [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" ""))
-                  (mem:BLK (match_operand:SI 1 "register_operand" "")))
-             (use (match_operand:SI 2 "immediate_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))
+  [(parallel [(set (match_operand 0 "" "")
+                  (match_operand 1 "" ""))
+             (use (match_operand 2 "" ""))
+             (use (match_operand 3 "" ""))
              (clobber (reg:SI  7))
              (clobber (reg:SI  8))
              (clobber (reg:SI  9))
 ;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill problems
 ;; with TImode
 (define_expand "movstrsi_4reg"
-  [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" ""))
-                  (mem:BLK (match_operand:SI 1 "register_operand" "")))
-             (use (match_operand:SI 2 "immediate_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))
+  [(parallel [(set (match_operand 0 "" "")
+                  (match_operand 1 "" ""))
+             (use (match_operand 2 "" ""))
+             (use (match_operand 3 "" ""))
              (clobber (reg:SI  9))
              (clobber (reg:SI 10))
              (clobber (reg:SI 11))
 
 ;; Move up to 8 bytes at a time.
 (define_expand "movstrsi_2reg"
-  [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" ""))
-                  (mem:BLK (match_operand:SI 1 "register_operand" "")))
-             (use (match_operand:SI 2 "immediate_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))
+  [(parallel [(set (match_operand 0 "" "")
+                  (match_operand 1 "" ""))
+             (use (match_operand 2 "" ""))
+             (use (match_operand 3 "" ""))
              (clobber (match_scratch:DI 4 ""))
              (clobber (match_scratch:SI 5 ""))])]
   "TARGET_STRING && !TARGET_64BIT"
 
 ;; Move up to 4 bytes at a time.
 (define_expand "movstrsi_1reg"
-  [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" ""))
-                  (mem:BLK (match_operand:SI 1 "register_operand" "")))
-             (use (match_operand:SI 2 "immediate_operand" ""))
-             (use (match_operand:SI 3 "immediate_operand" ""))
+  [(parallel [(set (match_operand 0 "" "")
+                  (match_operand 1 "" ""))
+             (use (match_operand 2 "" ""))
+             (use (match_operand 3 "" ""))
              (clobber (match_scratch:SI 4 ""))
              (clobber (match_scratch:SI 5 ""))])]
   "TARGET_STRING"
   DONE;
 }")
 \f
-;; A function pointer is a pointer to a data area whose first word contains
-;; the actual address of the function, whose second word contains a pointer
-;; to its TOC, and whose third word contains a value to place in the static
-;; chain register (r11).  Note that if we load the static chain, our
+
+;; A function pointer under AIX is a pointer to a data area whose first word
+;; contains the actual address of the function, whose second word contains a
+;; pointer to its TOC, and whose third word contains a value to place in the
+;; static chain register (r11).  Note that if we load the static chain, our
 ;; "trampoline" need not have any executable code.
 ;;
-;; operands[0] is an SImode pseudo in which we place the address of the
-;;            function.
-;; operands[1] is the address of data area of the function to call
+;; operands[0] is a register pointing to the 3 word descriptor (aka, the function address)
+;; operands[1] is the stack size to clean up
+;; operands[2] is the value FUNCTION_ARG returns for the VOID argument (must be 0 for AIX)
+;; operands[3] is location to store the TOC
+;; operands[4] is the TOC register
+;; operands[5] is the static chain register
+;;
+;; We do not break this into separate insns, so that the scheduler will not try
+;; to move the load of the new TOC before any loads from the TOC.
+
+(define_insn "call_indirect_aix"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
+        (match_operand 1 "const_int_operand" "n"))
+   (use (match_operand 2 "const_int_operand" "O"))
+   (use (match_operand 3 "offsettable_addr_operand" "p"))
+   (use (match_operand 4 "register_operand" "r"))
+   (clobber (match_operand 5 "register_operand" "=r"))
+   (clobber (match_scratch:SI 6 "=&r"))
+   (clobber (match_scratch:SI 7 "=l"))]
+  "DEFAULT_ABI == ABI_AIX"
+  "{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%7 %6\;{l|lwz} %5,8(%0)\;{brl|blrl}\;{l|lwz} %4,%a3"
+  [(set_attr "length" "28")])
+
+(define_insn "call_value_indirect_aix"
+  [(set (match_operand 0 "register_operand" "fg")
+       (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
+             (match_operand 2 "const_int_operand" "n")))
+   (use (match_operand 3 "const_int_operand" "O"))
+   (use (match_operand 4 "offsettable_addr_operand" "p"))
+   (use (match_operand 5 "register_operand" "r"))
+   (clobber (match_operand 6 "register_operand" "=r"))
+   (clobber (match_scratch:SI 7 "=&r"))
+   (clobber (match_scratch:SI 8 "=l"))]
+  "DEFAULT_ABI == ABI_AIX"
+  "{st|stw} %5,%a4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1);\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%a4"
+  [(set_attr "length" "28")])
+
+;; A function pointer undef NT is a pointer to a data area whose first word
+;; contains the actual address of the function, whose second word contains a
+;; pointer to its TOC.  The static chain is not stored under NT, which means
+;; that we need a trampoline.
+;;
+;; operands[0] is an SImode pseudo in which we place the address of the function.
+;; operands[1] is the stack size to clean up
+;; operands[2] is the value FUNCTION_ARG returns for the VOID argument (must be 0 for NT)
+;; operands[3] is location to store the TOC
+;; operands[4] is the TOC register
+;;
+;; We do not break this into separate insns, so that the scheduler will not try
+;; to move the load of the new TOC before any loads from the TOC.
+
+(define_insn "call_indirect_nt"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
+        (match_operand 1 "const_int_operand" "n"))
+   (use (match_operand 2 "const_int_operand" "O"))
+   (use (match_operand 3 "offsettable_addr_operand" "p"))
+   (use (match_operand 4 "register_operand" "r"))
+   (clobber (match_scratch:SI 5 "=&r"))
+   (clobber (match_scratch:SI 6 "=l"))]
+  "DEFAULT_ABI == ABI_NT"
+  "{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%6 %5\;{brl|blrl}\;{l|lwz} %4,%a3"
+  [(set_attr "length" "24")])
+
+(define_insn "call_value_indirect_nt"
+  [(set (match_operand 0 "register_operand" "fg")
+       (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
+             (match_operand 2 "const_int_operand" "n")))
+   (use (match_operand 3 "const_int_operand" "O"))
+   (use (match_operand 4 "offsettable_addr_operand" "p"))
+   (use (match_operand 5 "register_operand" "r"))
+   (clobber (match_scratch:SI 6 "=&r"))
+   (clobber (match_scratch:SI 7 "=l"))]
+  "DEFAULT_ABI == ABI_NT"
+  "{st|stw} %5,%a4\;{l|lwz} %6,0(%1)\;{l|lwz} %5,4(%1);\;mt%7 %6\;{brl|blrl}\;{l|lwz} %5,%a4"
+  [(set_attr "length" "24")])
+
+;; A function pointer under System V is just a normal pointer
+;; operands[0] is the function pointer
+;; operands[1] is the stack size to clean up
+;; operands[2] is the value FUNCTION_ARG returns for the VOID argument which indicates how to set cr1
+
+(define_insn "call_indirect_sysv"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "l,l"))
+        (match_operand 1 "const_int_operand" "n,n"))
+   (use (match_operand 2 "const_int_operand" "O,n"))
+   (clobber (match_scratch:SI 3 "=l,l"))]
+  "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC"
+  "*
+{
+  if (INTVAL (operands[2]) > 0)
+    return \"creqv 6,6,6\;{brl|blrl}\";
 
-(define_expand "call_via_ptr"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (mem:SI (match_operand:SI 1 "gpc_reg_operand" "")))
-   (set (mem:SI (plus:SI (reg:SI 1) (const_int 20)))
-       (reg:SI 2))
-   (set (reg:SI 2)
-       (mem:SI (plus:SI (match_dup 1)
-                        (const_int 4))))
-   (set (reg:SI 11)
-       (mem:SI (plus:SI (match_dup 1)
-                        (const_int 8))))
-   (use (reg:SI 2))
-   (use (reg:SI 11))]
-  ""
-  "")
+  else if (INTVAL (operands[2]) < 0)
+    return \"crxor 6,6,6\;{brl|blrl}\";
+
+  return \"{brl|blrl}\";
+}"
+  [(set_attr "length" "4,8")])
+
+(define_insn "call_value_indirect_sysv"
+  [(set (match_operand 0 "register_operand" "=fg,fg")
+       (call (mem:SI (match_operand:SI 1 "register_operand" "l,l"))
+             (match_operand 2 "const_int_operand" "n,n")))
+   (use (match_operand 3 "const_int_operand" "O,n"))
+   (clobber (match_scratch:SI 4 "=l,l"))]
+  "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC"
+  "*
+{
+  if (INTVAL (operands[3]) > 0)
+    return \"creqv 6,6,6\;{brl|blrl}\";
+
+  else if (INTVAL (operands[3]) < 0)
+    return \"crxor 6,6,6\;{brl|blrl}\";
+
+  return \"{brl|blrl}\";
+}"
+  [(set_attr "length" "4,8")])
 
+;; Now the definitions for the call and call_value insns
 (define_expand "call"
   [(parallel [(call (mem:SI (match_operand:SI 0 "address_operand" ""))
                    (match_operand 1 "" ""))
   operands[0] = XEXP (operands[0], 0);
   if (GET_CODE (operands[0]) != SYMBOL_REF)
     {
-#ifndef USING_SVR4_H
-      /* AIX function pointers are really pointers to a three word area */
-      rtx temp = gen_reg_rtx (SImode);
+      if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
+       emit_call_insn (gen_call_indirect_sysv (force_reg (Pmode, operands[0]),
+                                               operands[1], operands[2]));
+      else
+       {
+         rtx toc_reg = gen_rtx (REG, Pmode, 2);
+         rtx toc_addr = RS6000_SAVE_TOC;
 
-      emit_insn (gen_call_via_ptr (temp, force_reg (SImode, operands[0])));
-      operands[0] = temp;
-#endif /* !USING_SVR4_H */
+         if (DEFAULT_ABI == ABI_AIX)
+           {
+             /* AIX function pointers are really pointers to a three word area */
+             rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
+             emit_call_insn (gen_call_indirect_aix (force_reg (Pmode, operands[0]),
+                                                    operands[1], operands[2],
+                                                    toc_addr, toc_reg, static_chain));
+           }
+         else if (DEFAULT_ABI == ABI_NT)
+           {
+             /* NT function pointers are really pointers to a two word area */
+             emit_call_insn (gen_call_indirect_nt (force_reg (Pmode, operands[0]),
+                                                   operands[1], operands[2],
+                                                   toc_addr, toc_reg));
+           }
+         else
+           abort ();
+       }
+      DONE;
     }
 }")
 
   operands[1] = XEXP (operands[1], 0);
   if (GET_CODE (operands[1]) != SYMBOL_REF)
     {
-#ifndef USING_SVR4_H
-      /* AIX function pointers are really pointers to a three word area */
-      rtx temp = gen_reg_rtx (SImode);
+      if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
+       emit_call_insn (gen_call_value_indirect_sysv (operands[0], operands[1],
+                                                     operands[2], operands[3]));
+      else
+       {
+         rtx toc_reg = gen_rtx (REG, Pmode, 2);
+         rtx toc_addr = RS6000_SAVE_TOC;
 
-      emit_insn (gen_call_via_ptr (temp, force_reg (SImode, operands[1])));
-      operands[1] = temp;
-#endif /* !USING_SVR4_H */
+         if (DEFAULT_ABI == ABI_AIX)
+           {
+             /* AIX function pointers are really pointers to a three word area */
+             rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
+             emit_call_insn (gen_call_value_indirect_aix (operands[0],
+                                                          force_reg (Pmode, operands[1]),
+                                                          operands[2], operands[3],
+                                                          toc_addr, toc_reg, static_chain));
+           }
+         else if (DEFAULT_ABI == ABI_NT)
+           {
+             /* NT function pointers are really pointers to a two word area */
+             emit_call_insn (gen_call_value_indirect_nt (operands[0],
+                                                         force_reg (Pmode, operands[1]),
+                                                         operands[2], operands[3],
+                                                         toc_addr, toc_reg));
+           }
+         else
+           abort ();
+       }
+      DONE;
     }
 }")
 
 ;; and < 0 if they were not.
 
 (define_insn ""
-  [(call (mem:SI (match_operand:SI 0 "call_operand" "l,s,l,s"))
-        (match_operand 1 "" "fg,fg,fg,fg"))
-   (use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
-   (clobber (match_scratch:SI 3 "=l,l,l,l"))]
-  ""
+  [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
+        (match_operand 1 "" "fg,fg"))
+   (use (match_operand:SI 2 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 3 "=l,l"))]
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
   "*
 {
   if (INTVAL (operands[2]) > 0)
   else if (INTVAL (operands[2]) < 0)
     output_asm_insn (\"crxor 6,6,6\", operands);
 
-#ifndef USING_SVR4_H
+  /* Indirect calls should go through call_indirect */
   if (GET_CODE (operands[0]) == REG)
-    return \"{brl|blrl}\;{l|lwz} 2,20(1)\";
+    abort ();
 
-  return \"bl %z0\;%.\";
+  return (TARGET_WINDOWS_NT) ? \"bl %z0\;.znop %z0\" : \"bl %z0\;%.\";
+}"
+  [(set_attr "length" "8,12")])
 
-#else
+(define_insn ""
+  [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
+        (match_operand 1 "" "fg,fg"))
+   (use (match_operand:SI 2 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 3 "=l,l"))]
+  "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
+  "*
+{
+  if (INTVAL (operands[2]) > 0)
+    output_asm_insn (\"creqv 6,6,6\", operands);
+
+  else if (INTVAL (operands[2]) < 0)
+    output_asm_insn (\"crxor 6,6,6\", operands);
+
+  /* Indirect calls should go through call_indirect */
   if (GET_CODE (operands[0]) == REG)
-    return \"{brl|blrl}\";
+    abort ();
 
   return \"bl %z0\";
-#endif
 }"
-  [(set_attr "length" "8,8,12,12")])
+  [(set_attr "length" "4,8")])
 
 (define_insn ""
   [(set (match_operand 0 "" "=fg,fg")
   [(set_attr "length" "4,8")])
 
 (define_insn ""
-  [(set (match_operand 0 "" "=fg,fg,fg,fg")
-       (call (mem:SI (match_operand:SI 1 "call_operand" "l,s,l,s"))
-             (match_operand 2 "" "fg,fg,fg,fg")))
-   (use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
-   (clobber (match_scratch:SI 4 "=l,l,l,l"))]
-  ""
+  [(set (match_operand 0 "" "=fg,fg")
+       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
+             (match_operand 2 "" "fg,fg")))
+   (use (match_operand:SI 3 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 4 "=l,l"))]
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
   "*
 {
   if (INTVAL (operands[3]) > 0)
   else if (INTVAL (operands[3]) < 0)
     output_asm_insn (\"crxor 6,6,6\", operands);
 
-#ifndef USING_SVR4_H
+  /* This should be handled by call_value_indirect */
   if (GET_CODE (operands[1]) == REG)
-    return \"{brl|blrl}\;{l|lwz} 2,20(1)\";
+    abort ();
+
+  return (TARGET_WINDOWS_NT) ? \"bl %z1\;.znop %z1\" : \"bl %z1\;%.\";
+}"
+  [(set_attr "length" "8,12")])
+
+(define_insn ""
+  [(set (match_operand 0 "" "=fg,fg")
+       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
+             (match_operand 2 "" "fg,fg")))
+   (use (match_operand:SI 3 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 4 "=l,l"))]
+  "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
+  "*
+{
+  if (INTVAL (operands[3]) > 0)
+    output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return \"bl %z1\;%.\";
+  else if (INTVAL (operands[3]) < 0)
+    output_asm_insn (\"crxor 6,6,6\", operands);
 
-#else
+  /* This should be handled by call_value_indirect */
   if (GET_CODE (operands[1]) == REG)
-    return \"{brl|blrl}\";
+    abort ();
 
   return \"bl %z1\";
-#endif
 }"
-  [(set_attr "length" "8,8,12,12")])
+  [(set_attr "length" "4,8")])
+
 
 ;; Call subroutine returning any type.
 
   ""
   "")
 
-;; Synchronize instruction/data caches for V.4 trampolines
-(define_insn "sync_isync"
-  [(unspec [(match_operand 0 "memory_operand" "=m")] 1)]
+;; Synchronize instructions/data caches for V.4 trampolines
+;; The extra memory_operand is to prevent the optimizer from
+;; deleting insns with "no" effect.
+(define_insn "icbi"
+  [(unspec [(match_operand 0 "memory_operand" "=m")
+           (match_operand 1 "register_operand" "b")
+           (match_operand 2 "register_operand" "r")] 3)]
+  "TARGET_POWERPC"
+  "icbi %1,%2")
+
+(define_insn "dcbst"
+  [(unspec [(match_operand 0 "memory_operand" "=m")
+           (match_operand 1 "register_operand" "b")
+           (match_operand 2 "register_operand" "r")] 4)]
+  "TARGET_POWERPC"
+  "dcbst %1,%2")
+
+(define_insn "sync"
+  [(unspec [(match_operand 0 "memory_operand" "=m")] 5)]
   ""
-  "{dcs|sync}\;{ics|isync}"
-  [(set_attr "length" "8")])
+  "{dcs|sync}")
+
+(define_insn "isync"
+  [(unspec [(match_operand 0 "memory_operand" "=m")] 6)]
+  ""
+  "{ics|isync}")
 
 \f
 ;; Compare insns are next.  Note that the RS/6000 has two types of compares,
 ;; Define the subtract-one-and-jump insns, starting with the template
 ;; so loop.c knows what to generate.
 
-(define_expand "decrement_and_branchsi"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (plus:SI (match_dup 0)
-                           (const_int -1)))
-             (set (pc) (if_then_else (ne (match_dup 0)
+(define_expand "decrement_and_branch_on_count"
+  [(parallel [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "")
                                          (const_int 1))
                                      (label_ref (match_operand 1 "" ""))
                                      (pc)))
+             (set (match_dup 0)
+                  (plus:SI (match_dup 0)
+                           (const_int -1)))
              (clobber (match_scratch:CC 2 ""))
              (clobber (match_scratch:SI 3 ""))])]
   ""
   "
 { operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
                         const0_rtx); }")
+
index 1c54c6f..d7e8af0 100644 (file)
@@ -25,30 +25,38 @@ Boston, MA 02111-1307, USA.  */
 #define        MASK_NO_BITFIELD_TYPE   0x40000000      /* Set PCC_BITFIELD_TYPE_MATTERS to 0 */
 #define        MASK_STRICT_ALIGN       0x20000000      /* Set STRICT_ALIGNMENT to 1.  */
 #define MASK_RELOCATABLE       0x10000000      /* GOT pointers are PC relative */
-#define        MASK_NO_TRACEBACK       0x08000000      /* eliminate traceback words */
+#define        MASK_UNUSED             0x08000000      /* UNUSED, was no-traceback */
 #define MASK_LITTLE_ENDIAN     0x04000000      /* target is little endian */
-#define MASK_AIX_CALLS         0x02000000      /* Use AIX calling sequence */
+#define MASK_CALLS_1           0x02000000      /* First ABI bit (AIX, AIXDESC) */
 #define MASK_PROTOTYPE         0x01000000      /* Only prototyped fcns pass variable args */
+#define        MASK_CALLS_2            0x00800000      /* Second ABI bit (NT) */
+
+#define        MASK_CALLS              (MASK_CALLS_1 | MASK_CALLS_2)
+#define        MASK_CALLS_V4           0
+#define        MASK_CALLS_AIX          MASK_CALLS_1
+#define        MASK_CALLS_NT           MASK_CALLS_2
+#define        MASK_CALLS_AIXDESC      MASK_CALLS
 
 #define        TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
 #define TARGET_STRICT_ALIGN    (target_flags & MASK_STRICT_ALIGN)
 #define TARGET_RELOCATABLE     (target_flags & MASK_RELOCATABLE)
-#define TARGET_NO_TRACEBACK    (target_flags & MASK_NO_TRACEBACK)
 #define TARGET_LITTLE_ENDIAN   (target_flags & MASK_LITTLE_ENDIAN)
-#define TARGET_AIX_CALLS       (target_flags & MASK_AIX_CALLS)
 #define        TARGET_PROTOTYPE        (target_flags & MASK_PROTOTYPE)
-#define        TARGET_TOC              (target_flags & (MASK_64BIT             \
+#define        TARGET_TOC              ((target_flags & (MASK_64BIT            \
                                                 | MASK_RELOCATABLE     \
-                                                | MASK_MINIMAL_TOC))
+                                                | MASK_MINIMAL_TOC))   \
+                                || DEFAULT_ABI == ABI_AIX              \
+                                || DEFAULT_ABI == ABI_NT)
 
 #define        TARGET_BITFIELD_TYPE    (! TARGET_NO_BITFIELD_TYPE)
-#define        TARGET_TRACEBACK        (! TARGET_NO_TRACEBACK)
 #define TARGET_BIG_ENDIAN      (! TARGET_LITTLE_ENDIAN)
-#define TARGET_NO_AIX_CALLS    (! TARGET_AIX_CALLS)
 #define        TARGET_NO_PROTOTYPE     (! TARGET_PROTOTYPE)
 #define        TARGET_NO_TOC           (! TARGET_TOC)
 
-#define TARGET_V4_CALLS                TARGET_NO_AIX_CALLS
+#define TARGET_AIX_CALLS       (target_flags & MASK_CALLS_1)   /* either -mcall-aix or -mcall-aixdesc */
+#define TARGET_V4_CALLS                ((target_flags & MASK_CALLS) == MASK_CALLS_V4)
+#define TARGET_NT_CALLS                ((target_flags & MASK_CALLS) == MASK_CALLS_NT)
+#define TARGET_AIXDESC_CALLS   ((target_flags & MASK_CALLS) == MASK_CALLS_AIXDESC)
 
 /* Pseudo target to indicate whether the object format is ELF
    (to get around not having conditional compilation in the md file)  */
@@ -64,8 +72,8 @@ Boston, MA 02111-1307, USA.  */
   { "no-strict-align", -MASK_STRICT_ALIGN },                           \
   { "relocatable",      MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
   { "no-relocatable",  -MASK_RELOCATABLE },                            \
-  { "traceback",       -MASK_NO_TRACEBACK },                           \
-  { "no-traceback",     MASK_NO_TRACEBACK },                           \
+  { "relocatable-lib",  MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
+  { "no-relocatable-lib", -MASK_RELOCATABLE },                         \
   { "little-endian",    MASK_LITTLE_ENDIAN },                          \
   { "little",           MASK_LITTLE_ENDIAN },                          \
   { "big-endian",      -MASK_LITTLE_ENDIAN },                          \
@@ -73,10 +81,19 @@ Boston, MA 02111-1307, USA.  */
   { "no-toc",           0 },                                           \
   { "toc",              MASK_MINIMAL_TOC },                            \
   { "full-toc",                 MASK_MINIMAL_TOC },                            \
-  { "call-aix",                 MASK_AIX_CALLS },                              \
-  { "call-sysv",       -MASK_AIX_CALLS },                              \
+  { "call-aix",                 MASK_CALLS_AIX },                              \
+  { "call-aix",                -MASK_CALLS_NT },                               \
+  { "call-aixdesc",     MASK_CALLS_AIXDESC },                          \
+  { "call-aixdesc",    -MASK_LITTLE_ENDIAN },                          \
+  { "call-sysv",       -MASK_CALLS },                                  \
+  { "call-nt",          MASK_CALLS_NT | MASK_LITTLE_ENDIAN },          \
+  { "call-nt",         -MASK_CALLS_AIX },                              \
   { "prototype",        MASK_PROTOTYPE },                              \
-  { "no-prototype",    -MASK_PROTOTYPE },
+  { "no-prototype",    -MASK_PROTOTYPE },                              \
+  { "no-traceback",     0 },                                           \
+  { "sim",              0 },                                           \
+  { "mvme",             0 },                                           \
+  { "emb",              0 },                                           \
 
 /* Sometimes certain combinations of command options do not make sense
    on a particular target machine.  You can define a macro
@@ -94,8 +111,40 @@ do {                                                                        \
       target_flags |= MASK_MINIMAL_TOC;                                        \
       error ("-mrelocatable and -mno-minimal-toc are incompatible.");  \
     }                                                                  \
+                                                                       \
+  if (TARGET_RELOCATABLE && TARGET_AIXDESC_CALLS)                      \
+    {                                                                  \
+      target_flags &= ~MASK_RELOCATABLE;                               \
+      error ("-mrelocatable and -mcall-aixdesc are incompatible.");    \
+    }                                                                  \
+                                                                       \
+  if (TARGET_RELOCATABLE && TARGET_NT_CALLS)                           \
+    {                                                                  \
+      target_flags &= ~MASK_MINIMAL_TOC;                               \
+      error ("-mrelocatable and -mcall-nt are incompatible.");         \
+    }                                                                  \
+                                                                       \
+  if (TARGET_AIXDESC_CALLS && TARGET_LITTLE_ENDIAN)                    \
+    {                                                                  \
+      target_flags &= ~MASK_LITTLE_ENDIAN;                             \
+      error ("-mcall-aixdesc must be big endian");                     \
+    }                                                                  \
+                                                                       \
+  if (TARGET_NT_CALLS && TARGET_BIG_ENDIAN)                            \
+    {                                                                  \
+      target_flags |= MASK_LITTLE_ENDIAN;                              \
+      error ("-mcall-nt must be little endian");                       \
+    }                                                                  \
+                                                                       \
+  rs6000_current_abi = ((TARGET_AIXDESC_CALLS) ? ABI_AIX :             \
+                       (TARGET_NT_CALLS)      ? ABI_NT :               \
+                       (TARGET_AIX_CALLS)     ? ABI_AIX_NODESC :       \
+                                                ABI_V4);               \
 } while (0)
 
+/* Default ABI to compile code for */
+#define DEFAULT_ABI rs6000_current_abi
+
 #include "rs6000/powerpc.h"
 
 /* System V.4 uses register 13 as a pointer to the small data area,
@@ -152,12 +201,6 @@ do {                                                                       \
 
 #undef OBJECT_FORMAT_COFF
 
-/* The XCOFF support uses weird symbol suffixes, which we don't want
-   for ELF.  */
-
-#undef RS6000_OUTPUT_BASENAME
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME)
-
 /* Don't bother to output .extern pseudo-ops.  They are not needed by
    ELF assemblers.  */
 
@@ -237,12 +280,39 @@ toc_section ()                                                            \
   if (in_section != in_toc)                                            \
     {                                                                  \
       in_section = in_toc;                                             \
-      fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);      \
-      if (! toc_initialized)                                           \
+      if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)            \
+         && TARGET_MINIMAL_TOC                                         \
+         && !TARGET_RELOCATABLE)                                       \
+       {                                                               \
+         if (! toc_initialized)                                        \
+           {                                                           \
+             toc_initialized = 1;                                      \
+             fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);       \
+             ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LCTOC", 0);     \
+             fprintf (asm_out_file, "\t.tc ");                         \
+             ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); \
+             ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+             fprintf (asm_out_file, "\n");                             \
+                                                                       \
+             fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+             ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+             fprintf (asm_out_file, " = .+32768\n");                   \
+           }                                                           \
+         else                                                          \
+           fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+       }                                                               \
+      else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)       \
+              && !TARGET_RELOCATABLE)                                  \
+       fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);             \
+      else                                                             \
        {                                                               \
-         ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");    \
-         fprintf (asm_out_file, " = .+32768\n");                       \
-         toc_initialized = 1;                                          \
+         fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);   \
+         if (! toc_initialized)                                        \
+           {                                                           \
+             ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+             fprintf (asm_out_file, " = .+32768\n");                   \
+             toc_initialized = 1;                                      \
+           }                                                           \
        }                                                               \
     }                                                                  \
 }
@@ -260,6 +330,30 @@ toc_section ()                                                             \
     const_section ();                          \
 }
 
+/* Return non-zero if this entry is to be written into the constant pool
+   in a special way.  We do so if this is a SYMBOL_REF, LABEL_REF or a CONST
+   containing one of them.  If -mfp-in-toc (the default), we also do
+   this for floating-point constants.  We actually can only do this
+   if the FP formats of the target and host machines are the same, but
+   we can't check that since not every file that uses
+   GO_IF_LEGITIMATE_ADDRESS_P includes real.h.
+
+   Unlike AIX, we don't key off of -mmininal-toc, but instead do not
+   allow floating point constants in the TOC if -mrelocatable.  */
+
+#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X)                             \
+  (TARGET_TOC                                                          \
+   && (GET_CODE (X) == SYMBOL_REF                                      \
+       || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS     \
+          && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF)           \
+       || GET_CODE (X) == LABEL_REF                                    \
+       || (!TARGET_NO_FP_IN_TOC                                                \
+          && !TARGET_RELOCATABLE                                       \
+          && GET_CODE (X) == CONST_DOUBLE                              \
+          && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT               \
+          && BITS_PER_WORD == HOST_BITS_PER_INT)))
+
 /* These macros generate the special .type and .size directives which
    are used to set the corresponding fields of the linker symbol table
    entries in an ELF object file under SVR4.  These macros also output
@@ -269,37 +363,53 @@ toc_section ()                                                            \
    Some svr4 assemblers need to also have something extra said about the
    function's return value.  We allow for that here.  */
 
-extern void svr4_traceback ();
 extern int rs6000_pic_labelno;
 
 #undef ASM_DECLARE_FUNCTION_NAME
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)                    \
   do {                                                                 \
+    char *orig_name;                                                   \
+    char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long";               \
+    STRIP_NAME_ENCODING (orig_name, NAME);                             \
+                                                                       \
     if (TARGET_RELOCATABLE && get_pool_size () != 0)                   \
       {                                                                        \
-       char buf[256];                                                  \
+       char buf[256], *buf_ptr;                                        \
                                                                        \
        ASM_OUTPUT_INTERNAL_LABEL (FILE, "LCL", rs6000_pic_labelno);    \
                                                                        \
        ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);                  \
-       fprintf (FILE, (TARGET_POWERPC64) ? "\t.quad " : "\t.long ");   \
-       assemble_name (FILE, buf);                                      \
-       putc ('-', FILE);                                               \
+       STRIP_NAME_ENCODING (buf_ptr, buf);                             \
+       fprintf (FILE, "\t%s %s-", init_ptr, buf_ptr);                  \
                                                                        \
        ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);   \
-       assemble_name (FILE, buf);                                      \
-       putc ('\n', FILE);                                              \
+       fprintf (FILE, "%s\n", buf_ptr);                                \
       }                                                                        \
                                                                        \
-    fprintf (FILE, "\t%s\t ", TYPE_ASM_OP);                            \
-    assemble_name (FILE, NAME);                                                \
-    putc (',', FILE);                                                  \
+    fprintf (FILE, "\t%s\t %s,", TYPE_ASM_OP, orig_name);              \
     fprintf (FILE, TYPE_OPERAND_FMT, "function");                      \
     putc ('\n', FILE);                                                 \
-    if (TARGET_TRACEBACK)                                              \
-      svr4_traceback (FILE, NAME, DECL);                               \
     ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));                     \
-    ASM_OUTPUT_LABEL(FILE, NAME);                                      \
+                                                                       \
+    if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)               \
+      {                                                                        \
+       char *desc_name = orig_name;                                    \
+                                                                       \
+       while (*desc_name == '.')                                       \
+         desc_name++;                                                  \
+                                                                       \
+       if (TREE_PUBLIC (DECL))                                         \
+         fprintf (FILE, "\t.globl %s\n", desc_name);                   \
+                                                                       \
+       fprintf (FILE, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);             \
+       fprintf (FILE, "%s:\n", desc_name);                             \
+       fprintf (FILE, "\t%s %s\n", init_ptr, orig_name);               \
+       fprintf (FILE, "\t%s _GLOBAL_OFFSET_TABLE_\n", init_ptr);       \
+       if (DEFAULT_ABI == ABI_AIX)                                     \
+         fprintf (FILE, "\t%s 0\n", init_ptr);                         \
+       fprintf (FILE, "\t.previous\n");                                \
+      }                                                                        \
+    fprintf (FILE, "%s:\n", orig_name);                                        \
   } while (0)
 
 /* How to renumber registers for dbx and gdb.  */
@@ -315,11 +425,30 @@ extern int rs6000_pic_labelno;
 /* Pass -mppc to the assembler, since that is what powerpc.h currently
    implies.  */
 #undef ASM_SPEC
-#define ASM_SPEC \
-  "-u \
-%{mcpu=601: -m601} %{!mcpu=601: -mppc} \
+#define ASM_SPEC "\
+-u \
+%{!mcpu*: \
+  %{mpower2: -mpwrx} \
+  %{mpowerpc*: %{!mpower: -mppc}} \
+  %{mno-powerpc: %{!mpower: %{!mpower2: -mcom}}} \
+  %{mno-powerpc: %{mpower: %{!mpower2: -mpwr}}} \
+  %{!mno-powerpc: %{mpower: -m601}} \
+  %{!mno-powerpc: %{!mpower: -mppc}}} \
+%{mcpu=common: -mcom} \
+%{mcpu=power: -mpwr} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rios: -mpwr} \
+%{mcpu=rios1: -mpwr} \
+%{mcpu=rios2: -mpwrx} \
+%{mcpu=rsc: -mpwr} \
+%{mcpu=rsc1: -mpwr} \
+%{mcpu=403: -mppc} \
+%{mcpu=601: -m601} \
+%{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
+%{mcpu=604: -mppc} \
 %{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
-%{mrelocatable} \
+%{mrelocatable} %{mrelocatable-lib} %{memb} \
 %{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian}"
 
 /* Output .file and comments listing what options there are */
@@ -330,6 +459,61 @@ do {                                                                       \
   output_file_directive ((FILE), main_input_filename);                 \
 } while (0)
 
+
+/* This is how to output an assembler line defining an `int' constant.
+   For -mrelocatable, we mark all addresses that need to be fixed up
+   in the .fixup section.  */
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE)                                     \
+do {                                                                   \
+  static int recurse = 0;                                              \
+  if (TARGET_RELOCATABLE                                               \
+      && in_section != in_toc                                          \
+      && in_section != in_text                                         \
+      && in_section != in_ctors                                                \
+      && in_section != in_dtors                                                \
+      && !recurse                                                      \
+      && GET_CODE (VALUE) != CONST_INT                                 \
+      && GET_CODE (VALUE) != CONST_DOUBLE                              \
+      && CONSTANT_P (VALUE))                                           \
+    {                                                                  \
+      static int labelno = 0;                                          \
+      char buf[256], *p;                                               \
+                                                                       \
+      recurse = 1;                                                     \
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++);             \
+      STRIP_NAME_ENCODING (p, buf);                                    \
+      fprintf (FILE, "%s:\n", p);                                      \
+      fprintf (FILE, "\t.long (");                                     \
+      output_addr_const (FILE, (VALUE));                               \
+      fprintf (FILE, ")@fixup\n");                                     \
+      fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n");               \
+      ASM_OUTPUT_ALIGN (FILE, 2);                                      \
+      fprintf (FILE, "\t.long\t%s\n", p);                              \
+      fprintf (FILE, "\t.previous\n");                                 \
+      recurse = 0;                                                     \
+    }                                                                  \
+  /* Remove initial .'s to turn a -mcall-aixdesc or -mcall-nt function \
+     address into the address of the descriptor, not the function      \
+     itself.  */                                                       \
+  else if (GET_CODE (VALUE) == SYMBOL_REF                              \
+          && XSTR (VALUE, 0)[0] == '.'                                 \
+          && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT))        \
+    {                                                                  \
+      char *name = XSTR (VALUE, 0);                                    \
+      while (*name == '.')                                             \
+       name++;                                                         \
+                                                                       \
+      fprintf (FILE, "\t.long %s\n", name);                            \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      fprintf (FILE, "\t.long ");                                      \
+      output_addr_const (FILE, (VALUE));                               \
+      fprintf (FILE, "\n");                                            \
+    }                                                                  \
+} while (0)
+
 /* This is the end of what might become sysv4.h.  */
 
 /* Allow stabs and dwarf, prefer dwarf.  */
@@ -337,6 +521,35 @@ do {                                                                       \
 #define        DBX_DEBUGGING_INFO
 #define        DWARF_DEBUGGING_INFO
 
+/* If we are referencing a function that is static or is known to be
+   in this file, make the SYMBOL_REF special.  We can use this to indicate
+   that we can branch to this function without emitting a no-op after the
+   call.  For real AIX and NT calling sequences, we also replace the
+   function name with the real name (1 or 2 leading .'s), rather than
+   the function descriptor name.  This saves a lot of overriding code
+   to readd the prefixes.  */
+
+#undef ENCODE_SECTION_INFO
+#define ENCODE_SECTION_INFO(DECL)                                      \
+  do {                                                                 \
+    if (TREE_CODE (DECL) == FUNCTION_DECL)                             \
+      {                                                                        \
+       rtx sym_ref = XEXP (DECL_RTL (DECL), 0);                        \
+       if (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL))            \
+         SYMBOL_REF_FLAG (sym_ref) = 1;                                \
+                                                                       \
+       if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)            \
+         {                                                             \
+           char *prefix = (DEFAULT_ABI == ABI_AIX) ? "." : "..";       \
+           char *str = permalloc (strlen (prefix) + 1                  \
+                                  + strlen (XSTR (sym_ref, 0)));       \
+           strcpy (str, prefix);                                       \
+           strcat (str, XSTR (sym_ref, 0));                            \
+           XSTR (sym_ref, 0) = str;                                    \
+         }                                                             \
+      }                                                                        \
+  } while (0)
+
 /* This macro gets just the user-specified name
    out of the string in a SYMBOL_REF.  Discard
    a leading * */
@@ -344,24 +557,6 @@ do {                                                                       \
 #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
   (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
 
-/* Like block addresses, stabs line numbers are relative to the
-   current function.  */
-
-#undef  ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(file, line)                             \
-do                                                                     \
-  {                                                                    \
-    static int sym_lineno = 1;                                         \
-    char *_p;                                                          \
-    fprintf (file, "\t.stabn 68,0,%d,.LM%d-",                          \
-            line, sym_lineno);                                         \
-    STRIP_NAME_ENCODING (_p, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
-    assemble_name (file, _p);                                          \
-    fprintf (file, "\n.LM%d:\n", sym_lineno);                          \
-    sym_lineno += 1;                                                   \
-  }                                                                    \
-while (0)
-
 /* But, to make this work, we have to output the stabs for the function
    name *first*...  */
 
@@ -372,77 +567,6 @@ while (0)
 #undef TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
 \f
-
-/* Output assembler code for a block containing the constant parts
-   of a trampoline, leaving space for the variable parts.
-
-   The trampoline should set the static chain pointer to value placed
-   into the trampoline and should branch to the specified routine.
-
-   Unlike AIX, this needs real code.  */
-
-#undef TRAMPOLINE_TEMPLATE
-#define TRAMPOLINE_TEMPLATE(FILE)                                      \
-do {                                                                   \
-  char *sc = reg_names[STATIC_CHAIN_REGNUM];                           \
-  char *r0 = reg_names[0];                                             \
-                                                                       \
-  if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS)               \
-    abort ();                                                          \
-                                                                       \
-  if (TARGET_64BIT)                                                    \
-    {                                                                  \
-      fprintf (FILE, "\tmflr %s\n", r0);               /* offset  0 */ \
-      fprintf (FILE, "\tbl .LTRAMP1\n");               /* offset  4 */ \
-      fprintf (FILE, "\t.long 0,0,0,0\n");             /* offset  8 */ \
-      fprintf (FILE, ".LTRAMP1:\n");                                   \
-      fprintf (FILE, "\tmflr %s\n", sc);               /* offset 28 */ \
-      fprintf (FILE, "\tmtlr %s\n", r0);               /* offset 32 */ \
-      fprintf (FILE, "\tld %s,0(%s)\n", r0, sc);       /* offset 36 */ \
-      fprintf (FILE, "\tld %s,8(%s)\n", sc, sc);       /* offset 40 */ \
-      fprintf (FILE, "\tmtctr %s\n", r0);              /* offset 44 */ \
-      fprintf (FILE, "\tbctr\n");                      /* offset 48 */ \
-    }                                                                  \
-  else                                                                 \
-    {                                                                  \
-      fprintf (FILE, "\tmflr %s\n", r0);               /* offset  0 */ \
-      fprintf (FILE, "\tbl .LTRAMP1\n");               /* offset  4 */ \
-      fprintf (FILE, "\t.long 0,0\n");                 /* offset  8 */ \
-      fprintf (FILE, ".LTRAMP1:\n");                                   \
-      fprintf (FILE, "\tmflr %s\n", sc);               /* offset 20 */ \
-      fprintf (FILE, "\tmtlr %s\n", r0);               /* offset 24 */ \
-      fprintf (FILE, "\tlwz %s,0(%s)\n", r0, sc);      /* offset 28 */ \
-      fprintf (FILE, "\tlwz %s,4(%s)\n", sc, sc);      /* offset 32 */ \
-      fprintf (FILE, "\tmtctr %s\n", r0);              /* offset 36 */ \
-      fprintf (FILE, "\tbctr\n");                      /* offset 40 */ \
-    }                                                                  \
-} while (0)
-
-/* Length in units of the trampoline for entering a nested function.  */
-
-#undef TRAMPOLINE_SIZE
-#define TRAMPOLINE_SIZE    (TARGET_64BIT ? 48 : 40)
-
-/* Emit RTL insns to initialize the variable parts of a trampoline.
-   FNADDR is an RTX for the address of the function's pure code.
-   CXT is an RTX for the static chain value for the function.  */
-
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT)                       \
-{                                                                      \
-  rtx reg = gen_reg_rtx (Pmode);                                       \
-                                                                       \
-  emit_move_insn (reg, FNADDR);                                                \
-  emit_move_insn (gen_rtx (MEM, Pmode,                                 \
-                          plus_constant (ADDR, 8)),                    \
-                 reg);                                                 \
-  emit_move_insn (gen_rtx (MEM, Pmode,                                 \
-                          plus_constant (ADDR, (TARGET_64BIT ? 16 : 12))), \
-                 CXT);                                                 \
-  emit_insn (gen_sync_isync (gen_rtx (MEM, BLKmode, ADDR)));           \
-}
-
-\f
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES \
   "-DPPC -Dunix -D__svr4__ -Asystem(unix) -Asystem(svr4) -Acpu(powerpc) -Amachine(powerpc)"
@@ -482,7 +606,9 @@ do {                                                                        \
 #define CPP_SPEC "\
 %{posix: -D_POSIX_SOURCE} \
 %{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
+%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
+%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
+%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \
 %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
 %{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
 %{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
@@ -503,5 +629,20 @@ do {                                                                       \
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef MULTILIB_DEFAULTS
+#define        MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-sysv" }
index 59bd1b7..7a2e55b 100644 (file)
@@ -29,7 +29,9 @@ Boston, MA 02111-1307, USA.  */
 #define CPP_SPEC "\
 %{posix: -D_POSIX_SOURCE} \
 %{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
+%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
+%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
+%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \
 %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
 %{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
 %{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
@@ -50,5 +52,20 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=rsc1: -D_ARCH_PWR} \
 %{mcpu=403: -D_ARCH_PPC} \
 %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
 %{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC}"
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef MULTILIB_DEFAULTS
+#define        MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" }
index 5fcb3d8..e664aa5 100644 (file)
@@ -2,6 +2,8 @@
 LIBGCC1 =
 CROSS_LIBGCC1 =
 
+EXTRA_HEADERS = $(srcdir)/ginclude/ppc-asm.h
+
 # These are really part of libgcc1, but this will cause them to be
 # built correctly, so... [taken from t-sparclite]
 LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
index db4b936..1169ef6 100644 (file)
@@ -2,6 +2,8 @@
 LIBGCC1 =
 CROSS_LIBGCC1 =
 
+EXTRA_HEADERS = $(srcdir)/ginclude/ppc-asm.h
+
 # These are really part of libgcc1, but this will cause them to be
 # built correctly, so... [taken from t-sparclite]
 LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
@@ -16,15 +18,18 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
 # Build libgcc.a with different options.
 
 MULTILIB_OPTIONS       = msoft-float \
-                         mlittle
+                         mlittle/mbig \
+                         mcall-sysv/mcall-aix/mcall-aixdesc
 
 MULTILIB_DIRNAMES      = soft-float \
-                         little-endian
+                         little big \
+                         sysv aix aixdesc
 
 MULTILIB_MATCHES       = mlittle=mlittle-endian \
-                         msoft-float=mcpu?403 \
-                         msoft-float=mcpu?mpc403 \
-                         msoft-float=mcpu?ppc403
+                         mbig=mbig-endian \
+                         msoft-float=mcpu?403
+
+MULTILIB_EXCEPTIONS    = *mlittle/*mcall-aixdesc*
 
 LIBGCC = stmp-multilib
 INSTALL_LIBGCC = install-multilib