tree.c (get_inner_array_type): New function.
authorDavid Edelsohn <edelsohn@mhpcc.edu>
Thu, 4 Jun 1998 11:47:15 +0000 (11:47 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Thu, 4 Jun 1998 11:47:15 +0000 (07:47 -0400)
Thu Jun  4 14:35:27 1998  David Edelsohn  <edelsohn@mhpcc.edu>
* tree.c (get_inner_array_type): New function.
* tree.h (get_inner_array_type): Prototype.
* expr.h (STACK_SAVEAREA_MODE): New macro.
* expr.c (expand_builtin_setjmp): Initialize sa_mode using
STACK_SAVEAREA_MODE.
(expand_builtin_longjmp): Likewise.
* explow.c (emit_stack_save): Likewise.
(allocate_dynamic_stack_space): Use Pmode not insn_operand_mode.
* rs6000/aix41.h (ASM_CPU_SPEC): Define relative to ASM_DEFAULT_SPEC.
(CPP_CPU_SPEC): Define relative to CPU_DEFAULT_SPEC.
* rs6000/aix43.h: New file.
* rs6000/t-aix43: New file.
* rs6000/x-aix41: New file.
* rs6000/x-aix43: New file.
* configure.in (rs6000-ibm-aix*): Use them.
* rs6000/powerpc.h: Delete.
* rs6000/sysv4.h: Move necessary powerpc.h definitions to here.
* rs6000/netware.h: and here.
* rs6000/win-nt.h: and here.
* rs6000/rs6000.c (processor_target_table, 620): Do not affect
MASK_POWERPC64.
(rs6000_override_options): Ignore flag_pic for AIX.
(rs6000_immed_double_const): Delete.
(u_short_cint_operand): Don't assume 32-bit CONST_INT.
(reg_or_u_short_operand): Don't assume 32-bit CONST_INT.
(num_insns_constant): mask64_operand() is 2 insns.
(logical_operand): Don't assume 32-bit CONST_INT.
(non_logical_cint_operand): Don't assume 32-bit CONST_INT.
(easy_fp_constant): Any CONST_DOUBLE_HIGH is okay for 64-bit.
(mask_constant): HOST_WIDE_INT parameter.
(non_and_cint_operand): Delete.
(mask64_operand): New function.
(and64_operand): New function.
(function_arg_advance): DImode arguments do not need special
alignment when 64-bit.
(function_arg): Likewise.
(setup_incoming_varargs): Reverse reg_size assignment.
(print_operand): HOST_WIDE_INT second parameter.
(print_operand, 'B'): New case.
(print_operand, 'M'): Fix typo in lossage string.
(print_operandm 'S'): New case.
(rs6000_stack_info): Reverse reg_size assignment.  Use total_raw_size
to compute AIX push_p.  Use reg_size to compute {cr,lr}_save_offset.
(rs6000_output_load_toc_table): Reverse init_ptr assignment.  Use
TARGET_64BIT not TARGET_POWERPC64.  Convert fprintf to fputs.
Load GOT highpart, don't add it.  Add lowpart with {cal|la}.
(rs6000_allocate_stack_space): Use {cal|la}.
(output_epilog): Use {cal|la}
(output_function_profiler): Add call glue to mcount call.
Load GOT highpart, don't add it.  Add lowpart with {cal|la}.
* rs6000/rs6000.h (TARGET_SWITCHES): Add powerpc64.
(STACK_BOUNDARY): Depend on TARGET_32BIT.
(ADJUST_FIELD_ALIGN): Calculate array alignment using innermost type.
(CONST_OK_FOR_LETTER_P): Don't assume 32-bit CONST_INT.
(EXTRA_CONSTRAINTS): Remove NT 'S' and 'T'.  Replace 'S' with
64-bit mask operand.
(RS6000_SAVE_TOC): Depend on TARGET_32BIT.
(STACK_SAVEAREA_MODE): New macro.
(LEGITIMATE_CONSTANT_P): DImode okay for 64bit.
(LEGITIMIZE_RELOAD_ADDRESS): New macro.
(RTX_COSTS, AND/IOR/XOR): Reflect current machine description.
(ASM_FILE_START): Emit 64-bit ABI directive.
(ASM_DECLARE_FUNCTION_NAME): Align CSECT on doubleword in 64-bit mode.
(ASM_OUTPUT_SPECIAL_POOL_ENTRY): DImode okay for 64-bit.
(PREDICATE_CODES): Add "and64_operand" and "mask64_operand".
Delete "non_and_cint_operand".  "input_operand" includes CONST_DOUBLE.
* rs6000/rs6000.md (iorsi3, xorsi3): Use HOST_WIDE_INT for mask.
Restore define_splits.
(floatsidf2, floatunssidf2): Remove !TARGET_POWERPC64 final constraint.
(floatsidf2_internal, floatunssidf2_internal2): Likewise.
Do not specify base register operand mode.
(floatsidf2_loadaddr): Do not specify base register operand mode.
(floatsidf2_store1, floatsidf2_store2): Operand 1 must be base
register; do not specify mode.  Remove !TARGET_POWERPC64 final
constraint.
(floatsidf2_load): Do not specify base register operand mode.  Remove
!TARGET_POWERPC64 final constraint.
(fix_truncdfsi2_internal, fix_truncdfsi2_{store,load}): Do not specify
base register operand mode.
(adddi3): Split large constants early.
(absdi3): Shift by 63, not 31.
(*mulsidi3_ppc64): New pattern.
(rotldi3): Add masking combiner patterns.
(anddi3): Add rldic{r,l} masking.  Remove split of large constants
because PPC insns zero-extend.
(iordi3, xordi3): Split large constants early.
(movsi matcher): Remove S and T constraints.
(movsf const_double): create SImode constant from TARGET_DOUBLE.
(movdf_hardfloat32): Add default abort() case.
(movdf easy_fp_const): create DImode constant from TARGET_DOUBLE.
(movdi): Remove 64-bit constant generator.  Try to convert
CONST_DOUBLE to CONST_INT.  Handle TOC memory constants.
(movdi_32): Add default abort() case.
(movdi_64): Add numerous ways to split 64-bit constants.
Make catch-all define_split more optimal and never FAIL.
(movti_ppc64): Add default abort() case.
(allocate_stack): Remove operand modes.  Use Pmode.
(restore_stack_block): Remove operand modes.  Generate Pmode
temporary.
(save_stack_nonlocal, restore_stack_nonlocal):  Generate Pmode
temporary.  Save area is double Pmode.
(call_indirect_aix64, call_value_indirect_aix64): New patterns.
(call, call_value): Do not specify address operand mode.  Choose
appropriate AIX ABI.
(*call_local64, *ret_call_local64): New patterns.
(*call_nonlocal_aix64, *ret_call_nonlocal_aix64): New patterns.
(*ret_call_nonlocal_aix32): Use call_value_indirect for REG.
(compare): Materialize DImode truthvalues.

From-SVN: r20229

19 files changed:
gcc/ChangeLog
gcc/config/rs6000/aix41.h
gcc/config/rs6000/aix43.h [new file with mode: 0644]
gcc/config/rs6000/netware.h
gcc/config/rs6000/powerpc.h [deleted file]
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h
gcc/config/rs6000/t-aix43 [new file with mode: 0644]
gcc/config/rs6000/win-nt.h
gcc/config/rs6000/x-aix41 [new file with mode: 0644]
gcc/config/rs6000/x-aix43 [new file with mode: 0644]
gcc/configure.in
gcc/explow.c
gcc/expr.c
gcc/expr.h
gcc/tree.c
gcc/tree.h

index 06e47f7b3f6112a7c42d858108892cf94afaecf8..0e5a1d46d732be9c398b8d41265ac224df14a1b3 100644 (file)
@@ -1,3 +1,118 @@
+Thu Jun  4 14:35:27 1998  David Edelsohn  <edelsohn@mhpcc.edu>
+
+       * tree.c (get_inner_array_type): New function.
+       * tree.h (get_inner_array_type): Prototype.
+       * expr.h (STACK_SAVEAREA_MODE): New macro.
+       * expr.c (expand_builtin_setjmp): Initialize sa_mode using
+       STACK_SAVEAREA_MODE.
+       (expand_builtin_longjmp): Likewise.
+       * explow.c (emit_stack_save): Likewise.
+       (allocate_dynamic_stack_space): Use Pmode not insn_operand_mode.
+
+       * rs6000/aix41.h (ASM_CPU_SPEC): Define relative to ASM_DEFAULT_SPEC.
+       (CPP_CPU_SPEC): Define relative to CPU_DEFAULT_SPEC.
+       * rs6000/aix43.h: New file.
+       * rs6000/t-aix43: New file.
+       * rs6000/x-aix41: New file.
+       * rs6000/x-aix43: New file.
+       * configure.in (rs6000-ibm-aix*): Use them.
+       * rs6000/powerpc.h: Delete.
+       * rs6000/sysv4.h: Move necessary powerpc.h definitions to here.
+       * rs6000/netware.h: and here.
+       * rs6000/win-nt.h: and here.
+
+       * rs6000/rs6000.c (processor_target_table, 620): Do not affect
+       MASK_POWERPC64.
+       (rs6000_override_options): Ignore flag_pic for AIX.
+       (rs6000_immed_double_const): Delete.
+       (u_short_cint_operand): Don't assume 32-bit CONST_INT.
+       (reg_or_u_short_operand): Don't assume 32-bit CONST_INT.
+       (num_insns_constant): mask64_operand() is 2 insns.
+       (logical_operand): Don't assume 32-bit CONST_INT.
+       (non_logical_cint_operand): Don't assume 32-bit CONST_INT.
+       (easy_fp_constant): Any CONST_DOUBLE_HIGH is okay for 64-bit.
+       (mask_constant): HOST_WIDE_INT parameter.
+       (non_and_cint_operand): Delete.
+       (mask64_operand): New function.
+       (and64_operand): New function.
+       (function_arg_advance): DImode arguments do not need special
+       alignment when 64-bit.
+       (function_arg): Likewise.
+       (setup_incoming_varargs): Reverse reg_size assignment.
+       (print_operand): HOST_WIDE_INT second parameter.
+       (print_operand, 'B'): New case.
+       (print_operand, 'M'): Fix typo in lossage string.
+       (print_operandm 'S'): New case.
+       (rs6000_stack_info): Reverse reg_size assignment.  Use total_raw_size
+       to compute AIX push_p.  Use reg_size to compute {cr,lr}_save_offset.
+       (rs6000_output_load_toc_table): Reverse init_ptr assignment.  Use
+       TARGET_64BIT not TARGET_POWERPC64.  Convert fprintf to fputs.
+       Load GOT highpart, don't add it.  Add lowpart with {cal|la}.
+       (rs6000_allocate_stack_space): Use {cal|la}.
+       (output_epilog): Use {cal|la}
+       (output_function_profiler): Add call glue to mcount call.
+       Load GOT highpart, don't add it.  Add lowpart with {cal|la}.
+
+       * rs6000/rs6000.h (TARGET_SWITCHES): Add powerpc64.
+       (STACK_BOUNDARY): Depend on TARGET_32BIT.
+       (ADJUST_FIELD_ALIGN): Calculate array alignment using innermost type.
+       (CONST_OK_FOR_LETTER_P): Don't assume 32-bit CONST_INT.
+       (EXTRA_CONSTRAINTS): Remove NT 'S' and 'T'.  Replace 'S' with
+       64-bit mask operand.
+       (RS6000_SAVE_TOC): Depend on TARGET_32BIT.
+       (STACK_SAVEAREA_MODE): New macro.
+       (LEGITIMATE_CONSTANT_P): DImode okay for 64bit.
+       (LEGITIMIZE_RELOAD_ADDRESS): New macro.
+       (RTX_COSTS, AND/IOR/XOR): Reflect current machine description.
+       (ASM_FILE_START): Emit 64-bit ABI directive.
+       (ASM_DECLARE_FUNCTION_NAME): Align CSECT on doubleword in 64-bit mode.
+       (ASM_OUTPUT_SPECIAL_POOL_ENTRY): DImode okay for 64-bit.
+       (PREDICATE_CODES): Add "and64_operand" and "mask64_operand".
+       Delete "non_and_cint_operand".  "input_operand" includes CONST_DOUBLE.
+
+       * rs6000/rs6000.md (iorsi3, xorsi3): Use HOST_WIDE_INT for mask.
+       Restore define_splits.
+       (floatsidf2, floatunssidf2): Remove !TARGET_POWERPC64 final constraint.
+       (floatsidf2_internal, floatunssidf2_internal2): Likewise.
+       Do not specify base register operand mode.
+       (floatsidf2_loadaddr): Do not specify base register operand mode.
+       (floatsidf2_store1, floatsidf2_store2): Operand 1 must be base
+       register; do not specify mode.  Remove !TARGET_POWERPC64 final
+       constraint.
+       (floatsidf2_load): Do not specify base register operand mode.  Remove
+       !TARGET_POWERPC64 final constraint.
+       (fix_truncdfsi2_internal, fix_truncdfsi2_{store,load}): Do not specify
+       base register operand mode.
+       (adddi3): Split large constants early.
+       (absdi3): Shift by 63, not 31.
+       (*mulsidi3_ppc64): New pattern.
+       (rotldi3): Add masking combiner patterns.
+       (anddi3): Add rldic{r,l} masking.  Remove split of large constants
+       because PPC insns zero-extend.
+       (iordi3, xordi3): Split large constants early.
+       (movsi matcher): Remove S and T constraints.
+       (movsf const_double): create SImode constant from TARGET_DOUBLE.
+       (movdf_hardfloat32): Add default abort() case.
+       (movdf easy_fp_const): create DImode constant from TARGET_DOUBLE.
+       (movdi): Remove 64-bit constant generator.  Try to convert
+       CONST_DOUBLE to CONST_INT.  Handle TOC memory constants.
+       (movdi_32): Add default abort() case.
+       (movdi_64): Add numerous ways to split 64-bit constants.
+       Make catch-all define_split more optimal and never FAIL.
+       (movti_ppc64): Add default abort() case.
+       (allocate_stack): Remove operand modes.  Use Pmode.
+       (restore_stack_block): Remove operand modes.  Generate Pmode
+       temporary.
+       (save_stack_nonlocal, restore_stack_nonlocal):  Generate Pmode
+       temporary.  Save area is double Pmode.
+       (call_indirect_aix64, call_value_indirect_aix64): New patterns.
+       (call, call_value): Do not specify address operand mode.  Choose
+       appropriate AIX ABI.
+       (*call_local64, *ret_call_local64): New patterns.
+       (*call_nonlocal_aix64, *ret_call_nonlocal_aix64): New patterns.
+       (*ret_call_nonlocal_aix32): Use call_value_indirect for REG.
+       (compare): Materialize DImode truthvalues.
+
 Thu Jun  4 01:26:57 1998  Craig Burley  <burley@gnu.org>
 
        * expr.c (safe_from_p): Avoid combinatorial explosion
index 2e9b093eacaabab6fc75f380c140d6dbacf5f66d..a7664be572a3df490c512f8bca4c82ed517060f3 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler,
    for IBM RS/6000 POWER running AIX version 4.1.
-   Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Contributed by David Edelsohn (edelsohn@npac.syr.edu).
 
 This file is part of GNU CC.
@@ -38,15 +38,13 @@ Boston, MA 02111-1307, USA.  */
 
 /* Common ASM definitions used by ASM_SPEC amonst the various targets
    for handling -mcpu=xxx switches.  */
-
 #undef ASM_CPU_SPEC
 #define ASM_CPU_SPEC \
 "%{!mcpu*: \
   %{mpower: %{!mpower2: -mpwr}} \
   %{mpower2: -mpwr2} \
   %{mpowerpc*: -mppc} \
-  %{mno-power: %{!mpowerpc*: -mcom}} \
-  %{!mno-power: %{!mpower2: %(asm_default)}}} \
+  %{!mpower*: %{!mpowerpc*: %(asm_default)}}} \
 %{mcpu=common: -mcom} \
 %{mcpu=power: -mpwr} \
 %{mcpu=power2: -mpwr2} \
@@ -67,6 +65,9 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=821: -mppc} \
 %{mcpu=860: -mppc}"
 
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mcom"
+
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 \
 -Asystem(unix) -Asystem(aix)"
@@ -77,12 +78,38 @@ Boston, MA 02111-1307, USA.  */
    %{mthreads: -D_THREAD_SAFE}\
    %(cpp_cpu)"
 
+/* Common CPP definitions used by CPP_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#undef CPP_CPU_SPEC
+#define CPP_CPU_SPEC \
+"%{!mcpu*: \
+  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
+  %{mpower2: -D_ARCH_PWR2} \
+  %{mpowerpc*: -D_ARCH_PPC} \
+  %{!mpower*: %{!mpowerpc*: %(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=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=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC} \
+%{mcpu=821: -D_ARCH_PPC} \
+%{mcpu=860: -D_ARCH_PPC}"
+
 #undef CPP_DEFAULT_SPEC
 #define CPP_DEFAULT_SPEC "-D_ARCH_COM"
 
-#undef ASM_DEFAULT_SPEC
-#define ASM_DEFAULT_SPEC "-mcom"
-
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT MASK_NEW_MNEMONICS
 
diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h
new file mode 100644 (file)
index 0000000..fa7b716
--- /dev/null
@@ -0,0 +1,199 @@
+/* Definitions of target machine for GNU compiler,
+   for IBM RS/6000 POWER running AIX version 4.3.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Contributed by David Edelsohn (edelsohn@mhpcc.edu).
+
+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.  */
+
+
+/* Enable AIX XL compiler calling convention breakage compatibility.  */
+#define MASK_XL_CALL           0x40000000
+#define        TARGET_XL_CALL          (target_flags & MASK_XL_CALL)
+#undef  SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES                                     \
+  {"aix64",            MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC}, \
+  {"aix32",            - (MASK_64BIT | MASK_POWERPC64)},       \
+  {"xl-call",          MASK_XL_CALL},                          \
+  {"no-xl-call",       - MASK_XL_CALL},                        \
+  {"threads",          0},                                     \
+  {"pe",               0},
+
+/* Sometimes certain combinations of command options do not make sense
+   on a particular target machine.  You can define a macro
+   `OVERRIDE_OPTIONS' to take account of this.  This macro, if
+   defined, is executed once just after all the command options have
+   been parsed.
+
+   The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
+   get control.  */
+
+#define NON_POWERPC_MASKS (MASK_POWER | MASK_POWER2 | MASK_STRING)
+#define SUBTARGET_OVERRIDE_OPTIONS                                     \
+do {                                                                   \
+  if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS))              \
+    {                                                                  \
+      target_flags &= ~NON_POWERPC_MASKS;                              \
+      error ("-maix64 and POWER architecture are incompatible.");      \
+    }                                                                  \
+} while (0);
+
+#include "rs6000/rs6000.h"
+
+#undef ASM_SPEC
+#define ASM_SPEC "-u %{maix64:-a64 -mppc64} %(asm_cpu)"
+
+/* Common ASM definitions used by ASM_SPEC amonst the various targets
+   for handling -mcpu=xxx switches.  */
+#undef ASM_CPU_SPEC
+#define ASM_CPU_SPEC \
+"%{!mcpu*: %{!maix64: \
+  %{mpower: %{!mpower2: -mpwr}} \
+  %{mpower2: -mpwr2} \
+  %{mpowerpc*: %{!mpowerpc64: -mppc}} \
+  %{mpowerpc64: -mppc64} \
+  %{!mpower*: %{!mpowerpc*: %(asm_default)}}}} \
+%{mcpu=common: -mcom} \
+%{mcpu=power: -mpwr} \
+%{mcpu=power2: -mpwr2} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rios: -mpwr} \
+%{mcpu=rios1: -mpwr} \
+%{mcpu=rios2: -mpwr2} \
+%{mcpu=rsc: -mpwr} \
+%{mcpu=rsc1: -mpwr} \
+%{mcpu=403: -mppc} \
+%{mcpu=505: -mppc} \
+%{mcpu=601: -m601} \
+%{mcpu=602: -mppc} \
+%{mcpu=603: -m603} \
+%{mcpu=603e: -m603} \
+%{mcpu=604: -m604} \
+%{mcpu=620: -mppc} \
+%{mcpu=821: -mppc} \
+%{mcpu=860: -mppc}"
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mcom"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 \
+-Asystem(unix) -Asystem(aix)"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
+   %{maix64: -D__64BIT__ -D_ARCH_PPC}\
+   %{mpe: -I/usr/lpp/ppe.poe/include}\
+   %{mthreads: -D_THREAD_SAFE}\
+   %(cpp_cpu)"
+
+/* Common CPP definitions used by CPP_SPEC among the various targets
+   for handling -mcpu=xxx switches.  */
+#undef CPP_CPU_SPEC
+#define CPP_CPU_SPEC \
+"%{!mcpu*: %{!maix64: \
+  %{mpower: %{!mpower2: -D_ARCH_PWR}} \
+  %{mpower2: -D_ARCH_PWR2} \
+  %{mpowerpc*: -D_ARCH_PPC} \
+  %{!mpower*: %{!mpowerpc*: %(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=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=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC} \
+%{mcpu=821: -D_ARCH_PPC} \
+%{mcpu=860: -D_ARCH_PPC}"
+
+#undef CPP_DEFAULT_SPEC
+#define CPP_DEFAULT_SPEC "-D_ARCH_COM"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT MASK_NEW_MNEMONICS
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC604
+
+/* Define this macro as a C expression for the initializer of an
+   array of string to tell the driver program which options are
+   defaults for this target and thus do not need to be handled
+   specially when using `MULTILIB_OPTIONS'.
+
+   Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+   the target makefile fragment or if none of the options listed in
+   `MULTILIB_OPTIONS' are set by default.  *Note Target Fragment::.  */
+
+#undef MULTILIB_DEFAULTS
+#define        MULTILIB_DEFAULTS { "mcpu=common" }
+
+/* These are not necessary when we pass -u to the assembler, and undefining
+   them saves a great deal of space in object files.  */
+
+#undef ASM_OUTPUT_EXTERNAL
+#undef ASM_OUTPUT_EXTERNAL_LIBCALL
+#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;               \
+    }                                          \
+}
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
+   %{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}}\
+   %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+   %{mthreads: -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a}\
+   %{!mthreads: -lc}"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
+   %{static:-bnso %(link_syscalls) } %{!shared: %{g*: %(link_libg) }}\
+   %{shared:-bM:SRE %{!e:-bnoentry}} %{maix64:-b64}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared:\
+   %{mpe:%{pg:/usr/lpp/ppe.poe/lib/gcrt0.o}\
+         %{!pg:%{p:/usr/lpp/ppe.poe/lib/mcrt0.o}\
+               %{!p:/usr/lpp/ppe.poe/lib/crt0.o}}}\
+   %{!mpe:\
+     %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
+     %{!maix64:\
+       %{mthreads:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
+       %{!mthreads:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}}"
+
+/* AIX 4.3 typedefs ptrdiff_t as "long" while earlier releases used "int".  */
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
index f6de2aab0eafb92465d0d6a22f5240c82502523f..a465c63fe3b7e5fefbf017f3d297f29c9de3ac5d 100644 (file)
@@ -1,6 +1,6 @@
 /* Core target definitions for GNU compiler
    for IBM RS/6000 PowerPC running NetWare
-   Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
 This file is part of GNU CC.
@@ -21,7 +21,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define TARGET_AIX 0
 
-#include "rs6000/powerpc.h"
+#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+
+#define ASM_DEFAULT_SPEC "-mppc"
+
+#include "rs6000/rs6000.h"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC601
 
 /* Don't generate XCOFF debugging information.  */
 
diff --git a/gcc/config/rs6000/powerpc.h b/gcc/config/rs6000/powerpc.h
deleted file mode 100644 (file)
index 9f1ffd6..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Definitions of target machine for GNU compiler,
-   for IBM RS/6000 PowerPC running AIX version 3.2.
-   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-   Contributed by David Edelsohn (edelsohn@npac.syr.edu).
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-
-#include "rs6000/rs6000.h"
-
-#undef ASM_SPEC
-#define ASM_SPEC "-u %(asm_cpu)"
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 \
--Asystem(unix) -Asystem(aix) -Acpu(powerpc) -Amachine(powerpc)"
-
-#undef CPP_DEFAULT_SPEC
-#define        CPP_DEFAULT_SPEC "-D_ARCH_PPC"
-
-#undef ASM_DEFAULT_SPEC
-#define        ASM_DEFAULT_SPEC "-mppc"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
-
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC601
-
-/* These are not necessary when we pass -u to the assembler, and undefining
-   them saves a great deal of space in object files.  */
-
-#undef ASM_OUTPUT_EXTERNAL
-#undef ASM_OUTPUT_EXTERNAL_LIBCALL
-#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;               \
-    }                                          \
-}
index 635054fb015cf7569f6a5dd92bd0b9b438c62aa0..6a04d552855eaf6ccabb1755b9eb57b8cd199abb 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used for code generation on IBM RS/6000.
-   Copyright (C) 1991, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1991, 93-7, 1998 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
@@ -226,7 +226,7 @@ rs6000_override_options (default_cpu)
            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
         {"620", PROCESSOR_PPC620,
            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWER_MASKS | MASK_PPC_GPOPT},
         {"801", PROCESSOR_MPCCORE,
            MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
            POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
@@ -304,6 +304,13 @@ rs6000_override_options (default_cpu)
        }
     }
 
