aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@mhpcc.edu>1998-06-04 11:47:15 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>1998-06-04 07:47:15 -0400
commita260abc996f80102ba3820e02f4b281bd9b86a4a (patch)
tree247f3a24f7b915cea6a0ba3261e58eac6c1ad9e1
parenta66c6fe2a8a20cfd5d798fe9e667ef1aa3c4c648 (diff)
downloadgcc-a260abc996f80102ba3820e02f4b281bd9b86a4a.zip
gcc-a260abc996f80102ba3820e02f4b281bd9b86a4a.tar.gz
gcc-a260abc996f80102ba3820e02f4b281bd9b86a4a.tar.bz2
tree.c (get_inner_array_type): New function.
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
-rw-r--r--gcc/ChangeLog115
-rw-r--r--gcc/config/rs6000/aix41.h41
-rw-r--r--gcc/config/rs6000/aix43.h199
-rw-r--r--gcc/config/rs6000/netware.h14
-rw-r--r--gcc/config/rs6000/powerpc.h61
-rw-r--r--gcc/config/rs6000/rs6000.c355
-rw-r--r--gcc/config/rs6000/rs6000.h118
-rw-r--r--gcc/config/rs6000/rs6000.md1096
-rw-r--r--gcc/config/rs6000/sysv4.h12
-rw-r--r--gcc/config/rs6000/t-aix4348
-rw-r--r--gcc/config/rs6000/win-nt.h23
-rw-r--r--gcc/config/rs6000/x-aix4112
-rw-r--r--gcc/config/rs6000/x-aix4315
-rw-r--r--gcc/configure.in26
-rw-r--r--gcc/explow.c27
-rw-r--r--gcc/expr.c18
-rw-r--r--gcc/expr.h7
-rw-r--r--gcc/tree.c15
-rw-r--r--gcc/tree.h1
19 files changed, 1646 insertions, 557 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 06e47f7..0e5a1d4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/rs6000/aix41.h b/gcc/config/rs6000/aix41.h
index 2e9b093..a7664be 100644
--- a/gcc/config/rs6000/aix41.h
+++ b/gcc/config/rs6000/aix41.h
@@ -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
index 0000000..fa7b716
--- /dev/null
+++ b/gcc/config/rs6000/aix43.h
@@ -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"
+
diff --git a/gcc/config/rs6000/netware.h b/gcc/config/rs6000/netware.h
index f6de2aa..a465c63 100644
--- a/gcc/config/rs6000/netware.h
+++ b/gcc/config/rs6000/netware.h
@@ -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
index 9f1ffd6..0000000
--- a/gcc/config/rs6000/powerpc.h
+++ /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; \
- } \
-}
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 635054f..6a04d55 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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);
}
-
-
-/* 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);
-}
-
/* 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)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 66756a0..7190de7 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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 ();
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 678286c..61398db 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -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.
@@ -1761,8 +1761,9 @@
|| 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;
}
}")
@@ -1799,6 +1800,22 @@
"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" "")
@@ -1814,8 +1831,9 @@
|| 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;
}
}")
@@ -1852,14 +1870,30 @@
"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")))
@@ -1869,7 +1903,7 @@
"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")))
@@ -1880,14 +1914,14 @@
"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"))
@@ -1897,7 +1931,7 @@
"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"))
@@ -1908,14 +1942,14 @@
"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"))
@@ -1925,7 +1959,7 @@
"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"))
@@ -1936,14 +1970,14 @@
"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")))
@@ -1953,7 +1987,7 @@
"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")))
@@ -1964,14 +1998,14 @@
"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")))
@@ -1981,7 +2015,7 @@
"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")))
@@ -2384,7 +2418,7 @@
""
"{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"))
@@ -2394,7 +2428,7 @@
"{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"))
@@ -2405,7 +2439,7 @@
"{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"))
@@ -2413,7 +2447,7 @@
""
"{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")
@@ -2425,7 +2459,7 @@
"{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")
@@ -2438,7 +2472,7 @@
"{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
@@ -2447,7 +2481,7 @@
""
"{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
@@ -2459,7 +2493,7 @@
"{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
@@ -2472,7 +2506,7 @@
"{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
@@ -2481,7 +2515,7 @@
""
"{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
@@ -2493,7 +2527,7 @@
"{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
@@ -3580,7 +3614,7 @@
(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));
@@ -3595,9 +3629,9 @@
(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")])
@@ -3607,9 +3641,9 @@
(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)))
@@ -3641,7 +3675,7 @@
(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));
@@ -3654,9 +3688,9 @@
(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")])
@@ -3665,9 +3699,9 @@
(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)
@@ -3687,7 +3721,7 @@
;; 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"
"*
@@ -3709,8 +3743,8 @@
(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;
@@ -3735,9 +3769,9 @@
(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;
@@ -3762,8 +3796,8 @@
(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;
@@ -3811,7 +3845,7 @@
[(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"
"#"
@@ -3821,7 +3855,7 @@
[(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)
@@ -3836,17 +3870,10 @@
(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"
"*
{
@@ -3872,7 +3899,7 @@
(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"
"*
{
@@ -3940,6 +3967,13 @@
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")))]
@@ -4286,18 +4320,39 @@
(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")))]
@@ -4308,7 +4363,7 @@
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"))
@@ -4320,7 +4375,7 @@
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"))
@@ -4431,7 +4486,7 @@
(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
@@ -4439,7 +4494,7 @@
(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)))]
"")
@@ -4449,7 +4504,7 @@
(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
@@ -4457,7 +4512,7 @@
(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)))]
"")
@@ -4508,6 +4563,14 @@
"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
@@ -4603,7 +4666,7 @@
(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")])
@@ -4623,7 +4686,7 @@
"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"))
@@ -4633,7 +4696,7 @@
"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"))
@@ -4644,6 +4707,141 @@
"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" "")
@@ -4784,84 +4982,69 @@
[(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")))]
@@ -4871,7 +5054,7 @@
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"))
@@ -4881,7 +5064,7 @@
"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"))
@@ -4908,7 +5091,29 @@
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")))]
@@ -4918,7 +5123,7 @@
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"))
@@ -4928,7 +5133,7 @@
"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"))
@@ -4944,25 +5149,25 @@
(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")))
@@ -4972,7 +5177,7 @@
"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")))
@@ -4983,14 +5188,14 @@
"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"))
@@ -5000,7 +5205,7 @@
"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"))
@@ -5011,14 +5216,14 @@
"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"))
@@ -5028,7 +5233,7 @@
"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"))
@@ -5039,14 +5244,14 @@
"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")))
@@ -5056,7 +5261,7 @@
"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")))
@@ -5067,14 +5272,14 @@
"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")))
@@ -5084,7 +5289,7 @@
"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")))
@@ -5312,14 +5517,12 @@
}")
(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
@@ -5331,8 +5534,8 @@
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.
@@ -5567,7 +5770,7 @@
(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
@@ -5585,6 +5788,27 @@
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"))]
@@ -5656,7 +5880,7 @@
(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
@@ -5674,7 +5898,7 @@
(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
@@ -5699,14 +5923,25 @@
(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
@@ -5724,6 +5959,8 @@
{
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
@@ -5769,6 +6006,8 @@
{
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
@@ -5844,77 +6083,74 @@
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
@@ -5955,7 +6191,7 @@
(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))]
"
@@ -5968,7 +6204,7 @@
(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))]
"
@@ -5982,7 +6218,7 @@
(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))"
"@
@@ -6002,28 +6238,111 @@
[(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;
@@ -6047,14 +6366,8 @@
}
#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 ""
@@ -6097,7 +6410,7 @@
;; 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"))]
@@ -6151,7 +6464,7 @@
[(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"))]
@@ -6196,7 +6509,7 @@
[(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)
@@ -6205,6 +6518,8 @@
{
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
@@ -6919,10 +7234,10 @@
;; 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);
@@ -6937,9 +7252,9 @@
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;
@@ -6966,9 +7281,7 @@
{
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);
@@ -7005,40 +7318,44 @@
"")
(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;
}")
@@ -7070,7 +7387,7 @@
;; 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"))
@@ -7085,7 +7402,22 @@
[(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")))
@@ -7097,7 +7429,23 @@
(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")])
@@ -7190,7 +7538,7 @@
;; 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))])]
@@ -7228,9 +7576,13 @@
{
/* 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)
{
@@ -7248,7 +7600,7 @@
(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))])]
@@ -7286,10 +7638,15 @@
{
/* 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)
{
@@ -7312,7 +7669,7 @@
;; 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"))
@@ -7331,6 +7688,66 @@
[(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
@@ -7338,7 +7755,7 @@
;; 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"))
@@ -7362,7 +7779,31 @@
[(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"))
@@ -7386,33 +7827,38 @@
[(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"
"*
{
@@ -7431,7 +7877,7 @@
[(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")))
@@ -8139,6 +8585,20 @@
[(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
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
@@ -8157,6 +8617,25 @@
[(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
@@ -8251,6 +8730,15 @@
"{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")
@@ -8264,6 +8752,17 @@
[(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
(plus:SI (lshiftrt:SI
@@ -8278,6 +8777,20 @@
(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
(plus:SI (lshiftrt:SI
@@ -8295,6 +8808,23 @@
(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")
(match_operand:SI 2 "reg_or_short_operand" "r,O")))
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 1a7439a..d85f513 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -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
index 0000000..56ddb45
--- /dev/null
+++ b/gcc/config/rs6000/t-aix43
@@ -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
+
diff --git a/gcc/config/rs6000/win-nt.h b/gcc/config/rs6000/win-nt.h
index 7c11c1b..742a5e8 100644
--- a/gcc/config/rs6000/win-nt.h
+++ b/gcc/config/rs6000/win-nt.h
@@ -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
index 0000000..69c666b
--- /dev/null
+++ b/gcc/config/rs6000/x-aix41
@@ -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
index 0000000..69fe1b3
--- /dev/null
+++ b/gcc/config/rs6000/x-aix43
@@ -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
diff --git a/gcc/configure.in b/gcc/configure.in
index d79c4dd..95c2fed 100644
--- a/gcc/configure.in
+++ b/gcc/configure.in
@@ -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*)
diff --git a/gcc/explow.c b/gcc/explow.c
index 15663c1..affb219 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -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));
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 9f59dd5..dc5e5eb 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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)));
diff --git a/gcc/expr.h b/gcc/expr.h
index 509cbeb..30e8d8c 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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
diff --git a/gcc/tree.c b/gcc/tree.c
index 41704ad..de4e2f8 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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.
diff --git a/gcc/tree.h b/gcc/tree.h
index 6320077..9549d23 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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