]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PowerPC reorg and support for powerpc64-*-linux*.
authorDaniel Berlin <dan@cgsoftware.com>
Tue, 31 Jul 2001 17:20:20 +0000 (17:20 +0000)
committerDaniel Berlin <dberlin@gcc.gnu.org>
Tue, 31 Jul 2001 17:20:20 +0000 (17:20 +0000)
2001-07-31  Daniel Berlin  <dan@cgsoftware.com>

PowerPC reorg and support for powerpc64-*-linux*.

Also fixes emitting of constants on 32 bit and 64 bit
platforms.

* config.gcc: powerpc64-*-linux* is a new target.
Things that needed aix.h now also include xcoff.h

* config/rs6000/rs6000.h: Split XCOFF specific stuff into
xcoff.h.
Move AIX specific stuff into aix.h.
(ASM_LONG): Use DOUBLE_INT_ASM_OP if we are on a 64 bit target.
(ASM_OUTPUT_DOUBLE_INT): Ditto.
(TARGET_AIX): Renamed to TARGET_XCOFF, since the AIX ABI is used
with more than just XCOFF now.
(SET_ASM_OP): Remove, now defined where needed.
(FUNCTION_PROLOGUE): New macro definition.
(FUNCTION_EPILOGUE): New macro definition.
(CONST_OK_FOR_LETTER_P): Change N to require that value is
positive, too.
(ASM_OPEN_PAREN, ASM_CLOSE_PAREN): New macro definition.
(PREDICATE_CODES): Added exact_log2_cint_operand,
reg_or_add_cint64_operand, reg_or_sub_cint64_operand.

* config/rs6000/rs6000.c: #ifdef XCOFF debugging info stuff on
XCOFF_DEBUGGING_INFO.
Use DOUBLE_INT_ASM_OP where approriate.
(rs6000_emit_set_long_const): New function.
(rs6000_emit_set_const): New function.
(reg_or_sub_cint64_operand): New function.
(reg_or_add_cint64_operand): New function.
(exact_log2_cint_operand): New function.

* config/rs6000/rs6000.md: Fix emitting of constants.
Fix patterns that were AIX ABI specific, but depended on
!TARGET_ELF (instead of DEFAULT_ABI == ABI_AIX).

* config/rs6000/xcoff.h: New file.

* config/rs6000/linux64.h: New file.

* config/rs6000/darwin.h: Copy needed AIX alignment definitions.

From-SVN: r44516

12 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/rs6000/aix.h
gcc/config/rs6000/darwin.h
gcc/config/rs6000/linux.h
gcc/config/rs6000/linux64.h [new file with mode: 0644]
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h
gcc/config/rs6000/xcoff.h [new file with mode: 0644]

index 03817588f9ad569b1e830a238ee19e4200c4fd8f..1c009f3bd39b4d974307dc67b6e556449e4bad01 100644 (file)
@@ -1,3 +1,49 @@
+2001-07-31  Daniel Berlin  <dan@cgsoftware.com>
+
+       PowerPC reorg and support for powerpc64-*-linux*.
+
+       Also fixes emitting of constants on 32 bit and 64 bit
+       platforms.
+       
+       * config.gcc: powerpc64-*-linux* is a new target.
+       Things that needed aix.h now also include xcoff.h       
+
+       * config/rs6000/rs6000.h: Split XCOFF specific stuff into
+       xcoff.h. 
+       Move AIX specific stuff into aix.h.
+       (ASM_LONG): Use DOUBLE_INT_ASM_OP if we are on a 64 bit target.
+       (ASM_OUTPUT_DOUBLE_INT): Ditto.
+       (TARGET_AIX): Renamed to TARGET_XCOFF, since the AIX ABI is used
+       with more than just XCOFF now.
+       (SET_ASM_OP): Remove, now defined where needed.
+       (FUNCTION_PROLOGUE): New macro definition.
+       (FUNCTION_EPILOGUE): New macro definition.
+       (CONST_OK_FOR_LETTER_P): Change N to require that value is
+       positive, too.
+       (ASM_OPEN_PAREN, ASM_CLOSE_PAREN): New macro definition.
+       (PREDICATE_CODES): Added exact_log2_cint_operand,
+       reg_or_add_cint64_operand, reg_or_sub_cint64_operand.
+
+       * config/rs6000/rs6000.c: #ifdef XCOFF debugging info stuff on
+       XCOFF_DEBUGGING_INFO.
+       Use DOUBLE_INT_ASM_OP where approriate.
+       (rs6000_emit_set_long_const): New function.
+       (rs6000_emit_set_const): New function.
+       (reg_or_sub_cint64_operand): New function.
+       (reg_or_add_cint64_operand): New function.
+       (exact_log2_cint_operand): New function.
+
+       * config/rs6000/rs6000.md: Fix emitting of constants.
+       Fix patterns that were AIX ABI specific, but depended on
+       !TARGET_ELF (instead of DEFAULT_ABI == ABI_AIX).        
+       
+       * config/rs6000/xcoff.h: New file.
+
+       * config/rs6000/linux64.h: New file.
+
+       * config/rs6000/darwin.h: Copy needed AIX alignment definitions.
+       
+
 2001-07-31  Graham Stott <grahams@redhat.com>
 
        * function.c (pad_below): Revert 2001-07-26 patch.
index 7a14135fa11ae1031de8b846a5d90baa0b4bb1b2..6380bab81a800a513ce874c00912e9d804e4f189 100644 (file)
@@ -2559,9 +2559,16 @@ romp-*-openbsd*)
 powerpc-*-openbsd*)
        tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd"
        ;;
+powerpc64-*-linux*)
+       tm_file="${tm_file} svr4.h rs6000/sysv4.h rs6000/linux64.h"
+       out_file=rs6000/rs6000.c
+       tmake_file="rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
+       xmake_file=x-linux
+       extra_headers=ppc-asm.h
+       ;;
 powerpc-*-beos*)
        cpu_type=rs6000
-       tm_file="${tm_file} rs6000/aix.h rs6000/beos.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/beos.h rs6000/xcoff.h"
        xm_defines=POSIX
        xm_file=rs6000/xm-beos.h
        tmake_file=rs6000/t-beos
@@ -2700,27 +2707,27 @@ powerpcle-*-solaris2*)
        ;;
 rs6000-ibm-aix3.[01]*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h rs6000/aix31.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/aix31.h rs6000/xcoff.h"
        float_format=none
        use_collect2=yes
        ;;
 rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h rs6000/aix3newas.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/aix3newas.h rs6000/xcoff.h"
        tmake_file=rs6000/t-newas
        float_format=none
        use_collect2=yes
        ;;
 rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h rs6000/aix41.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/aix41.h rs6000/xcoff.h"
        tmake_file=rs6000/t-newas
        float_format=none
        use_collect2=yes
        ;;
 rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h rs6000/aix43.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/aix43.h rs6000/xcoff.h"
        tmake_file=rs6000/t-aix43
        float_format=none
        use_collect2=yes
@@ -2728,7 +2735,7 @@ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
        ;;
 rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h rs6000/aix51.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/aix51.h rs6000/xcoff.h"
        tmake_file=rs6000/t-aix43
        float_format=none
        use_collect2=yes
@@ -2736,13 +2743,13 @@ rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
        ;;
 rs6000-ibm-aix*)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
        float_format=none
        use_collect2=yes
        ;;
 rs6000-bull-bosx)
        xm_defines=POSIX
-       tm_file="${tm_file} rs6000/aix.h"
+       tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
        float_format=none
        use_collect2=yes
        ;;
index d5c103fb9f3ad44afa3a426ced6b004ae446c4b3..e478e86b2a57da1469bededbd39372d9d07dc8f2 100644 (file)
@@ -21,58 +21,20 @@ Boston, MA 02111-1307, USA.  */
 
 /* Yes!  We are AIX!  */
 #define DEFAULT_ABI ABI_AIX
-#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
-
+#undef TARGET_AIX
+#define TARGET_AIX 1
 /* The AIX linker will discard static constructors in object files before
    collect has a chance to see them, so scan the object files directly.  */
 #define COLLECT_EXPORT_LIST
 
-/* The RS/6000 uses the XCOFF format.  */
-#define XCOFF_DEBUGGING_INFO
-
-/* Define if the object format being used is COFF or a superset.  */
-#define OBJECT_FORMAT_COFF
-
-/* Define the magic numbers that we recognize as COFF.
-    AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit objects and AIX V5 adds
-    U64_TOCMAGIC (0767), but collect2.c does not include files in the
-    correct order to conditionally define the symbolic name in this macro.
-    The AIX linker accepts import/export files as object files,
-    so accept "#!" (0x2321) magic number.  */
-#define MY_ISCOFF(magic) \
-  ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC \
-   || (magic) == U802TOCMAGIC || (magic) == 0757 || (magic) == 0767 \
-   || (magic) == 0x2321)
-
 /* This is the only version of nm that collect2 can work with.  */
 #define REAL_NM_FILE_NAME "/usr/ucb/nm"
 
-/* We don't have GAS for the RS/6000 yet, so don't write out special
-    .stabs in cc1plus.  */
-
-#define FASCIST_ASSEMBLER
-
-/* We define this to prevent the name mangler from putting dollar signs into
-   function names.  */
-
-#define NO_DOLLAR_IN_LABEL
-
-/* We define this to 0 so that gcc will never accept a dollar sign in a
-   variable name.  This is needed because the AIX assembler will not accept
-   dollar signs.  */
-
-#define DOLLARS_IN_IDENTIFIERS 0
-
 /* AIX does not have any init/fini or ctor/dtor sections, so create
     static constructors and destructors as normal functions.  */
 /* #define ASM_OUTPUT_CONSTRUCTOR(file, name) */
 /* #define ASM_OUTPUT_DESTRUCTOR(file, name) */
-
-/* The prefix to add to user-visible assembler symbols. */
-#define USER_LABEL_PREFIX ""
-
+#define USER_LABEL_PREFIX  ""
 /* Don't turn -B into -L if the argument specifies a relative file name.  */
 #define RELATIVE_PREFIX_NOT_LINKDIR
 
@@ -90,6 +52,82 @@ Boston, MA 02111-1307, USA.  */
    %{ansi: -D_ANSI_C_SOURCE}\
    %(cpp_cpu)"
 