+  if (flag_pic && (DEFAULT_ABI == ABI_AIX))
+    {
+      warning ("-f%s ignored for AIX (all code is position independent)",
+              (flag_pic > 1) ? "PIC" : "pic");
+      flag_pic = 0;
+    }
+
   /* Set debug flags */
   if (rs6000_debug_name)
     {
@@ -388,22 +395,6 @@ rs6000_float_const (string, mode)
   REAL_VALUE_TYPE value = REAL_VALUE_ATOF (string, mode);
   return immed_real_const_1 (value, mode);
 }
-
-\f
-/* Create a CONST_DOUBLE like immed_double_const, except reverse the
-   two parts of the constant if the target is little endian.  */
-
-struct rtx_def *
-rs6000_immed_double_const (i0, i1, mode)
-     HOST_WIDE_INT i0, i1;
-     enum machine_mode mode;
-{
-  if (! WORDS_BIG_ENDIAN)
-    return immed_double_const (i1, i0, mode);
-
-  return immed_double_const (i0, i1, mode);
-}
-
 \f
 /* Return non-zero if this function is known to have a null epilogue.  */
 
@@ -492,7 +483,8 @@ u_short_cint_operand (op, mode)
      register rtx op;
      enum machine_mode mode;
 {
-  return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0);
+  return (GET_CODE (op) == CONST_INT
+         && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) == 0);
 }
 
 /* Return 1 if OP is a CONST_INT that cannot fit in a signed D field.  */
@@ -569,7 +561,7 @@ reg_or_u_short_operand (op, mode)
      enum machine_mode mode;
 {
   if (GET_CODE (op) == CONST_INT
-      && (INTVAL (op) & 0xffff0000) == 0)
+      && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) == 0)
     return 1;
 
   return gpc_reg_operand (op, mode);
@@ -706,6 +698,9 @@ num_insns_constant (op, mode)
                   && ((low & 0x80000000) != 0))
            return num_insns_constant_wide (low);
 
+         else if (mask64_operand (op, mode))
+           return 2;
+
          else if (low == 0)
            return num_insns_constant_wide (high) + 1;
 
@@ -770,8 +765,10 @@ easy_fp_constant (op, mode)
       return num_insns_constant_wide (l) == 1;
     }
 
-  else if (mode == DImode && TARGET_32BIT)
-    return num_insns_constant (op, DImode) == 2;
+  else if (mode == DImode)
+    return ((TARGET_64BIT
+            && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
+           || (num_insns_constant (op, DImode) <= 2));
 
   else
     abort ();
@@ -861,7 +858,7 @@ logical_operand (op, mode)
 {
   return (gpc_reg_operand (op, mode)
          || (GET_CODE (op) == CONST_INT
-             && ((INTVAL (op) & 0xffff0000) == 0
+             && ((INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) == 0
                  || (INTVAL (op) & 0xffff) == 0)));
 }
 
@@ -874,7 +871,7 @@ non_logical_cint_operand (op, mode)
      enum machine_mode mode;
 {
   return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) & 0xffff0000) != 0
+         && (INTVAL (op) & (~ (HOST_WIDE_INT) 0xffff)) != 0
          && (INTVAL (op) & 0xffff) != 0);
 }
 
@@ -885,7 +882,7 @@ non_logical_cint_operand (op, mode)
 
 int
 mask_constant (c)
-     register int c;
+     register HOST_WIDE_INT c;
 {
   int i;
   int last_bit_value;
@@ -913,27 +910,105 @@ mask_operand (op, mode)
   return GET_CODE (op) == CONST_INT && mask_constant (INTVAL (op));
 }
 
-/* Return 1 if the operand is either a non-special register or a
-   constant that can be used as the operand of an RS/6000 logical AND insn.  */
+/* Return 1 if the operand is a constant that is a PowerPC64 mask.
+   It is if there are no more than one 1->0 or 0->1 transitions.
+   Reject all ones and all zeros, since these should have been optimized
+   away and confuse the making of MB and ME.  */
 
 int
-and_operand (op, mode)
+mask64_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (GET_CODE (op) == CONST_INT)
+    {
+      HOST_WIDE_INT c = INTVAL (op);
+      int i;
+      int last_bit_value;
+      int transitions = 0;
+
+      if (c == 0 || c == ~0)
+       return 0;
+
+      last_bit_value = c & 1;
+
+      for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
+       if (((c >>= 1) & 1) != last_bit_value)
+         last_bit_value ^= 1, transitions++;
+
+#if HOST_BITS_PER_INT == 32
+      /* Consider CONST_INT sign-extended.  */
+      transitions += (last_bit_value != 1);
+#endif
+
+      return transitions <= 1;
+    }
+  else if (GET_CODE (op) == CONST_DOUBLE
+          && (mode == VOIDmode || mode == DImode))
+    {
+      HOST_WIDE_INT low = CONST_DOUBLE_LOW (op);
+#if HOST_BITS_PER_INT == 32
+      HOST_WIDE_INT high = CONST_DOUBLE_HIGH (op);
+#endif
+      int i;
+      int last_bit_value;
+      int transitions = 0;
+
+      if ((low == 0
+#if HOST_BITS_PER_INT == 32
+         && high == 0
+#endif
+          )
+         || (low == ~0
+#if HOST_BITS_PER_INT == 32
+             && high == ~0
+#endif
+             ))
+       return 0;
+
+      last_bit_value = low & 1;
+
+      for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
+       if (((low >>= 1) & 1) != last_bit_value)
+         last_bit_value ^= 1, transitions++;
+
+#if HOST_BITS_PER_INT == 32
+      if ((high & 1) != last_bit_value)
+       last_bit_value ^= 1, transitions++;
+
+      for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
+       if (((high >>= 1) & 1) != last_bit_value)
+         last_bit_value ^= 1, transitions++;
+#endif
+
+      return transitions <= 1;
+    }
+  else
+    return 0;
+}
+
+/* Return 1 if the operand is either a non-special register or a constant
+   that can be used as the operand of a PowerPC64 logical AND insn.  */
+
+int
+and64_operand (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
   return (logical_operand (op, mode)
-         || mask_operand (op, mode));
+         || mask64_operand (op, mode));
 }
 
-/* Return 1 if the operand is a constant but not a valid operand for an AND
-   insn.  */
+/* Return 1 if the operand is either a non-special register or a
+   constant that can be used as the operand of an RS/6000 logical AND insn.  */
 
 int
-non_and_cint_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
+and_operand (op, mode)
+    register rtx op;
+    enum machine_mode mode;
 {
-  return GET_CODE (op) == CONST_INT && ! and_operand (op, mode);
+  return (logical_operand (op, mode)
+         || mask_operand (op, mode));
 }
 
 /* Return 1 if the operand is a general register or memory operand.  */
