aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@gnu.org>2005-02-28 19:07:36 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>2005-02-28 14:07:36 -0500
commit48d723357cd70e728528986d1ed82d7fd0eaa424 (patch)
tree1f8539c6d34bd651421b24d77dda48652523f485 /gcc
parent2203a881041c8ecd559282229f6bc8cd019c4697 (diff)
downloadgcc-48d723357cd70e728528986d1ed82d7fd0eaa424.zip
gcc-48d723357cd70e728528986d1ed82d7fd0eaa424.tar.gz
gcc-48d723357cd70e728528986d1ed82d7fd0eaa424.tar.bz2
rs6000.c (EASY_VECTOR_15): Remove.
* config/rs6000/rs6000.c (EASY_VECTOR_15): Remove. (EASY_VECTOR_15_ADD_SELF): Remove. (num_insns_constant_wide): Not static. (validate_condition_mode): Not static. (toc_relative_expr_p): Not static. (legitimate_indirect_address_p): Not static. (macho_lo_sum_memory_operand): Not static. (invalid_e500_subreg): Not static. (easy_vector_same): Not static. (easy_vector_splat_const): Not static. (RS6000_SYMBOL_REF_TLS_P): Remove. (any_operand): Delete. (any_parallel_operand): Delete. (count_register_operand): Delete. (altivec_register_operand): Delete. (xer_operand): Delete. (s8bit_cint_operand): Delete. (short_cint_operand): Delete. (u_short_cint_operand): Delete. (non_short_cint_operand): Delete. (exact_log2_cint_operand): Delete. (gpc_reg_operand): Delete. (cc_reg_operand): Delete. (cc_reg_not_cr0_operand): Delete. (reg_or_short_operand): Delete. (reg_or_neg_short_operand): Delete. (reg_or_aligned_short_operand): Delete. (reg_or_u_short_operand): Delete. (reg_or_cint_operand): Delete. (reg_or_arith_cint_operand): Delete. (reg_or_add_cint64_operand): Delete. (reg_or_sub_cint64_operand): Delete. (reg_or_logical_cint_operand): Delete. (got_operand): Delete. (got_no_const_operand): Delete. (easy_fp_constant): Delete. (easy_vector_constant): Delete. (easy_vector_constant_add_self): Delete. (zero_constant): Delete. (zero_fp_constant): Delete. (volatile_mem_operand): Delete. (offsettable_mem_operand): Delete. (mem_or_easy_const_operand): Delete. (add_operand): Delete. (non_add_cint_operand): Delete. (logical_operand): Delete. (non_logical_cint_operand): Delete. (mask_operand): Delete. (mask_operand_wrap): Delete. (mask64_operand): Delete. (mask64_2_operand): Delete. (and64_operand): Delete. (and64_2_operand): Delete. (and_operand): Delete. (reg_or_mem_operand): Delete. (lwa_operand): Delete. (symbol_ref_operand): Delete. (call_operand): Delete. (current_file_function_operand): Delete. (input_operand): Delete. (rs6000_nonimmediate_operand): Delete. (rs6000_tls_symbol_ref): Delete. (save_world_operation): Delete. (restore_world_operation): Delete. (load_multiple_operation): Delete. (store_multiple_operation): Delete. (vrsave_operation): Delete. (mfcr_operation): Delete. (mtcrf_operation): Delete. (lmw_operation): Delete. (stmw_operation): Delete. (branch_comparison_operator): Delete. (branch_positive_comparison_operator): Delete. (scc_comparison_operator): Delete. (trap_comparison_operator): Delete. (boolean_operator): Delete. (boolean_or_operator): Delete. (min_max_operator): Delete. * config/rs6000/rs6000.h (RS6000_SYMBOL_REF_TLS_P): Move to here. (EASY_VECTOR_15): Moved to here. (EASY_VECTOR_15_ADD_SELF): Move to here. (PREDICATE_CODES): Delete. * config/rs6000/rs6000-protos.h: Delete predicate functions. Declare functions no longer static. * config/rs6000/predicates.md: New. * config/rs6000/rs6000.md: Include predicates.md From-SVN: r95692
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog89
-rw-r--r--gcc/config/rs6000/predicates.md1206
-rw-r--r--gcc/config/rs6000/rs6000-protos.h80
-rw-r--r--gcc/config/rs6000/rs6000.c1488
-rw-r--r--gcc/config/rs6000/rs6000.h88
-rw-r--r--gcc/config/rs6000/rs6000.md3
6 files changed, 1328 insertions, 1626 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3df5494..283128a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,92 @@
+2005-02-28 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (EASY_VECTOR_15): Remove.
+ (EASY_VECTOR_15_ADD_SELF): Remove.
+ (num_insns_constant_wide): Not static.
+ (validate_condition_mode): Not static.
+ (toc_relative_expr_p): Not static.
+ (legitimate_indirect_address_p): Not static.
+ (macho_lo_sum_memory_operand): Not static.
+ (invalid_e500_subreg): Not static.
+ (easy_vector_same): Not static.
+ (easy_vector_splat_const): Not static.
+ (RS6000_SYMBOL_REF_TLS_P): Remove.
+ (any_operand): Delete.
+ (any_parallel_operand): Delete.
+ (count_register_operand): Delete.
+ (altivec_register_operand): Delete.
+ (xer_operand): Delete.
+ (s8bit_cint_operand): Delete.
+ (short_cint_operand): Delete.
+ (u_short_cint_operand): Delete.
+ (non_short_cint_operand): Delete.
+ (exact_log2_cint_operand): Delete.
+ (gpc_reg_operand): Delete.
+ (cc_reg_operand): Delete.
+ (cc_reg_not_cr0_operand): Delete.
+ (reg_or_short_operand): Delete.
+ (reg_or_neg_short_operand): Delete.
+ (reg_or_aligned_short_operand): Delete.
+ (reg_or_u_short_operand): Delete.
+ (reg_or_cint_operand): Delete.
+ (reg_or_arith_cint_operand): Delete.
+ (reg_or_add_cint64_operand): Delete.
+ (reg_or_sub_cint64_operand): Delete.
+ (reg_or_logical_cint_operand): Delete.
+ (got_operand): Delete.
+ (got_no_const_operand): Delete.
+ (easy_fp_constant): Delete.
+ (easy_vector_constant): Delete.
+ (easy_vector_constant_add_self): Delete.
+ (zero_constant): Delete.
+ (zero_fp_constant): Delete.
+ (volatile_mem_operand): Delete.
+ (offsettable_mem_operand): Delete.
+ (mem_or_easy_const_operand): Delete.
+ (add_operand): Delete.
+ (non_add_cint_operand): Delete.
+ (logical_operand): Delete.
+ (non_logical_cint_operand): Delete.
+ (mask_operand): Delete.
+ (mask_operand_wrap): Delete.
+ (mask64_operand): Delete.
+ (mask64_2_operand): Delete.
+ (and64_operand): Delete.
+ (and64_2_operand): Delete.
+ (and_operand): Delete.
+ (reg_or_mem_operand): Delete.
+ (lwa_operand): Delete.
+ (symbol_ref_operand): Delete.
+ (call_operand): Delete.
+ (current_file_function_operand): Delete.
+ (input_operand): Delete.
+ (rs6000_nonimmediate_operand): Delete.
+ (rs6000_tls_symbol_ref): Delete.
+ (save_world_operation): Delete.
+ (restore_world_operation): Delete.
+ (load_multiple_operation): Delete.
+ (store_multiple_operation): Delete.
+ (vrsave_operation): Delete.
+ (mfcr_operation): Delete.
+ (mtcrf_operation): Delete.
+ (lmw_operation): Delete.
+ (stmw_operation): Delete.
+ (branch_comparison_operator): Delete.
+ (branch_positive_comparison_operator): Delete.
+ (scc_comparison_operator): Delete.
+ (trap_comparison_operator): Delete.
+ (boolean_operator): Delete.
+ (boolean_or_operator): Delete.
+ (min_max_operator): Delete.
+ * config/rs6000/rs6000.h (RS6000_SYMBOL_REF_TLS_P): Move to here.
+ (EASY_VECTOR_15): Moved to here.
+ (EASY_VECTOR_15_ADD_SELF): Move to here.
+ (PREDICATE_CODES): Delete.
+ * config/rs6000/rs6000-protos.h: Delete predicate functions.
+ Declare functions no longer static.
+ * config/rs6000/predicates.md: New.
+ * config/rs6000/rs6000.md: Include predicates.md
+
2005-02-28 Kazu Hirata <kazu@cs.umass.edu>
* calls.c (emit_call_1): Don't use REG_ALWAYS_RETURN.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
new file mode 100644
index 0000000..10e12af
--- /dev/null
+++ b/gcc/config/rs6000/predicates.md
@@ -0,0 +1,1206 @@
+;; Predicate definitions for POWER and PowerPC.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; Return 1 for anything except PARALLEL.
+(define_predicate "any_operand"
+ (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem"))
+
+;; Return 1 for any PARALLEL.
+(define_predicate "any_parallel_operand"
+ (match_code "parallel"))
+
+;; Return 1 if op is COUNT register.
+(define_predicate "count_register_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == COUNT_REGISTER_REGNUM
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is an Altivec register.
+(define_predicate "altivec_register_operand"
+ (and (match_code "reg")
+ (match_test "ALTIVEC_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is XER register.
+(define_predicate "xer_operand"
+ (and (match_code "reg")
+ (match_test "XER_REGNO_P (REGNO (op))")))
+
+;; Return 1 if op is a signed 8-bit constant integer.
+;; Integer multiplcation complete more quickly
+(define_predicate "s8bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= -128 && INTVAL (op) <= 127")))
+
+;; Return 1 if op is a constant integer that can fit in a D field.
+(define_predicate "short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')")))
+
+;; Return 1 if op is a constant integer that can fit in an unsigned D field.
+(define_predicate "u_short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')")))
+
+;; Return 1 if op is a constant integer that cannot fit in a signed D field.
+(define_predicate "non_short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "(unsigned HOST_WIDE_INT)
+ (INTVAL (op) + 0x8000) >= 0x10000")))
+
+;; Return 1 if op is a positive constant integer that is an exact power of 2.
+(define_predicate "exact_log2_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) > 0 && exact_log2 (INTVAL (op)) >= 0")))
+
+;; Return 1 if op is a register that is not special.
+(define_predicate "gpc_reg_operand"
+ (and (match_code "reg,subreg")
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || (REGNO (op) >= ARG_POINTER_REGNUM
+ && !XER_REGNO_P (REGNO (op)))
+ || REGNO (op) < MQ_REGNO"))))
+
+;; Return 1 if op is a register that is a condition register field.
+(define_predicate "cc_reg_operand"
+ (and (match_code "reg,subreg")
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || REGNO (op) > LAST_VIRTUAL_REGISTER
+ || CR_REGNO_P (REGNO (op))"))))
+
+;; Return 1 if op is a register that is a condition register field not cr0.
+(define_predicate "cc_reg_not_cr0_operand"
+ (and (match_code "reg,subreg")
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || REGNO (op) > LAST_VIRTUAL_REGISTER
+ || CR_REGNO_NOT_CR0_P (REGNO (op))"))))
+
+;; Return 1 if op is a constant integer valid for D field
+;; or non-special register register.
+(define_predicate "reg_or_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "short_cint_operand")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid whose negation is valid for
+;; D field or non-special register register.
+;; Do not allow a constant zero because all patterns that call this
+;; predicate use "addic r1,r2,-const" to set carry when r2 is greater than
+;; or equal to const, which does not work for zero.
+(define_predicate "reg_or_neg_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'P')
+ && INTVAL (op) != 0")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid for DS field
+;; or non-special register.
+(define_predicate "reg_or_aligned_short_operand"
+ (if_then_else (match_code "const_int")
+ (and (match_operand 0 "short_cint_operand")
+ (match_test "!(INTVAL (op) & 3)"))
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer whose high-order 16 bits are zero
+;; or non-special register.
+(define_predicate "reg_or_u_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "u_short_cint_operand")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is any constant integer
+;; or non-special register.
+(define_predicate "reg_or_cint_operand"
+ (ior (match_code "const_int")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a 32-bit signed constant integer valid for arithmetic
+;; or non-special register.
+(define_predicate "reg_or_arith_cint_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "HOST_BITS_PER_WIDE_INT == 32
+ || ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
+ < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a 32-bit signed constant integer valid for 64-bit addition
+;; or non-special register.
+(define_predicate "reg_or_add_cint64_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(HOST_BITS_PER_WIDE_INT == 32 && INTVAL (op) < 0x7fff8000)
+ || ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
+ < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a 32-bit constant integer valid for 64-bit subtraction
+;; or non-special register.
+(define_predicate "reg_or_sub_cint64_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(HOST_BITS_PER_WIDE_INT == 32 && INTVAL (op) < 0x7fff8000)
+ || ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80000000)
+ < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is any 32-bit unsigned constant integer
+;; or non-special register.
+(define_predicate "reg_or_logical_cint_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
+ && INTVAL (op) >= 0)
+ || ((INTVAL (op) & GET_MODE_MASK (mode)
+ & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0)")
+ (if_then_else (match_code "const_double")
+ (match_test "GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
+ && mode == DImode
+ && CONST_DOUBLE_HIGH (op) == 0")
+ (match_operand 0 "gpc_reg_operand"))))
+
+;; Return 1 if operand is a CONST_DOUBLE that can be set in a register
+;; with no more than one instruction per word.
+(define_predicate "easy_fp_constant"
+ (match_code "const_double")
+{
+ if (GET_MODE (op) != mode
+ || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
+ return 0;
+
+ /* Consider all constants with -msoft-float to be easy. */
+ if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
+ && mode != DImode)
+ return 1;
+
+ /* If we are using V.4 style PIC, consider all constants to be hard. */
+ if (flag_pic && DEFAULT_ABI == ABI_V4)
+ return 0;
+
+#ifdef TARGET_RELOCATABLE
+ /* Similarly if we are using -mrelocatable, consider all constants
+ to be hard. */
+ if (TARGET_RELOCATABLE)
+ return 0;
+#endif
+
+ if (mode == TFmode)
+ {
+ long k[4];
+ REAL_VALUE_TYPE rv;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
+ }
+
+ else if (mode == DFmode)
+ {
+ long k[2];
+ REAL_VALUE_TYPE rv;
+
+ if (TARGET_E500_DOUBLE)
+ return 0;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
+
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
+ }
+
+ else if (mode == SFmode)
+ {
+ long l;
+ REAL_VALUE_TYPE rv;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+
+ return num_insns_constant_wide (l) == 1;
+ }
+
+ else if (mode == DImode)
+ return ((TARGET_POWERPC64
+ && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
+ || (num_insns_constant (op, DImode) <= 2));
+
+ else if (mode == SImode)
+ return 1;
+ else
+ abort ();
+})
+
+;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a
+;; vector register without using memory.
+(define_predicate "easy_vector_constant"
+ (match_code "const_vector")
+{
+ int cst, cst2;
+
+ if (!TARGET_ALTIVEC && !TARGET_SPE)
+ return 0;
+
+ if (zero_constant (op, mode)
+ && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
+ return 1;
+
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+ return 0;
+
+ if (TARGET_SPE && mode == V1DImode)
+ return 0;
+
+ cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+ cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
+
+ /* Limit SPE vectors to 15 bits signed. These we can generate with:
+ li r0, CONSTANT1
+ evmergelo r0, r0, r0
+ li r0, CONSTANT2
+
+ I don't know how efficient it would be to allow bigger constants,
+ considering we'll have an extra 'ori' for every 'li'. I doubt 5
+ instructions is better than a 64-bit memory load, but I don't
+ have the e500 timing specs. */
+ if (TARGET_SPE && mode == V2SImode
+ && cst >= -0x7fff && cst <= 0x7fff
+ && cst2 >= -0x7fff && cst2 <= 0x7fff)
+ return 1;
+
+ if (TARGET_ALTIVEC
+ && easy_vector_same (op, mode))
+ {
+ cst = easy_vector_splat_const (cst, mode);
+ if (EASY_VECTOR_15_ADD_SELF (cst)
+ || EASY_VECTOR_15 (cst))
+ return 1;
+ }
+ return 0;
+})
+
+;; Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF.
+(define_predicate "easy_vector_constant_add_self"
+ (and (match_code "const_vector")
+ (and (match_test "TARGET_ALTIVEC")
+ (and (match_test "easy_vector_same (op, mode)")
+ (match_test "EASY_VECTOR_15_ADD_SELF
+ (easy_vector_splat_const
+ (INTVAL (CONST_VECTOR_ELT (op, 0)),
+ mode))")))))
+
+;; Return 1 if operand is constant zero (scalars and vectors).
+(define_predicate "zero_constant"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; Return 1 if operand is 0.0.
+;; or non-special register register field no cr0
+(define_predicate "zero_fp_constant"
+ (and (match_code "const_double")
+ (match_test "GET_MODE_CLASS (mode) == MODE_FLOAT
+ && op == CONST0_RTX (mode)")))
+
+;; Return 1 if the operand is in volatile memory. Note that during the
+;; RTL generation phase, memory_operand does not return TRUE for volatile
+;; memory references. So this function allows us to recognize volatile
+;; references where its safe.
+(define_predicate "volatile_mem_operand"
+ (and (and (match_code "mem")
+ (match_test "MEM_VOLATILE_P (op)"))
+ (if_then_else (match_test "reload_completed")
+ (match_operand 0 "memory_operand")
+ (if_then_else (match_test "reload_in_progress")
+ (match_test "strict_memory_address_p (mode, XEXP (op, 0))")
+ (match_test "memory_address_p (mode, XEXP (op, 0))")))))
+
+;; Return 1 if the operand is an offsettable memory operand.
+(define_predicate "offsettable_mem_operand"
+ (and (match_code "mem")
+ (match_test "offsettable_address_p (reload_completed
+ || reload_in_progress,
+ mode, XEXP (op, 0))")))
+
+;; Return 1 if the operand is either an easy FP constant or memory.
+(define_predicate "mem_or_easy_const_operand"
+ (if_then_else (match_code "const_double")
+ (match_operand 0 "easy_fp_constant")
+ (match_operand 0 "memory_operand")))
+
+;; Return 1 if the operand is either a non-special register or can be used
+;; as the operand of a `mode' add insn.
+(define_predicate "add_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if OP is a constant but not a valid add_operand.
+(define_predicate "non_add_cint_operand"
+ (and (match_code "const_int")
+ (match_test "!CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
+ && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')")))
+
+;; Return 1 if the operand is a non-special register or a constant that
+;; can be used as the operand of an OR or XOR.
+(define_predicate "logical_operand"
+ (match_code "reg,subreg,const_int,const_double")
+{
+ HOST_WIDE_INT opl, oph;
+
+ if (gpc_reg_operand (op, mode))
+ return 1;
+
+ if (GET_CODE (op) == CONST_INT)
+ {
+ opl = INTVAL (op) & GET_MODE_MASK (mode);
+
+ if (HOST_BITS_PER_WIDE_INT <= 32
+ && GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
+ return 0;
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+ abort ();
+
+ opl = CONST_DOUBLE_LOW (op);
+ oph = CONST_DOUBLE_HIGH (op);
+ if (oph != 0)
+ return 0;
+ }
+ else
+ return 0;
+
+ return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
+ || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
+})
+
+;; Return 1 if op is a constant that is not a logical operand, but could
+;; be split into one.
+(define_predicate "non_logical_cint_operand"
+ (and (match_code "const_int,const_double")
+ (and (not (match_operand 0 "logical_operand"))
+ (match_operand 0 "reg_or_logical_cint_operand"))))
+
+;; Return 1 if op is a constant that can be encoded in a 32-bit mask (no
+;; more than two 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.
+(define_predicate "mask_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Fail in 64-bit mode if the mask wraps around because the upper
+ 32-bits of the mask will all be 1s, contrary to GCC's internal view. */
+ if (TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
+ return 0;
+
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
+ /* Reject all zeros or all ones. */
+ if (c == 0)
+ return 0;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a second transition. */
+ c = ~c;
+
+ /* Erase first transition. */
+ c &= -lsb;
+
+ /* Find the second transition (if any). */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Return 1 for the PowerPC64 rlwinm corner case.
+(define_predicate "mask_operand_wrap"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ if ((c & 0x80000001) != 0x80000001)
+ return 0;
+
+ c = ~c;
+ if (c == 0)
+ return 0;
+
+ lsb = c & -c;
+ c = ~c;
+ c &= -lsb;
+ lsb = c & -c;
+ return c == -lsb;
+})
+
+;; Return 1 if the operand is a constant that is a PowerPC64 mask (no more
+;; than one 1->0 or 0->1 transitions). Reject all zeros, since zero
+;; should have been optimized away and confuses the making of MB and ME.
+(define_predicate "mask64_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Reject all zeros. */
+ if (c == 0)
+ return 0;
+
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
+ /* Find the transition, and check that all bits above are 1's. */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Like mask64_operand, but allow up to three transitions. This
+;; predicate is used by insn patterns that generate two rldicl or
+;; rldicr machine insns.
+(define_predicate "mask64_2_operand"
+ (match_code "const_int")
+{
+ return mask64_1or2_operand (op, mode, false);
+})
+
+;; 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.
+(define_predicate "and64_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "mask64_operand")
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand"))))
+
+;; Like and64_operand, but also match constants that can be implemented
+;; with two rldicl or rldicr insns.
+(define_predicate "and64_2_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "mask64_1or2_operand (op, mode, true)")
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand"))))
+
+;; Return 1 if the operand is either a non-special register or a
+;; constant that can be used as the operand of a logical AND.
+(define_predicate "and_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "mask_operand")
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand"))))
+
+;; Return 1 if the operand is a general non-special register or memory operand.
+(define_predicate "reg_or_mem_operand"
+ (if_then_else (match_code "mem")
+ (ior (match_operand 0 "memory_operand")
+ (ior (match_test "macho_lo_sum_memory_operand (op, mode)")
+ (match_operand 0 "volatile_mem_operand")))
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if the operand is a general register or memory operand without
+;; pre_inc or pre_dec, which produces invalid form of PowerPC lwa
+;; instruction.
+(define_predicate "lwa_operand"
+ (match_code "reg,subreg,mem")
+{
+ rtx inner = op;
+
+ if (reload_completed && GET_CODE (inner) == SUBREG)
+ inner = SUBREG_REG (inner);
+
+ return gpc_reg_operand (inner, mode)
+ || (memory_operand (inner, mode)
+ && GET_CODE (XEXP (inner, 0)) != PRE_INC
+ && GET_CODE (XEXP (inner, 0)) != PRE_DEC
+ && (GET_CODE (XEXP (inner, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
+})
+
+;; Return 1 if the operand, used inside a MEM, is a SYMBOL_REF.
+(define_predicate "symbol_ref_operand"
+ (and (match_code "symbol_ref")
+ (match_test "(mode == VOIDmode || GET_MODE (op) == mode)
+ && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))")))
+
+;; Return 1 if op is an operand that can be loaded via the GOT.
+;; or non-special register register field no cr0
+(define_predicate "got_operand"
+ (match_code "symbol_ref,const,label_ref"))
+
+;; Return 1 if op is a simple reference that can be loaded via the GOT,
+;; exclusing labels involving addition.
+(define_predicate "got_no_const_operand"
+ (match_code "symbol_ref,label_ref"))
+
+;; Return 1 if op is a SYMBOL_REF for a TLS symbol.
+(define_predicate "rs6000_tls_symbol_ref"
+ (and (match_code "symbol_ref")
+ (match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
+
+;; Return 1 if the operand, used inside a MEM, is a valid first argument
+;; to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR.
+(define_predicate "call_operand"
+ (if_then_else (match_code "reg")
+ (match_test "REGNO (op) == LINK_REGISTER_REGNUM
+ || REGNO (op) == COUNT_REGISTER_REGNUM
+ || REGNO (op) >= FIRST_PSEUDO_REGISTER")
+ (match_code "symbol_ref")))
+
+;; Return 1 if the operand is a SYMBOL_REF for a function known to be in
+;; this file.
+(define_predicate "current_file_function_operand"
+ (and (match_code "symbol_ref")
+ (match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
+ && (SYMBOL_REF_LOCAL_P (op)
+ || (op == XEXP (DECL_RTL (current_function_decl),
+ 0)))")))
+
+;; Return 1 if this operand is a valid input for a move insn.
+(define_predicate "input_operand"
+ (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem,
+ const_double,const_vector,const_int,plus")
+{
+ /* Memory is always valid. */
+ if (memory_operand (op, mode))
+ return 1;
+
+ /* For floating-point, easy constants are valid. */
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && CONSTANT_P (op)
+ && easy_fp_constant (op, mode))
+ return 1;
+
+ /* Allow any integer constant. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && (GET_CODE (op) == CONST_INT
+ || GET_CODE (op) == CONST_DOUBLE))
+ return 1;
+
+ /* Allow easy vector constants. */
+ if (GET_CODE (op) == CONST_VECTOR
+ && easy_vector_constant (op, mode))
+ return 1;
+
+ /* For floating-point or multi-word mode, the only remaining valid type
+ is a register. */
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ return register_operand (op, mode);
+
+ /* The only cases left are integral modes one word or smaller (we
+ do not get called for MODE_CC values). These can be in any
+ register. */
+ if (register_operand (op, mode))
+ return 1;
+
+ /* A SYMBOL_REF referring to the TOC is valid. */
+ if (legitimate_constant_pool_address_p (op))
+ return 1;
+
+ /* A constant pool expression (relative to the TOC) is valid */
+ if (toc_relative_expr_p (op))
+ return 1;
+
+ /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
+ to be valid. */
+ if (DEFAULT_ABI == ABI_V4
+ && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
+ && small_data_operand (op, Pmode))
+ return 1;
+
+ return 0;
+})
+
+;; Return true if OP is an invalid SUBREG operation on the e500.
+(define_predicate "rs6000_nonimmediate_operand"
+ (match_code "reg,subreg,mem")
+{
+ if (TARGET_E500_DOUBLE
+ && GET_CODE (op) == SUBREG
+ && invalid_e500_subreg (op, mode))
+ return 0;
+
+ return nonimmediate_operand (op, mode);
+})
+
+;; Return true if operand is boolean operator.
+(define_predicate "boolean_operator"
+ (match_code "and,ior,xor"))
+
+;; Return true if operand is OR-form of boolean operator.
+(define_predicate "boolean_or_operator"
+ (match_code "ior,xor"))
+
+;; Return true if operand is MIN or MAX operator.
+(define_predicate "min_max_operator"
+ (match_code "smin,smax,umin,umax"))
+
+;; Return 1 if OP is a comparison operation that is valid for a branch
+;; instruction. We only check the opcode against the mode of the CC value.
+(define_predicate "branch_comparison_operator"
+ (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu,unordered,ordered,unge,unle")
+{
+ enum rtx_code code = GET_CODE (op);
+ enum machine_mode cc_mode;
+
+ if (!COMPARISON_P (op))
+ return 0;
+
+ cc_mode = GET_MODE (XEXP (op, 0));
+ if (GET_MODE_CLASS (cc_mode) != MODE_CC)
+ return 0;
+
+ validate_condition_mode (code, cc_mode);
+
+ return 1;
+})
+
+;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
+;; it must be a positive comparison.
+(define_predicate "scc_comparison_operator"
+ (and (match_code "eq,lt,gt,ltu,gtu,unordered")
+ (match_operand 0 "branch_comparison_operator")))
+
+;; Return 1 if OP is a comparison operation that is valid for a branch
+;; insn, which is true if the corresponding bit in the CC register is set.
+(define_predicate "branch_positive_comparison_operator"
+ (and (match_code "eq,lt,gt,ltu,gtu,unordered")
+ (match_operand 0 "branch_comparison_operator")))
+
+;; Return 1 is OP is a comparison operation that is valid for a trap insn.
+(define_predicate "trap_comparison_operator"
+ (and (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu")
+ (match_test "(mode == VOIDmode || mode == GET_MODE (op))
+ && COMPARISON_P (op)")))
+
+;; Return 1 if OP is a load multiple operation, known to be a PARALLEL.
+(define_predicate "load_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is a store multiple operation, known to be a PARALLEL.
+;; The second vector element is a CLOBBER.
+(define_predicate "store_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0) - 1;
+ unsigned int src_regno;
+ rtx dest_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return 0;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i + 1);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is valid for a save_world call in prologue, known to be
+;; a PARLLEL.
+(define_predicate "save_world_operation"
+ (match_code "parallel")
+{
+ int index;
+ int i;
+ rtx elt;
+ int count = XVECLEN (op, 0);
+
+ if (count != 55)
+ return 0;
+
+ index = 0;
+ if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE)
+ return 0;
+
+ for (i=1; i <= 18; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), DFmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != DFmode)
+ return 0;
+ }
+
+ for (i=1; i <= 12; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != V4SImode)
+ return 0;
+ }
+
+ for (i=1; i <= 19; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), Pmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != Pmode)
+ return 0;
+ }
+
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), Pmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || REGNO (SET_SRC (elt)) != CR2_REGNO
+ || GET_MODE (SET_SRC (elt)) != Pmode)
+ return 0;
+
+ if (GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
+ return 0;
+ return 1;
+})
+
+;; Return 1 if OP is valid for a restore_world call in epilogue, known to be
+;; a PARLLEL.
+(define_predicate "restore_world_operation"
+ (match_code "parallel")
+{
+ int index;
+ int i;
+ rtx elt;
+ int count = XVECLEN (op, 0);
+
+ if (count != 59)
+ return 0;
+
+ index = 0;
+ if (GET_CODE (XVECEXP (op, 0, index++)) != RETURN
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
+ return 0;
+
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), Pmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || REGNO (SET_DEST (elt)) != CR2_REGNO
+ || GET_MODE (SET_DEST (elt)) != Pmode)
+ return 0;
+
+ for (i=1; i <= 19; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), Pmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != Pmode)
+ return 0;
+ }
+
+ for (i=1; i <= 12; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V4SImode)
+ return 0;
+ }
+
+ for (i=1; i <= 18; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), DFmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != DFmode)
+ return 0;
+ }
+
+ if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE)
+ return 0;
+ return 1;
+})
+
+;; Return 1 if OP is valid for a vrsave call, known to be a PARALLEL.
+(define_predicate "vrsave_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno, src_regno;
+ int i;
+
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC_VOLATILE)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+
+ if (dest_regno != VRSAVE_REGNO
+ && src_regno != VRSAVE_REGNO)
+ return 0;
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != CLOBBER
+ && GET_CODE (elt) != SET)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is valid for mfcr insn, known to be a PARALLEL.
+(define_predicate "mfcr_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count < 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+ || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+ rtx unspec;
+ int maskval;
+ rtx src_reg;
+
+ src_reg = XVECEXP (SET_SRC (exp), 0, 0);
+
+ if (GET_CODE (src_reg) != REG
+ || GET_MODE (src_reg) != CCmode
+ || ! CR_REGNO_P (REGNO (src_reg)))
+ return 0;
+
+ if (GET_CODE (exp) != SET
+ || GET_CODE (SET_DEST (exp)) != REG
+ || GET_MODE (SET_DEST (exp)) != SImode
+ || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
+ return 0;
+ unspec = SET_SRC (exp);
+ maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
+
+ if (GET_CODE (unspec) != UNSPEC
+ || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
+ || XVECLEN (unspec, 0) != 2
+ || XVECEXP (unspec, 0, 0) != src_reg
+ || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ return 0;
+ }
+ return 1;
+})
+
+;; Return 1 if OP is valid for mtcrf insn, known to be a PARALLEL.
+(define_predicate "mtcrf_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int i;
+ rtx src_reg;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count < 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+ || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+ return 0;
+ src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
+
+ if (GET_CODE (src_reg) != REG
+ || GET_MODE (src_reg) != SImode
+ || ! INT_REGNO_P (REGNO (src_reg)))
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+ rtx unspec;
+ int maskval;
+
+ if (GET_CODE (exp) != SET
+ || GET_CODE (SET_DEST (exp)) != REG
+ || GET_MODE (SET_DEST (exp)) != CCmode
+ || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
+ return 0;
+ unspec = SET_SRC (exp);
+ maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
+
+ if (GET_CODE (unspec) != UNSPEC
+ || XINT (unspec, 1) != UNSPEC_MOVESI_TO_CR
+ || XVECLEN (unspec, 0) != 2
+ || XVECEXP (unspec, 0, 0) != src_reg
+ || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ return 0;
+ }
+ return 1;
+})
+
+;; Return 1 if OP is valid for lmw insn, known to be a PARALLEL.
+(define_predicate "lmw_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr;
+ unsigned int base_regno;
+ HOST_WIDE_INT offset;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+
+ if (dest_regno > 31
+ || count != 32 - (int) dest_regno)
+ return 0;
+
+ if (legitimate_indirect_address_p (src_addr, 0))
+ {
+ offset = 0;
+ base_regno = REGNO (src_addr);
+ if (base_regno == 0)
+ return 0;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
+ {
+ offset = INTVAL (XEXP (src_addr, 1));
+ base_regno = REGNO (XEXP (src_addr, 0));
+ }
+ else
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+ rtx newaddr;
+ rtx addr_reg;
+ HOST_WIDE_INT newoffset;
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode)
+ return 0;
+ newaddr = XEXP (SET_SRC (elt), 0);
+ if (legitimate_indirect_address_p (newaddr, 0))
+ {
+ newoffset = 0;
+ addr_reg = newaddr;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
+ {
+ addr_reg = XEXP (newaddr, 0);
+ newoffset = INTVAL (XEXP (newaddr, 1));
+ }
+ else
+ return 0;
+ if (REGNO (addr_reg) != base_regno
+ || newoffset != offset + 4 * i)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is valid for stmw insn, known to be a PARALLEL.
+(define_predicate "stmw_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int src_regno;
+ rtx dest_addr;
+ unsigned int base_regno;
+ HOST_WIDE_INT offset;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return 0;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+
+ if (src_regno > 31
+ || count != 32 - (int) src_regno)
+ return 0;
+
+ if (legitimate_indirect_address_p (dest_addr, 0))
+ {
+ offset = 0;
+ base_regno = REGNO (dest_addr);
+ if (base_regno == 0)
+ return 0;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
+ {
+ offset = INTVAL (XEXP (dest_addr, 1));
+ base_regno = REGNO (XEXP (dest_addr, 0));
+ }
+ else
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+ rtx newaddr;
+ rtx addr_reg;
+ HOST_WIDE_INT newoffset;
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode)
+ return 0;
+ newaddr = XEXP (SET_DEST (elt), 0);
+ if (legitimate_indirect_address_p (newaddr, 0))
+ {
+ newoffset = 0;
+ addr_reg = newaddr;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
+ {
+ addr_reg = XEXP (newaddr, 0);
+ newoffset = INTVAL (XEXP (newaddr, 1));
+ }
+ else
+ return 0;
+ if (REGNO (addr_reg) != base_regno
+ || newoffset != offset + 4 * i)
+ return 0;
+ }
+
+ return 1;
+})
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 4a4fcde..efaca41 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -32,74 +32,29 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int);
extern void rs6000_va_start (tree, rtx);
#endif /* TREE_CODE */
+extern int easy_vector_same (rtx, enum machine_mode);
+extern int easy_vector_splat_const (int, enum machine_mode);
+extern int mask64_1or2_operand (rtx, enum machine_mode, bool);
+extern bool macho_lo_sum_memory_operand (rtx, enum machine_mode);
+extern int num_insns_constant (rtx, enum machine_mode);
+extern int num_insns_constant_wide (HOST_WIDE_INT);
+extern int small_data_operand (rtx, enum machine_mode);
+extern bool toc_relative_expr_p (rtx);
+extern bool invalid_e500_subreg (rtx, enum machine_mode);
+extern void validate_condition_mode (enum rtx_code, enum machine_mode);
+extern bool legitimate_constant_pool_address_p (rtx);
+extern bool legitimate_indirect_address_p (rtx, int);
+extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int);
+
extern struct rtx_def *rs6000_got_register (rtx);
extern struct rtx_def *find_addr_reg (rtx);
-extern int any_operand (rtx, enum machine_mode);
-extern int short_cint_operand (rtx, enum machine_mode);
-extern int u_short_cint_operand (rtx, enum machine_mode);
-extern int non_short_cint_operand (rtx, enum machine_mode);
-extern int exact_log2_cint_operand (rtx, enum machine_mode);
-extern int gpc_reg_operand (rtx, enum machine_mode);
-extern int cc_reg_operand (rtx, enum machine_mode);
-extern int cc_reg_not_cr0_operand (rtx, enum machine_mode);
-extern int reg_or_short_operand (rtx, enum machine_mode);
-extern int reg_or_neg_short_operand (rtx, enum machine_mode);
-extern int reg_or_aligned_short_operand (rtx, enum machine_mode);
-extern int reg_or_u_short_operand (rtx, enum machine_mode);
-extern int reg_or_cint_operand (rtx, enum machine_mode);
-extern int reg_or_arith_cint_operand (rtx, enum machine_mode);
-extern int reg_or_add_cint64_operand (rtx, enum machine_mode);
-extern int reg_or_sub_cint64_operand (rtx, enum machine_mode);
-extern int reg_or_logical_cint_operand (rtx, enum machine_mode);
-extern int got_operand (rtx, enum machine_mode);
extern int word_offset_memref_operand (rtx, enum machine_mode);
-extern int got_no_const_operand (rtx, enum machine_mode);
-extern int num_insns_constant (rtx, enum machine_mode);
-extern int easy_fp_constant (rtx, enum machine_mode);
-extern int easy_vector_constant (rtx, enum machine_mode);
extern rtx gen_easy_vector_constant_add_self (rtx);
extern const char *output_vec_const_move (rtx *);
-extern int zero_fp_constant (rtx, enum machine_mode);
-extern int zero_constant (rtx, enum machine_mode);
-extern int volatile_mem_operand (rtx, enum machine_mode);
-extern int offsettable_mem_operand (rtx, enum machine_mode);
-extern int mem_or_easy_const_operand (rtx, enum machine_mode);
-extern int add_operand (rtx, enum machine_mode);
-extern int non_add_cint_operand (rtx, enum machine_mode);
-extern int non_logical_cint_operand (rtx, enum machine_mode);
-extern int logical_operand (rtx, enum machine_mode);
-extern int mask_operand (rtx, enum machine_mode);
-extern int mask_operand_wrap (rtx, enum machine_mode);
-extern int mask64_operand (rtx, enum machine_mode);
-extern int mask64_2_operand (rtx, enum machine_mode);
extern void build_mask64_2_operands (rtx, rtx *);
-extern int and64_operand (rtx, enum machine_mode);
-extern int and64_2_operand (rtx, enum machine_mode);
-extern int and_operand (rtx, enum machine_mode);
-extern int count_register_operand (rtx, enum machine_mode);
-extern int xer_operand (rtx, enum machine_mode);
-extern int reg_or_mem_operand (rtx, enum machine_mode);
-extern int lwa_operand (rtx, enum machine_mode);
-extern int call_operand (rtx, enum machine_mode);
-extern int current_file_function_operand (rtx, enum machine_mode);
-extern int input_operand (rtx, enum machine_mode);
-extern int small_data_operand (rtx, enum machine_mode);
-extern int s8bit_cint_operand (rtx, enum machine_mode);
-extern bool legitimate_constant_pool_address_p (rtx);
extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
-extern int load_multiple_operation (rtx, enum machine_mode);
-extern int save_world_operation (rtx, enum machine_mode);
-extern int restore_world_operation (rtx, enum machine_mode);
extern const char * rs6000_output_load_multiple (rtx[]);
-extern int store_multiple_operation (rtx, enum machine_mode);
-extern int branch_comparison_operator (rtx, enum machine_mode);
-extern int branch_positive_comparison_operator (rtx, enum machine_mode);
-extern int scc_comparison_operator (rtx, enum machine_mode);
-extern int trap_comparison_operator (rtx, enum machine_mode);
-extern int boolean_operator (rtx, enum machine_mode);
-extern int boolean_or_operator (rtx, enum machine_mode);
-extern int min_max_operator (rtx, enum machine_mode);
extern int includes_lshift_p (rtx, rtx);
extern int includes_rshift_p (rtx, rtx);
extern int includes_rldic_lshift_p (rtx, rtx);
@@ -130,10 +85,6 @@ extern void output_toc (FILE *, rtx, int, enum machine_mode);
extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
extern struct rtx_def *rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx);
-extern int stmw_operation (rtx, enum machine_mode);
-extern int mfcr_operation (rtx, enum machine_mode);
-extern int mtcrf_operation (rtx, enum machine_mode);
-extern int lmw_operation (rtx, enum machine_mode);
extern struct rtx_def *create_TOC_reference (rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
@@ -145,7 +96,6 @@ extern bool rs6000_mode_dependent_address (rtx);
extern rtx rs6000_return_addr (int, rtx);
extern void rs6000_output_symbol_ref (FILE*, rtx);
extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int);
-extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int);
extern rtx rs6000_machopic_legitimize_pic_address (rtx orig,
enum machine_mode mode,
@@ -197,12 +147,10 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *);
-extern int vrsave_operation (rtx, enum machine_mode);
extern int rs6000_register_move_cost (enum machine_mode,
enum reg_class, enum reg_class);
extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
extern bool rs6000_tls_referenced_p (rtx);
-extern int rs6000_tls_symbol_ref (rtx, enum machine_mode);
extern void rs6000_output_dwarf_dtprel (FILE*, int, rtx);
extern int rs6000_hard_regno_nregs (int, enum machine_mode);
extern void rs6000_conditional_register_usage (void);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e07ac50..f0b7c18 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -64,9 +64,6 @@
#define TARGET_NO_PROTOTYPE 0
#endif
-#define EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
-#define EASY_VECTOR_15_ADD_SELF(n) ((n) >= 0x10 && (n) <= 0x1e && !((n) & 1))
-
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
@@ -603,8 +600,6 @@ struct processor_costs power4_cost = {
static bool rs6000_function_ok_for_sibcall (tree, tree);
-static int num_insns_constant_wide (HOST_WIDE_INT);
-static void validate_condition_mode (enum rtx_code, enum machine_mode);
static rtx rs6000_generate_compare (enum rtx_code);
static void rs6000_maybe_dead (rtx);
static void rs6000_emit_stack_tie (void);
@@ -620,11 +615,8 @@ static unsigned toc_hash_function (const void *);
static int toc_hash_eq (const void *, const void *);
static int constant_pool_expr_1 (rtx, int *, int *);
static bool constant_pool_expr_p (rtx);
-static bool toc_relative_expr_p (rtx);
static bool legitimate_small_data_p (enum machine_mode, rtx);
static bool legitimate_indexed_address_p (rtx, int);
-static bool legitimate_indirect_address_p (rtx, int);
-static bool macho_lo_sum_memory_operand (rtx x, enum machine_mode mode);
static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
static struct machine_function * rs6000_init_machine_status (void);
static bool rs6000_assemble_integer (rtx, unsigned int, int);
@@ -710,7 +702,6 @@ static rtx spe_expand_builtin (tree, rtx, bool *);
static rtx spe_expand_stv_builtin (enum insn_code, tree);
static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
-static bool invalid_e500_subreg (rtx, enum machine_mode);
static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
static rs6000_stack_t *rs6000_stack_info (void);
static void debug_stack_info (rs6000_stack_t *);
@@ -735,8 +726,6 @@ static void compute_save_world_info(rs6000_stack_t *info_ptr);
static void is_altivec_return_reg (rtx, void *);
static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
int easy_vector_constant (rtx, enum machine_mode);
-static int easy_vector_same (rtx, enum machine_mode);
-static int easy_vector_splat_const (int, enum machine_mode);
static bool is_ev64_opaque_type (tree);
static rtx rs6000_dwarf_register_span (rtx);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
@@ -853,10 +842,6 @@ static const char alt_reg_names[][8] =
/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
-
-/* Return 1 for a symbol ref for a thread-local storage symbol. */
-#define RS6000_SYMBOL_REF_TLS_P(RTX) \
- (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -1810,312 +1795,10 @@ direct_return (void)
return 0;
}
-/* Returns 1 always. */
-
-int
-any_operand (rtx op ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-/* Returns 1 always. */
-
-int
-any_parallel_operand (rtx op ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-/* Returns 1 if op is the count register. */
-
-int
-count_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != REG)
- return 0;
-
- if (REGNO (op) == COUNT_REGISTER_REGNUM)
- return 1;
-
- if (REGNO (op) > FIRST_PSEUDO_REGISTER)
- return 1;
-
- return 0;
-}
-
-/* Returns 1 if op is an altivec register. */
-
-int
-altivec_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) > FIRST_PSEUDO_REGISTER
- || ALTIVEC_REGNO_P (REGNO (op))));
-}
-
-int
-xer_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != REG)
- return 0;
-
- if (XER_REGNO_P (REGNO (op)))
- return 1;
-
- return 0;
-}
-
-/* Return 1 if OP is a signed 8-bit constant. Int multiplication
- by such constants completes more quickly. */
-
-int
-s8bit_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= -128 && INTVAL (op) <= 127));
-}
-
-/* Return 1 if OP is a constant that can fit in a D field. */
-
-int
-short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
-}
-
-/* Similar for an unsigned D field. */
-
-int
-u_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op) & GET_MODE_MASK (mode), 'K'));
-}
-
-/* Return 1 if OP is a CONST_INT that cannot fit in a signed D field. */
-
-int
-non_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
-}
-
-/* Returns 1 if OP is a CONST_INT that is a positive value
- and an exact power of 2. */
-
-int
-exact_log2_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) > 0
- && exact_log2 (INTVAL (op)) >= 0);
-}
-
-/* Returns 1 if OP is a register that is not special (i.e., not MQ,
- ctr, or lr). */
-
-int
-gpc_reg_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || (REGNO (op) >= ARG_POINTER_REGNUM
- && !XER_REGNO_P (REGNO (op)))
- || REGNO (op) < MQ_REGNO));
-}
-
-/* Returns 1 if OP is either a pseudo-register or a register denoting a
- CR field. */
-
-int
-cc_reg_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) >= FIRST_PSEUDO_REGISTER
- || CR_REGNO_P (REGNO (op))));
-}
-
-/* Returns 1 if OP is either a pseudo-register or a register denoting a
- CR field that isn't CR0. */
-
-int
-cc_reg_not_cr0_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) >= FIRST_PSEUDO_REGISTER
- || CR_REGNO_NOT_CR0_P (REGNO (op))));
-}
-
-/* Returns 1 if OP is either a constant integer valid for a D-field or
- a non-special register. If a register, it must be in the proper
- mode unless MODE is VOIDmode. */
-
-int
-reg_or_short_operand (rtx op, enum machine_mode mode)
-{
- return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
-}
-
-/* Similar, except check if the negation of the constant would be
- valid for a D-field. Don't allow a constant zero, since all the
- patterns that call this predicate use "addic r1,r2,-constant" on
- a constant value to set a carry when r2 is greater or equal to
- "constant". That doesn't work for zero. */
-
-int
-reg_or_neg_short_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P') && INTVAL (op) != 0;
-
- return gpc_reg_operand (op, mode);
-}
-
-/* Returns 1 if OP is either a constant integer valid for a DS-field or
- a non-special register. If a register, it must be in the proper
- mode unless MODE is VOIDmode. */
-
-int
-reg_or_aligned_short_operand (rtx op, enum machine_mode mode)
-{
- if (gpc_reg_operand (op, mode))
- return 1;
- else if (short_cint_operand (op, mode) && !(INTVAL (op) & 3))
- return 1;
-
- return 0;
-}
-
-
-/* Return 1 if the operand is either a register or an integer whose
- high-order 16 bits are zero. */
-
-int
-reg_or_u_short_operand (rtx op, enum machine_mode mode)
-{
- return u_short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- constant integer. */
-
-int
-reg_or_cint_operand (rtx op, enum machine_mode mode)
-{
- return (GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode));
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- 32-bit signed constant integer. */
-
-int
-reg_or_arith_cint_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT != 32
- && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
- < (unsigned HOST_WIDE_INT) 0x100000000ll)
-#endif
- ));
-}
-
-/* Return 1 is the operand is either a non-special register or a 32-bit
- signed constant integer valid for 64-bit addition. */
-
-int
-reg_or_add_cint64_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT == 32
- && INTVAL (op) < 0x7fff8000
-#else
- && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
- < 0x100000000ll)
-#endif
- ));
-}
-
-/* Return 1 is the operand is either a non-special register or a 32-bit
- signed constant integer valid for 64-bit subtraction. */
-
-int
-reg_or_sub_cint64_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT == 32
- && (- INTVAL (op)) < 0x7fff8000
-#else
- && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
- < 0x100000000ll)
-#endif
- ));
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- 32-bit unsigned constant integer. */
-
-int
-reg_or_logical_cint_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
- {
- if (GET_MODE_BITSIZE (mode) <= 32)
- abort ();
-
- if (INTVAL (op) < 0)
- return 0;
- }
-
- return ((INTVAL (op) & GET_MODE_MASK (mode)
- & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0);
- }
- else if (GET_CODE (op) == CONST_DOUBLE)
- {
- if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- || mode != DImode)
- abort ();
-
- return CONST_DOUBLE_HIGH (op) == 0;
- }
- else
- return gpc_reg_operand (op, mode);
-}
-
-/* Return 1 if the operand is an operand that can be loaded via the GOT. */
-
-int
-got_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF
- || GET_CODE (op) == CONST
- || GET_CODE (op) == LABEL_REF);
-}
-
-/* Return 1 if the operand is a simple references that can be loaded via
- the GOT (labels involving addition aren't allowed). */
-
-int
-got_no_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
-}
-
/* Return the number of instructions it takes to form a constant in an
integer register. */
-static int
+int
num_insns_constant_wide (HOST_WIDE_INT value)
{
/* signed constant loadable with {cal|addi} */
@@ -2222,88 +1905,9 @@ num_insns_constant (rtx op, enum machine_mode mode)
abort ();
}
-/* Return 1 if the operand is a CONST_DOUBLE and it can be put into a
- register with one instruction per word. We only do this if we can
- safely read CONST_DOUBLE_{LOW,HIGH}. */
-
-int
-easy_fp_constant (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != CONST_DOUBLE
- || GET_MODE (op) != mode
- || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
- return 0;
-
- /* Consider all constants with -msoft-float to be easy. */
- if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
- && mode != DImode)
- return 1;
-
- /* If we are using V.4 style PIC, consider all constants to be hard. */
- if (flag_pic && DEFAULT_ABI == ABI_V4)
- return 0;
-
-#ifdef TARGET_RELOCATABLE
- /* Similarly if we are using -mrelocatable, consider all constants
- to be hard. */
- if (TARGET_RELOCATABLE)
- return 0;
-#endif
-
- if (mode == TFmode)
- {
- long k[4];
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
-
- return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
- }
-
- else if (mode == DFmode)
- {
- long k[2];
- REAL_VALUE_TYPE rv;
-
- if (TARGET_E500_DOUBLE)
- return 0;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
-
- return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
- }
-
- else if (mode == SFmode)
- {
- long l;
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_SINGLE (rv, l);
-
- return num_insns_constant_wide (l) == 1;
- }
-
- else if (mode == DImode)
- return ((TARGET_POWERPC64
- && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
- || (num_insns_constant (op, DImode) <= 2));
-
- else if (mode == SImode)
- return 1;
- else
- abort ();
-}
-
/* Returns the constant for the splat instruction, if exists. */
-static int
+int
easy_vector_splat_const (int cst, enum machine_mode mode)
{
switch (mode)
@@ -2336,10 +1940,9 @@ easy_vector_splat_const (int cst, enum machine_mode mode)
return 0;
}
-
/* Return nonzero if all elements of a vector have the same value. */
-static int
+int
easy_vector_same (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
int units, i, cst;
@@ -2355,75 +1958,6 @@ easy_vector_same (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
return 0;
}
-/* Return 1 if the operand is a CONST_INT and can be put into a
- register without using memory. */
-
-int
-easy_vector_constant (rtx op, enum machine_mode mode)
-{
- int cst, cst2;
-
- if (GET_CODE (op) != CONST_VECTOR
- || (!TARGET_ALTIVEC
- && !TARGET_SPE))
- return 0;
-
- if (zero_constant (op, mode)
- && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
- || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
- return 1;
-
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
- return 0;
-
- if (TARGET_SPE && mode == V1DImode)
- return 0;
-
- cst = INTVAL (CONST_VECTOR_ELT (op, 0));
- cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
-
- /* Limit SPE vectors to 15 bits signed. These we can generate with:
- li r0, CONSTANT1
- evmergelo r0, r0, r0
- li r0, CONSTANT2
-
- I don't know how efficient it would be to allow bigger constants,
- considering we'll have an extra 'ori' for every 'li'. I doubt 5
- instructions is better than a 64-bit memory load, but I don't
- have the e500 timing specs. */
- if (TARGET_SPE && mode == V2SImode
- && cst >= -0x7fff && cst <= 0x7fff
- && cst2 >= -0x7fff && cst2 <= 0x7fff)
- return 1;
-
- if (TARGET_ALTIVEC
- && easy_vector_same (op, mode))
- {
- cst = easy_vector_splat_const (cst, mode);
- if (EASY_VECTOR_15_ADD_SELF (cst)
- || EASY_VECTOR_15 (cst))
- return 1;
- }
- return 0;
-}
-
-/* Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF. */
-
-int
-easy_vector_constant_add_self (rtx op, enum machine_mode mode)
-{
- int cst;
- if (TARGET_ALTIVEC
- && GET_CODE (op) == CONST_VECTOR
- && easy_vector_same (op, mode))
- {
- cst = easy_vector_splat_const (INTVAL (CONST_VECTOR_ELT (op, 0)), mode);
- if (EASY_VECTOR_15_ADD_SELF (cst))
- return 1;
- }
- return 0;
-}
-
/* Generate easy_vector_constant out of a easy_vector_constant_add_self. */
rtx
@@ -2520,241 +2054,7 @@ output_vec_const_move (rtx *operands)
abort ();
}
-/* Return 1 if the operand is the constant 0. This works for scalars
- as well as vectors. */
-int
-zero_constant (rtx op, enum machine_mode mode)
-{
- return op == CONST0_RTX (mode);
-}
-
-/* Return 1 if the operand is 0.0. */
-int
-zero_fp_constant (rtx op, enum machine_mode mode)
-{
- return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
-}
-
-/* Return 1 if the operand is in volatile memory. Note that during
- the RTL generation phase, memory_operand does not return TRUE for
- volatile memory references. So this function allows us to
- recognize volatile references where its safe. */
-
-int
-volatile_mem_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM)
- return 0;
-
- if (!MEM_VOLATILE_P (op))
- return 0;
-
- if (mode != GET_MODE (op))
- return 0;
-
- if (reload_completed)
- return memory_operand (op, mode);
-
- if (reload_in_progress)
- return strict_memory_address_p (mode, XEXP (op, 0));
-
- return memory_address_p (mode, XEXP (op, 0));
-}
-
-/* Return 1 if the operand is an offsettable memory operand. */
-
-int
-offsettable_mem_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == MEM)
- && offsettable_address_p (reload_completed || reload_in_progress,
- mode, XEXP (op, 0)));
-}
-
-/* Return 1 if the operand is either an easy FP constant (see above) or
- memory. */
-
-int
-mem_or_easy_const_operand (rtx op, enum machine_mode mode)
-{
- return memory_operand (op, mode) || easy_fp_constant (op, mode);
-}
-
-/* Return 1 if the operand is either a non-special register or an item
- that can be used as the operand of a `mode' add insn. */
-
-int
-add_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
-
- return gpc_reg_operand (op, mode);
-}
-
-/* Return 1 if OP is a constant but not a valid add_operand. */
-
-int
-non_add_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
- && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
-}
-
-/* Return 1 if the operand is a non-special register or a constant that
- can be used as the operand of an OR or XOR insn on the RS/6000. */
-
-int
-logical_operand (rtx op, enum machine_mode mode)
-{
- HOST_WIDE_INT opl, oph;
-
- if (gpc_reg_operand (op, mode))
- return 1;
-
- if (GET_CODE (op) == CONST_INT)
- {
- opl = INTVAL (op) & GET_MODE_MASK (mode);
-
-#if HOST_BITS_PER_WIDE_INT <= 32
- if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
- return 0;
-#endif
- }
- else if (GET_CODE (op) == CONST_DOUBLE)
- {
- if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
- abort ();
-
- opl = CONST_DOUBLE_LOW (op);
- oph = CONST_DOUBLE_HIGH (op);
- if (oph != 0)
- return 0;
- }
- else
- return 0;
-
- return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
- || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
-}
-
-/* Return 1 if C is a constant that is not a logical operand (as
- above), but could be split into one. */
-
-int
-non_logical_cint_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- && ! logical_operand (op, mode)
- && reg_or_logical_cint_operand (op, mode));
-}
-
-/* Return 1 if C is a constant that can be encoded in a 32-bit mask on the
- RS/6000. It is if there are no more than two 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
-mask_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT c, lsb;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- c = INTVAL (op);
-
- /* Fail in 64-bit mode if the mask wraps around because the upper
- 32-bits of the mask will all be 1s, contrary to GCC's internal view. */
- if (TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
- return 0;
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Reject all zeros or all ones. */
- if (c == 0)
- return 0;
-
- /* Find the first transition. */
- lsb = c & -c;
-
- /* Invert to look for a second transition. */
- c = ~c;
-
- /* Erase first transition. */
- c &= -lsb;
-
- /* Find the second transition (if any). */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
-}
-
-/* Return 1 for the PowerPC64 rlwinm corner case. */
-
int
-mask_operand_wrap (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT c, lsb;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- c = INTVAL (op);
-
- if ((c & 0x80000001) != 0x80000001)
- return 0;
-
- c = ~c;
- if (c == 0)
- return 0;
-
- lsb = c & -c;
- c = ~c;
- c &= -lsb;
- lsb = c & -c;
- return c == -lsb;
-}
-
-/* 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 zeros, since zero should have been optimized away and
- confuses the making of MB and ME. */
-
-int
-mask64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- HOST_WIDE_INT c, lsb;
-
- c = INTVAL (op);
-
- /* Reject all zeros. */
- if (c == 0)
- return 0;
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Find the transition, and check that all bits above are 1's. */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
- }
- return 0;
-}
-
-static int
mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED,
bool allow_one)
{
@@ -2809,14 +2109,6 @@ mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED,
return 0;
}
-/* Like mask64_operand, but allow up to three transitions. This
- predicate is used by insn patterns that generate two rldicl or
- rldicr machine insns. */
-int mask64_2_operand (rtx op, enum machine_mode mode)
-{
- return mask64_1or2_operand (op, mode, false);
-}
-
/* Generates shifts and masks for a pair of rldicl or rldicr insns to
implement ANDing by the mask IN. */
void
@@ -2887,174 +2179,9 @@ build_mask64_2_operands (rtx in, rtx *out)
#endif
}
-/* 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 (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return (gpc_reg_operand (op, mode) || mask64_operand (op, mode));
-
- return (logical_operand (op, mode) || mask64_operand (op, mode));
-}
-
-/* Like the above, but also match constants that can be implemented
- with two rldicl or rldicr insns. */
-
-int
-and64_2_operand (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return gpc_reg_operand (op, mode) || mask64_1or2_operand (op, mode, true);
-
- return logical_operand (op, mode) || mask64_1or2_operand (op, mode, true);
-}
-
-/* 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
-and_operand (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return (gpc_reg_operand (op, mode) || mask_operand (op, mode));
-
- return (logical_operand (op, mode) || mask_operand (op, mode));
-}
-
-/* Return 1 if the operand is a general register or memory operand. */
-
-int
-reg_or_mem_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || memory_operand (op, mode)
- || macho_lo_sum_memory_operand (op, mode)
- || volatile_mem_operand (op, mode));
-}
-
-/* Return 1 if the operand is a general register or memory operand without
- pre_inc or pre_dec which produces invalid form of PowerPC lwa
- instruction. */
-
-int
-lwa_operand (rtx op, enum machine_mode mode)
-{
- rtx inner = op;
-
- if (reload_completed && GET_CODE (inner) == SUBREG)
- inner = SUBREG_REG (inner);
-
- return gpc_reg_operand (inner, mode)
- || (memory_operand (inner, mode)
- && GET_CODE (XEXP (inner, 0)) != PRE_INC
- && GET_CODE (XEXP (inner, 0)) != PRE_DEC
- && (GET_CODE (XEXP (inner, 0)) != PLUS
- || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
-}
-
-/* Return 1 if the operand, used inside a MEM, is a SYMBOL_REF. */
-
-int
-symbol_ref_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF
- && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op)));
-}
-
-/* Return 1 if the operand, used inside a MEM, is a valid first argument
- to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF
- || (GET_CODE (op) == REG
- && (REGNO (op) == LINK_REGISTER_REGNUM
- || REGNO (op) == COUNT_REGISTER_REGNUM
- || REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return 1 if the operand is a SYMBOL_REF for a function known to be in
- this file. */
-
-int
-current_file_function_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF
- && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
- && (SYMBOL_REF_LOCAL_P (op)
- || (DECL_RTL_SET_P (current_function_decl)
- && op == XEXP (DECL_RTL (current_function_decl), 0))));
-}
-
-/* Return 1 if this operand is a valid input for a move insn. */
-
-int
-input_operand (rtx op, enum machine_mode mode)
-{
- /* Memory is always valid. */
- if (memory_operand (op, mode))
- return 1;
-
- /* For floating-point, easy constants are valid. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && CONSTANT_P (op)
- && easy_fp_constant (op, mode))
- return 1;
-
- /* Allow any integer constant. */
- if (GET_MODE_CLASS (mode) == MODE_INT
- && (GET_CODE (op) == CONST_INT
- || GET_CODE (op) == CONST_DOUBLE))
- return 1;
-
- /* Allow easy vector constants. */
- if (GET_CODE (op) == CONST_VECTOR
- && easy_vector_constant (op, mode))
- return 1;
-
- /* For floating-point or multi-word mode, the only remaining valid type
- is a register. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
- return register_operand (op, mode);
-
- /* The only cases left are integral modes one word or smaller (we
- do not get called for MODE_CC values). These can be in any
- register. */
- if (register_operand (op, mode))
- return 1;
-
- /* A SYMBOL_REF referring to the TOC is valid. */
- if (legitimate_constant_pool_address_p (op))
- return 1;
-
- /* A constant pool expression (relative to the TOC) is valid */
- if (toc_relative_expr_p (op))
- return 1;
-
- /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
- to be valid. */
- if (DEFAULT_ABI == ABI_V4
- && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
- && small_data_operand (op, Pmode))
- return 1;
-
- return 0;
-}
-
/* Return TRUE if OP is an invalid SUBREG operation on the e500. */
-static bool
+
+bool
invalid_e500_subreg (rtx op, enum machine_mode mode)
{
/* Reject (subreg:SI (reg:DF)). */
@@ -3074,19 +2201,6 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
return false;
}
-/* Just like nonimmediate_operand, but return 0 for invalid SUBREG's
- on the e500. */
-int
-rs6000_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (TARGET_E500_DOUBLE
- && GET_CODE (op) == SUBREG
- && invalid_e500_subreg (op, mode))
- return 0;
-
- return nonimmediate_operand (op, mode);
-}
-
/* Darwin, AIX increases natural record alignment to doubleword if the first
field is an FP double while the FP fields remain word aligned. */
@@ -3228,7 +2342,7 @@ constant_pool_expr_p (rtx op)
return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
}
-static bool
+bool
toc_relative_expr_p (rtx op)
{
int have_sym = 0;
@@ -3351,13 +2465,13 @@ legitimate_indexed_address_p (rtx x, int strict)
&& INT_REG_OK_FOR_INDEX_P (op0, strict)));
}
-static inline bool
+inline bool
legitimate_indirect_address_p (rtx x, int strict)
{
return GET_CODE (x) == REG && INT_REG_OK_FOR_BASE_P (x, strict);
}
-static bool
+bool
macho_lo_sum_memory_operand (rtx x, enum machine_mode mode)
{
if (!TARGET_MACHO || !flag_pic
@@ -3783,15 +2897,6 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
return dest;
}
-/* Return 1 if X is a SYMBOL_REF for a TLS symbol. This is used in
- instruction definitions. */
-
-int
-rs6000_tls_symbol_ref (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return RS6000_SYMBOL_REF_TLS_P (x);
-}
-
/* Return 1 if X contains a thread-local symbol. */
bool
@@ -9193,225 +8298,6 @@ expand_block_move (rtx operands[])
}
-/* Return 1 if OP is suitable for a save_world call in prologue. It is
- known to be a PARALLEL. */
-int
-save_world_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int index;
- int i;
- rtx elt;
- int count = XVECLEN (op, 0);
-
- if (count != 55)
- return 0;
-
- index = 0;
- if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
- || GET_CODE (XVECEXP (op, 0, index++)) != USE)
- return 0;
-
- for (i=1; i <= 18; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != MEM
- || ! memory_operand (SET_DEST (elt), DFmode)
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != DFmode)
- return 0;
- }
-
- for (i=1; i <= 12; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != V4SImode)
- return 0;
- }
-
- for (i=1; i <= 19; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != MEM
- || ! memory_operand (SET_DEST (elt), Pmode)
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != Pmode)
- return 0;
- }
-
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != MEM
- || ! memory_operand (SET_DEST (elt), Pmode)
- || GET_CODE (SET_SRC (elt)) != REG
- || REGNO (SET_SRC (elt)) != CR2_REGNO
- || GET_MODE (SET_SRC (elt)) != Pmode)
- return 0;
-
- if (GET_CODE (XVECEXP (op, 0, index++)) != USE
- || GET_CODE (XVECEXP (op, 0, index++)) != USE
- || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
- return 0;
- return 1;
-}
-
-/* Return 1 if OP is suitable for a save_world call in prologue. It is
- known to be a PARALLEL. */
-int
-restore_world_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int index;
- int i;
- rtx elt;
- int count = XVECLEN (op, 0);
-
- if (count != 59)
- return 0;
-
- index = 0;
- if (GET_CODE (XVECEXP (op, 0, index++)) != RETURN
- || GET_CODE (XVECEXP (op, 0, index++)) != USE
- || GET_CODE (XVECEXP (op, 0, index++)) != USE
- || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
- return 0;
-
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != MEM
- || ! memory_operand (SET_SRC (elt), Pmode)
- || GET_CODE (SET_DEST (elt)) != REG
- || REGNO (SET_DEST (elt)) != CR2_REGNO
- || GET_MODE (SET_DEST (elt)) != Pmode)
- return 0;
-
- for (i=1; i <= 19; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != MEM
- || ! memory_operand (SET_SRC (elt), Pmode)
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != Pmode)
- return 0;
- }
-
- for (i=1; i <= 12; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != V4SImode)
- return 0;
- }
-
- for (i=1; i <= 18; i++)
- {
- elt = XVECEXP (op, 0, index++);
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != MEM
- || ! memory_operand (SET_SRC (elt), DFmode)
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != DFmode)
- return 0;
- }
-
- if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
- || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
- || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
- || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
- || GET_CODE (XVECEXP (op, 0, index++)) != USE)
- return 0;
- return 1;
-}
-
-
-/* Return 1 if OP is a load multiple operation. It is known to be a
- PARALLEL and the first section will be tested. */
-
-int
-load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int dest_regno;
- rtx src_addr;
- int i;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
- || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
- return 0;
- }
-
- return 1;
-}
-
-/* Similar, but tests for store multiple. Here, the second vector element
- is a CLOBBER. It will be tested later. */
-
-int
-store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0) - 1;
- unsigned int src_regno;
- rtx dest_addr;
- int i;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
- return 0;
-
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i + 1);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode
- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
- || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
- return 0;
- }
-
- return 1;
-}
-
/* Return a string to perform a load_multiple operation.
operands[0] is the vector.
operands[1] is the source address.
@@ -9469,292 +8355,12 @@ rs6000_output_load_multiple (rtx operands[3])
return "{lsi|lswi} %2,%1,%N0";
}
-/* Return 1 for a parallel vrsave operation. */
-
-int
-vrsave_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int dest_regno, src_regno;
- int i;
-
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC_VOLATILE)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
-
- if (dest_regno != VRSAVE_REGNO
- && src_regno != VRSAVE_REGNO)
- return 0;
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != CLOBBER
- && GET_CODE (elt) != SET)
- return 0;
- }
-
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for mfcr. */
-
-int
-mfcr_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- int i;
-
- /* Perform a quick check so we don't blow up below. */
- if (count < 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
- || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx exp = XVECEXP (op, 0, i);
- rtx unspec;
- int maskval;
- rtx src_reg;
-
- src_reg = XVECEXP (SET_SRC (exp), 0, 0);
-
- if (GET_CODE (src_reg) != REG
- || GET_MODE (src_reg) != CCmode
- || ! CR_REGNO_P (REGNO (src_reg)))
- return 0;
-
- if (GET_CODE (exp) != SET
- || GET_CODE (SET_DEST (exp)) != REG
- || GET_MODE (SET_DEST (exp)) != SImode
- || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
- return 0;
- unspec = SET_SRC (exp);
- maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
-
- if (GET_CODE (unspec) != UNSPEC
- || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
- || XVECLEN (unspec, 0) != 2
- || XVECEXP (unspec, 0, 0) != src_reg
- || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
- || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
- return 0;
- }
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for mtcrf. */
-
-int
-mtcrf_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- int i;
- rtx src_reg;
-
- /* Perform a quick check so we don't blow up below. */
- if (count < 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
- || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
- return 0;
- src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
-
- if (GET_CODE (src_reg) != REG
- || GET_MODE (src_reg) != SImode
- || ! INT_REGNO_P (REGNO (src_reg)))
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx exp = XVECEXP (op, 0, i);
- rtx unspec;
- int maskval;
-
- if (GET_CODE (exp) != SET
- || GET_CODE (SET_DEST (exp)) != REG
- || GET_MODE (SET_DEST (exp)) != CCmode
- || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
- return 0;
- unspec = SET_SRC (exp);
- maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
-
- if (GET_CODE (unspec) != UNSPEC
- || XINT (unspec, 1) != UNSPEC_MOVESI_TO_CR
- || XVECLEN (unspec, 0) != 2
- || XVECEXP (unspec, 0, 0) != src_reg
- || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
- || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
- return 0;
- }
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for lmw. */
-
-int
-lmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int dest_regno;
- rtx src_addr;
- unsigned int base_regno;
- HOST_WIDE_INT offset;
- int i;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
-
- if (dest_regno > 31
- || count != 32 - (int) dest_regno)
- return 0;
-
- if (legitimate_indirect_address_p (src_addr, 0))
- {
- offset = 0;
- base_regno = REGNO (src_addr);
- if (base_regno == 0)
- return 0;
- }
- else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
- {
- offset = INTVAL (XEXP (src_addr, 1));
- base_regno = REGNO (XEXP (src_addr, 0));
- }
- else
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
- rtx newaddr;
- rtx addr_reg;
- HOST_WIDE_INT newoffset;
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode)
- return 0;
- newaddr = XEXP (SET_SRC (elt), 0);
- if (legitimate_indirect_address_p (newaddr, 0))
- {
- newoffset = 0;
- addr_reg = newaddr;
- }
- else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
- {
- addr_reg = XEXP (newaddr, 0);
- newoffset = INTVAL (XEXP (newaddr, 1));
- }
- else
- return 0;
- if (REGNO (addr_reg) != base_regno
- || newoffset != offset + 4 * i)
- return 0;
- }
-
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for stmw. */
-
-int
-stmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int src_regno;
- rtx dest_addr;
- unsigned int base_regno;
- HOST_WIDE_INT offset;
- int i;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
- return 0;
-
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
-
- if (src_regno > 31
- || count != 32 - (int) src_regno)
- return 0;
-
- if (legitimate_indirect_address_p (dest_addr, 0))
- {
- offset = 0;
- base_regno = REGNO (dest_addr);
- if (base_regno == 0)
- return 0;
- }
- else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
- {
- offset = INTVAL (XEXP (dest_addr, 1));
- base_regno = REGNO (XEXP (dest_addr, 0));
- }
- else
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
- rtx newaddr;
- rtx addr_reg;
- HOST_WIDE_INT newoffset;
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode)
- return 0;
- newaddr = XEXP (SET_DEST (elt), 0);
- if (legitimate_indirect_address_p (newaddr, 0))
- {
- newoffset = 0;
- addr_reg = newaddr;
- }
- else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
- {
- addr_reg = XEXP (newaddr, 0);
- newoffset = INTVAL (XEXP (newaddr, 1));
- }
- else
- return 0;
- if (REGNO (addr_reg) != base_regno
- || newoffset != offset + 4 * i)
- return 0;
- }
-
- return 1;
-}
/* A validation routine: say whether CODE, a condition code, and MODE
match. The other alternatives either don't make sense or should
never be generated. */
-static void
+void
validate_condition_mode (enum rtx_code code, enum machine_mode mode)
{
if ((GET_RTX_CLASS (code) != RTX_COMPARE
@@ -9793,82 +8399,6 @@ validate_condition_mode (enum rtx_code code, enum machine_mode mode)
abort ();
}
-/* Return 1 if OP is a comparison operation that is valid for a branch insn.
- We only check the opcode against the mode of the CC value here. */
-
-int
-branch_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- enum machine_mode cc_mode;
-
- if (!COMPARISON_P (op))
- return 0;
-
- cc_mode = GET_MODE (XEXP (op, 0));
- if (GET_MODE_CLASS (cc_mode) != MODE_CC)
- return 0;
-
- validate_condition_mode (code, cc_mode);
-
- return 1;
-}
-
-/* Return 1 if OP is a comparison operation that is valid for a branch
- insn and which is true if the corresponding bit in the CC register
- is set. */
-
-int
-branch_positive_comparison_operator (rtx op, enum machine_mode mode)
-{
- enum rtx_code code;
-
- if (! branch_comparison_operator (op, mode))
- return 0;
-
- code = GET_CODE (op);
- return (code == EQ || code == LT || code == GT
- || code == LTU || code == GTU
- || code == UNORDERED);
-}
-
-/* Return 1 if OP is a comparison operation that is valid for an scc
- insn: it must be a positive comparison. */
-
-int
-scc_comparison_operator (rtx op, enum machine_mode mode)
-{
- return branch_positive_comparison_operator (op, mode);
-}
-
-int
-trap_comparison_operator (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- return COMPARISON_P (op);
-}
-
-int
-boolean_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- return (code == AND || code == IOR || code == XOR);
-}
-
-int
-boolean_or_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- return (code == IOR || code == XOR);
-}
-
-int
-min_max_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- return (code == SMIN || code == SMAX || code == UMIN || code == UMAX);
-}
/* Return 1 if ANDOP is a mask that has no bits on that are not in the
mask required to convert the result of a rotate insn into a shift
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 1a2d12d..9b8f1fd 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -251,6 +251,10 @@ extern int target_flags;
#define HAVE_AS_TLS 0
#endif
+/* Return 1 for a symbol ref for a thread-local storage symbol. */
+#define RS6000_SYMBOL_REF_TLS_P(RTX) \
+ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
+
#ifdef IN_LIBGCC2
/* For libgcc2 we make sure this is a compile time constant */
#if defined (__64BIT__) || defined (__powerpc64__)
@@ -1931,6 +1935,9 @@ typedef struct rs6000_args
|| easy_vector_constant (X, GET_MODE (X))) \
&& !rs6000_tls_referenced_p (X))
+#define EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
+#define EASY_VECTOR_15_ADD_SELF(n) ((n) >= 0x10 && (n) <= 0x1e && !((n) & 1))
+
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
We have two alternate definitions for each of them.
@@ -2538,87 +2545,6 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-/* Define the codes that are matched by predicates in rs6000.c. */
-
-#define PREDICATE_CODES \
- {"any_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
- LABEL_REF, SUBREG, REG, MEM}}, \
- {"any_parallel_operand", {PARALLEL}}, \
- {"zero_constant", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
- LABEL_REF, SUBREG, REG, MEM}}, \
- {"short_cint_operand", {CONST_INT}}, \
- {"u_short_cint_operand", {CONST_INT}}, \
- {"non_short_cint_operand", {CONST_INT}}, \
- {"exact_log2_cint_operand", {CONST_INT}}, \
- {"gpc_reg_operand", {SUBREG, REG}}, \
- {"cc_reg_operand", {SUBREG, REG}}, \
- {"cc_reg_not_cr0_operand", {SUBREG, REG}}, \
- {"reg_or_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_neg_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_aligned_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_arith_cint_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_add_cint64_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_sub_cint64_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_logical_cint_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
- {"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
- {"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
- {"easy_fp_constant", {CONST_DOUBLE}}, \
- {"easy_vector_constant", {CONST_VECTOR}}, \
- {"easy_vector_constant_add_self", {CONST_VECTOR}}, \
- {"zero_fp_constant", {CONST_DOUBLE}}, \
- {"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
- {"lwa_operand", {SUBREG, MEM, REG}}, \
- {"volatile_mem_operand", {MEM}}, \
- {"offsettable_mem_operand", {MEM}}, \
- {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \
- {"add_operand", {SUBREG, REG, CONST_INT}}, \
- {"non_add_cint_operand", {CONST_INT}}, \
- {"and_operand", {SUBREG, REG, CONST_INT}}, \
- {"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
- {"and64_2_operand", {SUBREG, REG, CONST_INT}}, \
- {"logical_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
- {"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \
- {"mask_operand", {CONST_INT}}, \
- {"mask_operand_wrap", {CONST_INT}}, \
- {"mask64_operand", {CONST_INT}}, \
- {"mask64_2_operand", {CONST_INT}}, \
- {"count_register_operand", {REG}}, \
- {"xer_operand", {REG}}, \
- {"symbol_ref_operand", {SYMBOL_REF}}, \
- {"rs6000_tls_symbol_ref", {SYMBOL_REF}}, \
- {"call_operand", {SYMBOL_REF, REG}}, \
- {"current_file_function_operand", {SYMBOL_REF}}, \
- {"input_operand", {SUBREG, MEM, REG, CONST_INT, \
- CONST_DOUBLE, SYMBOL_REF}}, \
- {"rs6000_nonimmediate_operand", {SUBREG, MEM, REG}}, \
- {"load_multiple_operation", {PARALLEL}}, \
- {"store_multiple_operation", {PARALLEL}}, \
- {"lmw_operation", {PARALLEL}}, \
- {"stmw_operation", {PARALLEL}}, \
- {"vrsave_operation", {PARALLEL}}, \
- {"save_world_operation", {PARALLEL}}, \
- {"restore_world_operation", {PARALLEL}}, \
- {"mfcr_operation", {PARALLEL}}, \
- {"mtcrf_operation", {PARALLEL}}, \
- {"branch_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU, \
- UNORDERED, ORDERED, \
- UNGE, UNLE }}, \
- {"branch_positive_comparison_operator", {EQ, LT, GT, LTU, GTU, \
- UNORDERED }}, \
- {"scc_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU, \
- UNORDERED, ORDERED, \
- UNGE, UNLE }}, \
- {"trap_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU}}, \
- {"boolean_operator", {AND, IOR, XOR}}, \
- {"boolean_or_operator", {IOR, XOR}}, \
- {"altivec_register_operand", {REG}}, \
- {"min_max_operator", {SMIN, SMAX, UMIN, UMAX}},
-
/* uncomment for disabling the corresponding default options */
/* #define MACHINE_no_sched_interblock */
/* #define MACHINE_no_sched_speculative */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index bf2bf4c..5f297cc 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -101,6 +101,9 @@
(include "8540.md")
(include "power4.md")
(include "power5.md")
+
+(include "predicates.md")
+
(include "darwin.md")