+/* Common CPP definitions used by CPP_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#define CPP_CPU_SPEC \
+"%{!mcpu*: \
+  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
+  %{mpower2: -D_ARCH_PWR2} \
+  %{mpowerpc*: -D_ARCH_PPC} \
+  %{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
+  %{!mno-power: %{!mpower2: %(cpp_default)}}} \
+%{mcpu=common: -D_ARCH_COM} \
+%{mcpu=power: -D_ARCH_PWR} \
+%{mcpu=power2: -D_ARCH_PWR2} \
+%{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=401: -D_ARCH_PPC} \
+%{mcpu=403: -D_ARCH_PPC} \
+%{mcpu=505: -D_ARCH_PPC} \
+%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
+%{mcpu=603: -D_ARCH_PPC} \
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=ec603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=604e: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC} \
+%{mcpu=740: -D_ARCH_PPC} \
+%{mcpu=750: -D_ARCH_PPC} \
+%{mcpu=801: -D_ARCH_PPC} \
+%{mcpu=821: -D_ARCH_PPC} \
+%{mcpu=823: -D_ARCH_PPC} \
+%{mcpu=860: -D_ARCH_PPC}"
+
+#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
+
+/* Common ASM definitions used by ASM_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#define ASM_CPU_SPEC \
+"%{!mcpu*: \
+  %{mpower: %{!mpower2: -mpwr}} \
+  %{mpower2: -mpwrx} \
+  %{mpowerpc*: -mppc} \
+  %{mno-power: %{!mpowerpc*: -mcom}} \
+  %{!mno-power: %{!mpower2: %(asm_default)}}} \
+%{mcpu=common: -mcom} \
+%{mcpu=power: -mpwr} \
+%{mcpu=power2: -mpwrx} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rios: -mpwr} \
+%{mcpu=rios1: -mpwr} \
+%{mcpu=rios2: -mpwrx} \
+%{mcpu=rsc: -mpwr} \
+%{mcpu=rsc1: -mpwr} \
+%{mcpu=401: -mppc} \
+%{mcpu=403: -mppc} \
+%{mcpu=505: -mppc} \
+%{mcpu=601: -m601} \
+%{mcpu=602: -mppc} \
+%{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
+%{mcpu=ec603e: -mppc} \
+%{mcpu=604: -mppc} \
+%{mcpu=604e: -mppc} \
+%{mcpu=620: -mppc} \
+%{mcpu=740: -mppc} \
+%{mcpu=750: -mppc} \
+%{mcpu=801: -mppc} \
+%{mcpu=821: -mppc} \
+%{mcpu=823: -mppc} \
+%{mcpu=860: -mppc}"
+
+#define ASM_DEFAULT_SPEC ""
+
 /* Tell the assembler to assume that all undefined names are external.
 
    Don't do this until the fixed IBM assembler is more generally available.
@@ -136,161 +174,25 @@ Boston, MA 02111-1307, USA.  */
 #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
 %{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
 
-/* Define the extra sections we need.  We define three: one is the read-only
-   data section which is used for constants.  This is a csect whose name is
-   derived from the name of the input file.  The second is for initialized
-   global variables.  This is a csect whose name is that of the variable.
-   The third is the TOC.  */
-
-#define EXTRA_SECTIONS \
-   read_only_data, private_data, read_only_private_data, toc, bss
-
-/* Define the routines to implement these extra sections.
-   BIGGEST_ALIGNMENT is 64, so align the sections that much.  */
-
-#define EXTRA_SECTION_FUNCTIONS                                \
-                                                       \
-void                                                   \
-read_only_data_section ()                              \
-{                                                      \
-  if (in_section != read_only_data)                    \
-    {                                                  \
-      fprintf (asm_out_file, "\t.csect %s[RO],3\n",    \
-              xcoff_read_only_section_name);           \
-      in_section = read_only_data;                     \
-    }                                                  \
-}                                                      \
-                                                       \
-void                                                   \
-private_data_section ()                                        \
-{                                                      \
-  if (in_section != private_data)                      \
-    {                                                  \
-      fprintf (asm_out_file, "\t.csect %s[RW],3\n",    \
-              xcoff_private_data_section_name);        \
-      in_section = private_data;                       \
-    }                                                  \
-}                                                      \
-                                                       \
-void                                                   \
-read_only_private_data_section ()                      \
-{                                                      \
-  if (in_section != read_only_private_data)            \
-    {                                                  \
-      fprintf (asm_out_file, "\t.csect %s[RO],3\n",    \
-              xcoff_private_data_section_name);        \
-      in_section = read_only_private_data;             \
-    }                                                  \
-}                                                      \
-                                                       \
-void                                                   \
-toc_section ()                                         \
-{                                                      \
-  if (TARGET_MINIMAL_TOC)                              \
-    {                                                  \
-      /* toc_section is always called at least once from ASM_FILE_START, \
-        so this is guaranteed to always be defined once and only once   \
-        in each file.  */                                               \
-      if (! toc_initialized)                           \
-       {                                               \
-         fputs ("\t.toc\nLCTOC..1:\n", asm_out_file);  \
-         fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
-         toc_initialized = 1;                          \
-       }                                               \
-                                                       \
-      if (in_section != toc)                           \
-       fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n",    \
-                (TARGET_32BIT ? "" : ",3"));           \
-    }                                                  \
-  else                                                 \
-    {                                                  \
-      if (in_section != toc)                           \
-        fputs ("\t.toc\n", asm_out_file);              \
-    }                                                  \
-  in_section = toc;                                    \
-}
-
-/* Define the name of our readonly data section.  */
-
-#define READONLY_DATA_SECTION read_only_data_section
-
-/* Select the section for an initialized data object.
-
-   On the RS/6000, we have a special section for all variables except those
-   that are static.  */
-
-#define SELECT_SECTION(EXP,RELOC)                      \
-{                                                      \
-  if ((TREE_CODE (EXP) == STRING_CST                   \
-       && ! flag_writable_strings)                     \
-      || (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd'     \
-         && TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
-         && DECL_INITIAL (EXP)                         \
-         && (DECL_INITIAL (EXP) == error_mark_node     \
-             || TREE_CONSTANT (DECL_INITIAL (EXP)))    \
-         && ! (RELOC)))                                \
-    {                                                  \
-      if (TREE_PUBLIC (EXP))                           \
-        read_only_data_section ();                     \
-      else                                             \
-        read_only_private_data_section ();             \
-    }                                                  \
-  else                                                 \
-    {                                                  \
-      if (TREE_PUBLIC (EXP))                           \
-        data_section ();                               \
-      else                                             \
-        private_data_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.  We also do this when
-   we can write the entry into the TOC and the entry is not larger
-   than a TOC entry.  */
-
-#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)                       \
-  (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                                    \
-       || (GET_CODE (X) == CONST_INT                                   \
-          && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))      \
-       || (GET_CODE (X) == CONST_DOUBLE                                        \
-          && (TARGET_POWERPC64                                         \
-              || TARGET_MINIMAL_TOC                                    \
-              || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT          \
-                  && ! TARGET_NO_FP_IN_TOC)))))
-
-/* Select section for constant in constant pool.
-
-   On RS/6000, all constants are in the private read-only data area.
-   However, if this is being placed in the TOC it must be output as a
-   toc entry.  */
-
-#define SELECT_RTX_SECTION(MODE, X)                    \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE))       \
-    toc_section ();                                    \
-  else                                                 \
-    read_only_private_data_section ();                 \
-}
-
-/* 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.  Do not set this flag if the function is weakly defined. */
-
-#define ENCODE_SECTION_INFO(DECL)                      \
-  if (TREE_CODE (DECL) == FUNCTION_DECL                        \
-      && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL)) \
-      && ! DECL_WEAK (DECL))                           \
-    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
+             ? get_inner_array_type (FIELD) \
+             : TREE_TYPE (FIELD)) == DFmode \
+   ? MIN ((COMPUTED), 32) : (COMPUTED))
+
+/* AIX increases natural record alignment to doubleword if the first
+   field is an FP double while the FP fields remain word aligned.  */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)  \
+  ((TREE_CODE (STRUCT) == RECORD_TYPE                  \
+    || TREE_CODE (STRUCT) == UNION_TYPE                        \
+    || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)          \
+   && TYPE_FIELDS (STRUCT) != 0                                \
+   && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode       \
+   ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+   : MAX ((COMPUTED), (SPECIFIED)))
+
+
 
 /* Indicate that jump tables go in the text section.  */
 
@@ -315,23 +217,9 @@ toc_section ()                                             \
   { "link_syscalls",            LINK_SYSCALLS_SPEC },                  \
   { "link_libg",                LINK_LIBG_SPEC }
 
-/* FP save and restore routines.  */
-#define        SAVE_FP_PREFIX "._savef"
-#define SAVE_FP_SUFFIX ""
-#define        RESTORE_FP_PREFIX "._restf"
-#define RESTORE_FP_SUFFIX ""
-
 /* Define cutoff for using external functions to save floating point.  */
 #define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
 
-/* Function name to call to do profiling.  */
-#define RS6000_MCOUNT ".__mcount"
-
-/* Function names to call to do floating point truncation.  */
-
-#define RS6000_ITRUNC "__itrunc"
-#define RS6000_UITRUNC "__uitrunc"
-
 /* Optabs entries for the int->float routines, using the standard
    AIX names.  */
 #define INIT_TARGET_OPTABS                                             \
@@ -350,250 +238,6 @@ toc_section ()                                            \
 /* AIX allows r13 to be used.  */
 #define FIXED_R13 0
 
-/* This outputs NAME to FILE up to the first null or '['.  */
-
-#define RS6000_OUTPUT_BASENAME(FILE, NAME)     \
-  {                                            \
-    const char *_p;                            \
-                                               \
-    STRIP_NAME_ENCODING (_p, (NAME));          \
-    assemble_name ((FILE), _p);                        \
-  }
-
-/* This is how to output the definition of a user-level label named NAME,
-   such as the label on a static function or variable NAME.  */
-
-#define ASM_OUTPUT_LABEL(FILE,NAME)    \
-  do { RS6000_OUTPUT_BASENAME (FILE, NAME); fputs (":\n", FILE); } while (0)
-
-/* This is how to output a command to make the user-level label named NAME
-   defined for reference from other files.  */
-
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
-  do { fputs ("\t.globl ", FILE);      \
-       RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
-
-/* Remove any trailing [DS] or the like from the symbol name.  */
-
-#define STRIP_NAME_ENCODING(VAR,NAME)                  \
-  do                                                   \
-    {                                                  \
-      const char *_name = (NAME);                      \
-      size_t _len;                                     \
-      if (*_name == '*')                               \
-        _name++;                                       \
-      _len = strlen (_name);                           \
-      if (_name[_len - 1] != ']')                      \
-       (VAR) = _name;                                  \
-      else                                             \
-       {                                               \
-         char *_new_name = (char *) alloca (_len + 1); \
-         strcpy (_new_name, _name);                    \
-         _new_name[_len - 4] = '\0';                   \
-         (VAR) = _new_name;                            \
-       }                                               \
-    }                                                  \
-  while (0)
-
-/* Output at beginning of assembler file.
-
-   Initialize the section names for the RS/6000 at this point.
-
-   Specify filename, including full path, to assembler.
-
-   We want to go into the TOC section so at least one .toc will be emitted.
-   Also, in order to output proper .bs/.es pairs, we need at least one static
-   [RW] section emitted.
-
-   Finally, declare mcount when profiling to make the assembler happy.  */
-
-#define ASM_FILE_START(FILE)                                   \
-{                                                              \
-  rs6000_gen_section_name (&xcoff_bss_section_name,            \
-                          main_input_filename, ".bss_");       \
-  rs6000_gen_section_name (&xcoff_private_data_section_name,   \
-                          main_input_filename, ".rw_");        \
-  rs6000_gen_section_name (&xcoff_read_only_section_name,      \
-                          main_input_filename, ".ro_");        \
-                                                               \
-  fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename);    \
-  if (TARGET_64BIT)                                            \
-    fputs ("\t.machine\t\"ppc64\"\n", FILE);                   \
-  toc_section ();                                              \
-  if (write_symbols != NO_DEBUG)                               \
-    private_data_section ();                                   \
-  text_section ();                                             \
-  if (profile_flag)                                            \
-    fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT);           \
-  rs6000_file_start (FILE, TARGET_CPU_DEFAULT);                        \
-}
-
-/* Output at end of assembler file.
-
-   On the RS/6000, referencing data should automatically pull in text.  */
-
-#define ASM_FILE_END(FILE)                                     \
-{                                                              \
-  text_section ();                                             \
-  fputs ("_section_.text:\n", FILE);                           \
-  data_section ();                                             \
-  fputs (TARGET_32BIT                                          \
-        ? "\t.long _section_.text\n" : "\t.llong _section_.text\n", FILE); \
-}
-
-/* This macro produces the initial definition of a function name.
-   On the RS/6000, we need to place an extra '.' in the function name and
-   output the function descriptor.
-
-   The csect for the function will have already been created by the
-   `text_section' call previously done.  We do have to go back to that
-   csect, however.
-
-   The third and fourth parameters to the .function pseudo-op (16 and 044)
-   are placeholders which no longer have any use.  */
-
-#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)              \
-{ if (TREE_PUBLIC (DECL))                                      \
-    {                                                          \
-      fputs ("\t.globl .", FILE);                              \
-      RS6000_OUTPUT_BASENAME (FILE, NAME);                     \
-      putc ('\n', FILE);                                       \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      fputs ("\t.lglobl .", FILE);                             \
-      RS6000_OUTPUT_BASENAME (FILE, NAME);                     \
-      putc ('\n', FILE);                                       \
-    }                                                          \
-  fputs ("\t.csect ", FILE);                                   \
-  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
-  fputs (TARGET_32BIT ? "[DS]\n" : "[DS],3\n", FILE);          \
-  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
-  fputs (":\n", FILE);                                         \
-  fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE);     \
-  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
-  fputs (", TOC[tc0], 0\n", FILE);                             \
-  in_section = no_section;                                     \
-  function_section(DECL);                                      \
-  putc ('.', FILE);                                            \
-  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
-  fputs (":\n", FILE);                                         \
-  if (write_symbols == XCOFF_DEBUG)                            \
-    xcoffout_declare_function (FILE, DECL, NAME);              \
-}
-
-/* Output a reference to SYM on FILE.  */
-
-#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
-  rs6000_output_symbol_ref (FILE, SYM)
-
-/* This says how to output an external.  */
-
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)  \
-{ rtx _symref = XEXP (DECL_RTL (DECL), 0);     \
-  if ((TREE_CODE (DECL) == VAR_DECL            \
-       || TREE_CODE (DECL) == FUNCTION_DECL)   \
-      && (NAME)[strlen (NAME) - 1] != ']')     \
-    {                                          \
-      char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
-      strcpy (_name, XSTR (_symref, 0));       \
-      strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
-      XSTR (_symref, 0) = _name;               \
-    }                                          \
-}
-
-/* This is how to output an internal numbered label where
-   PREFIX is the class of label and NUM is the number within the class.  */
-
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)     \
-  fprintf (FILE, "%s..%d:\n", PREFIX, NUM)
-
-/* This is how to output an internal label prefix.  rs6000.c uses this
-   when generating traceback tables.  */
-
-#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX)   \
-  fprintf (FILE, "%s..", PREFIX)
-
-/* This is how to output a label for a jump table.  Arguments are the same as
-   for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
-   passed. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN)       \
-{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
-
-/* This is how to store into the string LABEL
-   the symbol_ref name of an internal numbered label where
-   PREFIX is the class of label and NUM is the number within the class.
-   This is suitable for output with `assemble_name'.  */
-
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
-  sprintf (LABEL, "*%s..%ld", (PREFIX), (long)(NUM))
-
-/* This is how to output an assembler line to define N characters starting
-   at P to FILE.  */
-
-#define ASM_OUTPUT_ASCII(FILE, P, N)  output_ascii ((FILE), (P), (N))
-
-/* This is how to advance the location counter by SIZE bytes.  */
-
-#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
-  fprintf (FILE, "\t.space %d\n", (SIZE))
-
-/* This says how to output an assembler line
-   to define a global common symbol.  */
-
-#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
-  do { fputs (".comm ", (FILE));                       \
-       RS6000_OUTPUT_BASENAME ((FILE), (NAME));                \
-       if ( (SIZE) > 4)                                        \
-         fprintf ((FILE), ",%d,3\n", (SIZE));          \
-       else                                            \
-        fprintf( (FILE), ",%d\n", (SIZE));             \
-  } while (0)
-
-/* These are various definitions for DWARF output.  They could just
-   use '.long' or '.word', but that aligns to a 4-byte boundary which
-   is not what is required.  So we define a million macros...  */
-
-#define UNALIGNED_SHORT_ASM_OP         "\t.vbyte\t2,"
-#define UNALIGNED_INT_ASM_OP           "\t.vbyte\t4,"
-#define UNALIGNED_DOUBLE_INT_ASM_OP    "\t.vbyte\t8,"
-
-/* Output before instructions.  */
-#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
-
-/* Output before writable data.
-   Align entire section to BIGGEST_ALIGNMENT.  */
-#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
-
-/* Define unique section name -- functions only.  */
-#define UNIQUE_SECTION(DECL,RELOC)                     \
-  do {                                                 \
-    int len;                                           \
-    const char *name;                                  \
-    char *string;                                      \
-                                                       \
-    if (TREE_CODE (DECL) == FUNCTION_DECL) {           \
-      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
-      len = strlen (name) + 5;                         \
-      string = alloca (len) + 1;                       \
-      sprintf (string, ".%s[PR]", name);               \
-      DECL_SECTION_NAME (DECL) = build_string (len, string); \
-    }                                                  \
-  } while (0)
-
-#define ASM_OUTPUT_SECTION_NAME(ASM_OUT_FILE,DECL,NAME,RELOC)  \
-  do { fputs ("\t.csect ", ASM_OUT_FILE);                      \
-       fputs (TREE_STRING_POINTER (DECL_SECTION_NAME (DECL)), ASM_OUT_FILE); \
-       putc ('\n', ASM_OUT_FILE);                              \
-  } while (0)
-
-/* Define the name of the section to use for the exception tables.
-   TODO: test and see if we can use read_only_data_section, if so,
-   remove this.  */
-
-#define EXCEPTION_SECTION data_section
-
 /* __throw will restore its own return address to be the same as the
    return address of the function that the throw is being made to.
    This is unfortunate, because we want to check the original
index aef5d722e82d2ed1b66665793b627d328158ba22..0ae4923600b3dc7fc802c5ead0ec19bc1f31707f 100644 (file)
@@ -173,3 +173,21 @@ Boston, MA 02111-1307, USA.  */
 
 /* Fix for emit_group_load (): force large constants to be pushed via regs.  */
 #define ALWAYS_PUSH_CONSTS_USING_REGS_P                1