@@ -1240,7 +1315,8 @@ function_arg_advance (cum, mode, type, named)
      tree type;
      int named;
 {
-  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
+  int align = (TARGET_32BIT && (cum->words & 1) != 0
+              && function_arg_boundary (mode, type) == 64) ? 1 : 0;
   cum->words += align;
   cum->nargs_prototype--;
 
@@ -1313,7 +1389,8 @@ function_arg (cum, mode, type, named)
      tree type;
      int named;
 {
-  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
+  int align = (TARGET_32BIT && (cum->words & 1) != 0
+              && function_arg_boundary (mode, type) == 64) ? 1 : 0;
   int align_words = cum->words + align;
 
   if (TARGET_DEBUG_ARG)
@@ -1489,7 +1566,7 @@ setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
 
 {
   rtx save_area = virtual_incoming_args_rtx;
-  int reg_size = (TARGET_64BIT) ? 8 : 4;
+  int reg_size = TARGET_32BIT ? 4 : 8;
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
@@ -2395,7 +2472,7 @@ print_operand (file, x, code)
     char code;
 {
   int i;
-  int val;
+  HOST_WIDE_INT val;
 
   /* These macros test for integers and extract the low-order bits.  */
 #define INT_P(X)  \
@@ -2443,6 +2520,11 @@ print_operand (file, x, code)
       fprintf (file, "%d", INT_LOWPART (x) & 0xffff);
       return;
 
+    case 'B':
+      /* If the low-order bit is zero, write 'r'; otherwise, write 'l'
+        for 64-bit mask direction.  */
+      putc ((INT_LOWPART(x) & 1 == 0 ? 'r' : 'l'), file);
+
     case 'C':
       /* This is an optional cror needed for LE or GE floating-point
         comparisons.  Otherwise write nothing.  */
@@ -2619,7 +2701,7 @@ print_operand (file, x, code)
        if (((val >>= 1) & 1) == 0)
          break;
 
-      /* If we ended in ...01, I would be 0.  The correct value is 31, so
+      /* If we ended in ...01, i would be 0.  The correct value is 31, so
         we want 31 - i.  */
       fprintf (file, "%d", 31 - i);
       return;
@@ -2627,7 +2709,7 @@ print_operand (file, x, code)
     case 'M':
       /* ME value for a mask operand.  */
       if (! mask_operand (x, VOIDmode))
-       output_operand_lossage ("invalid %%m value");
+       output_operand_lossage ("invalid %%M value");
 
       val = INT_LOWPART (x);
 
@@ -2645,7 +2727,7 @@ print_operand (file, x, code)
            if ((val >>= 1) & 1)
              break;
 
-         /* If we had ....10, I would be 0.  The result should be
+         /* If we had ....10, i would be 0.  The result should be
             30, so we need 30 - i.  */
          fprintf (file, "%d", 30 - i);
          return;
@@ -2711,6 +2793,72 @@ print_operand (file, x, code)
       fprintf (file, "%d", (32 - INT_LOWPART (x)) & 31);
       return;
 
+    case 'S':
+      /* PowerPC64 mask position.  All 0's and all 1's are excluded.
+        CONST_INT 32-bit mask is considered sign-extended so any
+        transition must occur within the CONST_INT, not on the boundary.  */
+      if (! mask64_operand (x, VOIDmode))
+       output_operand_lossage ("invalid %%S value");
+
+      val = INT_LOWPART (x);
+
+      if (val & 1)      /* Clear Left */
+       {
+         if (val == 1)
+           i = 0;
+         else
+           for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
+             if (!((val >>= 1) & 1))
+               break;
+
+#if HOST_BITS_PER_INT == 32
+       if (GET_CODE (x) == CONST_DOUBLE && i == 32)
+         {
+           val = CONST_DOUBLE_HIGH (x);
+
+           if (val == 0)
+             --i;
+           else if (val == 1)
+             ;
+           else
+             for (i = 33; i < 64; i++)
+               if (!((val >>= 1) & 1))
+                 break;
+         }
+#endif
+         fprintf (file, "%d", 63 - i);
+         return;
+       }
+      else     /* Clear Right */
+       {
+         val = (GET_CODE (x) == CONST_INT ? INTVAL (x) : CONST_DOUBLE_HIGH (x));
+
+         if (val == (-1 << (HOST_BITS_PER_WIDE_INT-1)))
+           i = 0;
+         else
+           for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
+             if ((val <<= 1) < 0)
+               break;
+
+#if HOST_BITS_PER_INT == 32
+       if (GET_CODE (x) == CONST_DOUBLE && i == 32)
+         {
+           val = CONST_DOUBLE_LOW (x);
+
+           if (val == 0)
+             --i;
+           else if (val == (-1 << (HOST_BITS_PER_WIDE_INT-1)))
+             ;
+           else
+             for (i = 33; i < 64; i++)
+               if ((val <<= 1) < 0)
+                 break;
+         }
+#endif
+         fprintf (file, "%d", i);
+         return;
+       }
+
     case 't':
       /* Write 12 if this jump operation will branch if true, 4 otherwise. 
         All floating-point operations except NE branch true and integer
@@ -3006,23 +3154,23 @@ rs6000_makes_calls ()
    sequence and the V.4 calling sequence.
 
    AIX stack frames look like:
-
+                                                         32-bit  64-bit
        SP----> +---------------------------------------+
-               | back chain to caller                  | 0
+               | back chain to caller                  | 0       0
                +---------------------------------------+
-               | saved CR                              | 4
+               | saved CR                              | 4       8 (8-11)
                +---------------------------------------+
-               | saved LR                              | 8
+               | saved LR                              | 8       16
                +---------------------------------------+
-               | reserved for compilers                | 12
+               | reserved for compilers                | 12      24
                +---------------------------------------+
-               | reserved for binders                  | 16
+               | reserved for binders                  | 16      32
                +---------------------------------------+
-               | saved TOC pointer                     | 20
+               | saved TOC pointer                     | 20      40
                +---------------------------------------+
-               | Parameter save area (P)               | 24
+               | Parameter save area (P)               | 24      48
                +---------------------------------------+
-               | Alloca space (A)                      | 24+P
+               | Alloca space (A)                      | 24+P    etc.
                +---------------------------------------+
                | Local variable space (L)              | 24+P+A
                +---------------------------------------+
@@ -3115,7 +3263,7 @@ rs6000_stack_info ()
 {
   static rs6000_stack_t info, zero_info;
   rs6000_stack_t *info_ptr = &info;
-  int reg_size = TARGET_64BIT ? 8 : 4;
+  int reg_size = TARGET_32BIT ? 4 : 8;
   enum rs6000_abi abi;
   int total_raw_size;
 
@@ -3257,7 +3405,7 @@ rs6000_stack_info ()
   else
     info_ptr->push_p = (frame_pointer_needed
                        || write_symbols != NO_DEBUG
-                       || ((info_ptr->total_size - info_ptr->fixed_size)
+                       || ((total_raw_size - info_ptr->fixed_size)
                            > (TARGET_32BIT ? 220 : 296)));
 
   /* Calculate the offsets */
@@ -3272,8 +3420,8 @@ rs6000_stack_info ()
       info_ptr->fp_save_offset   = - info_ptr->fp_size;
       info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
       info_ptr->main_save_offset = info_ptr->gp_save_offset - info_ptr->main_size;
-      info_ptr->cr_save_offset   = 4;
-      info_ptr->lr_save_offset   = 8;
+      info_ptr->cr_save_offset   = reg_size; /* first word when 64-bit.  */
+      info_ptr->lr_save_offset   = 2*reg_size;
       break;
 
     case ABI_V4:
@@ -3287,13 +3435,13 @@ rs6000_stack_info ()
       break;
 
     case ABI_NT:
-      info_ptr->lr_save_offset    = -4;
+      info_ptr->lr_save_offset    = -reg_size;
       info_ptr->toc_save_offset   = info_ptr->lr_save_offset - info_ptr->lr_size;
       info_ptr->cr_save_offset    = info_ptr->toc_save_offset - info_ptr->toc_size;
       info_ptr->gp_save_offset    = info_ptr->cr_save_offset - info_ptr->cr_size - info_ptr->gp_size + reg_size;
       info_ptr->fp_save_offset    = info_ptr->gp_save_offset - info_ptr->fp_size;
       if (info_ptr->fp_size && ((- info_ptr->fp_save_offset) % 8) != 0)
-       info_ptr->fp_save_offset -= 4;
+       info_ptr->fp_save_offset -= reg_size;
 
       info_ptr->main_save_offset = info_ptr->fp_save_offset - info_ptr->main_size;
       break;
@@ -3303,9 +3451,9 @@ rs6000_stack_info ()
     {
       info_ptr->fpmem_offset = info_ptr->main_save_offset - info_ptr->fpmem_size;
       rs6000_fpmem_size   = info_ptr->fpmem_size;
-      rs6000_fpmem_offset = info_ptr->push_p
-         ? info_ptr->total_size + info_ptr->fpmem_offset
-         : info_ptr->fpmem_offset;
+      rs6000_fpmem_offset = (info_ptr->push_p
+                            ? info_ptr->total_size + info_ptr->fpmem_offset
+                            : info_ptr->fpmem_offset);
     }
   else
     info_ptr->fpmem_offset = 0;  
@@ -3491,7 +3639,7 @@ rs6000_output_load_toc_table (file, reg)
         address before loading.  */
       if (rs6000_pic_func_labelno != rs6000_pic_labelno)
        {
-         char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long";
+         char *init_ptr = TARGET_32BIT ? ".long" : ".quad";
          char *buf_ptr;
 
          ASM_OUTPUT_INTERNAL_LABEL (file, "LCL", rs6000_pic_labelno);
@@ -3508,26 +3656,14 @@ rs6000_output_load_toc_table (file, reg)
       fprintf (file, "\tmflr %s\n", reg_names[reg]);
 
       if (rs6000_pic_func_labelno != rs6000_pic_labelno)
-       {
-         if (TARGET_POWERPC64)
-           fprintf (file, "\taddi %s,%s,8\n", reg_names[reg], reg_names[reg]);
-         else if (TARGET_NEW_MNEMONICS)
-           fprintf (file, "\taddi %s,%s,4\n", reg_names[reg], reg_names[reg]);
-         else
-           fprintf (file, "\tcal %s,4(%s)\n", reg_names[reg], reg_names[reg]);
-       }
+         asm_fprintf(file, "\t{cal|la} %s,%d(%s)\n", reg_names[reg],
+                     (TARGET_32BIT ? 4 : 8), reg_names[reg]);
 
-      if (TARGET_POWERPC64)
-       fprintf (file, "\tld");
-      else if (TARGET_NEW_MNEMONICS)
-       fprintf (file, "\tlwz");
-      else
-       fprintf (file, "\tl");
-
-      fprintf (file, " %s,(", reg_names[0]);
+      asm_fprintf (file, (TARGET_32BIT) ? "\t{l|lwz} %s,(" : "\tld %s,(",
+                  reg_names[0]);
       ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
       assemble_name (file, buf);
-      fprintf (file, "-");
+      fputs ("-", file);
       ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
       assemble_name (file, buf);
       fprintf (file, ")(%s)\n", reg_names[reg]);
@@ -3538,21 +3674,12 @@ rs6000_output_load_toc_table (file, reg)
   else if (!TARGET_64BIT)
     {
       ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
-      asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[reg], reg_names[0]);
+      asm_fprintf (file, "\t{liu|lis} %s,", reg_names[reg]);
       assemble_name (file, buf);
       asm_fprintf (file, "@ha\n");
-      if (TARGET_NEW_MNEMONICS)
-       {
-         asm_fprintf (file, "\taddi %s,%s,", reg_names[reg], reg_names[reg]);
-         assemble_name (file, buf);
-         asm_fprintf (file, "@l\n");
-       }
-      else
-       {
-         asm_fprintf (file, "\tcal %s,", reg_names[reg]);
-         assemble_name (file, buf);
-         asm_fprintf (file, "@l(%s)\n", reg_names[reg]);
-       }
+      asm_fprintf (file, "\t{cal|la} %s,", reg_names[reg]);
+      assemble_name (file, buf);
+      asm_fprintf (file, "@l(%s)\n", reg_names[reg]);
     }
   else
     abort ();
@@ -3599,12 +3726,8 @@ rs6000_allocate_stack_space (file, size, copy_r12)
     {
       fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
       if (size < 32767)
-       {
-         if (TARGET_NEW_MNEMONICS)
-           fprintf (file, "\taddi %s,%s,%d\n", reg_names[1], reg_names[1], neg_size);
-         else
-           fprintf (file, "\tcal %s,%d(%s)\n", reg_names[1], neg_size, reg_names[1]);
-       }
+       fprintf (file, "\t{cal|la} %s,%d(%s)\n",
+                reg_names[1], neg_size, reg_names[1]);
       else
        {
          asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
@@ -3912,10 +4035,9 @@ output_epilog (file, size)
        {
          if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
            sp_offset = info->total_size;
-         else if (TARGET_NEW_MNEMONICS)
-           asm_fprintf (file, "\taddi %s,%s,%d\n", reg_names[1], reg_names[1], info->total_size);
          else
-           asm_fprintf (file, "\tcal %s,%d(%s)\n", reg_names[1], info->total_size, reg_names[1]);
+           asm_fprintf (file, "\t{cal|la} %s,%d(%s)\n",
+                        reg_names[1], info->total_size, reg_names[1]);
        }
 
       /* Get the old lr if we saved it.  */
@@ -3967,12 +4089,8 @@ output_epilog (file, size)
 
       /* If this is V.4, unwind the stack pointer after all of the loads have been done */
       if (sp_offset)
-       {
-         if (TARGET_NEW_MNEMONICS)
-           asm_fprintf (file, "\taddi %s,%s,%d\n", reg_names[1], reg_names[1], sp_offset);
-         else
-           asm_fprintf (file, "\tcal %s,%d(%s)\n", reg_names[1], sp_offset, reg_names[1]);
-       }
+       asm_fprintf (file, "\t{cal|la} %s,%d(%s)\n",
+                    reg_names[1], sp_offset, reg_names[1]);
       else if (sp_reg != 1)
        asm_fprintf (file, "\tmr %s,%s\n", reg_names[1], reg_names[sp_reg]);
 
@@ -4521,25 +4639,15 @@ output_function_profiler (file, labelno)
          fputs ("\n\t.previous\n", file);
        }
 #endif
-      else if (TARGET_NEW_MNEMONICS)
-       {
-         fprintf (file, "\taddis %s,%s,", reg_names[11], reg_names[11]);
-         assemble_name (file, buf);
-         fprintf (file, "@ha\n");
-         fprintf (file, "\tstw %s,4(%s)\n", reg_names[0], reg_names[1]);
-         fprintf (file, "\taddi %s,%s,", reg_names[0], reg_names[11]);
-         assemble_name (file, buf);
-         fputs ("@l\n", file);
-       }
       else
        {
-         fprintf (file, "\tcau %s,%s,", reg_names[11], reg_names[11]);
+         asm_fprintf (file, "\t{liu|lis} %s,", reg_names[11]);
          assemble_name (file, buf);
-         fprintf (file, "@ha\n");
-         fprintf (file, "\tst %s,4(%s)\n", reg_names[0], reg_names[1]);
-         fprintf (file, "\tcal %s,", reg_names[11]);
+         asm_fprintf (file, "@ha\n");
+         asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]);
+         asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
          assemble_name (file, buf);
-         fprintf (file, "@l(%s)\n", reg_names[11]);
+         asm_fprintf (file, "@l(%s)\n", reg_names[11]);
        }
 
       fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
@@ -4585,7 +4693,8 @@ output_function_profiler (file, labelno)
       ASM_GENERATE_INTERNAL_LABEL (buf, "LPC", labelno);
       asm_fprintf (file, "\t{l|lwz} %s,", reg_names[3]);
       assemble_name (file, buf);
-      asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
+      asm_fprintf (file, "(%s)\n\tbl %s\n\t%s\n",
+                  reg_names[2], RS6000_MCOUNT, RS6000_CALL_GLUE);
 
   /* Restore parameter registers.  */
 
@@ -5058,7 +5167,7 @@ rs6000_select_section (decl, reloc)
    call.  For real AIX and NT calling sequences, we also replace the
    function name with the real name (1 or 2 leading .'s), rather than
    the function descriptor name.  This saves a lot of overriding code
-   to readd the prefixes.  */
+   to read the prefixes.  */
 
 void
 rs6000_encode_section_info (decl)
index 66756a0b975821b27f5b51185446bc9ba59123b8..7190de757de40d32a64fb05e454cd2945289a252 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler, for IBM RS/6000.
-   Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93-7, 1998 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
@@ -351,6 +351,8 @@ extern int target_flags;
   {"no-powerpc-gpopt", - MASK_PPC_GPOPT},                              \
   {"powerpc-gfxopt",   MASK_POWERPC | MASK_PPC_GFXOPT},                \
   {"no-powerpc-gfxopt",        - MASK_PPC_GFXOPT},                             \
+  {"powerpc64",                MASK_POWERPC64},                                \
+  {"no-powerpc64",     - MASK_POWERPC64},                              \
   {"new-mnemonics",    MASK_NEW_MNEMONICS},                            \
   {"old-mnemonics",    -MASK_NEW_MNEMONICS},                           \
   {"full-toc",         - (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC       \
@@ -577,7 +579,7 @@ extern int rs6000_debug_arg;                /* debug argument handling */
 #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
-#define STACK_BOUNDARY 64
+#define STACK_BOUNDARY (TARGET_32BIT ? 64 : 128)
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY 32
@@ -587,7 +589,10 @@ extern int rs6000_debug_arg;               /* debug argument handling */
 
 /* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
 #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-  (DECL_MODE (FIELD) != DFmode ? (COMPUTED) : MIN ((COMPUTED), 32))
+  (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
@@ -737,8 +742,8 @@ extern int rs6000_debug_arg;                /* debug argument handling */
    This is ordinarily the length in words of a value of mode MODE
    but can be less for certain modes in special long registers.
 
-   On RS/6000, ordinary registers hold 32 bits worth;
-   a single floating point register holds 64 bits worth.  */
+   POWER and PowerPC GPRs hold 32 bits worth;
+   PowerPC64 GPRs and FPRs point register holds 64 bits worth.  */
 
 #define HARD_REGNO_NREGS(REGNO, MODE)                                  \
   (FP_REGNO_P (REGNO) || FPMEM_REGNO_P (REGNO)                         \
@@ -1042,7 +1047,7 @@ enum reg_class
 #define CONST_OK_FOR_LETTER_P(VALUE, C)                                        \
    ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000        \
    : (C) == 'J' ? ((VALUE) & 0xffff) == 0                              \
-   : (C) == 'K' ? ((VALUE) & 0xffff0000) == 0                          \
+   : (C) == 'K' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff)) == 0          \
    : (C) == 'L' ? mask_constant (VALUE)                                        \
    : (C) == 'M' ? (VALUE) > 31                                         \
    : (C) == 'N' ? exact_log2 (VALUE) >= 0                              \
@@ -1068,15 +1073,13 @@ enum reg_class
 
    'Q' means that is a memory operand that is just an offset from a reg.
    'R' is for AIX TOC entries.
-   'S' is for Windows NT SYMBOL_REFs
-   'T' is for Windows NT LABEL_REFs.
+   'S' is a constant that can be placed into a 64-bit mask operand
    'U' is for V.4 small data references.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                                \
   ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
    : (C) == 'R' ? LEGITIMATE_CONSTANT_POOL_ADDRESS_P (OP)              \
-   : (C) == 'S' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == SYMBOL_REF)\
-   : (C) == 'T' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == LABEL_REF) \
+   : (C) == 'S' ? mask64_operand (OP, VOIDmode)                                \
    : (C) == 'U' ? ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
                   && small_data_operand (OP, GET_MODE (OP)))           \
    : 0)
@@ -1201,7 +1204,7 @@ typedef struct rs6000_stack {
 #define RS6000_SAVE_AREA (TARGET_32BIT ? 24 : 48)
 
 /* Address to save the TOC register */
-#define RS6000_SAVE_TOC plus_constant (stack_pointer_rtx, 20)
+#define RS6000_SAVE_TOC plus_constant (stack_pointer_rtx, (TARGET_32BIT ? 20 : 40))
 
 /* Offset & size for fpmem stack locations used for converting between
    float and integral types.  */
@@ -1320,6 +1323,11 @@ extern int rs6000_sysv_varargs_p;
   (TYPE_MODE (TYPE) == BLKmode                                         \
    && (DEFAULT_ABI != ABI_SOLARIS || int_size_in_bytes (TYPE) > 8))
 
+/* Mode of stack savearea.
+   NONLOCAL needs twice Pmode to maintain both backchain and SP.  */
+#define STACK_SAVEAREA_MODE(LEVEL)     \
+    (LEVEL == SAVE_NONLOCAL ? (TARGET_32BIT ? DImode : TImode) : Pmode)
+
 /* Minimum and maximum general purpose registers used to hold arguments.  */
 #define GP_ARG_MIN_REG 3
 #define GP_ARG_MAX_REG 10
@@ -1723,6 +1731,7 @@ typedef struct rs6000_args
 
 #define LEGITIMATE_CONSTANT_P(X)                               \
   (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode    \
+   || (TARGET_POWERPC64 && GET_MODE (X) == DImode)             \
    || easy_fp_constant (X, GET_MODE (X)))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
@@ -1777,7 +1786,7 @@ typedef struct rs6000_args
    && CONSTANT_POOL_ADDRESS_P (X)                                      \
    && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X)))
 
