From a260abc996f80102ba3820e02f4b281bd9b86a4a Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Thu, 4 Jun 1998 11:47:15 +0000 Subject: [PATCH] tree.c (get_inner_array_type): New function. Thu Jun 4 14:35:27 1998 David Edelsohn * 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 --- gcc/ChangeLog | 115 ++++ gcc/config/rs6000/aix41.h | 41 +- gcc/config/rs6000/aix43.h | 199 +++++++ gcc/config/rs6000/netware.h | 14 +- gcc/config/rs6000/powerpc.h | 61 -- gcc/config/rs6000/rs6000.c | 355 ++++++++---- gcc/config/rs6000/rs6000.h | 118 ++-- gcc/config/rs6000/rs6000.md | 1096 ++++++++++++++++++++++++++--------- gcc/config/rs6000/sysv4.h | 12 +- gcc/config/rs6000/t-aix43 | 48 ++ gcc/config/rs6000/win-nt.h | 23 +- gcc/config/rs6000/x-aix41 | 12 + gcc/config/rs6000/x-aix43 | 15 + gcc/configure.in | 26 +- gcc/explow.c | 27 +- gcc/expr.c | 18 +- gcc/expr.h | 7 + gcc/tree.c | 15 + gcc/tree.h | 1 + 19 files changed, 1646 insertions(+), 557 deletions(-) create mode 100644 gcc/config/rs6000/aix43.h delete mode 100644 gcc/config/rs6000/powerpc.h create mode 100644 gcc/config/rs6000/t-aix43 create mode 100644 gcc/config/rs6000/x-aix41 create mode 100644 gcc/config/rs6000/x-aix43 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06e47f7b3f6..0e5a1d46d73 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,118 @@ +Thu Jun 4 14:35:27 1998 David Edelsohn + + * 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 * expr.c (safe_from_p): Avoid combinatorial explosion diff --git a/gcc/config/rs6000/aix41.h b/gcc/config/rs6000/aix41.h index 2e9b093eaca..a7664be572a 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 00000000000..fa7b7164761 --- /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 f6de2aab0ea..a465c63fe3b 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 9f1ffd606cc..00000000000 --- 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 635054fb015..6a04d552855 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 66756a0b975..7190de757de 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 678286cb868..61398db34b2 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"))) @@ -8138,6 +8584,20 @@ {sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0" [(set_attr "length" "12,8,12,12,12")]) +(define_insn "" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r") + (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I"))) + (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))] + "TARGET_POWERPC64" + "@ + xor %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0 + subfic %3,%1,0\;adde %0,%3,%1 + xori %0,%1,%b2\;subfic %3,%0,0\;adde %0,%3,%0 + xoris %0,%1,%u2\;subfic %3,%0,0\;adde %0,%3,%0 + subfic %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0" + [(set_attr "length" "12,8,12,12,12")]) + (define_insn "" [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x") (compare:CC @@ -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") @@ -8263,6 +8751,17 @@ "{ai|addic} %3,%1,-1\;{aze|addze} %0,%2" [(set_attr "length" "8")]) +(define_insn "" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (plus:DI (lshiftrt:DI + (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r"))) + (const_int 63)) + (match_operand:DI 2 "gpc_reg_operand" "r"))) + (clobber (match_scratch:DI 3 "=&r"))] + "TARGET_POWERPC64" + "addic %3,%1,-1\;addze %0,%2" + [(set_attr "length" "8")]) + (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x") (compare:CC @@ -8277,6 +8776,20 @@ [(set_attr "type" "compare") (set_attr "length" "8")]) +(define_insn "" + [(set (match_operand:CC 0 "cc_reg_operand" "=x") + (compare:CC + (plus:DI (lshiftrt:DI + (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r"))) + (const_int 63)) + (match_operand:DI 2 "gpc_reg_operand" "r")) + (const_int 0))) + (clobber (match_scratch:DI 3 "=&r"))] + "TARGET_POWERPC64" + "addic %3,%1,-1\;addze. %3,%2" + [(set_attr "type" "compare") + (set_attr "length" "8")]) + (define_insn "" [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC @@ -8294,6 +8807,23 @@ [(set_attr "type" "compare") (set_attr "length" "8")]) +(define_insn "" + [(set (match_operand:CC 4 "cc_reg_operand" "=x") + (compare:CC + (plus:DI (lshiftrt:DI + (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r"))) + (const_int 63)) + (match_operand:DI 2 "gpc_reg_operand" "r")) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r") + (plus:DI (lshiftrt:DI (neg:DI (abs:DI (match_dup 1))) (const_int 63)) + (match_dup 2))) + (clobber (match_scratch:DI 3 "=&r"))] + "TARGET_POWERPC64" + "addic %3,%1,-1\;addze. %0,%2" + [(set_attr "type" "compare") + (set_attr "length" "8")]) + (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (le:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 1a7439a3383..d85f51356e5 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 00000000000..56ddb45395d --- /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 7c11c1b2ae6..742a5e8c5fc 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 00000000000..69c666b43bc --- /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 00000000000..69fe1b3537f --- /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 d79c4dd0f82..95c2fedec70 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 15663c1cfb4..affb2196bd9 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 9f59dd5e6fb..dc5e5ebaf19 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 509cbebe46d..30e8d8c2c01 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 41704ad6dcf..de4e2f870c8 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 6320077f23b..9549d23ba9b 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 -- 2.30.2