+
+/* Darwin word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
+             ? get_inner_array_type (FIELD) \
+             : TREE_TYPE (FIELD)) == DFmode \
+   ? MIN ((COMPUTED), 32) : (COMPUTED))
+
+/* Darwin increases natural record alignment to doubleword if the first
+   field is an FP double while the FP fields remain word aligned.  */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)  \
+  ((TREE_CODE (STRUCT) == RECORD_TYPE                  \
+    || TREE_CODE (STRUCT) == UNION_TYPE                        \
+    || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)          \
+   && TYPE_FIELDS (STRUCT) != 0                                \
+   && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode       \
+   ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+   : MAX ((COMPUTED), (SPECIFIED)))
index 5100bb549eeccb976ea45adced53975a417039dd..6e06ecbd78107ef84ffff4c8626e98bc504ea264 100644 (file)
@@ -69,6 +69,11 @@ Boston, MA 02111-1307, USA.  */
 #undef ASM_APP_OFF
 #define ASM_APP_OFF "#NO_APP\n"
 
+#undef DEFAULT_VTABLE_THUNKS
+#ifndef USE_GNULIBC_1
+#define DEFAULT_VTABLE_THUNKS 1
+#endif
+
 /* Do code reading to identify a signal frame, and set the frame
    state data appropriately.  See unwind-dw2.c for the structs.  */
 
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
new file mode 100644 (file)
index 0000000..9fba46e
--- /dev/null
@@ -0,0 +1,307 @@
+/* Definitions of target machine for GNU compiler,
+   for 64 bit powerpc linux.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Yes!  We are AIX! Err. Wait. We're Linux!. No, wait, we're a
+  combo of both!*/
+#undef DEFAULT_ABI
+#define DEFAULT_ABI ABI_AIX
+
+#undef TARGET_AIX
+#define TARGET_AIX 1
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_POWERPC64 | MASK_64BIT | MASK_NEW_MNEMONICS)
+
+/* AIX does not have any init/fini or ctor/dtor sections, so create
+    static constructors and destructors as normal functions.  */
+/* #define ASM_OUTPUT_CONSTRUCTOR(file, name) */
+/* #define ASM_OUTPUT_DESTRUCTOR(file, name) */
+#define USER_LABEL_PREFIX  ""
+
+/* Tell the assembler to assume that all undefined names are external.
+
+   Don't do this until the fixed IBM assembler is more generally available.
+   When this becomes permanently defined, the ASM_OUTPUT_EXTERNAL,
+   ASM_OUTPUT_EXTERNAL_LIBCALL, and RS6000_OUTPUT_BASENAME macros will no
+   longer be needed.  Also, the extern declaration of mcount in ASM_FILE_START
+   will no longer be needed.  */
+
+/* #define ASM_SPEC "-u %(asm_cpu)" */
+
+/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
+             ? get_inner_array_type (FIELD) \
+             : TREE_TYPE (FIELD)) == DFmode \
+   ? MIN ((COMPUTED), 32) : (COMPUTED))
+
+/* AIX increases natural record alignment to doubleword if the first
+   field is an FP double while the FP fields remain word aligned.  */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)  \
+  ((TREE_CODE (STRUCT) == RECORD_TYPE                  \
+    || TREE_CODE (STRUCT) == UNION_TYPE                        \
+    || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)          \
+   && TYPE_FIELDS (STRUCT) != 0                                \
+   && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode       \
+   ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+   : MAX ((COMPUTED), (SPECIFIED)))
+
+/* Indicate that jump tables go in the text section.  */
+#undef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Define cutoff for using external functions to save floating point.  */
+#undef FP_SAVE_INLINE
+#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
+
+#undef TARGET_NO_TOC
+#undef TARGET_TOC
+
+/* 64-bit PowerPC Linux always has a TOC.  */
+#define TARGET_NO_TOC          0
+#define        TARGET_TOC              1
+
+/* 64-bit PowerPC Linux always has GPR13 fixed.  */
+#define FIXED_R13              1
+
+/* __throw will restore its own return address to be the same as the
+   return address of the function that the throw is being made to.
+   This is unfortunate, because we want to check the original
+   return address to see if we need to restore the TOC.
+   So we have to squirrel it away with this.  */
+#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
+
+#define PROFILE_HOOK(LABEL)   output_profile_hook (LABEL)
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+ "-D_PPC_ -D__PPC__ -D_PPC64_ -D__PPC64__ -D__powerpc__ -D__powerpc64__ \
+  -D_PIC_ -D__PIC__ -D_BIG_ENDIAN -D__BIG_ENDIAN__ -D__ELF__ \
+  -D__LONG_MAX__=9223372036854775807L \
+  -Acpu=powerpc64 -Amachine=powerpc64"
+
+#undef CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+
+/* The GNU C++ standard library currently requires _GNU_SOURCE being
+   defined on glibc-based systems. This temporary hack accomplishes this,
+   it should go away as soon as libstdc++-v3 has a real fix.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef LINK_SHLIB_SPEC
+#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
+
+#undef LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC "%(lib_linux)"
+
+#undef STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC "%(startfile_linux)"
+
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "%(endfile_linux)"
+
+#undef LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+
+#undef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
+
+#undef  LINK_OS_LINUX_SPEC
+#define LINK_OS_LINUX_SPEC "-m elf64ppc %{!shared: %{!static: \
+  %{rdynamic:-export-dynamic} \
+  %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+
+#undef TOC_SECTION_ASM_OP
+#define TOC_SECTION_ASM_OP "\t.section\t\".toc\",\"aw\""
+
+#undef MINIMAL_TOC_SECTION_ASM_OP
+#define        MINIMAL_TOC_SECTION_ASM_OP "\t.section\t\".toc1\",\"aw\"\n\t.align 3"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC64 GNU/Linux)");
+
+/* Must be at least as big as our pointer type.  */
+#undef  SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+#undef  WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#undef  WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Override rs6000.h definition.  */
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+/* Override rs6000.h definition.  */
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+#undef DEFAULT_VTABLE_THUNKS
+#ifndef USE_GNULIBC_1
+#define DEFAULT_VTABLE_THUNKS 1
+#endif
+
+/* PowerPC no-op instruction.  */
+#undef RS6000_CALL_GLUE
+#define RS6000_CALL_GLUE "nop"
+
+/* Dwarf2 debugging.  */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE  DWARF2_DEBUG
+
+/* This macro gets just the user-specified name
+   out of the string in a SYMBOL_REF.  Discard
+   a leading * or @.  */
+#define        STRIP_NAME_ENCODING(VAR,SYMBOL_NAME)                            \
+do {                                                                   \
+  const char *_name = SYMBOL_NAME;                                     \
+  while (*_name == '*' || *_name == '@')                               \
+    _name++;                                                           \
+  (VAR) = _name;                                                       \
+} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+   `assemble_name' uses this.  */
+
+/* Override elfos.h definition.  */
+#undef ASM_OUTPUT_LABELREF
+#define        ASM_OUTPUT_LABELREF(FILE,NAME)          \
+do {                                           \
+  const char *_name = NAME;                    \
+  if (*_name == '@')                           \
+    _name++;                                   \
+                                               \
+  if (*_name == '*')                           \
+    fprintf (FILE, "%s", _name + 1);           \
+  else                                         \
+    asm_fprintf (FILE, "%U%s", _name);         \
+} while (0)
+
+#undef  ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)                    \
+  do {                                                                 \
+    if (TARGET_RELOCATABLE && (get_pool_size () != 0 || profile_flag)  \
+       && uses_TOC())                                                  \
+      {                                                                        \
+       char buf[256];                                                  \
+                                                                       \
+       ASM_OUTPUT_INTERNAL_LABEL (FILE, "LCL", rs6000_pic_labelno);    \
+                                                                       \
+       ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);                  \
+       fputs ("\t.quad ", FILE);                                       \
+       assemble_name (FILE, buf);                                      \
+       putc ('-', FILE);                                               \
+       ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);   \
+       assemble_name (FILE, buf);                                      \
+       putc ('\n', FILE);                                              \
+      }                                                                        \
+                                                                       \
+    fprintf (FILE, "%s", TYPE_ASM_OP);                                 \
+    assemble_name (FILE, NAME);                                                \
+    putc (',', FILE);                                                  \
+    fprintf (FILE, TYPE_OPERAND_FMT, "function");                      \
+    putc ('\n', FILE);                                                 \
+    ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));                     \
+                                                                       \
+    if (DEFAULT_ABI == ABI_AIX)                                                \
+      {                                                                        \
+       const char *desc_name, *orig_name;                              \
+                                                                       \
+        STRIP_NAME_ENCODING (orig_name, NAME);                         \
+        desc_name = orig_name;                                         \
+       while (*desc_name == '.')                                       \
+         desc_name++;                                                  \
+                                                                       \
+       if (TREE_PUBLIC (DECL))                                         \
+         fprintf (FILE, "\t.globl %s\n", desc_name);                   \
+                                                                       \
+       fputs ("\t.section\t\".opd\",\"aw\"\n", FILE);                  \
+       fprintf (FILE, "%s:\n", desc_name);                             \
+       fprintf (FILE, "\t.quad %s\n", orig_name);                      \
+       fputs ("\t.quad .TOC.@tocbase\n", FILE);                        \
+       if (DEFAULT_ABI == ABI_AIX)                                     \
+         fputs ("\t.quad 0\n", FILE);                                  \
+       fprintf (FILE, "\t.previous\n");                                \
+      }                                                                        \
+    ASM_OUTPUT_LABEL (FILE, NAME);                                     \
+  } while (0)
+
+/* 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.  We also do this when
+   we can write the entry into the TOC and the entry is not larger
+   than a TOC entry.  */
+
+#undef  ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)                       \
+  (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                                    \
+       || (GET_CODE (X) == CONST_INT                                   \
+          && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))      \
+       || (GET_CODE (X) == CONST_DOUBLE                                        \
+          && (TARGET_POWERPC64                                         \
+              || TARGET_MINIMAL_TOC                                    \
+              || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT          \
+                  && ! TARGET_NO_FP_IN_TOC)))))
+
+/* This is how to output an assembler line defining an `int'
+   constant.  */
+#undef  ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE, VALUE)            \
+  do                                           \
+    {                                          \
+      fputs ("\t.long ", (FILE));              \
+      output_addr_const ((FILE), (VALUE));     \
+      putc ('\n', (FILE));                     \
+    }                                          \
+  while (0)
+
+/* This is how to output an assembler line defining a `double int'
+   constant.  */
+#undef  ASM_OUTPUT_DOUBLE_INT
+#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE)     \
+  do                                           \
+    {                                          \
+      fputs (DOUBLE_INT_ASM_OP, (FILE));       \
+      output_addr_const ((FILE), (VALUE));     \
+      putc ('\n', (FILE));                     \
+    }                                          \
+  while (0)
+
+#undef  ASM_DEFAULT_SPEC
+#define        ASM_DEFAULT_SPEC "-mppc64"
index 66547b10ba0fa38b45117543a5a4efdfed2bba2c..a6c2b013df1006bfc86499a2c4f94f6613031a00 100644 (file)
@@ -34,6 +34,7 @@ extern int any_operand PARAMS ((rtx, enum machine_mode));
 extern int short_cint_operand PARAMS ((rtx, enum machine_mode));
 extern int u_short_cint_operand PARAMS ((rtx, enum machine_mode));
 extern int non_short_cint_operand PARAMS ((rtx, enum machine_mode));