-/* TARGET_64BIT TOC64 guaranteed to have 64 bit alignment.  */
+/* AIX64 guaranteed to have 64 bit TOC alignment.  */
 #define LEGITIMATE_CONSTANT_POOL_ADDRESS_P(X)                          \
   (LEGITIMATE_CONSTANT_POOL_BASE_P (X)                                 \
    || (TARGET_TOC                                                      \
@@ -1916,6 +1925,46 @@ typedef struct rs6000_args
     }                                                                  \
 }
 
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.
+
+   For RS/6000, we wish to handle large displacements off a base
+   register by splitting the addend across an addiu/addis and the mem insn.
+   This cuts number of extra insns needed from 3 to 1.  */
+   
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
+do {                                                                    \
+  if (GET_CODE (X) == PLUS                                              \
+      && GET_CODE (XEXP (X, 0)) == REG                                  \
+      && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER                    \
+      && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE)                     \
+      && GET_CODE (XEXP (X, 1)) == CONST_INT)                           \
+    {                                                                   \
+      HOST_WIDE_INT val = INTVAL (XEXP (X, 1));                         \
+      HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;           \
+      HOST_WIDE_INT high                                                \
+        = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;       \
+                                                                        \
+      /* Check for 32-bit overflow.  */                                 \
+      if (high + low != val)                                            \
+        break;                                                          \
+                                                                        \
+      /* Reload the high part into a base reg; leave the low part       \
+         in the mem directly.  */                                       \
+                                                                        \
+      X = gen_rtx_PLUS (GET_MODE (X),                                   \
+                        gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0),        \
+                                      GEN_INT (high)),                  \
+                        GEN_INT (low));                                 \
+                                                                        \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,       \
+                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,        \
+                   OPNUM, TYPE);                                        \
+      goto WIN;                                                         \
+    }                                                                   \
+} while (0)
+
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.
 
@@ -2053,10 +2102,9 @@ typedef struct rs6000_args
 #define OBJECT_FORMAT_COFF
 
 /* Define the magic numbers that we recognize as COFF.
-   AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit executables, but collect2.c
-   does not include these files in the right order to conditionally define
-   the value in the macro.  */
-
+   AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit objects, but collect2.c
+   does not include files in the correct order to conditionally define
+   the symbolic name in this macro.  */
 #define MY_ISCOFF(magic) \
   ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC \
    || (magic) == U802TOCMAGIC || (magic) == 0757)
@@ -2086,7 +2134,6 @@ typedef struct rs6000_args
 #define Pmode (TARGET_32BIT ? SImode : DImode)
 
 /* Mode of a function address in a call instruction (for indexing purposes).
-
    Doesn't matter on RS/6000.  */
 #define FUNCTION_MODE (TARGET_32BIT ? SImode : DImode)
 
@@ -2131,17 +2178,17 @@ typedef struct rs6000_args
 #define RTX_COSTS(X,CODE,OUTER_CODE)                                   \
   case PLUS:                                                           \
     return ((GET_CODE (XEXP (X, 1)) == CONST_INT                       \
-            && (unsigned HOST_WIDE_INT) ((INTVAL (XEXP (X, 1))         \
-                                          + 0x8000) >= 0x10000))       \
+            && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (X, 1))         \
+                                          + 0x8000) >= 0x10000)        \
+            && (INTVAL (XEXP (X, 1)) & 0xffff != 0))                   \
            ? COSTS_N_INSNS (2)                                         \
            : COSTS_N_INSNS (1));                                       \
   case AND:                                                            \
-    return ((non_and_cint_operand (XEXP (X, 1), SImode))               \
-           ? COSTS_N_INSNS (2)                                         \
-           : COSTS_N_INSNS (1));                                       \
   case IOR:                                                            \
   case XOR:                                                            \
-    return ((non_logical_cint_operand (XEXP (X, 1), SImode))           \
+    return ((GET_CODE (XEXP (X, 1)) == CONST_INT                       \
+            && (INTVAL (XEXP (X, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0 \
+            && (INTVAL (XEXP (X, 1)) & 0xffff != 0))                   \
            ? COSTS_N_INSNS (2)                                         \
            : COSTS_N_INSNS (1));                                       \
   case MULT:                                                           \
@@ -2307,6 +2354,8 @@ extern int rs6000_trunc_used;
                           main_input_filename, ".ro_");        \
                                                                \
   output_file_directive (FILE, main_input_filename);           \
+  if (TARGET_64BIT)                                            \
+    fputs ("\t.machine\t\"ppc64\"\n", FILE);                   \
   toc_section ();                                              \
   if (write_symbols != NO_DEBUG)                               \
     private_data_section ();                                   \
@@ -2469,10 +2518,10 @@ extern int toc_initialized;
     }                                                          \
   fputs (".csect ", FILE);                                     \
   RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
-  fputs ("[DS]\n", FILE);                                      \
+  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);   \
+  fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE);     \
   RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
   fputs (", TOC[tc0], 0\n", FILE);                             \
   fputs (".csect .text[PR]\n.", FILE);                         \
@@ -2498,8 +2547,11 @@ extern int toc_initialized;
        || GET_CODE (X) == LABEL_REF                                    \
        || (! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)             \
           && GET_CODE (X) == CONST_DOUBLE                              \
-          && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT               \
+          && (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT              \
+              || (TARGET_POWERPC64 && GET_MODE (X) == DImode)))))
+#if 0
           && BITS_PER_WORD == HOST_BITS_PER_INT)))
+#endif
 
 /* Select section for constant in constant pool.
 
@@ -2949,7 +3001,7 @@ do {                                                                      \
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)           \
   do { char buf[100];                                  \
-       fputs ((TARGET_32BIT) ? "\t.long " : "\t.llong ", FILE);        \
+       fputs (TARGET_32BIT ? "\t.long " : "\t.llong ", FILE);  \
        ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE);  \
        assemble_name (FILE, buf);                      \
        putc ('\n', FILE);                              \
@@ -2959,7 +3011,7 @@ do {                                                                      \
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)\
   do { char buf[100];                                  \
-       fputs ((TARGET_32BIT) ? "\t.long " : "\t.llong ", FILE);        \
+       fputs (TARGET_32BIT ? "\t.long " : "\t.llong ", FILE);  \
        ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE);  \
        assemble_name (FILE, buf);                      \
        putc ('-', FILE);                               \
@@ -3061,15 +3113,16 @@ do {                                                                    \
   {"add_operand", {SUBREG, REG, CONST_INT}},                   \
   {"non_add_cint_operand", {CONST_INT}},                       \
   {"and_operand", {SUBREG, REG, CONST_INT}},                   \
-  {"non_and_cint_operand", {CONST_INT}},                       \
+  {"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},   \
   {"logical_operand", {SUBREG, REG, CONST_INT}},               \
   {"non_logical_cint_operand", {CONST_INT}},                   \
   {"mask_operand", {CONST_INT}},                               \
+  {"mask64_operand", {CONST_INT, CONST_DOUBLE}},               \
   {"count_register_operand", {REG}},                           \
   {"fpmem_operand", {REG}},                                    \
   {"call_operand", {SYMBOL_REF, REG}},                         \
   {"current_file_function_operand", {SYMBOL_REF}},             \
-  {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}},        \
+  {"input_operand", {SUBREG, MEM, REG, CONST_INT, CONST_DOUBLE, SYMBOL_REF}}, \
   {"load_multiple_operation", {PARALLEL}},                     \
   {"store_multiple_operation", {PARALLEL}},                    \
   {"branch_comparison_operator", {EQ, NE, LE, LT, GE,          \
@@ -3098,7 +3151,6 @@ extern void output_options ();
 extern void rs6000_override_options ();
 extern void rs6000_file_start ();
 extern struct rtx_def *rs6000_float_const ();
-extern struct rtx_def *rs6000_immed_double_const ();
 extern struct rtx_def *rs6000_got_register ();
 extern int direct_return ();
 extern int get_issue_rate ();
@@ -3123,13 +3175,13 @@ extern int add_operand ();
 extern int non_add_cint_operand ();
 extern int non_logical_cint_operand ();
 extern int logical_operand ();
-extern int non_logical_operand ();
 extern int mask_constant ();
 extern int mask_operand ();
+extern int mask64_operand ();
+extern int and64_operand ();
 extern int and_operand ();
 extern int count_register_operand ();
 extern int fpmem_operand ();
-extern int non_and_cint_operand ();
 extern int reg_or_mem_operand ();
 extern int lwa_operand ();
 extern int call_operand ();
index 678286cb868c0a750d540834fe9de86fd1aaae6e..61398db34b2ce6936adea91fb62bc0ebee1d4bf9 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
-;; Copyright (C) 1990, 91-96, 1997, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 91-97, 1998 Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GNU CC.
                  || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (SImode));
 
-      emit_insn (gen_iorsi3 (tmp, operands[1], GEN_INT (value & 0xffff0000)));
-      emit_insn (gen_iorsi3 (operands[0], tmp, GEN_INT (value & 0x0000ffff)));
+      emit_insn (gen_iorsi3 (tmp, operands[1],
+                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
+      emit_insn (gen_iorsi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
 }")
   "or. %0,%1,%2"
   [(set_attr "type" "compare")])
 
+;; Split an IOR that we can't do in one insn into two insns, each of which
+;; does one 16-bit part.  This is used by combine.
+
+(define_split
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
+               (match_operand:SI 2 "non_logical_cint_operand" "")))]
+  ""
+  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))
+   (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 4)))]
+"
+{
+  operands[3] = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
+  operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff);
+}")
+
 (define_expand "xorsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (xor:SI (match_operand:SI 1 "gpc_reg_operand" "")
                  || rtx_equal_p (operands[0], operands[1]))
                 ? operands[0] : gen_reg_rtx (SImode));
 
-      emit_insn (gen_xorsi3 (tmp, operands[1], GEN_INT (value & 0xffff0000)));
-      emit_insn (gen_xorsi3 (operands[0], tmp, GEN_INT (value & 0x0000ffff)));
+      emit_insn (gen_xorsi3 (tmp, operands[1],
+                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
+      emit_insn (gen_xorsi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
       DONE;
     }
 }")
   "xor. %0,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn "*eqv_internal1"
+;; Split an XOR that we can't do in one insn into two insns, each of which
+;; does one 16-bit part.  This is used by combine.
+
+(define_split
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+        (xor:SI (match_operand:SI 1 "gpc_reg_operand" "")
+                (match_operand:SI 2 "non_logical_cint_operand" "")))]
+  ""
+  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 3)))
+   (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4)))]
+"
+{
+  operands[3] = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
+  operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff);
+}")
+
+(define_insn "*eqvsi3_internal1"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (not:SI (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
                        (match_operand:SI 2 "gpc_reg_operand" "r"))))]
    ""
    "eqv %0,%1,%2")
 
-(define_insn "*eqv_internal2"
+(define_insn "*eqvsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (not:SI (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
                                    (match_operand:SI 2 "gpc_reg_operand" "r")))
    "eqv. %3,%1,%2"
    [(set_attr "type" "compare")])
 
-(define_insn "*eqv_internal3"
+(define_insn "*eqvsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (not:SI (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
                                    (match_operand:SI 2 "gpc_reg_operand" "r")))
    "eqv. %0,%1,%2"
    [(set_attr "type" "compare")])
 
-(define_insn "*andc_internal1"
+(define_insn "*andcsi3_internal1"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                (match_operand:SI 2 "gpc_reg_operand" "r")))]
   ""
   "andc %0,%2,%1")
 
-(define_insn "*andc_internal2"
+(define_insn "*andcsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                            (match_operand:SI 2 "gpc_reg_operand" "r"))
   "andc. %3,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn "*andc_internal3"
+(define_insn "*andcsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                            (match_operand:SI 2 "gpc_reg_operand" "r"))
   "andc. %0,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn "*iorc_internal1"
+(define_insn "*iorcsi3_internal1"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                (match_operand:SI 2 "gpc_reg_operand" "r")))]
   ""
   "orc %0,%2,%1")
 
-(define_insn "*iorc_internal2"
+(define_insn "*iorcsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                            (match_operand:SI 2 "gpc_reg_operand" "r"))
   "orc. %3,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn "*iorc_internal3"
+(define_insn "*iorcsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
                            (match_operand:SI 2 "gpc_reg_operand" "r"))
   "orc. %0,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn "*nand_internal1"
+(define_insn "*nandsi3_internal1"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                (not:SI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
   ""
   "nand %0,%1,%2")
 
-(define_insn "*nand_internal2"
+(define_insn "*nandsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                            (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")))
   "nand. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn "*nand_internal3"
+(define_insn "*nandsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                            (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")))
   "nand. %0,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn "*nor_internal1"
+(define_insn "*norsi3_internal1"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                (not:SI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
   ""
   "nor %0,%1,%2")
 
-(define_insn "*nor_internal2"
+(define_insn "*norsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                            (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")))
   "nor. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn "*nor_internal3"
+(define_insn "*norsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
                            (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")))
   ""
   "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xffffffff")
 
-(define_insn ""
+(define_insn "*rotlsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                               (match_operand:SI 2 "reg_or_cint_operand" "ri"))
   "{rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xffffffff"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                               (match_operand:SI 2 "reg_or_cint_operand" "ri"))
   "{rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xffffffff"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal4"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (and:SI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                           (match_operand:SI 2 "reg_or_cint_operand" "ri"))
   ""
   "{rl%I2nm|rlw%I2nm} %0,%1,%h2,%m3,%M3")
 
-(define_insn ""
+(define_insn "*rotlsi3_internal5"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (and:SI
                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
   "{rl%I2nm.|rlw%I2nm.} %4,%1,%h2,%m3,%M3"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal6"
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
        (compare:CC (and:SI
                     (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
   "{rl%I2nm.|rlw%I2nm.} %0,%1,%h2,%m3,%M3"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal7"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extend:SI
         (subreg:QI
   ""
   "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xff")
 
-(define_insn ""
+(define_insn "*rotlsi3_internal8"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (zero_extend:SI
                     (subreg:QI
   "{rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xff"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal9"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (zero_extend:SI
                     (subreg:QI
   "{rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xff"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal10"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extend:SI
         (subreg:HI
   ""
   "{rl%I2nm|rlw%I2nm} %0,%1,%h2,0xffff")
 
-(define_insn ""
+(define_insn "*rotlsi3_internal11"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (zero_extend:SI
                     (subreg:HI
   "{rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xffff"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotlsi3_internal12"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (zero_extend:SI
                     (subreg:HI
              (clobber (match_dup 4))
              (clobber (match_dup 5))
              (clobber (reg:DF 76))])]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   "
 {
   operands[2] = force_reg (SImode, GEN_INT (0x43300000));
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (use (match_operand:DF 3 "gpc_reg_operand" "f"))
    (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
-   (clobber (match_operand:SI 5 "gpc_reg_operand" "=b"))
+   (clobber (match_operand 5 "gpc_reg_operand" "=b"))
    (clobber (reg:DF 76))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   "#"
   [(set_attr "length" "24")])
 
    (use (match_operand:SI 2 "gpc_reg_operand" ""))
    (use (match_operand:DF 3 "gpc_reg_operand" ""))
    (clobber (match_operand:SI 4 "gpc_reg_operand" ""))
-   (clobber (match_operand:SI 5 "gpc_reg_operand" ""))
+   (clobber (match_operand 5 "gpc_reg_operand" ""))
    (clobber (reg:DF 76))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   [(set (match_dup 4)
        (xor:SI (match_dup 1)
                (match_dup 6)))
              (use (match_dup 3))
              (clobber (match_dup 4))
              (clobber (reg:DF 76))])]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   "
 {
   operands[2] = force_reg (SImode, GEN_INT (0x43300000));
        (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (use (match_operand:SI 2 "gpc_reg_operand" "r"))
    (use (match_operand:DF 3 "gpc_reg_operand" "f"))
-   (clobber (match_operand:SI 4 "gpc_reg_operand" "=b"))
+   (clobber (match_operand 4 "gpc_reg_operand" "=b"))
    (clobber (reg:DF 76))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   "#"
   [(set_attr "length" "20")])
 
        (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
    (use (match_operand:SI 2 "gpc_reg_operand" ""))
    (use (match_operand:DF 3 "gpc_reg_operand" ""))
-   (clobber (match_operand:SI 4 "gpc_reg_operand" "=b"))
+   (clobber (match_operand 4 "gpc_reg_operand" "=b"))
    (clobber (reg:DF 76))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   [(set (match_dup 4)
        (unspec [(const_int 0)] 11))
    (set (match_dup 5)
 
 ;; Load up scratch register with base address + offset if needed
 (define_insn "*floatsidf2_loadaddr"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+  [(set (match_operand 0 "gpc_reg_operand" "=b")
        (unspec [(const_int 0)] 11))]
   "TARGET_HARD_FLOAT"
   "*
 (define_insn "*floatsidf2_store1"
   [(set (reg:DF 76)
        (unspec [(match_operand:SI 0 "gpc_reg_operand" "r")
-                (match_operand:SI 1 "gpc_reg_operand" "r")] 12))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+                (match_operand 1 "gpc_reg_operand" "b")] 12))]
+  "TARGET_HARD_FLOAT"
   "*
 {
   rtx indx;
 (define_insn "*floatsidf2_store2"
   [(set (reg:DF 76)
        (unspec [(match_operand:SI 0 "gpc_reg_operand" "r")
-                (match_operand:SI 1 "gpc_reg_operand" "r")
+                (match_operand 1 "gpc_reg_operand" "b")
                 (reg:DF 76)] 13))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT"
   "*
 {
   rtx indx;
 (define_insn "*floatsidf2_load"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (unspec [(reg:DF 76)
-                (match_operand:SI 1 "gpc_reg_operand" "b")] 14))]
-  "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+                (match_operand 1 "gpc_reg_operand" "b")] 14))]
+  "TARGET_HARD_FLOAT"
   "*
 {
   rtx indx;
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
    (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
-   (clobber (match_operand:SI 3 "gpc_reg_operand" "=b"))
+   (clobber (match_operand 3 "gpc_reg_operand" "=b"))
    (clobber (reg:DI 76))]
   "TARGET_HARD_FLOAT"
   "#"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
    (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
-   (clobber (match_operand:SI 3 "gpc_reg_operand" ""))
+   (clobber (match_operand 3 "gpc_reg_operand" ""))
    (clobber (reg:DI 76))]
   "TARGET_HARD_FLOAT"
   [(set (match_dup 2)
                 (match_dup 3)] 16))]
   "operands[4] = gen_rtx (REG, DImode, FPMEM_REGNUM);")
 
-(define_insn "*fctiwz"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
-       (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
-  "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
-  "{fcirz|fctiwz} %0,%1"
-  [(set_attr "type" "fp")])
-
 (define_insn "*fix_truncdfsi2_store"
   [(set (reg:DI 76)
        (unspec [(match_operand:DI 0 "gpc_reg_operand" "f")
-                (match_operand:SI 1 "gpc_reg_operand" "b")] 15))]
+                (match_operand 1 "gpc_reg_operand" "b")] 15))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
   "*
 {
 (define_insn "*fix_truncdfsi2_load"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (unspec [(reg:DI 76)
-                (match_operand:SI 1 "gpc_reg_operand" "b")] 16))]
+                (match_operand 1 "gpc_reg_operand" "b")] 16))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
   "*
 {
   rs6000_trunc_used = 1;
 }")
 
+(define_insn "*fctiwz"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+       (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
+  "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
+  "{fcirz|fctiwz} %0,%1"
+  [(set_attr "type" "fp")])
+
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
        (float:DF (match_operand:DI 1 "gpc_reg_operand" "f")))]
 (define_expand "adddi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                (match_operand:DI 2 "add_operand" "")))]
+                (match_operand:DI 2 "reg_or_cint_operand" "")))]
   ""
   "
 {
-  if (! TARGET_POWERPC64 && non_short_cint_operand (operands[2], DImode))
-    FAIL;
+  if (! TARGET_POWERPC64)
+    {
+      if (non_short_cint_operand (operands[2], DImode))
+       FAIL;
+    }
+  else
+    if (GET_CODE (operands[2]) == CONST_INT
+       && !add_operand (operands[2], DImode))
+      {
+       rtx tmp = ((reload_in_progress || reload_completed
+                   || 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);
+
+       if (low & 0x8000)
+         high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+
+       emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
+       emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
+       DONE;
+      }
 }")
 
 ;; Discourage ai/addic because of carry but provide it in an alternative
 ;; allowing register zero as source.
 
-(define_insn ""
+(define_insn "*adddi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,?r,r")
        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,b,r,b")
                 (match_operand:DI 2 "add_operand" "r,I,I,J")))]
    addic %0,%1,%2
    addis %0,%1,%v2")
 
-(define_insn ""
+(define_insn "*adddi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
        (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
                             (match_operand:DI 2 "reg_or_short_operand" "r,I"))
    addic. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*adddi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x")
        (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
                             (match_operand:DI 2 "reg_or_short_operand" "r,I"))
        (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
   "TARGET_POWERPC64"
-  "sradi %2,%1,31\;xor %0,%2,%1\;subf %0,%2,%0"
+  "sradi %2,%1,63\;xor %0,%2,%1\;subf %0,%2,%0"
   [(set_attr "length" "12")])
 
 (define_split
        (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
   "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 31)))
+  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
    (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
    (set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
   "")
        (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
   "TARGET_POWERPC64"
-  "sradi %2,%1,31\;xor %0,%2,%1\;subf %0,%0,%2"
+  "sradi %2,%1,63\;xor %0,%2,%1\;subf %0,%0,%2"
   [(set_attr "length" "12")])
 
 (define_split
        (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
   "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 31)))
+  [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
    (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
    (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
   "")
   "mulld %0,%1,%2"
    [(set_attr "type" "imul")])
 
+(define_insn "*mulsidi3_ppc64"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
+                (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
+  "TARGET_POWERPC64"
+  "mulld %0,%1,%2"
+  [(set_attr "type" "imul")])
+
 (define_insn "smuldi3_highpart"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (truncate:DI
 (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 "gpc_reg_operand" "r")))]
+                (match_operand:DI 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC64"
   "divd %0,%1,%2"
   [(set_attr "type" "idiv")])
   "TARGET_POWERPC64"
   "rld%I2cl %0,%1,%H2,0")
 
-(define_insn ""
+(define_insn "*rotldi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                               (match_operand:DI 2 "reg_or_cint_operand" "ri"))
   "rld%I2cl. %3,%1,%H2,0"
   [(set_attr "type" "delayed_compare")])
 
-(define_insn ""
+(define_insn "*rotldi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                               (match_operand:DI 2 "reg_or_cint_operand" "ri"))
   "rld%I2cl. %0,%1,%H2,0"
   [(set_attr "type" "delayed_compare")])
 
+(define_insn "*rotldi3_internal4"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                          (match_operand:DI 2 "reg_or_cint_operand" "ri"))
+               (match_operand:DI 3 "mask64_operand" "S")))]
+  "TARGET_POWERPC64"
+  "rld%I2c%B3 %0,%1,%H2,%S3")
+
+(define_insn "*rotldi3_internal5"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "ri"))
+                    (match_operand:DI 3 "mask64_operand" "S"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 4 "=r"))]
+  "TARGET_POWERPC64"
+  "rld%I2c%B3. %4,%1,%H2,%S3"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal6"
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x")
+       (compare:CC (and:DI
+                    (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                               (match_operand:DI 2 "reg_or_cint_operand" "ri"))
+                    (match_operand:DI 3 "mask64_operand" "S"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+  "TARGET_POWERPC64"
+  "rld%I2c%B3. %0,%1,%H2,%S3"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal7"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:QI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl %0,%1,%H2,56")
+
+(define_insn "*rotldi3_internal8"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r"))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %3,%1,%H2,56"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal9"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:QI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %0,%1,%H2,56"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal10"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:HI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl %0,%1,%H2,48")
+
+(define_insn "*rotldi3_internal11"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r"))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %3,%1,%H2,48"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal12"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:HI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %0,%1,%H2,48"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal13"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI
+        (subreg:SI
+         (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                    (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl %0,%1,%H2,32")
+
+(define_insn "*rotldi3_internal14"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 3 "=r"))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %3,%1,%H2,32"
+  [(set_attr "type" "delayed_compare")])
+
+(define_insn "*rotldi3_internal15"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI
+                    (subreg:SI
+                     (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+                                (match_operand:DI 2 "reg_or_cint_operand" "ri")) 0))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))]
+  "TARGET_POWERPC64"
+  "rld%I2cl. %0,%1,%H2,32"
+  [(set_attr "type" "delayed_compare")])
+
 (define_expand "ashldi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
   [(set_attr "type" "delayed_compare")])
 
 (define_insn "anddi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
-               (match_operand:DI 2 "and_operand" "?r,K,J")))
-   (clobber (match_scratch:CC 3 "=X,x,x"))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
+       (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
+               (match_operand:DI 2 "and64_operand" "?r,S,K,J")))
+   (clobber (match_scratch:CC 3 "=X,X,x,x"))]
   "TARGET_POWERPC64"
   "@
    and %0,%1,%2
+   rldic%B2 %0,%1,0,%S2
    andi. %0,%1,%b2
    andis. %0,%1,%u2")
 
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x")
-       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
-                           (match_operand:DI 2 "and_operand" "r,K,J"))
+(define_insn "*anddi3_internal2"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
+                           (match_operand:DI 2 "and64_operand" "r,K,J,S"))
                    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r"))]
+   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
   "TARGET_POWERPC64"
   "@
    and. %3,%1,%2
    andi. %3,%1,%b2
-   andis. %3,%1,%u2"
-  [(set_attr "type" "compare,compare,compare")])
+   andis. %3,%1,%u2
+   rldic%B2. %3,%1,0,%S2"
+  [(set_attr "type" "compare,compare,compare,delayed_compare")])
 
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x")
-       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
-                           (match_operand:DI 2 "and_operand" "r,K,J"))
+(define_insn "*anddi3_internal3"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x")
+       (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
+                           (match_operand:DI 2 "and64_operand" "r,K,J,S"))
                    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
        (and:DI (match_dup 1) (match_dup 2)))]
   "TARGET_POWERPC64"
   "@
    and. %0,%1,%2
    andi. %0,%1,%b2
-   andis. %0,%1,%u2"
-  [(set_attr "type" "compare,compare,compare")])
-
-;; Take a AND with a constant that cannot be done in a single insn and try to
-;; split it into two insns.  This does not verify that the insns are valid
-;; since this need not be done as combine will do it.
+   andis. %0,%1,%u2
+   rldic%B2. %3,%1,0,%S2"
+  [(set_attr "type" "compare,compare,compare,delayed_compare")])
 
-(define_split
+(define_expand "iordi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "non_and_cint_operand" "")))]
+       (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
+               (match_operand:DI 2 "reg_or_cint_operand" "")))]
   "TARGET_POWERPC64"
-  [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))]
   "
 {
-  int maskval = INTVAL (operands[2]);
-  int i, transitions, last_bit_value;
-  int orig = maskval, first_c = maskval, second_c;
-
-  /* We know that MASKVAL must have more than 2 bit-transitions.  Start at
-     the low-order bit and count for the third transition.  When we get there,
-     make a first mask that has everything to the left of that position
-     a one.  Then make the second mask to turn off whatever else is needed.  */
-
-  for (i = 1, transitions = 0, last_bit_value = maskval & 1; i < 32; i++)
+  if (GET_CODE (operands[2]) == CONST_INT
+      && !logical_operand (operands[2], DImode))
     {
-      if (((maskval >>= 1) & 1) != last_bit_value)
-       last_bit_value ^= 1, transitions++;
+      HOST_WIDE_INT value = INTVAL (operands[2]);
+      rtx tmp = ((reload_in_progress || reload_completed
+                 || rtx_equal_p (operands[0], operands[1]))
+                ? operands[0] : gen_reg_rtx (DImode));
 
-      if (transitions > 2)
-       {
-         first_c |= (~0) << i;
-         break;
-       }
+      emit_insn (gen_iordi3 (tmp, operands[1],
+                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
+      emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
+      DONE;
     }
-
-  second_c = orig | ~ first_c;
-
-  operands[3] = GEN_INT (first_c);
-  operands[4] = GEN_INT (second_c);
 }")
 
-(define_insn "iordi3"
+(define_insn "*iordi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
        (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
                (match_operand:DI 2 "logical_operand" "r,K,J")))]
    ori %0,%1,%b2
    oris %0,%1,%u2")
 
-(define_insn ""
+(define_insn "*iordi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "or. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*iordi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff);
 }")
 
-(define_insn "xordi3"
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
+               (match_operand:DI 2 "reg_or_cint_operand" "")))]
+  "TARGET_POWERPC64"
+  "
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && !logical_operand (operands[2], DImode))
+    {
+      HOST_WIDE_INT value = INTVAL (operands[2]);
+      rtx tmp = ((reload_in_progress || reload_completed
+                 || rtx_equal_p (operands[0], operands[1]))
+                ? operands[0] : gen_reg_rtx (DImode));
+
+      emit_insn (gen_xordi3 (tmp, operands[1],
+                            GEN_INT (value & (~ (HOST_WIDE_INT) 0xffff))));
+      emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff)));
+      DONE;
+    }
+}")
+
+(define_insn "*xordi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
        (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
                (match_operand:DI 2 "logical_operand" "r,K,J")))]
    xori %0,%1,%b2
    xoris %0,%1,%u2")
 