+extern int exact_log2_cint_operand PARAMS ((rtx, enum machine_mode));
 extern int gpc_reg_operand PARAMS ((rtx, enum machine_mode));
 extern int cc_reg_operand PARAMS ((rtx, enum machine_mode));
 extern int cc_reg_not_cr0_operand PARAMS ((rtx, enum machine_mode));
@@ -42,6 +43,8 @@ extern int reg_or_neg_short_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_or_u_short_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_or_cint_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_or_arith_cint_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_add_cint64_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_sub_cint64_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_or_logical_cint_operand PARAMS ((rtx, enum machine_mode));
 extern int got_operand PARAMS ((rtx, enum machine_mode));
 extern int got_no_const_operand PARAMS ((rtx, enum machine_mode));
@@ -96,6 +99,7 @@ extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode,
 extern void rs6000_emit_sCOND PARAMS ((enum rtx_code, rtx));
 extern void rs6000_emit_cbranch PARAMS ((enum rtx_code, rtx));
 extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
+extern rtx rs6000_emit_set_const PARAMS ((rtx, enum machine_mode, rtx, int));
 extern int rs6000_emit_cmove PARAMS ((rtx, rtx, rtx, rtx));
 extern void rs6000_emit_minmax PARAMS ((rtx, enum rtx_code, rtx, rtx));
 extern void output_toc PARAMS ((FILE *, rtx, int, enum machine_mode));
index 73aa3d505f0926b403048daaadb430a3da63bfb4..867206dedf42983fd866705d0647857f4088075f 100644 (file)
@@ -128,6 +128,8 @@ static int rs6000_ra_ever_killed PARAMS ((void));
 static int rs6000_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
 static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static rtx rs6000_emit_set_long_const PARAMS ((rtx,
+  HOST_WIDE_INT, HOST_WIDE_INT));
 \f
 /* Default register names.  */
 char rs6000_reg_names[][8] =
@@ -364,15 +366,16 @@ rs6000_override_options (default_cpu)
        }
     }
 
-  if (flag_pic && (DEFAULT_ABI == ABI_AIX))
+  if (flag_pic && DEFAULT_ABI == ABI_AIX)
     {
-      warning ("-f%s ignored for AIX (all code is position independent)",
+      warning ("-f%s ignored (all code is position independent)",
               (flag_pic > 1) ? "PIC" : "pic");
       flag_pic = 0;
     }
 
+#ifdef XCOFF_DEBUGGING_INFO
   if (flag_function_sections && (write_symbols != NO_DEBUG)
-      && (DEFAULT_ABI == ABI_AIX))
+      && DEFAULT_ABI == ABI_AIX)
     {
       warning ("-ffunction-sections disabled on AIX when debugging");
       flag_function_sections = 0;
@@ -383,6 +386,7 @@ rs6000_override_options (default_cpu)
       warning ("-fdata-sections not supported on AIX");
       flag_data_sections = 0;
     }
+#endif
 
   /* Set debug flags */
   if (rs6000_debug_name)
@@ -585,6 +589,19 @@ non_short_cint_operand (op, mode)
          && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
 }
 
+/* Returns 1 if OP is a CONST_INT that is a positive value
+   and an exact power of 2.  */
+
+int
+exact_log2_cint_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return (GET_CODE (op) == CONST_INT
+         && INTVAL (op) > 0
+         && exact_log2 (INTVAL (op)) >= 0);
+}
+
 /* Returns 1 if OP is a register that is not special (i.e., not MQ,
    ctr, or lr).  */
 
@@ -693,6 +710,42 @@ reg_or_arith_cint_operand (op, mode)
                 ));
 }
 
+/* Return 1 is the operand is either a non-special register or a 32-bit
+   signed constant integer valid for 64-bit addition.  */
+
+int
+reg_or_add_cint64_operand (op, mode)
+    register rtx op;
+    enum machine_mode mode;
+{
+     return (gpc_reg_operand (op, mode)
+            || (GET_CODE (op) == CONST_INT
+                && INTVAL (op) < 0x7fff8000
+#if HOST_BITS_PER_WIDE_INT != 32
+                && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
+                    < 0x100000000ll)
+#endif
+                ));
+}
+
+/* Return 1 is the operand is either a non-special register or a 32-bit
+   signed constant integer valid for 64-bit subtraction.  */
+
+int
+reg_or_sub_cint64_operand (op, mode)
+    register rtx op;
+    enum machine_mode mode;
+{
+     return (gpc_reg_operand (op, mode)
+            || (GET_CODE (op) == CONST_INT
+                && (- INTVAL (op)) < 0x7fff8000
+#if HOST_BITS_PER_WIDE_INT != 32
+                && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
+                    < 0x100000000ll)
+#endif
+                ));
+}
+
 /* Return 1 is the operand is either a non-special register or ANY
    32-bit unsigned constant integer.  */
 
@@ -996,9 +1049,11 @@ add_operand (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
-  return (reg_or_short_operand (op, mode)
-         || (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')));
+  if (GET_CODE (op) == CONST_INT)
+    return (CONST_OK_FOR_LETTER_P (INTVAL(op), 'I')
+           || CONST_OK_FOR_LETTER_P (INTVAL(op), 'L'));
+
+  return gpc_reg_operand (op, mode);
 }
 
 /* Return 1 if OP is a constant but not a valid add_operand.  */
@@ -1636,6 +1691,124 @@ rs6000_legitimate_address (mode, x, reg_ok_strict)
   return 0;
 }
 \f
+/* Try to output insns to set TARGET equal to the constant C if it can be
+   done in less than N insns.  Do all computations in MODE.  Returns the place
+   where the output has been placed if it can be done and the insns have been
+   emitted.  If it would take more than N insns, zero is returned and no
+   insns and emitted.  */
+
+rtx
+rs6000_emit_set_const (dest, mode, source, n)
+     rtx dest, source;
+     enum machine_mode mode;
+     int n ATTRIBUTE_UNUSED;
+{
+  HOST_WIDE_INT c0, c1;
+
+  if (mode == QImode || mode == HImode || mode == SImode)
+    {
+      if (dest == NULL)
+        dest = gen_reg_rtx (mode);
+      emit_insn (gen_rtx_SET (VOIDmode, dest, source));
+      return dest;
+    }
+
+  if (GET_CODE (source) == CONST_INT)
+    {
+      c0 = INTVAL (source);
+      c1 = -(c0 < 0);
+    }
+  else if (GET_CODE (source) == CONST_DOUBLE)
+    {
+#if HOST_BITS_PER_WIDE_INT >= 64
+      c0 = CONST_DOUBLE_LOW (source);
+      c1 = -(c0 < 0);
+#else
+      c0 = CONST_DOUBLE_LOW (source);
+      c1 = CONST_DOUBLE_HIGH (source);
+#endif
+    }
+  else
+    abort();
+
+  return rs6000_emit_set_long_const (dest, c0, c1);
+}
+
+/* Having failed to find a 3 insn sequence in rs6000_emit_set_const,
+   fall back to a straight forward decomposition.  We do this to avoid
+   exponential run times encountered when looking for longer sequences
+   with rs6000_emit_set_const.  */
+static rtx
+rs6000_emit_set_long_const (dest, c1, c2)
+     rtx dest;
+     HOST_WIDE_INT c1, c2;
+{
+  if (!TARGET_POWERPC64)
+    {
+      rtx operand1, operand2;
+
+      operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
+                                       DImode);
+      operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
+                                       DImode);
+      emit_move_insn (operand1, GEN_INT (c1));
+      emit_move_insn (operand2, GEN_INT (c2));
+    }
+  else
+    {
+      HOST_WIDE_INT d1, d2, d3, d4;
+
+  /* Decompose the entire word */
+#if HOST_BITS_PER_WIDE_INT >= 64
+      if (c2 != -(c1 < 0))
+       abort ();
+      d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+      c1 -= d1;
+      d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+      c1 = (c1 - d2) >> 32;
+      d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+      c1 -= d3;
+      d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+      if (c1 != d4)
+       abort ();
+#else
+      d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+      c1 -= d1;
+      d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+      if (c1 != d2)
+       abort ();
+      c2 += (d2 < 0);
+      d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
+      c2 -= d3;
+      d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+      if (c2 != d4)
+       abort ();
+#endif
+
+      /* Construct the high word */
+      if (d4)
+       {
+         emit_move_insn (dest, GEN_INT (d4));
+         if (d3)
+           emit_move_insn (dest,
+                           gen_rtx_PLUS (DImode, dest, GEN_INT (d3)));
+       }
+      else
+       emit_move_insn (dest, GEN_INT (d3));
+
+      /* Shift it into place */
+      emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
+
+      /* Add in the low bits.  */
+      if (d2)
+       emit_move_insn (dest, gen_rtx_PLUS (DImode, dest, GEN_INT (d2)));
+      if (d1)
+       emit_move_insn (dest, gen_rtx_PLUS (DImode, dest, GEN_INT (d1)));
+    }
+
+  return dest;
+}
+
 /* Emit a move from SOURCE to DEST in mode MODE.  */
 void
 rs6000_emit_move (dest, source, mode)
@@ -4107,6 +4280,7 @@ print_operand (file, x, code)
     case 'p':
       /* X is a CONST_INT that is a power of two.  Output the logarithm.  */
       if (! INT_P (x)
+         || INT_LOWPART (x) < 0
          || (i = exact_log2 (INT_LOWPART (x))) < 0)
        output_operand_lossage ("invalid %%p value");
       else