-(define_insn ""
+(define_insn "*xordi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "xor. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*xordi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
-               (match_operand:DI 2 "non_logical_cint_operand" "")))]
+        (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                (match_operand:DI 2 "non_logical_cint_operand" "")))]
   "TARGET_POWERPC64"
   [(set (match_dup 0) (xor:DI (match_dup 1) (match_dup 3)))
    (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 4)))]
 "
 {
-  operands[3] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+  operands[3] = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
   operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff);
 }")
 
-(define_insn ""
+(define_insn "*eqvdi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                        (match_operand:DI 2 "gpc_reg_operand" "r"))))]
    "TARGET_POWERPC64"
    "eqv %0,%1,%2")
 
-(define_insn ""
+(define_insn "*eqvdi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                                    (match_operand:DI 2 "gpc_reg_operand" "r")))
    "eqv. %3,%1,%2"
    [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*eqvdi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                                    (match_operand:DI 2 "gpc_reg_operand" "r")))
    "eqv. %0,%1,%2"
    [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*andcdi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                (match_operand:DI 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC64"
   "andc %0,%2,%1")
 
-(define_insn ""
+(define_insn "*andcdi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "andc. %3,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*andcdi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "andc. %0,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*iorcdi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                (match_operand:DI 2 "gpc_reg_operand" "r")))]
   "TARGET_POWERPC64"
   "orc %0,%2,%1")
 
-(define_insn ""
+(define_insn "*iorcdi3_inernal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "orc. %3,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*iorcdi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
                            (match_operand:DI 2 "gpc_reg_operand" "r"))
   "orc. %0,%2,%1"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*nanddi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                (not:DI (match_operand:DI 2 "gpc_reg_operand" "r"))))]
   "TARGET_POWERPC64"
   "nand %0,%1,%2")
 
-(define_insn ""
+(define_insn "*nanddi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                            (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
   "nand. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*nanddi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                            (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
   "nand. %0,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*nordi3_internal1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                (not:DI (match_operand:DI 2 "gpc_reg_operand" "r"))))]
   "TARGET_POWERPC64"
   "nor %0,%1,%2")
 
-(define_insn ""
+(define_insn "*nordi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                            (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
   "nor. %3,%1,%2"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "*nordi3_internal3"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
                            (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
 }")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
-       (match_operand:SI 1 "input_operand" "r,S,T,U,m,r,I,J,n,R,*h,r,r,0"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
+       (match_operand:SI 1 "input_operand" "r,U,m,r,I,J,n,R,*h,r,r,0"))]
   "gpc_reg_operand (operands[0], SImode)
    || gpc_reg_operand (operands[1], SImode)"
   "@
    mr %0,%1
-   {l|lwz} %0,[toc]%1(2)
-   {l|lwz} %0,[toc]%l1(2)
    {cal|la} %0,%a1
    {l%U1%X1|lwz%U1%X1} %0,%1
    {st%U0%X0|stw%U0%X0} %1,%0
    mt%0 %1
    mt%0 %1
    cror 0,0,0"
-  [(set_attr "type" "*,load,load,*,load,store,*,*,*,*,*,*,mtjmpr,*")
-   (set_attr "length" "4,4,4,4,4,4,4,4,8,4,4,4,4,4")])
+  [(set_attr "type" "*,*,load,store,*,*,*,*,*,*,mtjmpr,*")
+   (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4")])
 
 ;; Split a load of a large constant into the appropriate two-insn
 ;; sequence.
 (define_split
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
        (match_operand:SF 1 "const_double_operand" ""))]
-  "TARGET_32BIT && reload_completed
+  "! TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
           && GET_CODE (SUBREG_REG (operands[0])) == REG
   operands[3] = GEN_INT(l);
 }")
 
+(define_split
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (match_operand:SF 1 "const_double_operand" ""))]
+  "TARGET_POWERPC64 && reload_completed
+   && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
+       || (GET_CODE (operands[0]) == SUBREG
+          && GET_CODE (SUBREG_REG (operands[0])) == REG
+          && REGNO (SUBREG_REG (operands[0])) <= 31))"
+  [(set (match_dup 2) (match_dup 3))]
+  "
+{
+  long l;
+  REAL_VALUE_TYPE rv;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+  REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+
+  operands[2] = gen_lowpart (SImode, operands[0]);
+  operands[3] = GEN_INT(l);
+}")
+
 (define_insn "*movsf_hardfloat"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,!r,!r")
        (match_operand:SF 1 "input_operand" "f,m,f,G,Fn"))]
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (match_operand:DF 1 "const_int_operand" ""))]
-  "TARGET_32BIT && reload_completed
+  "! TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
           && GET_CODE (SUBREG_REG (operands[0])) == REG
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (match_operand:DF 1 "const_double_operand" ""))]
-  "TARGET_32BIT && reload_completed
+  "! TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
           && GET_CODE (SUBREG_REG (operands[0])) == REG
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (match_operand:DF 1 "easy_fp_constant" ""))]
-  "TARGET_64BIT && reload_completed
+  "TARGET_POWERPC64 && reload_completed
    && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
        || (GET_CODE (operands[0]) == SUBREG
           && GET_CODE (SUBREG_REG (operands[0])) == REG
           && REGNO (SUBREG_REG (operands[0])) <= 31))"
-  [(set (match_dup 2) (subreg:DI (match_dup 1) 0))]
+  [(set (match_dup 2) (match_dup 3))]
   "
-{ operands[2] = gen_lowpart (DImode, operands[0]); }")
+{
+  int endian = (WORDS_BIG_ENDIAN == 0);
+  long l[2];
+  REAL_VALUE_TYPE rv;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+  REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
+
+  operands[2] = gen_lowpart (DImode, operands[0]);
+  /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN.  */
+  operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
+}")
 
 ;; Don't have reload use general registers to load a constant.  First,
 ;; it might not work if the output operand has is the equivalent of
 {
   switch (which_alternative)
     {
+    default:
+      abort();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
         the first register operand 0 is the same as the second register of
 {
   switch (which_alternative)
     {
+    default:
+      abort();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
         the first register operand 0 is the same as the second register of
   if (GET_CODE (operands[0]) != REG)
     operands[1] = force_reg (DImode, operands[1]);
 
-  if (TARGET_64BIT
-      && (GET_CODE (operands[1]) == CONST_DOUBLE
-         || GET_CODE (operands[1]) == CONST_INT))
-    {
-      HOST_WIDE_INT low;
-      HOST_WIDE_INT high;
-
-      if (GET_CODE (operands[1]) == CONST_DOUBLE)
-       {
-         low = CONST_DOUBLE_LOW (operands[1]);
-         high = CONST_DOUBLE_HIGH (operands[1]);
-       }
-      else
+  /* Convert a move of a CONST_DOUBLE into a CONST_INT
+     only if sign-extended lower-half for 32-bit host.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
 #if HOST_BITS_PER_WIDE_INT == 32
-       {
-         low = INTVAL (operands[1]);
-         high = (low < 0) ? ~0 : 0;
-       }
-#else
-       {
-          low = INTVAL (operands[1]) & 0xffffffff;
-          high = (HOST_WIDE_INT) INTVAL (operands[1]) >> 32;
-       }
+      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
+          && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
+         || (CONST_DOUBLE_HIGH (operands[1]) == 0xffffffff
+             && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
 #endif
+        )
+    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
 
-       if (high)
-         {
-           emit_move_insn (operands[0], GEN_INT (high));
-           emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT(32)));
-           if (low)
-             {
-               HOST_WIDE_INT low_low = low & 0xffff;
-               HOST_WIDE_INT low_high = low & (~ (HOST_WIDE_INT) 0xffff);
-               if (low_high)
-                 emit_insn (gen_iordi3 (operands[0], operands[0],
-                                        GEN_INT (low_high)));
-               if (low_low)
-                 emit_insn (gen_iordi3 (operands[0], operands[0],
-                                        GEN_INT (low_low)));
-             }
-             DONE;
-         }
-    }
+  if (TARGET_64BIT
+      && CONSTANT_P (operands[1])
+#if HOST_BITS_PER_WIDE_INT == 32
+      && GET_CODE (operands[1]) != CONST_INT
+#endif
+      && ! easy_fp_constant (operands[1], DImode)
+      && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1]))
+    {
+      /* Emit a USE operation so that the constant isn't deleted if
+        expensive optimizations are turned on because nobody
+        references it.  This should only be done for operands that
+        contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
+        This should not be done for operands that contain LABEL_REFs.
+        For now, we just handle the obvious case.  */
+      if (GET_CODE (operands[1]) != LABEL_REF)
+       emit_insn (gen_rtx (USE, VOIDmode, operands[1]));
 
-      /* Stores between FPR and any non-FPR registers must go through a
-         temporary stack slot.  */
+      /* If we are to limit the number of things we put in the TOC and
+        this is a symbol plus a constant we can add in one insn,
+        just put the symbol in the TOC and add the constant.  Don't do
+        this if reload is in progress.  */
+      if (GET_CODE (operands[1]) == CONST
+         && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+         && GET_CODE (XEXP (operands[1], 0)) == PLUS
+         && add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
+         && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+             || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
+         && ! side_effects_p (operands[0]))
+       {
+         rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
+         rtx other = XEXP (XEXP (operands[1], 0), 1);
 
-  if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
-      && ((FP_REGNO_P (REGNO (operands[0]))
-          && ! FP_REGNO_P (REGNO (operands[1])))
-         || (FP_REGNO_P (REGNO (operands[1]))
-             && ! FP_REGNO_P (REGNO (operands[0])))))
-    {
-      rtx stack_slot = assign_stack_temp (DImode, 8, 0);
+         emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
+         DONE;
+       }
 
-      emit_move_insn (stack_slot, operands[1]);
-      emit_move_insn (operands[0], stack_slot);
-      DONE;
+      operands[1] = force_const_mem (DImode, operands[1]);
+      if (! memory_address_p (DImode, XEXP (operands[1], 0))
+         && ! reload_in_progress)
+       operands[1] = change_address (operands[1], DImode,
+                                     XEXP (operands[1], 0));
     }
 }")
 
 (define_insn "*movdi_32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
        (match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
-  "TARGET_32BIT
+  "! TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
   "*
 {
   switch (which_alternative)
     {
+    default:
+      abort();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
         the first register operand 0 is the same as the second register of
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (match_operand:DI 1 "const_int_operand" ""))]
-  "TARGET_32BIT && reload_completed"
+  "! TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 1))]
   "
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (match_operand:DI 1 "const_double_operand" ""))]
-  "TARGET_32BIT && reload_completed"
+  "! TARGET_POWERPC64 && reload_completed"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
   "
 (define_insn "*movdi_64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
        (match_operand:DI 1 "input_operand" "r,m,r,I,J,nF,R,f,m,f,*h,r,0"))]
-  "TARGET_64BIT
+  "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
   "@
   [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,*,mtjmpr,*")
    (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
 
-;; Split a load of a large constant into the appropriate five-instruction
-;; sequence.  The expansion in movdi tries to perform the minimum number of
-;; steps, but here we have to handle anything in a constant number of insns.
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (match_operand:DI 1 "const_double_operand" "F"))]
+  "TARGET_POWERPC64 && GET_CODE (operands[1]) == CONST_DOUBLE
+   && num_insns_constant (operands[1], DImode) == 1"
+  "*
+{
+  return ((unsigned HOST_WIDE_INT)
+         (CONST_DOUBLE_LOW (operands[1]) + 0x8000) < 0x10000)
+        ? \"li %0,%1\" : \"lis %0,%v1\";
+}")
+
+(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]) & 0xffff0000);
+  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" ""))]
-  "TARGET_64BIT && num_insns_constant (operands[1], DImode) > 1"
+  "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]) == 0xffffffff
+           && (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)))
+               (match_dup 3)))]
+  "
+{
+  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xffff0000);
+  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_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 (subreg:SI (match_dup 0) 0)))]
+  "
+{ operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); }")
+
+(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)))
+                  (const_int 32)))]
+  "
+{ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); }")
+
+;; Generate all one-bits and clear left or right.
+;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (match_operand:DI 1 "mask64_operand" ""))]
+  "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
+  [(set (match_dup 0) (const_int -1))
    (set (match_dup 0)
-       (ior:DI (match_dup 0)
-               (match_dup 4)))
+       (and:DI (rotate:DI (match_dup 0)
+                          (const_int 0))
+               (match_dup 1)))]
+  "")
+
+;; Split a load of a large constant into the appropriate five-instruction
+;; sequence.  Handle anything in a constant number of insns.
+;; When non-easy constants can go in the TOC, this should use
+;; easy_fp_constant predicate.
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (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)
+       (ashift:DI (match_dup 0)
+                  (const_int 32)))
    (set (match_dup 0)
        (ior:DI (match_dup 0)
-               (match_dup 5)))]
+               (match_dup 3)))]
   "
 {
   HOST_WIDE_INT low;
     }
 #endif
 