@@ -4512,19 +4686,33 @@ print_operand_address (file, x)
 #endif
   else if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
     {
-      if (TARGET_AIX)
+      if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
        {
-         rtx contains_minus = XEXP (x, 1); 
-         rtx minus;
+         rtx contains_minus = XEXP (x, 1);
+         rtx minus, symref;
+         const char *name;
          
          /* Find the (minus (sym) (toc)) buried in X, and temporarily
             turn it into (sym) for output_addr_const. */
          while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
            contains_minus = XEXP (contains_minus, 0);
 
-         minus = XEXP (contains_minus, 0); 
-         XEXP (contains_minus, 0) = XEXP (minus, 0);
-         output_addr_const (file, XEXP (x, 1));          
+         minus = XEXP (contains_minus, 0);
+         symref = XEXP (minus, 0);
+         XEXP (contains_minus, 0) = symref;
+         if (TARGET_ELF)
+           {
+             char *newname;
+
+             name = XSTR (symref, 0);
+             newname = alloca (strlen (name) + sizeof ("@toc"));
+             strcpy (newname, name);
+             strcat (newname, "@toc");
+             XSTR (symref, 0) = newname;
+           }
+         output_addr_const (file, XEXP (x, 1));
+         if (TARGET_ELF)
+           XSTR (symref, 0) = name;
          XEXP (contains_minus, 0) = minus;
        }
       else
@@ -5137,8 +5325,9 @@ rs6000_stack_info ()
   info_ptr->first_gp_reg_save = first_reg_to_save ();
   /* Assume that we will have to save PIC_OFFSET_TABLE_REGNUM, 
      even if it currently looks like we won't.  */
-  if (((flag_pic == 1
-       && (abi == ABI_V4 || abi == ABI_SOLARIS))
+  if (((TARGET_TOC && TARGET_MINIMAL_TOC)
+       || (flag_pic == 1
+          && (abi == ABI_V4 || abi == ABI_SOLARIS))
        || (flag_pic &&
           abi == ABI_DARWIN))
       && info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM)
@@ -5459,7 +5648,7 @@ rs6000_emit_load_toc_table (fromprolog)
   rtx dest;
   dest = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
 
-  if (TARGET_ELF)
+  if (TARGET_ELF && DEFAULT_ABI != ABI_AIX)
     {
       if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) 
          && flag_pic == 1)
@@ -5467,10 +5656,7 @@ rs6000_emit_load_toc_table (fromprolog)
          rtx temp = (fromprolog 
                      ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
                      : gen_reg_rtx (Pmode));
-         if (TARGET_32BIT)
-           rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
-         else
-           rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_di (temp)));
+         rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
          rs6000_maybe_dead (emit_move_insn (dest, temp));
        }
       else if (flag_pic == 2)
@@ -7259,19 +7445,19 @@ output_toc (file, x, labelno, mode)
       if (TARGET_64BIT)
        {
          if (TARGET_MINIMAL_TOC)
-           fprintf (file, "\t.llong 0x%lx%08lx\n", k[0], k[1]);
+           fputs (DOUBLE_INT_ASM_OP, file);
          else
-           fprintf (file, "\t.tc FD_%lx_%lx[TC],0x%lx%08lx\n",
-                    k[0], k[1], k[0] & 0xffffffff, k[1] & 0xffffffff);
+           fprintf (file, "\t.tc FD_%lx_%lx[TC],", k[0], k[1]);
+         fprintf (file, "0x%lx%08lx\n", k[0], k[1]);
          return;
        }
       else
        {
          if (TARGET_MINIMAL_TOC)
-           fprintf (file, "\t.long 0x%lx\n\t.long 0x%lx\n", k[0], k[1]);
+           fputs ("\t.long ", file);
          else
-           fprintf (file, "\t.tc FD_%lx_%lx[TC],0x%lx,0x%lx\n",
-                    k[0], k[1], k[0], k[1]);
+           fprintf (file, "\t.tc FD_%lx_%lx[TC],", k[0], k[1]);
+         fprintf (file, "0x%lx,0x%lx\n", k[0], k[1]);
          return;
        }
     }
@@ -7286,17 +7472,19 @@ output_toc (file, x, labelno, mode)
       if (TARGET_64BIT)
        {
          if (TARGET_MINIMAL_TOC)
-           fprintf (file, "\t.llong 0x%lx00000000\n", l);
+           fputs (DOUBLE_INT_ASM_OP, file);
          else
-           fprintf (file, "\t.tc FS_%lx[TC],0x%lx00000000\n", l, l);
+           fprintf (file, "\t.tc FS_%lx[TC],", l);
+         fprintf (file, "0x%lx00000000\n", l);
          return;
        }
       else
        {
          if (TARGET_MINIMAL_TOC)
-           fprintf (file, "\t.long 0x%lx\n", l);
+           fputs ("\t.long ", file);
          else
-           fprintf (file, "\t.tc FS_%lx[TC],0x%lx\n", l, l);
+           fprintf (file, "\t.tc FS_%lx[TC],", l);
+         fprintf (file, "0x%lx\n", l);
          return;
        }
     }
@@ -7344,10 +7532,10 @@ output_toc (file, x, labelno, mode)
       if (TARGET_64BIT)
        {
          if (TARGET_MINIMAL_TOC)
-           fprintf (file, "\t.llong 0x%lx%08lx\n", (long)high, (long)low);
+           fputs (DOUBLE_INT_ASM_OP, file);
          else
-           fprintf (file, "\t.tc ID_%lx_%lx[TC],0x%lx%08lx\n",
-                    (long)high, (long)low, (long)high, (long)low);
+           fprintf (file, "\t.tc ID_%lx_%lx[TC],", (long)high, (long)low);
+         fprintf (file, "0x%lx%08lx\n", (long) high, (long) low);
          return;
        }
       else
@@ -7355,20 +7543,19 @@ output_toc (file, x, labelno, mode)
          if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
            {
              if (TARGET_MINIMAL_TOC)
-               fprintf (file, "\t.long 0x%lx\n\t.long 0x%lx\n",
-                        (long)high, (long)low);
+               fputs ("\t.long ", file);
              else
-               fprintf (file, "\t.tc ID_%lx_%lx[TC],0x%lx,0x%lx\n",
-                        (long)high, (long)low, (long)high, (long)low);
+               fprintf (file, "\t.tc ID_%lx_%lx[TC],",
+                        (long)high, (long)low);
+             fprintf (file, "0x%lx,0x%lx\n", (long) high, (long) low);
            }
          else
            {
              if (TARGET_MINIMAL_TOC)
-               fprintf (file, "\t.long 0x%lx\n",
-                        (long)low);
+               fputs ("\t.long ", file);
              else
-               fprintf (file, "\t.tc IS_%lx[TC],0x%lx\n",
-                        (long)low, (long)low);
+               fprintf (file, "\t.tc IS_%lx[TC],", (long) low);
+             fprintf (file, "0x%lx\n", (long) low);
            }
          return;
        }
@@ -7376,6 +7563,9 @@ output_toc (file, x, labelno, mode)
 
   if (GET_CODE (x) == CONST)
     {
+      if (GET_CODE (XEXP (x, 0)) != PLUS)
+       abort ();
+
       base = XEXP (XEXP (x, 0), 0);
       offset = INTVAL (XEXP (XEXP (x, 0), 1));
     }
@@ -7391,7 +7581,7 @@ output_toc (file, x, labelno, mode)
 
   STRIP_NAME_ENCODING (real_name, name);
   if (TARGET_MINIMAL_TOC)
-    fputs (TARGET_32BIT ? "\t.long " : "\t.llong ", file);
+    fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
   else
     {
       fprintf (file, "\t.tc %s", real_name);
index 6464aa2c36efed284e410a7eddaa5cb06efa15d8..d7588300c88bd03c4ba47bb9aec6c7d76cfe2c51 100644 (file)
@@ -33,10 +33,14 @@ Boston, MA 02111-1307, USA.  */
 #define OBJECT_MACHO 4
 
 #define TARGET_ELF (TARGET_OBJECT_FORMAT == OBJECT_ELF)
-#define TARGET_AIX (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
+#define TARGET_XCOFF (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
 #define TARGET_MACOS (TARGET_OBJECT_FORMAT == OBJECT_PEF)
 #define TARGET_MACHO (TARGET_OBJECT_FORMAT == OBJECT_MACHO)
 
+#ifndef TARGET_AIX
+#define TARGET_AIX 0
+#endif
+
 /* Print subsidiary information on the compiler version in use.  */
 #define TARGET_VERSION ;
 
@@ -45,82 +49,6 @@ Boston, MA 02111-1307, USA.  */
 #define TARGET_CPU_DEFAULT ((char *)0)
 #endif
 
-/* Common CPP definitions used by CPP_SPEC among the various targets
-   for handling -mcpu=xxx switches.  */
-#define CPP_CPU_SPEC \
-"%{!mcpu*: \
-  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
-  %{mpower2: -D_ARCH_PWR2} \
-  %{mpowerpc*: -D_ARCH_PPC} \
-  %{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
-  %{!mno-power: %{!mpower2: %(cpp_default)}}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=power2: -D_ARCH_PWR2} \
-%{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=401: -D_ARCH_PPC} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=505: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=602: -D_ARCH_PPC} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=603e: -D_ARCH_PPC} \
-%{mcpu=ec603e: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC} \
-%{mcpu=604e: -D_ARCH_PPC} \
-%{mcpu=620: -D_ARCH_PPC} \
-%{mcpu=740: -D_ARCH_PPC} \
-%{mcpu=750: -D_ARCH_PPC} \
-%{mcpu=801: -D_ARCH_PPC} \
-%{mcpu=821: -D_ARCH_PPC} \
-%{mcpu=823: -D_ARCH_PPC} \
-%{mcpu=860: -D_ARCH_PPC}"
-
-#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
-
-/* Common ASM definitions used by ASM_SPEC among the various targets
-   for handling -mcpu=xxx switches.  */
-#define ASM_CPU_SPEC \
-"%{!mcpu*: \
-  %{mpower: %{!mpower2: -mpwr}} \
-  %{mpower2: -mpwrx} \
-  %{mpowerpc*: -mppc} \
-  %{mno-power: %{!mpowerpc*: -mcom}} \
-  %{!mno-power: %{!mpower2: %(asm_default)}}} \
-%{mcpu=common: -mcom} \
-%{mcpu=power: -mpwr} \
-%{mcpu=power2: -mpwrx} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rios: -mpwr} \
-%{mcpu=rios1: -mpwr} \
-%{mcpu=rios2: -mpwrx} \
-%{mcpu=rsc: -mpwr} \
-%{mcpu=rsc1: -mpwr} \
-%{mcpu=401: -mppc} \
-%{mcpu=403: -mppc} \
-%{mcpu=505: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=602: -mppc} \
-%{mcpu=603: -mppc} \
-%{mcpu=603e: -mppc} \
-%{mcpu=ec603e: -mppc} \
-%{mcpu=604: -mppc} \
-%{mcpu=604e: -mppc} \
-%{mcpu=620: -mppc} \
-%{mcpu=740: -mppc} \
-%{mcpu=750: -mppc} \
-%{mcpu=801: -mppc} \
-%{mcpu=821: -mppc} \
-%{mcpu=823: -mppc} \
-%{mcpu=860: -mppc}"
-
-#define ASM_DEFAULT_SPEC ""
-
 /* This macro defines names of additional specifications to put in the specs
    that can be used in various specifications like CC1_SPEC.  Its definition
    is an initializer with a subgrouping for each command option.
@@ -574,13 +502,6 @@ extern int rs6000_debug_arg;               /* debug argument handling */
 /* Handle #pragma pack.  */
 #define HANDLE_PRAGMA_PACK 1
 
-/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
-             ? get_inner_array_type (FIELD) \
-             : TREE_TYPE (FIELD)) == DFmode \
-   ? MIN ((COMPUTED), 32) : (COMPUTED))
-
 /* Alignment of field after `int : 0' in a structure.  */
 #define EMPTY_FIELD_BOUNDARY 32
 
@@ -590,17 +511,6 @@ extern int rs6000_debug_arg;               /* debug argument handling */
 /* A bitfield declared as `int' forces `int' alignment for the struct.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
 
-/* AIX increases natural record alignment to doubleword if the first
-   field is an FP double while the FP fields remain word aligned.  */
-#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)  \
-  ((TREE_CODE (STRUCT) == RECORD_TYPE                  \
-    || TREE_CODE (STRUCT) == UNION_TYPE                        \
-    || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)          \
-   && TYPE_FIELDS (STRUCT) != 0                                \
-   && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode       \
-   ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
-   : MAX ((COMPUTED), (SPECIFIED)))
-
 /* Make strings word-aligned so strcpy from constants will be faster.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
   (TREE_CODE (EXP) == STRING_CST       \
@@ -796,7 +706,7 @@ extern int rs6000_debug_arg;                /* debug argument handling */
    registers is expensive.  */
 
 #define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2)               \
-  ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2                \
+   ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2               \
    : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10     \
    : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10     \
    : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS         \
@@ -1050,7 +960,7 @@ enum reg_class
    `K' is a constant with only the low-order 16 bits non-zero
    `L' is a signed 16-bit constant shifted left 16 bits
    `M' is a constant that is greater than 31
-   `N' is a constant that is an exact power of two
+   `N' is a positive constant that is an exact power of two
    `O' is the constant zero
    `P' is a constant whose negation is a signed 16-bit constant */
 
@@ -1061,7 +971,7 @@ enum reg_class
    : (C) == 'L' ? (((VALUE) & 0xffff) == 0                             \
                   && ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0))      \
    : (C) == 'M' ? (VALUE) > 31                                         \
-   : (C) == 'N' ? exact_log2 (VALUE) >= 0                              \
+   : (C) == 'N' ? (VALUE) > 0 && exact_log2 (VALUE) >= 0               \
    : (C) == 'O' ? (VALUE) == 0                                         \
    : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
    : 0)
@@ -1384,8 +1294,8 @@ typedef struct rs6000_stack {
 /* 1 if N is a possible register number for function argument passing.
    On RS/6000, these are r3-r10 and fp1-fp13.  */
 #define FUNCTION_ARG_REGNO_P(N)                                                \
-  (((unsigned)((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG))     \
-   || ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
+  ((((N) - GP_ARG_MIN_REG) < (GP_ARG_NUM_REG)) \
+   || (((N) - FP_ARG_MIN_REG) < (FP_ARG_NUM_REG)))
 
 \f
 /* A C structure for machine-specific, per-function data.
@@ -1551,6 +1461,16 @@ typedef struct rs6000_args
    argument is passed depends on whether or not it is a named argument.  */
 #define STRICT_ARGUMENT_NAMING 1
 
+/* This macro generates the assembly code for function entry.
+   FILE is a stdio stream to output the code to.
+   SIZE is an int: how many units of temporary storage to allocate.
+   Refer to the array `regs_ever_live' to determine which registers
+   to save; `regs_ever_live[I]' is nonzero if register number I
+   is ever used in the function.  This macro is responsible for
+   knowing which registers should not be saved even if used.  */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
+
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
@@ -1575,6 +1495,18 @@ typedef struct rs6000_args
    || (current_function_calls_eh_return                                \
        && TARGET_AIX                                           \
        && (REGNO) == TOC_REGISTER))
+
+/* This macro generates the assembly code for function exit,
+   on machines that need it.  If FUNCTION_EPILOGUE is not defined
+   then individual return instructions are generated for each
+   return statement.  Args are same as for FUNCTION_PROLOGUE.
+
+   The function epilogue should not depend on the current stack pointer!
+   It should use the frame pointer only.  This is mandatory because
+   of alloca; we also take advantage of it to omit stack adjustments
+   before returning.  */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
 \f
 /* TRAMPOLINE_TEMPLATE deleted */
 
@@ -2281,10 +2213,6 @@ extern int toc_initialized;
     }                                                                    \
 }
 
-/* This is how we tell the assembler that two symbols have the same value.  */
-
-#define SET_ASM_OP "\t.set\t"
-
 /* This implementes the `alias' attribute.  */
 
 #define ASM_OUTPUT_DEF_FROM_DECLS(FILE,decl,target)    \
@@ -2498,7 +2426,7 @@ do {                                                                      \
     }                                                                  \
   else                                                                 \
     {                                                                  \
-      fputs ("\t.llong ", FILE);                                       \
+      fprintf (FILE, "\t%s ", DOUBLE_INT_ASM_OP);                      \
       output_addr_const (FILE, (VALUE));                               \
       putc ('\n', FILE);                                               \
     }                                                                  \
@@ -2527,7 +2455,7 @@ do {                                                                      \
   fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
 
 /* This is used by the definition of ASM_OUTPUT_ADDR_ELT in defaults.h.  */
-#define ASM_LONG (TARGET_32BIT ? ".long" : ".quad")
+#define ASM_LONG (TARGET_32BIT ? ".long" : DOUBLE_INT_ASM_OP)
 
 /* This is how to output an element of a case-vector that is relative.  */
 
@@ -2550,19 +2478,6 @@ do {                                                                     \
   if ((LOG) != 0)                      \
     fprintf (FILE, "\t.align %d\n", (LOG))
 
-/* This says how to output an assembler line
-   to define a local common symbol.
-   Alignment cannot be specified, but we can try to maintain
-   alignment after preceding TOC section if it was aligned
-   for 64-bit mode.  */
-
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)    \
-  do { fputs (".lcomm ", (FILE));                      \
-       RS6000_OUTPUT_BASENAME ((FILE), (NAME));                \
-       fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
-               xcoff_bss_section_name);                \
-     } while (0)
-
 /* Store in OUTPUT a string (made with alloca) containing
    an assembler-name for a local static variable named NAME.
    LABELNO is an integer which is different for each call.  */
@@ -2571,6 +2486,12 @@ do {                                                                     \
 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),   \
   sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
 
+/* Define the parentheses used to group arithmetic operations
+   in assembler code.  */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
 /* Pick up the return address upon entry to a procedure. Used for
    dwarf2 unwind information.  This also enables the table driven
    mechanism.  */
@@ -2603,6 +2524,7 @@ do {                                                                      \
   {"short_cint_operand", {CONST_INT}},                                    \
   {"u_short_cint_operand", {CONST_INT}},                                  \
   {"non_short_cint_operand", {CONST_INT}},                                \
+  {"exact_log2_cint_operand", {CONST_INT}},                               \
   {"gpc_reg_operand", {SUBREG, REG}},                                     \
   {"cc_reg_operand", {SUBREG, REG}},                                      \
   {"cc_reg_not_cr0_operand", {SUBREG, REG}},                              \
@@ -2611,6 +2533,8 @@ do {                                                                      \
   {"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}},                           \
   {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}},                      \
   {"reg_or_arith_cint_operand", {SUBREG, REG, CONST_INT}},                \
+  {"reg_or_add_cint64_operand", {SUBREG, REG, CONST_INT}},                \
+  {"reg_or_sub_cint64_operand", {SUBREG, REG, CONST_INT}},                \
   {"reg_or_logical_cint_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
   {"got_operand", {SYMBOL_REF, CONST, LABEL_REF}},                        \
   {"got_no_const_operand", {SYMBOL_REF, LABEL_REF}},                      \
index e23e289ec33a6fc9d6165edff06306776d86a06d..5f4036609b8551ac42f64fcab8d33f2b20be782f 100644 (file)
       rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (SImode));
 
-      HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
-      HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
-      if (low & 0x8000)
-       {
-         high = trunc_int_for_mode (high + 0x10000, SImode);
-         low = trunc_int_for_mode (low, HImode);
-       }
+      HOST_WIDE_INT val = INTVAL (operands[2]);
+      HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+      HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
 
       /* The ordering here is important for the prolog expander.
         When space is allocated from the stack, adding 'low' first may
         produce a temporary deallocation (which would be bad).  */
-      emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (high)));
+      emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest)));
       emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
       DONE;
     }
    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
 "
 {
-  HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
-  HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
-  if (low & 0x8000)
-    {
-      high = trunc_int_for_mode (high + 0x10000, SImode);
-      low = trunc_int_for_mode (low, HImode);
-    }
+  HOST_WIDE_INT val = INTVAL (operands[2]);
+  HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+  HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
 
-  operands[3] = GEN_INT (high);
+  operands[3] = GEN_INT (rest);
   operands[4] = GEN_INT (low);
 }")
 
   "
 {
   if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) > 0
       && exact_log2 (INTVAL (operands[2])) >= 0)
     ;
   else if (TARGET_POWERPC)
   rtx temp1;
   rtx temp2;
 
-  if (GET_CODE (operands[2]) != CONST_INT)
-    FAIL;
-
-  i = exact_log2 (INTVAL (operands[2]));
-
-  if (i < 0)
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) < 0
+      || (i = exact_log2 (INTVAL (operands[2]))) < 0)
     FAIL;
 
   temp1 = gen_reg_rtx (SImode);
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-               (match_operand:SI 2 "const_int_operand" "N")))]
-  "exact_log2 (INTVAL (operands[2])) >= 0"
+               (match_operand:SI 2 "exact_log2_cint_operand" "N")))]
+  ""
   "{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
   [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "const_int_operand" "N,N"))
+                           (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
    (clobber (match_scratch:SI 3 "=r,r"))]
-  "exact_log2 (INTVAL (operands[2])) >= 0"
+  ""
   "@
    {srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
    #"
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
        (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
+                           (match_operand:SI 2 "exact_log2_cint_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:SI 3 ""))]
-  "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+  "reload_completed"
   [(set (match_dup 3)
        (div:SI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:SI 2 "const_int_operand" "N,N"))
+                           (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
    (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (div:SI (match_dup 1) (match_dup 2)))]
-  "exact_log2 (INTVAL (operands[2])) >= 0"
+  ""
   "@
    {srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
    #"
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
        (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                           (match_operand:SI 2 "const_int_operand" ""))
+                           (match_operand:SI 2 "exact_log2_cint_operand" ""))
                    (const_int 0)))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
        (div:SI (match_dup 1) (match_dup 2)))]
-  "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+  "reload_completed"
   [(set (match_dup 0)
        (div:SI (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
 (define_expand "adddi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+                (match_operand:DI 2 "reg_or_add_cint64_operand" "")))]
   ""
   "
 {
        rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
                   ? operands[0] : gen_reg_rtx (DImode));
 
-       HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
-       HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+       HOST_WIDE_INT val = INTVAL (operands[2]);
+       HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+       HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
 
-       if (low & 0x8000)
-         {
-           high = trunc_int_for_mode (high + 0x10000, SImode);
-           low = trunc_int_for_mode (low, HImode);
-         }
+       if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
+         FAIL;
 
-       emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
+       /* The ordering here is important for the prolog expander.
+          When space is allocated from the stack, adding 'low' first may
+          produce a temporary deallocation (which would be bad).  */
+       emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest)));
        emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
        DONE;
       }
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
 "
 {
-  HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
-  HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+  HOST_WIDE_INT val = INTVAL (operands[2]);
+  HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+  HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
 
-  if (low & 0x8000)
+  operands[4] = GEN_INT (low);
+  if (CONST_OK_FOR_LETTER_P (rest, 'L'))
+    operands[3] = GEN_INT (rest);
+  else if (! no_new_pseudos)
     {
-      high = trunc_int_for_mode (high + 0x10000, SImode);
-      low = trunc_int_for_mode (low, HImode);
+      operands[3] = gen_reg_rtx (DImode);
+      emit_move_insn (operands[3], operands[2]);
+      emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
+      DONE;
     }
-
-  operands[3] = GEN_INT (high);
-  operands[4] = GEN_INT (low);
+  else
+    FAIL;
 }")
 
 (define_insn "one_cmpldi2"
 (define_expand "subdi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
-                 (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+                 (match_operand:DI 2 "reg_or_sub_cint64_operand" "")))]
   ""
   "
 {
   "
 {
   if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) > 0
       && exact_log2 (INTVAL (operands[2])) >= 0)
     ;
   else
   "TARGET_POWERPC64"
   "
 {
-  int i = exact_log2 (INTVAL (operands[2]));
+  int i;
   rtx temp1;
   rtx temp2;
 
-  if (GET_CODE (operands[2]) != CONST_INT || i < 0)
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) <= 0
+      || (i = exact_log2 (INTVAL (operands[2]))) < 0)
     FAIL;
 
   temp1 = gen_reg_rtx (DImode);
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
-               (match_operand:DI 2 "const_int_operand" "N")))]
-  "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+               (match_operand:DI 2 "exact_log2_cint_operand" "N")))]
+  "TARGET_POWERPC64"
   "sradi %0,%1,%p2\;addze %0,%0"
   [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
        (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:DI 2 "const_int_operand" "N,N"))
+                           (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
    (clobber (match_scratch:DI 3 "=r,r"))]
-  "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+  "TARGET_POWERPC64"
   "@
    sradi %3,%1,%p2\;addze. %3,%3
    #"
 (define_split
   [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
        (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "const_int_operand" ""))
+                           (match_operand:DI 2 "exact_log2_cint_operand" ""))
                    (const_int 0)))
    (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+  "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 3)
        (div:DI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
        (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                           (match_operand:DI 2 "const_int_operand" "N,N"))
+                           (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (div:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+  "TARGET_POWERPC64"
   "@
    sradi %0,%1,%p2\;addze. %0,%0
    #"
 (define_split
   [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
        (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                           (match_operand:DI 2 "const_int_operand" ""))
+                           (match_operand:DI 2 "exact_log2_cint_operand" ""))
                    (const_int 0)))
    (set (match_operand:DI 0 "gpc_reg_operand" "")
        (div:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+  "TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 0)
        (div:DI (match_dup 1) (match_dup 2)))
    (set (match_dup 3)
         ? \"li %0,%1\" : \"lis %0,%v1\";
 }")
 
-;; sign-extended 32-bit value
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_int_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
-   && num_insns_constant (operands[1], DImode) > 1"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 3)))]
-  "
-{
-  operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
-  operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
-}")
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && ((CONST_DOUBLE_HIGH (operands[1]) == 0
-        && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
-       || (CONST_DOUBLE_HIGH (operands[1]) == -1
-           && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 3)))]
-  "
-{
-  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
-  operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xffff);
-}")
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_int_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_INT
-   && (((INTVAL (operands[1]) >> 32) == 0
-        && (INTVAL (operands[1]) & 0x80000000) == 0)
-       || ((INTVAL (operands[1]) >> 32) == -1
-           && (INTVAL (operands[1]) & 0x80000000) != 0))
-   && num_insns_constant (operands[1], DImode) > 1"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 3)))]
-  "
-{
-  operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
-  operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
-}")
-
-;; zero-extended 32-bit value
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && CONST_DOUBLE_HIGH (operands[1]) == 0
-   && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (zero_extend:DI (match_dup 3)))]
-  "
-{ 
-  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); 
-  operands[3] = gen_lowpart_common (SImode, operands[0]);
-}")
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_int_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_INT
-   && INTVAL (operands[1]) >> 32 == 0
-   && (INTVAL (operands[1]) & 0x80000000) != 0
-   && num_insns_constant (operands[1], DImode) > 1"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (zero_extend:DI (match_dup 3)))]
-  "
-{
-#if HOST_BITS_PER_WIDE_INT != 32
-  operands[2] = GEN_INT ((INTVAL (operands[1]) ^ 0x80000000) - 0x80000000);
-#endif
-  operands[3] = gen_lowpart_common (SImode, operands[0]);
-}")
-
-;; 32-bit value in upper half of doubleword
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && CONST_DOUBLE_LOW (operands[1]) == 0"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ashift:DI (match_dup 0)
-                  (const_int 32)))]
-  "
-{ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); }")
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_int_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
-   && GET_CODE (operands[1]) == CONST_INT
-   && (INTVAL (operands[1]) & 0xffffffff) == 0"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ashift:DI (match_dup 0)
-                  (const_int 32)))]
-  "
-{
-#if HOST_BITS_PER_WIDE_INT != 32
-operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
-#endif
-}")
-
 ;; Generate all one-bits and clear left or right.
 ;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
 (define_split
@@ -8025,55 +7893,35 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 ;; easy_fp_constant predicate.
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
-   && num_insns_constant (operands[1], DImode) > 1"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ashift:DI (match_dup 0)
-                  (const_int 32)))
-   (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 3)))]
+       (match_operand:DI 1 "const_int_operand" ""))]
+  "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
   "