-  if ((high + 0x8000) < 0x10000
-      && ((low & 0xffff) == 0 || (low & (~ (HOST_WIDE_INT) 0xffff)) == 0))
-    FAIL;
-
-  operands[2] = GEN_INT (high & (~ (HOST_WIDE_INT) 0xffff));
-  operands[3] = GEN_INT (high & 0xffff);
-  operands[4] = GEN_INT (low & (~ (HOST_WIDE_INT) 0xffff));
-  operands[5] = GEN_INT (low & 0xffff);
+  operands[2] = GEN_INT (high);
+  operands[3] = GEN_INT (low);
 }")
 
 (define_insn ""
 ;; while the 2nd alternative would not.  We put memory cases first so they
 ;; are preferred.  Otherwise, we'd try to reload the output instead of
 ;; giving the SCRATCH mq.
-(define_insn ""
+(define_insn "*movti_power"
   [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
        (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
    (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
   [(set_attr "type" "store,store,*,load,load")
    (set_attr "length" "*,16,16,*,16")])
 
-(define_insn ""
+(define_insn "*movti_string"
   [(set (match_operand:TI 0 "reg_or_mem_operand" "=m,????r,????r")
        (match_operand:TI 1 "reg_or_mem_operand" "r,r,m"))
    (clobber (match_scratch:SI 2 "=X,X,X"))]
   [(set_attr "type" "store,*,load")
    (set_attr "length" "16,16,16")])
 
-(define_insn ""
+(define_insn "*movti_ppc64"
   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
        (match_operand:TI 1 "input_operand" "r,m,r"))]
   "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
 {
   switch (which_alternative)
     {
+    default:
+      abort();
     case 0:
       /* We normally copy the low-numbered register first.  However, if
         the first register operand 0 is the same as the second register of
 ;; We move the back-chain and decrement the stack pointer.
 
 (define_expand "allocate_stack"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (reg:SI 1) (match_operand:SI 1 "reg_or_short_operand" "")))
-   (set (reg:SI 1)
-       (minus:SI (reg:SI 1) (match_dup 1)))]
+  [(set (match_operand 0 "register_operand" "=r")
+       (minus (reg 1) (match_operand 1 "reg_or_short_operand" "")))
+   (set (reg 1)
+       (minus (reg 1) (match_dup 1)))]
   ""
   "
 { rtx chain = gen_reg_rtx (Pmode);
   if (DEFAULT_ABI == ABI_NT
       && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) > 4096))
     {
-      rtx tmp = gen_reg_rtx (SImode);
+      rtx tmp = gen_reg_rtx (Pmode);
       emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__allocate_stack\"),
-                              tmp, 0, SImode, 1, operands[1], Pmode);
+                              tmp, 0, Pmode, 1, operands[1], Pmode);
       emit_insn (gen_set_sp (tmp));
       emit_move_insn (operands[0], tmp);
       DONE;
     {
       emit_insn ((* ((TARGET_32BIT) ? gen_addsi3 : gen_adddi3))
                 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
-      emit_move_insn (gen_rtx (MEM, (TARGET_32BIT) ? SImode : DImode,
-                              stack_pointer_rtx),
-                     chain);
+      emit_move_insn (gen_rtx (MEM, Pmode, stack_pointer_rtx), chain);
     }
 
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
   "")
 
 (define_expand "restore_stack_block"
-  [(set (match_dup 2) (mem:SI (match_operand:SI 0 "register_operand" "")))
-   (set (match_dup 0) (match_operand:SI 1 "register_operand" ""))
-   (set (mem:SI (match_dup 0)) (match_dup 2))]
+  [(set (match_dup 2) (mem (match_operand 0 "register_operand" "")))
+   (set (match_dup 0) (match_operand 1 "register_operand" ""))
+   (set (mem (match_dup 0)) (match_dup 2))]
   ""
   "
-{ operands[2] = gen_reg_rtx (SImode); }")
+{ operands[2] = gen_reg_rtx (Pmode); }")
 
 (define_expand "save_stack_nonlocal"
-  [(match_operand:DI 0 "memory_operand" "")
-   (match_operand:SI 1 "register_operand" "")]
+  [(match_operand 0 "memory_operand" "")
+   (match_operand 1 "register_operand" "")]
   ""
   "
 {
-  rtx temp = gen_reg_rtx (SImode);
+  rtx temp = gen_reg_rtx (Pmode);
 
   /* Copy the backchain to the first word, sp to the second.  */
-  emit_move_insn (temp, gen_rtx (MEM, SImode, operands[1]));
-  emit_move_insn (operand_subword (operands[0], 0, 0, DImode), temp);
-  emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
+  emit_move_insn (temp, gen_rtx (MEM, Pmode, operands[1]));
+  emit_move_insn (operand_subword (operands[0], 0, 0, (TARGET_32BIT ? DImode : TImode)),
+                 temp);
+  emit_move_insn (operand_subword (operands[0], 1, 0, (TARGET_32BIT ? DImode : TImode)),
+                 operands[1]);
   DONE;
 }")
 
 (define_expand "restore_stack_nonlocal"
-  [(match_operand:SI 0 "register_operand" "")
-   (match_operand:DI 1 "memory_operand" "")]
+  [(match_operand 0 "register_operand" "")
+   (match_operand 1 "memory_operand" "")]
   ""
   "
 {
-  rtx temp = gen_reg_rtx (SImode);
+  rtx temp = gen_reg_rtx (Pmode);
 
   /* Restore the backchain from the first word, sp from the second.  */
-  emit_move_insn (temp, operand_subword (operands[1], 0, 0, DImode));
-  emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
-  emit_move_insn (gen_rtx (MEM, SImode, operands[0]), temp);
+  emit_move_insn (temp,
+                 operand_subword (operands[1], 0, 0, (TARGET_32BIT ? DImode : TImode)));
+  emit_move_insn (operands[0],
+                 operand_subword (operands[1], 1, 0, (TARGET_32BIT ? DImode : TImode)));
+  emit_move_insn (gen_rtx (MEM, Pmode, operands[0]), temp);
   DONE;
 }")
 
 ;; We do not break this into separate insns, so that the scheduler will not try
 ;; to move the load of the new TOC before any loads from the TOC.
 
-(define_insn "call_indirect_aix"
+(define_insn "call_indirect_aix32"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
         (match_operand 1 "const_int_operand" "n"))
    (use (match_operand 2 "const_int_operand" "n"))
   [(set_attr "type" "load")
    (set_attr "length" "28")])
 
-(define_insn "call_value_indirect_aix"
+(define_insn "call_indirect_aix64"
+  [(call (mem:SI (match_operand:DI 0 "register_operand" "b"))
+        (match_operand 1 "const_int_operand" "n"))
+   (use (match_operand 2 "const_int_operand" "n"))
+   (use (match_operand 3 "offsettable_addr_operand" "p"))
+   (use (match_operand 4 "register_operand" "r"))
+   (clobber (match_operand 5 "register_operand" "=r"))
+   (clobber (match_scratch:SI 6 "=&r"))
+   (clobber (match_scratch:SI 7 "=l"))]
+  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX
+   && (INTVAL (operands[2]) == CALL_NORMAL || (INTVAL (operands[2]) & CALL_LONG) != 0)"
+  "stw %4,%a3\;ld %6,0(%0)\;ld %4,8(%0)\;mt%7 %6\;ld %5,16(%0)\;blrl\;ld %4,%a3"
+  [(set_attr "type" "load")
+   (set_attr "length" "28")])
+
+(define_insn "call_value_indirect_aix32"
   [(set (match_operand 0 "register_operand" "fg")
        (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
              (match_operand 2 "const_int_operand" "n")))
    (clobber (match_scratch:SI 8 "=l"))]
   "DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
-  "{st|stw} %5,%a4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1);\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%a4"
+  "{st|stw} %5,%a4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1)\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%a4"
+  [(set_attr "type" "load")
+   (set_attr "length" "28")])
+
+(define_insn "call_value_indirect_aix64"
+  [(set (match_operand 0 "register_operand" "fg")
+       (call (mem:SI (match_operand:DI 1 "register_operand" "b"))
+             (match_operand 2 "const_int_operand" "n")))
+   (use (match_operand 3 "const_int_operand" "n"))
+   (use (match_operand 4 "offsettable_addr_operand" "p"))
+   (use (match_operand 5 "register_operand" "r"))
+   (clobber (match_operand 6 "register_operand" "=r"))
+   (clobber (match_scratch:SI 7 "=&r"))
+   (clobber (match_scratch:SI 8 "=l"))]
+  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX
+   && (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
+  "stw %5,%a4\;ld %7,0(%1)\;ld %5,8(%1)\;mt%8 %7\;ld %6,16(%1)\;blrl\;ld %5,%a4"
   [(set_attr "type" "load")
    (set_attr "length" "28")])
 
 
 ;; Now the definitions for the call and call_value insns
 (define_expand "call"
-  [(parallel [(call (mem:SI (match_operand:SI 0 "address_operand" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
                    (match_operand 1 "" ""))
              (use (match_operand 2 "" ""))
              (clobber (scratch:SI))])]
            {
              /* AIX function pointers are really pointers to a three word area */
              rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
-             emit_call_insn (gen_call_indirect_aix (force_reg (Pmode, operands[0]),
-                                                    operands[1], operands[2],
-                                                    toc_addr, toc_reg, static_chain));
+             emit_call_insn (TARGET_32BIT
+                             ? gen_call_indirect_aix32 (force_reg (Pmode, operands[0]),
+                                                        operands[1], operands[2],
+                                                        toc_addr, toc_reg, static_chain)
+                             : gen_call_indirect_aix64 (force_reg (Pmode, operands[0]),
+                                                        operands[1], operands[2],
+                                                        toc_addr, toc_reg, static_chain));
            }
          else if (DEFAULT_ABI == ABI_NT)
            {
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "" "")
-                  (call (mem:SI (match_operand:SI 1 "address_operand" ""))
+                  (call (mem:SI (match_operand 1 "address_operand" ""))
                         (match_operand 2 "" "")))
              (use (match_operand 3 "" ""))
              (clobber (scratch:SI))])]
            {
              /* AIX function pointers are really pointers to a three word area */
              rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
-             emit_call_insn (gen_call_value_indirect_aix (operands[0],
-                                                          force_reg (Pmode, operands[1]),
-                                                          operands[2], operands[3],
-                                                          toc_addr, toc_reg, static_chain));
+             emit_call_insn (TARGET_32BIT
+                             ? gen_call_value_indirect_aix32 (operands[0],
+                                                              force_reg (Pmode, operands[1]),
+                                                              operands[2], operands[3],
+                                                              toc_addr, toc_reg, static_chain)
+                             : gen_call_value_indirect_aix64 (operands[0],
+                                                              force_reg (Pmode, operands[1]),
+                                                              operands[2], operands[3],
+                                                              toc_addr, toc_reg, static_chain));
            }
          else if (DEFAULT_ABI == ABI_NT)
            {
 ;; variable argument function.  It is > 0 if FP registers were passed
 ;; and < 0 if they were not.
 
-(define_insn ""
+(define_insn "*call_local32"
   [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
   [(set_attr "type" "branch")
    (set_attr "length" "4,8")])
 
+(define_insn "*call_local64"
+  [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
+        (match_operand 1 "" "g,g"))
+   (use (match_operand:SI 2 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 3 "=l,l"))]
+  "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
+  "*
+{
+  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+    output_asm_insn (\"crxor 6,6,6\", operands);
+
+  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+    output_asm_insn (\"creqv 6,6,6\", operands);
+
+  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@local\" : \"bl %z0\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "4,8")])
+
+(define_insn "*ret_call_local32"
+  [(set (match_operand 0 "" "=fg,fg")
+       (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
+             (match_operand 2 "" "g,g")))
+   (use (match_operand:SI 3 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 4 "=l,l"))]
+  "(INTVAL (operands[3]) & CALL_LONG) == 0"
+  "*
+{
+  if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+    output_asm_insn (\"crxor 6,6,6\", operands);
+
+  else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+    output_asm_insn (\"creqv 6,6,6\", operands);
+
+  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "4,8")])
+
+
+(define_insn "*ret_call_local64"
+  [(set (match_operand 0 "" "=fg,fg")
+       (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
+             (match_operand 2 "" "g,g")))
+   (use (match_operand:SI 3 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 4 "=l,l"))]
+  "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
+  "*
+{
+  if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+    output_asm_insn (\"crxor 6,6,6\", operands);
+
+  else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+    output_asm_insn (\"creqv 6,6,6\", operands);
+
+  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "4,8")])
+
 ;; Call to function which may be in another module.  Restore the TOC
 ;; pointer (r2) after the call unless this is System V.
 ;; Operand2 is non-zero if we are using the V.4 calling sequence and
 ;; variable argument function.  It is > 0 if FP registers were passed
 ;; and < 0 if they were not.
 
-(define_insn ""
+(define_insn "*call_nonlocal_aix32"
   [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
         (match_operand 1 "" "fg,fg"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
   [(set_attr "type" "branch")
    (set_attr "length" "8,12")])
 
-(define_insn ""
+(define_insn "*call_nonlocal_aix64"
+  [(call (mem:SI (match_operand:DI 0 "call_operand" "s,s"))
+        (match_operand 1 "" "fg,fg"))
+   (use (match_operand:SI 2 "immediate_operand" "O,n"))
+   (clobber (match_scratch:SI 3 "=l,l"))]
+  "TARGET_64BIT && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
+   && (INTVAL (operands[2]) & CALL_LONG) == 0"
+  "*
+{
+  /* Indirect calls should go through call_indirect */
+  if (GET_CODE (operands[0]) == REG)
+    abort ();
+
+  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+    output_asm_insn (\"crxor 6,6,6\", operands);
+
+  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+    output_asm_insn (\"creqv 6,6,6\", operands);
+
+  return (TARGET_WINDOWS_NT) ? \"bl %z0\;.znop %z0\" : \"bl %z0\;%.\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "8,12")])
+
+(define_insn "*call_nonlocal_sysv"
   [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
         (match_operand 1 "" "fg,fg"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
   [(set_attr "type" "branch")
    (set_attr "length" "4,8")])
 
-(define_insn ""
+(define_insn "*ret_call_nonlocal_aix32"
   [(set (match_operand 0 "" "=fg,fg")
-       (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
-             (match_operand 2 "" "g,g")))
+       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
+             (match_operand 2 "" "fg,fg")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 4 "=l,l"))]
-  "(INTVAL (operands[3]) & CALL_LONG) == 0"
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
+   && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
+  /* This should be handled by call_value_indirect */
+  if (GET_CODE (operands[1]) == REG)
+    abort ();
+
   if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
     output_asm_insn (\"crxor 6,6,6\", operands);
 
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\";
+  return (TARGET_WINDOWS_NT) ? \"bl %z1\;.znop %z1\" : \"bl %z1\;%.\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "4,8")])
+   (set_attr "length" "8,12")])
 
-(define_insn ""
+(define_insn "*ret_call_nonlocal_aix64"
   [(set (match_operand 0 "" "=fg,fg")
-       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
+       (call (mem:SI (match_operand:DI 1 "call_operand" "s,s"))
              (match_operand 2 "" "fg,fg")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 4 "=l,l"))]
-  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
+  "TARGET_64BIT && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
   "*
 {
   [(set_attr "type" "branch")
    (set_attr "length" "8,12")])
 
-(define_insn ""
+(define_insn "*ret_call_nonlocal_sysv"
   [(set (match_operand 0 "" "=fg,fg")
        (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
              (match_operand 2 "" "fg,fg")))
    {sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0"
   [(set_attr "length" "12,8,12,12,12")])
 
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
+       (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
+              (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I")))
+   (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))]
+  "TARGET_POWERPC64"
+  "@
+   xor %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0
+   subfic %3,%1,0\;adde %0,%3,%1
+   xori %0,%1,%b2\;subfic %3,%0,0\;adde %0,%3,%0
+   xoris %0,%1,%u2\;subfic %3,%0,0\;adde %0,%3,%0
+   subfic %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0"
+  [(set_attr "length" "12,8,12,12,12")])
+
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x")
        (compare:CC
   [(set_attr "type" "compare")
    (set_attr "length" "12,8,12,12,12")])
 
+(define_insn ""
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x")
+       (compare:CC
+        (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
+               (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I"))
+        (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
+       (eq:DI (match_dup 1) (match_dup 2)))
+   (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))]
+  "TARGET_POWERPC64"
+  "@
+   xor %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0
+   subfic %3,%1,0\;adde. %0,%3,%1
+   xori %0,%1,%b2\;subfic %3,%0,0\;adde. %0,%3,%0
+   xoris %0,%1,%u2\;subfic %3,%0,0\;adde. %0,%3,%0
+   subfic %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "12,8,12,12,12")])
+
 ;; We have insns of the form shown by the first define_insn below.  If
 ;; there is something inside the comparison operation, we must split it.
 (define_split
   "{ai|addic} %2,%1,-1\;{sfe|subfe} %0,%2,%1"
   [(set_attr "length" "8")])
 
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (lshiftrt:DI (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
+                    (const_int 63)))
+   (clobber (match_scratch:DI 2 "=&r"))]
+  "TARGET_POWERPC64"
+  "addic %2,%1,-1\;subfe %0,%2,%1"
+  [(set_attr "length" "8")])
+
 ;; This is what (plus (ne X (const_int 0)) Y) looks like.
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   "{ai|addic} %3,%1,-1\;{aze|addze} %0,%2"
   [(set_attr "length" "8")])
 
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (plus:DI (lshiftrt:DI
+                 (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
+                 (const_int 63))
+                (match_operand:DI 2 "gpc_reg_operand" "r")))
+   (clobber (match_scratch:DI 3 "=&r"))]
+  "TARGET_POWERPC64"
+  "addic %3,%1,-1\;addze %0,%2"
+  [(set_attr "length" "8")])
+
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (compare:CC
   [(set_attr "type" "compare")
    (set_attr "length" "8")])
 
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC
+        (plus:DI (lshiftrt:DI
+                  (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
+                  (const_int 63))
+                 (match_operand:DI 2 "gpc_reg_operand" "r"))
+        (const_int 0)))
+   (clobber (match_scratch:DI 3 "=&r"))]
+  "TARGET_POWERPC64"
+  "addic %3,%1,-1\;addze. %3,%2"
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
+
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
        (compare:CC
   [(set_attr "type" "compare")
    (set_attr "length" "8")])
 
+(define_insn ""
+  [(set (match_operand:CC 4 "cc_reg_operand" "=x")
+       (compare:CC
+        (plus:DI (lshiftrt:DI
+                  (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
+                  (const_int 63))
+                 (match_operand:DI 2 "gpc_reg_operand" "r"))
+        (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (plus:DI (lshiftrt:DI (neg:DI (abs:DI (match_dup 1))) (const_int 63))
+                (match_dup 2)))
+   (clobber (match_scratch:DI 3 "=&r"))]
+  "TARGET_POWERPC64"
+  "addic %3,%1,-1\;addze. %0,%2"
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (le:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
index 1a7439a3383c681eaf59e2dda368f9420a6b7e96..d85f51356e55520dd2aaf14f55bda0b5f9023e36 100644 (file)
@@ -266,7 +266,17 @@ do {                                                                       \
 /* Default ABI to compile code for */
 #define DEFAULT_ABI rs6000_current_abi
 
-#include "rs6000/powerpc.h"
+#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+
+#define ASM_DEFAULT_SPEC "-mppc"
+
+#include "rs6000/rs6000.h"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC601
 
 /* System V.4 uses register 13 as a pointer to the small data area,
    so it is not available to the normal user.  */
diff --git a/gcc/config/rs6000/t-aix43 b/gcc/config/rs6000/t-aix43
new file mode 100644 (file)
index 0000000..56ddb45
--- /dev/null
@@ -0,0 +1,48 @@
+# Do not build libgcc1.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so... [taken from t-sparclite]
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+       cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#define FLOAT' > fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# Build the libraries for both hard and soft floating point and all of the 
+# different processor models
+
+MULTILIB_OPTIONS       = msoft-float \
+                         mcpu=common/mcpu=power/mcpu=powerpc/maix64
+
+MULTILIB_DIRNAMES      = soft-float \
+                         common power powerpc aix64
+
+MULTILIB_MATCHES       = msoft-float=mcpu?403 \
+                         maix64=maix64 \
+                         mcpu?power=mpower \
+                         mcpu?power=mrios1 \
+                         mcpu?power=mcpu?rios1 \
+                         mcpu?power=mcpu?rsc \
+                         mcpu?power=mcpu?rsc1 \
+                         mcpu?power=mpower2 \
+                         mcpu?power=mrios2 \
+                         mcpu?power=mcpu=rios2 \
+                         mcpu?powerpc=mcpu?601 \
+                         mcpu?powerpc=mcpu?602 \
+                         mcpu?powerpc=mcpu?603 \
+                         mcpu?powerpc=mcpu?603e \
+                         mcpu?powerpc=mcpu?604 \
+                         mcpu?powerpc=mcpu?620 \
+                         mcpu?powerpc=mcpu?403 \
+                         mcpu?powerpc=mpowerpc \
+                         mcpu?powerpc=mpowerpc-gpopt \
+                         mcpu?powerpc=mpowerpc-gfxopt
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
index 7c11c1b2ae6576f9362447d3a7abbdf719fd75a9..742a5e8c5fc67051b5b46a4369b31b6fcdca52ad 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler, for PowerPC
    running Windows/NT.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
 This file is part of GNU CC.
@@ -27,12 +27,21 @@ Boston, MA 02111-1307, USA.  */
 /* Default ABI to compile code for */
 #define DEFAULT_ABI ABI_NT
 
-#include "rs6000/powerpc.h"
+#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+
+#define ASM_DEFAULT_SPEC "-mppc"
 
 /* Pseudo target that we can test in the md file.  */
-#undef         TARGET_WINDOWS_NT
 #define        TARGET_WINDOWS_NT 1
 
+#include "rs6000/rs6000.h"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_POWERPC
+
 #undef CPP_PREDEFINES
 #define        CPP_PREDEFINES "-DWIN32 -D_WIN32 \
   -DWINNT -D__STDC__=0 -DALMOST_STDC \
@@ -71,9 +80,6 @@ Boston, MA 02111-1307, USA.  */
 #undef PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
 
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_POWERPC
-
 /* NT always runs little endian */
 #undef  BYTES_BIG_ENDIAN
 #define BYTES_BIG_ENDIAN 0 
@@ -113,9 +119,6 @@ Boston, MA 02111-1307, USA.  */
 #undef TARGET_DEFAULT 
 #define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC)
 
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC601
-
 /* Address to save the TOC register */
 #undef RS6000_SAVE_TOC
 #define RS6000_SAVE_TOC plus_constant (virtual_incoming_args_rtx, -RS6000_SAVE_AREA - 8)
@@ -162,7 +165,7 @@ do {                                                                        \
   ASM_OUTPUT_SKIP (FILE, SIZE);                                                \
 } while (0)
 
-/* Describe how to emit unitialized external linkage items  */
+/* Describe how to emit uninitialized external linkage items  */
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN)          \
 do {                                                                   \
   ASM_GLOBALIZE_LABEL (FILE, NAME);                                    \
diff --git a/gcc/config/rs6000/x-aix41 b/gcc/config/rs6000/x-aix41
new file mode 100644 (file)
index 0000000..69c666b
--- /dev/null
@@ -0,0 +1,12 @@
+# configuration for IBM RS/6000 running AIX 4.1+
+
+# Show we need to use the C version of ALLOCA
+ALLOCA=alloca.o
+
+# We need -lld for collect2 (actually this only matters
+# for a native compiler, but this is as good a place as any
+# to define the symbol).
+CLIB=-lld
+
+# f771 and cc1plus overflow the AIX TOC
+BOOT_LDFLAGS=-Wl,-bbigtoc
diff --git a/gcc/config/rs6000/x-aix43 b/gcc/config/rs6000/x-aix43
new file mode 100644 (file)
index 0000000..69fe1b3
--- /dev/null
@@ -0,0 +1,15 @@
+# configuration for IBM RS/6000 running AIX 4.3+
+
+# Show we need to use the C version of ALLOCA
+ALLOCA=alloca.o
+
+# We need -lld for collect2 (actually this only matters
+# for a native compiler, but this is as good a place as any
+# to define the symbol).
+CLIB=-lld
+
+# f771 and cc1plus overflow the AIX TOC
+BOOT_LDFLAGS=-Wl,-bbigtoc
+
+# Both 32-bit and 64-bit objects in archives
+AR=ar -X32_64
index d79c4dd0f82b200ad6c9f31610ff42af5702d214..95c2fedec707b43862690c54234f0e057ec85aa8 100644 (file)
@@ -2443,7 +2443,7 @@ for machine in $build $host $target; do
                fi
                use_collect2=yes
                ;;
-       rs6000-ibm-aix[[456789]].* | powerpc-ibm-aix[[456789]].*)
+       rs6000-ibm-aix4.[[12]].* | powerpc-ibm-aix4.[[12]].*)
                tm_file=rs6000/aix41.h
                if [[ x$host != x$target ]]
                then
@@ -2451,7 +2451,29 @@ for machine in $build $host $target; do
                else
                        tmake_file=rs6000/t-newas
                fi
-               xmake_file=rs6000/x-aix31
+               xmake_file=rs6000/x-aix41
+               use_collect2=yes
+               ;;
+       rs6000-ibm-aix4.[[3456789]].* | powerpc-ibm-aix4.[[3456789]].*)
+               tm_file=rs6000/aix43.h
+               if [[ x$host != x$target ]]
+               then
+                       tmake_file=rs6000/t-xaix43
+               else
+                       tmake_file=rs6000/t-aix43
+               fi
+               xmake_file=rs6000/x-aix43
+               use_collect2=yes
+               ;;
+       rs6000-ibm-aix[[56789]].* | powerpc-ibm-aix[[56789]].*)
+               tm_file=rs6000/aix43.h
+               if [[ x$host != x$target ]]
+               then
+                       tmake_file=rs6000/t-xaix43
+               else
+                       tmake_file=rs6000/t-aix43
+               fi
+               xmake_file=rs6000/x-aix43
                use_collect2=yes
                ;;
        rs6000-ibm-aix*)
index 15663c1cfb4c6839e3efa966d4d158439f621a12..affb2196bd956042d05f4dc9d2606d1b0b41f666 100644 (file)
@@ -867,7 +867,7 @@ emit_stack_save (save_level, psave, after)
   rtx sa = *psave;
   /* The default is that we use a move insn and save in a Pmode object.  */
   rtx (*fcn) () = gen_move_insn;
-  enum machine_mode mode = Pmode;
+  enum machine_mode mode = STACK_SAVEAREA_MODE (save_level);
 
   /* See if this machine has anything special to do for this kind of save.  */
   switch (save_level)
@@ -875,28 +875,19 @@ emit_stack_save (save_level, psave, after)
 #ifdef HAVE_save_stack_block
     case SAVE_BLOCK:
       if (HAVE_save_stack_block)
-       {
-         fcn = gen_save_stack_block;
-         mode = insn_operand_mode[CODE_FOR_save_stack_block][0];
-       }
+       fcn = gen_save_stack_block;
       break;
 #endif
 #ifdef HAVE_save_stack_function
     case SAVE_FUNCTION:
       if (HAVE_save_stack_function)
-       {
-         fcn = gen_save_stack_function;
-         mode = insn_operand_mode[CODE_FOR_save_stack_function][0];
-       }
+       fcn = gen_save_stack_function;
       break;
 #endif
 #ifdef HAVE_save_stack_nonlocal
     case SAVE_NONLOCAL:
       if (HAVE_save_stack_nonlocal)
-       {
-         fcn = gen_save_stack_nonlocal;
-         mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
-       }
+       fcn = gen_save_stack_nonlocal;
       break;
 #endif
     default:
@@ -975,7 +966,6 @@ emit_stack_restore (save_level, sa, after)
       break;
 #endif
 #ifdef HAVE_restore_stack_nonlocal
-
     case SAVE_NONLOCAL:
       if (HAVE_restore_stack_nonlocal)
        fcn = gen_restore_stack_nonlocal;
@@ -1243,18 +1233,15 @@ allocate_dynamic_stack_space (size, target, known_align)
 #ifdef HAVE_allocate_stack
   if (HAVE_allocate_stack)
     {
-      enum machine_mode mode;
-
       if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
          && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
                (target, Pmode)))
        target = copy_to_mode_reg (Pmode, target);
-      mode = insn_operand_mode[(int) CODE_FOR_allocate_stack][1];
-      size = convert_modes (mode, ptr_mode, size, 1);
+      size = convert_modes (Pmode, ptr_mode, size, 1);
       if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][1]
          && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][1])
-               (size, mode)))
-       size = copy_to_mode_reg (mode, size);
+               (size, Pmode)))
+       size = copy_to_mode_reg (Pmode, size);
 
       emit_insn (gen_allocate_stack (target, size));
     }
index 9f59dd5e6fbec2bd9e6e3734c256319f207b1d3c..dc5e5ebaf191eda2acae11a6fdedaef6f3f1e9a7 100644 (file)
@@ -7771,7 +7771,8 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
      rtx first_label, next_label;
 {
   rtx lab1 = gen_label_rtx ();
-  enum machine_mode sa_mode = Pmode, value_mode;
+  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+  enum machine_mode value_mode;
   rtx stack_save;
 
   value_mode = TYPE_MODE (integer_type_node);
@@ -7803,11 +7804,6 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
                                               GET_MODE_SIZE (Pmode)))),
                  gen_rtx_LABEL_REF (Pmode, lab1));
 
-#ifdef HAVE_save_stack_nonlocal
-  if (HAVE_save_stack_nonlocal)
-    sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
-#endif
-
   stack_save = gen_rtx_MEM (sa_mode,
                            plus_constant (buf_addr,
                                           2 * GET_MODE_SIZE (Pmode)));
@@ -7899,7 +7895,7 @@ expand_builtin_longjmp (buf_addr, value)
      rtx buf_addr, value;
 {
   rtx fp, lab, stack;
-  enum machine_mode sa_mode;
+  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
 
 #ifdef POINTERS_EXTEND_UNSIGNED
   buf_addr = convert_memory_address (Pmode, buf_addr);
@@ -7942,14 +7938,6 @@ expand_builtin_longjmp (buf_addr, value)
       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
                                               GET_MODE_SIZE (Pmode)));
 
-#ifdef HAVE_save_stack_nonlocal
-      sa_mode = (HAVE_save_stack_nonlocal
-                ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]
-                : Pmode);
-#else
-      sa_mode = Pmode;
-#endif
-
       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
                                                   2 * GET_MODE_SIZE (Pmode)));
 
index 509cbebe46d47837ee34a7a41f78fcd66ccf8e51..30e8d8c2c019d8537684b11f37df2bb5a86c5349 100644 (file)
@@ -245,6 +245,13 @@ enum direction {none, upward, downward};  /* Value has this type.  */
 #define RETURN_IN_MEMORY(TYPE) (TYPE_MODE (TYPE) == BLKmode)
 #endif
 
+/* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save.
+   Normally move_insn, so Pmode stack pointer.  */
+
+#ifndef STACK_SAVEAREA_MODE
+#define STACK_SAVEAREA_MODE(LEVEL) Pmode
+#endif
+
 /* Provide default values for the macros controlling stack checking.  */
 
 #ifndef STACK_CHECK_BUILTIN
index 41704ad6dcfeafd14aee18e7697629702b86f02e..de4e2f870c83c20707c850ba502b3e50cb7ce91f 100644 (file)
@@ -4242,6 +4242,21 @@ build_array_type (elt_type, index_type)
   return t;
 }
 
+/* Return the TYPE of the elements comprising
+   the innermost dimension of ARRAY.  */
+
+tree
+get_inner_array_type (array)
+    tree array;
+{
+  tree type = TREE_TYPE (array);
+
+  while (TREE_CODE (type) == ARRAY_TYPE)
+    type = TREE_TYPE (type);
+
+  return type;
+}
+
 /* Construct, lay out and return
    the type of functions returning type VALUE_TYPE
    given arguments of types ARG_TYPES.
index 6320077f23b529d0ea9d6972e5ccc5948020461d..9549d23ba9bb3088ce043acfc8e2359060307165 100644 (file)
@@ -1393,6 +1393,7 @@ extern int tree_int_cst_equal             PROTO((tree, tree));
 extern int tree_int_cst_lt             PROTO((tree, tree));
 extern int tree_int_cst_sgn            PROTO((tree));
 extern int index_type_equal            PROTO((tree, tree));
+extern tree get_inner_array_type       PROTO((tree));
 
 /* From expmed.c.  Since rtl.h is included after tree.h, we can't
    put the prototype here.  Rtl.h does declare the prototype if