-{
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    {
-      operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-      operands[3] = immed_double_const (CONST_DOUBLE_LOW (operands[1]),
-                                       0, DImode);
-    }
+{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
+
+  if (tem == operands[0])
+    DONE;
   else
-    {
-      HOST_WIDE_INT value = INTVAL (operands[1]);
-      operands[2] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
-      operands[3] = immed_double_const (value, 0, DImode);
-    }
+    FAIL;
 }")
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (match_operand:DI 1 "const_int_operand" ""))]
-  "HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
-   && num_insns_constant (operands[1], DImode) > 1"
-  [(set (match_dup 0)
-       (match_dup 2))
-   (set (match_dup 0)
-       (ashift:DI (match_dup 0)
-                  (const_int 32)))
-   (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 3)))]
+       (match_operand:DI 1 "const_double_operand" ""))]
+  "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
   "
-{
-#if HOST_BITS_PER_WIDE_INT != 32
-  HOST_WIDE_INT value = INTVAL (operands[1]);
-  operands[2] = GEN_INT (value >> 32);
-  operands[3] = GEN_INT ((value & 0x7fffffff) - (value & 0x80000000));
-#endif
+{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
+
+  if (tem == operands[0])
+    DONE;
+  else
+    FAIL;
 }")
 
+;; Split a load of a large constant into the appropriate five-instruction
 (define_insn "*movdi_internal2"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
        (compare:CC (match_operand:DI 1 "gpc_reg_operand" "r,r")
@@ -9068,7 +8916,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 (define_insn "load_toc_aix_si"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (unspec:SI [(const_int 0)] 7))]
-  "! TARGET_ELF && TARGET_32BIT"
+  "DEFAULT_ABI == ABI_AIX && TARGET_32BIT"
   "*
 {
   char buf[30];
@@ -9082,11 +8930,13 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 (define_insn "load_toc_aix_di"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(const_int 0)] 7))]
-  "! TARGET_ELF && TARGET_64BIT"
+  "DEFAULT_ABI == ABI_AIX && TARGET_64BIT"
   "*
 {
   char buf[30];
   ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", 1);
+  if (TARGET_ELF)
+    strcat (buf, \"@toc\");
   operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
   operands[2] = gen_rtx_REG (Pmode, 2);
   return \"ld %0,%1(%2)\";
@@ -9102,15 +8952,6 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
-(define_insn "load_toc_v4_pic_di"
-  [(set (match_operand:DI 0 "register_operand" "=l")
-       (unspec:DI [(const_int 0)] 7))]
-  "(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1
-   && TARGET_64BIT"
-  "bl _GLOBAL_OFFSET_TABLE_@local-4"
-  [(set_attr "type" "branch")
-   (set_attr "length" "4")])
-
 (define_insn "load_toc_v4_PIC_1"
   [(set (match_operand:SI 0 "register_operand" "=l")
        (match_operand:SI 1 "immediate_operand" "s"))
index 39017b11d5ec4eb6f61fbb675697a0947a3dced0..c8930c7e103316cc1094204cbf8b30905c5934ee 100644 (file)
@@ -37,6 +37,79 @@ Boston, MA 02111-1307, USA.  */
 /* Override rs6000.h definition.  */
 #undef CPP_DEFAULT_SPEC
 #define        CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+/* Common CPP definitions used by CPP_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#define CPP_CPU_SPEC \
+"%{!mcpu*: \
+  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
+  %{mpower2: -D_ARCH_PWR2} \
+  %{mpowerpc*: -D_ARCH_PPC} \
+  %{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
+  %{!mno-power: %{!mpower2: %(cpp_default)}}} \
+%{mcpu=common: -D_ARCH_COM} \
+%{mcpu=power: -D_ARCH_PWR} \
+%{mcpu=power2: -D_ARCH_PWR2} \
+%{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=401: -D_ARCH_PPC} \
+%{mcpu=403: -D_ARCH_PPC} \
+%{mcpu=505: -D_ARCH_PPC} \
+%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
+%{mcpu=603: -D_ARCH_PPC} \
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=ec603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=604e: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC} \
+%{mcpu=740: -D_ARCH_PPC} \
+%{mcpu=750: -D_ARCH_PPC} \
+%{mcpu=801: -D_ARCH_PPC} \
+%{mcpu=821: -D_ARCH_PPC} \
+%{mcpu=823: -D_ARCH_PPC} \
+%{mcpu=860: -D_ARCH_PPC}"
+
+#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+
+/* Common ASM definitions used by ASM_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#define ASM_CPU_SPEC \
+"%{!mcpu*: \
+  %{mpower: %{!mpower2: -mpwr}} \
+  %{mpower2: -mpwrx} \
+  %{mpowerpc*: -mppc} \
+  %{mno-power: %{!mpowerpc*: -mcom}} \
+  %{!mno-power: %{!mpower2: %(asm_default)}}} \
+%{mcpu=common: -mcom} \
+%{mcpu=power: -mpwr} \
+%{mcpu=power2: -mpwrx} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rios: -mpwr} \
+%{mcpu=rios1: -mpwr} \
+%{mcpu=rios2: -mpwrx} \
+%{mcpu=rsc: -mpwr} \
+%{mcpu=rsc1: -mpwr} \
+%{mcpu=401: -mppc} \
+%{mcpu=403: -mppc} \
+%{mcpu=505: -mppc} \
+%{mcpu=601: -m601} \
+%{mcpu=602: -mppc} \
+%{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
+%{mcpu=ec603e: -mppc} \
+%{mcpu=604: -mppc} \
+%{mcpu=604e: -mppc} \
+%{mcpu=620: -mppc} \
+%{mcpu=740: -mppc} \
+%{mcpu=750: -mppc} \
+%{mcpu=801: -mppc} \
+%{mcpu=821: -mppc} \
+%{mcpu=823: -mppc} \
+%{mcpu=860: -mppc}"
 
 /* Small data support types.  */
 enum rs6000_sdata_type {
@@ -694,10 +767,9 @@ extern int rs6000_pic_labelno;
     the return address.  Hence returning from FUNCTION will return to whoever
     called the current thunk'.
 
-    The effect must be as if FUNCTION had been called directly with
-    the adjusted first argument.  This macro is responsible for
-    emitting all of the code for a thunk function;
-    output_function_prologue() and output_function_epilogue() are not
+    The effect must be as if FUNCTION had been called directly with the adjusted
+    first argument.  This macro is responsible for emitting all of the code for
+    a thunk function; FUNCTION_PROLOGUE' and FUNCTION_EPILOGUE' are not
     invoked.
 
     The THUNK_FNDECL is redundant.  (DELTA and FUNCTION have already been
@@ -1191,11 +1263,11 @@ do {                                                                    \
 
 #define        CPP_SYSV_DEFAULT_SPEC "-D_CALL_SYSV"
 
-#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Aendian=big"
+#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Amachine=bigendian"
 
-#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Aendian=little"
+#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Amachine=littleendian"
 
-#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Aendian=little"
+#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Amachine=littleendian"
 
 /* For solaris, don't define _LITTLE_ENDIAN, it conflicts with a header file.  */
 #define        CPP_ENDIAN_SPEC \
@@ -1606,3 +1678,4 @@ do {                                                                      \
    : DW_EH_PE_absptr)
 
 #define EXCEPTION_SECTION readonly_data_section
+#define DOUBLE_INT_ASM_OP ".quad"
diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h
new file mode 100644 (file)
index 0000000..53cc7e7
--- /dev/null
@@ -0,0 +1,502 @@
+/* Definitions of target machine for GNU compiler,
+   for some generic XCOFF file format
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
+
+/* The AIX linker will discard static constructors in object files before
+   collect has a chance to see them, so scan the object files directly.  */
+#define COLLECT_EXPORT_LIST
+
+/* The RS/6000 uses the XCOFF format.  */
+#define XCOFF_DEBUGGING_INFO
+
+/* Define if the object format being used is COFF or a superset.  */
+#define OBJECT_FORMAT_COFF
+
+/* Define the magic numbers that we recognize as COFF.
+    AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit objects and AIX V5 adds
+    U64_TOCMAGIC (0767), but collect2.c does not include files in the
+    correct order to conditionally define the symbolic name in this macro.
+    The AIX linker accepts import/export files as object files,
+    so accept "#!" (0x2321) magic number.  */
+#define MY_ISCOFF(magic) \
+  ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC \
+   || (magic) == U802TOCMAGIC || (magic) == 0757 || (magic) == 0767 \
+   || (magic) == 0x2321)
+
+/* We don't have GAS for the RS/6000 yet, so don't write out special
+    .stabs in cc1plus.  */
+
+#define FASCIST_ASSEMBLER
+
+/* We define this to prevent the name mangler from putting dollar signs into
+   function names.  */
+
+#define NO_DOLLAR_IN_LABEL
+
+/* We define this to 0 so that gcc will never accept a dollar sign in a
+   variable name.  This is needed because the AIX assembler will not accept
+   dollar signs.  */
+
+#define DOLLARS_IN_IDENTIFIERS 0
+
+/* Define the extra sections we need.  We define three: one is the read-only
+   data section which is used for constants.  This is a csect whose name is
+   derived from the name of the input file.  The second is for initialized
+   global variables.  This is a csect whose name is that of the variable.
+   The third is the TOC.  */
+
+#define EXTRA_SECTIONS \
+   read_only_data, private_data, read_only_private_data, toc, bss
+
+/* Define the routines to implement these extra sections.
+   BIGGEST_ALIGNMENT is 64, so align the sections that much.  */
+
+#define EXTRA_SECTION_FUNCTIONS                                \
+                                                       \
+void                                                   \
+read_only_data_section ()                              \
+{                                                      \
+  if (in_section != read_only_data)                    \
+    {                                                  \
+      fprintf (asm_out_file, "\t.csect %s[RO],3\n",    \
+              xcoff_read_only_section_name);           \
+      in_section = read_only_data;                     \
+    }                                                  \
+}                                                      \
+                                                       \
+void                                                   \
+private_data_section ()                                        \
+{                                                      \
+  if (in_section != private_data)                      \
+    {                                                  \
+      fprintf (asm_out_file, "\t.csect %s[RW],3\n",    \
+              xcoff_private_data_section_name);        \
+      in_section = private_data;                       \
+    }                                                  \
+}                                                      \
+                                                       \
+void                                                   \
+read_only_private_data_section ()                      \
+{                                                      \
+  if (in_section != read_only_private_data)            \
+    {                                                  \
+      fprintf (asm_out_file, "\t.csect %s[RO],3\n",    \
+              xcoff_private_data_section_name);        \
+      in_section = read_only_private_data;             \
+    }                                                  \
+}                                                      \
+                                                       \
+void                                                   \
+toc_section ()                                         \
+{                                                      \
+  if (TARGET_MINIMAL_TOC)                              \
+    {                                                  \
+      /* toc_section is always called at least once from ASM_FILE_START, \
+        so this is guaranteed to always be defined once and only once   \
+        in each file.  */                                               \
+      if (! toc_initialized)                           \
+       {                                               \
+         fputs ("\t.toc\nLCTOC..1:\n", asm_out_file);  \
+         fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
+         toc_initialized = 1;                          \
+       }                                               \
+                                                       \
+      if (in_section != toc)                           \
+       fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n",    \
+                (TARGET_32BIT ? "" : ",3"));           \
+    }                                                  \
+  else                                                 \
+    {                                                  \
+      if (in_section != toc)                           \
+        fputs ("\t.toc\n", asm_out_file);              \
+    }                                                  \
+  in_section = toc;                                    \
+}
+
+/* Define the name of our readonly data section.  */
+
+#define READONLY_DATA_SECTION read_only_data_section
+
+/* Select the section for an initialized data object.
+
+   On the RS/6000, we have a special section for all variables except those
+   that are static.  */
+
+#define SELECT_SECTION(EXP,RELOC)                      \
+{                                                      \
+  if ((TREE_CODE (EXP) == STRING_CST                   \
+       && ! flag_writable_strings)                     \
+      || (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd'     \
+         && TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
+         && DECL_INITIAL (EXP)                         \
+         && (DECL_INITIAL (EXP) == error_mark_node     \
+             || TREE_CONSTANT (DECL_INITIAL (EXP)))    \
+         && ! (RELOC)))                                \
+    {                                                  \
+      if (TREE_PUBLIC (EXP))                           \
+        read_only_data_section ();                     \
+      else                                             \
+        read_only_private_data_section ();             \
+    }                                                  \
+  else                                                 \
+    {                                                  \
+      if (TREE_PUBLIC (EXP))                           \
+        data_section ();                               \
+      else                                             \
+        private_data_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.  We also do this when
+   we can write the entry into the TOC and the entry is not larger
+   than a TOC entry.  */
+
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)                       \
+  (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                                    \
+       || (GET_CODE (X) == CONST_INT                                   \
+          && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))      \
+       || (GET_CODE (X) == CONST_DOUBLE                                        \
+          && (TARGET_POWERPC64                                         \
+              || TARGET_MINIMAL_TOC                                    \
+              || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT          \
+                  && ! TARGET_NO_FP_IN_TOC)))))
+
+/* Select section for constant in constant pool.
+
+   On RS/6000, all constants are in the private read-only data area.
+   However, if this is being placed in the TOC it must be output as a
+   toc entry.  */
+
+#define SELECT_RTX_SECTION(MODE, X)                    \
+{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE))       \
+    toc_section ();                                    \
+  else                                                 \
+    read_only_private_data_section ();                 \
+}
+
+/* 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.  Do not set this flag if the function is weakly defined. */
+
+#define ENCODE_SECTION_INFO(DECL)                      \
+  if (TREE_CODE (DECL) == FUNCTION_DECL                        \
+      && !TREE_PUBLIC (DECL)                           \
+      && !DECL_WEAK (DECL))                            \
+    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+
+/* FP save and restore routines.  */
+#define        SAVE_FP_PREFIX "._savef"
+#define SAVE_FP_SUFFIX ""
+#define        RESTORE_FP_PREFIX "._restf"
+#define RESTORE_FP_SUFFIX ""
+
+/* Function name to call to do profiling.  */
+#define RS6000_MCOUNT ".__mcount"
+
+/* Function names to call to do floating point truncation.  */
+
+#define RS6000_ITRUNC "__itrunc"
+#define RS6000_UITRUNC "__uitrunc"
+
+/* This outputs NAME to FILE up to the first null or '['.  */
+
+#define RS6000_OUTPUT_BASENAME(FILE, NAME)     \
+  {                                            \
+    const char *_p;                            \
+                                               \
+    STRIP_NAME_ENCODING (_p, (NAME));          \
+    assemble_name ((FILE), _p);                        \
+  }
+
+/* This is how to output the definition of a user-level label named NAME,
+   such as the label on a static function or variable NAME.  */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME)    \
+  do { RS6000_OUTPUT_BASENAME (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+   defined for reference from other files.  */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+  do { fputs ("\t.globl ", FILE);      \
+       RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
+
+/* Remove any trailing [DS] or the like from the symbol name.  */
+
+#define STRIP_NAME_ENCODING(VAR,NAME)                  \
+  do                                                   \
+    {                                                  \
+      const char *_name = (NAME);                      \
+      size_t _len;                                     \
+      if (*_name == '*')                               \
+        _name++;                                       \
+      _len = strlen (_name);                           \
+      if (_name[_len - 1] != ']')                      \
+       (VAR) = _name;                                  \
+      else                                             \
+       {                                               \
+         char *_new_name = (char *) alloca (_len + 1); \
+         strcpy (_new_name, _name);                    \
+         _new_name[_len - 4] = '\0';                   \
+         (VAR) = _new_name;                            \
+       }                                               \
+    }                                                  \
+  while (0)
+
+/* Output at beginning of assembler file.
+
+   Initialize the section names for the RS/6000 at this point.
+
+   Specify filename, including full path, to assembler.
+
+   We want to go into the TOC section so at least one .toc will be emitted.
+   Also, in order to output proper .bs/.es pairs, we need at least one static
+   [RW] section emitted.
+
+   Finally, declare mcount when profiling to make the assembler happy.  */
+
+#define ASM_FILE_START(FILE)                                   \
+{                                                              \
+  rs6000_gen_section_name (&xcoff_bss_section_name,            \
+                          main_input_filename, ".bss_");       \
+  rs6000_gen_section_name (&xcoff_private_data_section_name,   \
+                          main_input_filename, ".rw_");        \
+  rs6000_gen_section_name (&xcoff_read_only_section_name,      \
+                          main_input_filename, ".ro_");        \
+                                                               \
+  fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename);    \
+  if (TARGET_64BIT)                                            \
+    fputs ("\t.machine\t\"ppc64\"\n", FILE);                   \
+  toc_section ();                                              \
+  if (write_symbols != NO_DEBUG)                               \
+    private_data_section ();                                   \
+  text_section ();                                             \
+  if (profile_flag)                                            \
+    fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT);           \
+  rs6000_file_start (FILE, TARGET_CPU_DEFAULT);                        \
+}
+
+/* Output at end of assembler file.
+
+   On the RS/6000, referencing data should automatically pull in text.  */
+
+#define ASM_FILE_END(FILE)                                     \
+{                                                              \
+  text_section ();                                             \
+  fputs ("_section_.text:\n", FILE);                           \
+  data_section ();                                             \
+  fputs (TARGET_32BIT                                          \
+        ? "\t.long _section_.text\n" : "\t.llong _section_.text\n", FILE); \
+}
+
+/* This macro produces the initial definition of a function name.
+   On the RS/6000, we need to place an extra '.' in the function name and
+   output the function descriptor.
+
+   The csect for the function will have already been created by the
+   `text_section' call previously done.  We do have to go back to that
+   csect, however.
+
+   We also record that the function exists in the current compilation
+   unit, reachable by short branch, by setting SYMBOL_REF_FLAG.
+
+   The third and fourth parameters to the .function pseudo-op (16 and 044)
+   are placeholders which no longer have any use.  */
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)              \
+{ rtx sym_ref = XEXP (DECL_RTL (DECL), 0);                     \
+  if (!DECL_WEAK (DECL))                                       \
+    SYMBOL_REF_FLAG (sym_ref) = 1;                             \
+  if (TREE_PUBLIC (DECL))                                      \
+    {                                                          \
+      fputs ("\t.globl .", FILE);                              \
+      RS6000_OUTPUT_BASENAME (FILE, NAME);                     \
+      putc ('\n', FILE);                                       \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      fputs ("\t.lglobl .", FILE);                             \
+      RS6000_OUTPUT_BASENAME (FILE, NAME);                     \
+      putc ('\n', FILE);                                       \
+    }                                                          \
+  fputs ("\t.csect ", FILE);                                   \
+  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
+  fputs (TARGET_32BIT ? "[DS]\n" : "[DS],3\n", FILE);          \
+  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
+  fputs (":\n", FILE);                                         \
+  fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE);     \
+  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
+  fputs (", TOC[tc0], 0\n", FILE);                             \
+  in_section = no_section;                                     \
+  function_section(DECL);                                      \
+  putc ('.', FILE);                                            \
+  RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
+  fputs (":\n", FILE);                                         \
+  if (write_symbols == XCOFF_DEBUG)                            \
+    xcoffout_declare_function (FILE, DECL, NAME);              \
+}
+
+/* Output a reference to SYM on FILE.  */
+
+#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
+  rs6000_output_symbol_ref (FILE, SYM)
+
+/* This says how to output an external.  */
+
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)  \
+{ rtx _symref = XEXP (DECL_RTL (DECL), 0);     \
+  if ((TREE_CODE (DECL) == VAR_DECL            \
+       || TREE_CODE (DECL) == FUNCTION_DECL)   \
+      && (NAME)[strlen (NAME) - 1] != ']')     \
+    {                                          \
+      char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
+      strcpy (_name, XSTR (_symref, 0));       \
+      strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
+      XSTR (_symref, 0) = _name;               \
+    }                                          \
+}
+
+/* This is how to output an internal numbered label where
+   PREFIX is the class of label and NUM is the number within the class.  */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)     \
+  fprintf (FILE, "%s..%d:\n", PREFIX, NUM)
+
+/* This is how to output an internal label prefix.  rs6000.c uses this
+   when generating traceback tables.  */
+
+#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX)   \
+  fprintf (FILE, "%s..", PREFIX)
+
+/* This is how to output a label for a jump table.  Arguments are the same as
+   for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
+   passed. */
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN)       \
+{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
+
+/* This is how to store into the string LABEL
+   the symbol_ref name of an internal numbered label where
+   PREFIX is the class of label and NUM is the number within the class.
+   This is suitable for output with `assemble_name'.  */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
+  sprintf (LABEL, "*%s..%ld", (PREFIX), (long)(NUM))
+
+/* This is how to output an assembler line to define N characters starting
+   at P to FILE.  */
+
+#define ASM_OUTPUT_ASCII(FILE, P, N)  output_ascii ((FILE), (P), (N))
+
+/* This is how to advance the location counter by SIZE bytes.  */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
+  fprintf (FILE, "\t.space %d\n", (SIZE))
+
+/* This says how to output an assembler line
+   to define a global common symbol.  */
+
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
+  do { fputs (".comm ", (FILE));                       \
+       RS6000_OUTPUT_BASENAME ((FILE), (NAME));                \
+       if ( (SIZE) > 4)                                        \
+         fprintf ((FILE), ",%d,3\n", (SIZE));          \
+       else                                            \
+        fprintf ((FILE), ",%d\n", (SIZE));             \
+  } while (0)
+
+/* Used by definition of ASM_OUTPUT_DOUBLE_INT */
+#define DOUBLE_INT_ASM_OP ".llong"
+
+/* This says how to output an assembler line
+   to define a local common symbol.
+   Alignment cannot be specified, but we can try to maintain
+   alignment after preceding TOC section if it was aligned
+   for 64-bit mode.  */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)    \
+  do { fputs (".lcomm ", (FILE));                      \
+       RS6000_OUTPUT_BASENAME ((FILE), (NAME));                \
+       fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
+               xcoff_bss_section_name);                \
+     } while (0)
+
+/* This is how we tell the assembler that two symbols have the same value.  */
+
+#define SET_ASM_OP "\t.set\t"
+
+/* These are various definitions for DWARF output.  They could just
+   use '.long' or '.word', but that aligns to a 4-byte boundary which
+   is not what is required.  So we define a million macros...  */
+
+#define UNALIGNED_SHORT_ASM_OP         "\t.vbyte\t2,"
+#define UNALIGNED_INT_ASM_OP           "\t.vbyte\t4,"
+#define UNALIGNED_DOUBLE_INT_ASM_OP    "\t.vbyte\t8,"
+
+/* Output before instructions.  */
+#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
+
+/* Output before writable data.
+   Align entire section to BIGGEST_ALIGNMENT.  */
+#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
+
+/* Define unique section name -- functions only.  */
+#define UNIQUE_SECTION(DECL,RELOC)                     \
+  do {                                                 \
+    int len;                                           \
+    const char *name;                                  \
+    char *string;                                      \
+                                                       \
+    if (TREE_CODE (DECL) == FUNCTION_DECL) {           \
+      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
+      len = strlen (name) + 5;                         \
+      string = alloca (len) + 1;                       \
+      sprintf (string, ".%s[PR]", name);               \
+      DECL_SECTION_NAME (DECL) = build_string (len, string); \
+    }                                                  \
+  } while (0)
+
+#define ASM_OUTPUT_SECTION_NAME(ASM_OUT_FILE,DECL,NAME,RELOC)  \
+  do { fputs ("\t.csect ", ASM_OUT_FILE);                      \
+       fputs (TREE_STRING_POINTER (DECL_SECTION_NAME (DECL)), ASM_OUT_FILE); \
+       putc ('\n', ASM_OUT_FILE);                              \
+  } while (0)
+
+/* Define the name of the section to use for the exception tables.
+   TODO: test and see if we can use read_only_data_section, if so,
+   remove this.  */
+
+#define EXCEPTION_SECTION data_section