summaryrefslogtreecommitdiff
path: root/gcc/config/sparc/sparc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sparc/sparc.c')
-rw-r--r--gcc/config/sparc/sparc.c855
1 files changed, 25 insertions, 830 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index a429bcfb8a5..8e2893d4cd3 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -805,56 +805,6 @@ v9_regcmp_p (enum rtx_code code)
/* Operand constraints. */
-/* Return nonzero only if OP is a register of mode MODE,
- or const0_rtx. */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
- if (op == const0_rtx)
- return 1;
- if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && CONST_DOUBLE_LOW (op) == 0)
- return 1;
- if (fp_zero_operand (op, mode))
- return 1;
- return 0;
-}
-
-/* Return nonzero only if OP is const1_rtx. */
-
-int
-const1_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return op == const1_rtx;
-}
-
-/* Nonzero if OP is a floating point value with value 0.0. */
-
-int
-fp_zero_operand (rtx op, enum machine_mode mode)
-{
- enum mode_class mclass = GET_MODE_CLASS (GET_MODE (op));
- if (mclass != MODE_FLOAT && mclass != MODE_VECTOR_INT)
- return 0;
- return op == CONST0_RTX (mode);
-}
-
-/* Nonzero if OP is a register operand in floating point register. */
-
-int
-fp_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op));
-}
-
/* Nonzero if OP is a floating point constant which can
be loaded into an integer register using a single
sethi instruction. */
@@ -931,94 +881,6 @@ fp_high_losum_p (rtx op)
return 0;
}
-/* Nonzero if OP is an integer register. */
-
-int
-intreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (register_operand (op, SImode)
- || (TARGET_ARCH64 && register_operand (op, DImode)));
-}
-
-/* Nonzero if OP is a floating point condition code register. */
-
-int
-fcc_reg_operand (rtx op, enum machine_mode mode)
-{
- /* This can happen when recog is called from combine. Op may be a MEM.
- Fail instead of calling abort in this case. */
- if (GET_CODE (op) != REG)
- return 0;
-
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
- return 0;
-
-#if 0 /* ??? ==> 1 when %fcc0-3 are pseudos first. See gen_compare_reg(). */
- if (reg_renumber == 0)
- return REGNO (op) >= FIRST_PSEUDO_REGISTER;
- return REGNO_OK_FOR_CCFP_P (REGNO (op));
-#else
- return (unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG < 4;
-#endif
-}
-
-/* Nonzero if OP is a floating point condition code fcc0 register. */
-
-int
-fcc0_reg_operand (rtx op, enum machine_mode mode)
-{
- /* This can happen when recog is called from combine. Op may be a MEM.
- Fail instead of calling abort in this case. */
- if (GET_CODE (op) != REG)
- return 0;
-
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
- return 0;
-
- return REGNO (op) == SPARC_FCC_REG;
-}
-
-/* Nonzero if OP is an integer or floating point condition code register. */
-
-int
-icc_or_fcc_reg_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == REG && REGNO (op) == SPARC_ICC_REG)
- {
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode)
- return 0;
- return 1;
- }
-
- return fcc_reg_operand (op, mode);
-}
-
-/* Call insn on SPARC can take a PC-relative constant address, or any regular
- memory address. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- gcc_assert (GET_CODE (op) == MEM);
- op = XEXP (op, 0);
- return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
-}
-
-int
-call_operand_address (rtx op, enum machine_mode mode)
-{
- return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
-}
-
/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
otherwise return 0. */
@@ -1029,628 +891,6 @@ tls_symbolic_operand (rtx op)
return 0;
return SYMBOL_REF_TLS_MODEL (op);
}
-
-int
-tgd_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC;
-}
-
-int
-tld_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC;
-}
-
-int
-tie_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC;
-}
-
-int
-tle_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC;
-}
-
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-symbolic_operand (register rtx op, enum machine_mode mode)
-{
- enum machine_mode omode = GET_MODE (op);
-
- if (omode != mode && omode != VOIDmode && mode != VOIDmode)
- return 0;
-
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- return !SYMBOL_REF_TLS_MODEL (op);
-
- case LABEL_REF:
- return 1;
-
- case CONST:
- op = XEXP (op, 0);
- return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
-
- default:
- return 0;
- }
-}
-
-/* Return truth value of statement that OP is a symbolic memory
- operand of mode MODE. */
-
-int
-symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- return ((GET_CODE (op) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (op))
- || GET_CODE (op) == CONST || GET_CODE (op) == HIGH
- || GET_CODE (op) == LABEL_REF);
-}
-
-/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */
-
-int
-label_ref_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != LABEL_REF)
- return 0;
- if (GET_MODE (op) != mode)
- return 0;
- return 1;
-}
-
-/* Return 1 if the operand is an argument used in generating pic references
- in either the medium/low or medium/anywhere code models of sparc64. */
-
-int
-sp64_medium_pic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* Check for (const (minus (symbol_ref:GOT)
- (const (minus (label) (pc))))). */
- if (GET_CODE (op) != CONST)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != MINUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- /* ??? Ensure symbol is GOT. */
- if (GET_CODE (XEXP (op, 1)) != CONST)
- return 0;
- if (GET_CODE (XEXP (XEXP (op, 1), 0)) != MINUS)
- return 0;
- return 1;
-}
-
-/* Return 1 if the operand is a data segment reference. This includes
- the readonly data segment, or in other words anything but the text segment.
- This is needed in the medium/anywhere code model on v9. These values
- are accessed with EMBMEDANY_BASE_REG. */
-
-int
-data_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- return ! SYMBOL_REF_FUNCTION_P (op);
- case PLUS :
- /* Assume canonical format of symbol + constant.
- Fall through. */
- case CONST :
- return data_segment_operand (XEXP (op, 0), VOIDmode);
- default :
- return 0;
- }
-}
-
-/* Return 1 if the operand is a text segment reference.
- This is needed in the medium/anywhere code model on v9. */
-
-int
-text_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case LABEL_REF :
- return 1;
- case SYMBOL_REF :
- return SYMBOL_REF_FUNCTION_P (op);
- case PLUS :
- /* Assume canonical format of symbol + constant.
- Fall through. */
- case CONST :
- return text_segment_operand (XEXP (op, 0), VOIDmode);
- default :
- return 0;
- }
-}
-
-/* Return 1 if the operand is either a register or a memory operand that is
- not symbolic. */
-
-int
-reg_or_nonsymb_mem_operand (register rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
-
- if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
- return 1;
-
- return 0;
-}
-
-int
-splittable_symbolic_memory_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- if (! symbolic_operand (XEXP (op, 0), Pmode))
- return 0;
- return 1;
-}
-
-int
-splittable_immediate_memory_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- if (! immediate_operand (XEXP (op, 0), Pmode))
- return 0;
- return 1;
-}
-
-/* Return truth value of whether OP is EQ or NE. */
-
-int
-eq_or_neq (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
-}
-
-/* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
- or LTU for non-floating-point. We handle those specially. */
-
-int
-normal_comp_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
-
- if (!COMPARISON_P (op))
- return 0;
-
- if (GET_MODE (XEXP (op, 0)) == CCFPmode
- || GET_MODE (XEXP (op, 0)) == CCFPEmode)
- return 1;
-
- code = GET_CODE (op);
- return (code != NE && code != EQ && code != GEU && code != LTU);
-}
-
-/* Return 1 if this is a comparison operator. This allows the use of
- MATCH_OPERATOR to recognize all the branch insns. */
-
-int
-noov_compare_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
-
- if (!COMPARISON_P (op))
- return 0;
-
- code = GET_CODE (op);
- if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
- || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
- /* These are the only branches which work with CC_NOOVmode. */
- return (code == EQ || code == NE || code == GE || code == LT);
- return 1;
-}
-
-/* Return 1 if this is a 64-bit comparison operator. This allows the use of
- MATCH_OPERATOR to recognize all the branch insns. */
-
-int
-noov_compare64_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
-
- if (! TARGET_V9)
- return 0;
-
- if (!COMPARISON_P (op))
- return 0;
-
- code = GET_CODE (op);
- if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
- /* These are the only branches which work with CCX_NOOVmode. */
- return (code == EQ || code == NE || code == GE || code == LT);
- return (GET_MODE (XEXP (op, 0)) == CCXmode);
-}
-
-/* Nonzero if OP is a comparison operator suitable for use in v9
- conditional move or branch on register contents instructions. */
-
-int
-v9_regcmp_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
-
- if (!COMPARISON_P (op))
- return 0;
-
- code = GET_CODE (op);
- return v9_regcmp_p (code);
-}
-
-/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
-
-int
-extend_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
-}
-
-/* Return nonzero if OP is an operator of mode MODE which can set
- the condition codes explicitly. We do not include PLUS and MINUS
- because these require CC_NOOVmode, which we handle explicitly. */
-
-int
-cc_arithop (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == AND
- || GET_CODE (op) == IOR
- || GET_CODE (op) == XOR)
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if OP is an operator of mode MODE which can bitwise
- complement its second operand and set the condition codes explicitly. */
-
-int
-cc_arithopn (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* XOR is not here because combine canonicalizes (xor (not ...) ...)
- and (xor ... (not ...)) to (not (xor ...)). */
- return (GET_CODE (op) == AND
- || GET_CODE (op) == IOR);
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 13 bit immediate field. This is an acceptable SImode operand for
- most 3 address instructions. */
-
-int
-arith_operand (rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return SMALL_INT32 (op);
-}
-
-/* Return true if OP is a constant 4096 */
-
-int
-arith_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- else
- return INTVAL (op) == 4096;
-}
-
-/* Return true if OP is suitable as second operand for add/sub */
-
-int
-arith_add_operand (rtx op, enum machine_mode mode)
-{
- return arith_operand (op, mode) || arith_4096_operand (op, mode);
-}
-
-/* Return true if OP is a CONST_INT or a CONST_DOUBLE which can fit in the
- immediate field of OR and XOR instructions. Used for 64-bit
- constant formation patterns. */
-int
-const64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT
- && SPARC_SIMM13_P (INTVAL (op)))
-#if HOST_BITS_PER_WIDE_INT != 64
- || (GET_CODE (op) == CONST_DOUBLE
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
- && (CONST_DOUBLE_HIGH (op) ==
- ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?
- (HOST_WIDE_INT)-1 : 0)))
-#endif
- );
-}
-
-/* The same, but only for sethi instructions. */
-int
-const64_high_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT
- && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0
- && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
- )
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0
- && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 11 bit immediate field. This is an acceptable SImode operand for
- the movcc instructions. */
-
-int
-arith11_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 10 bit immediate field. This is an acceptable SImode operand for
- the movrcc instructions. */
-
-int
-arith10_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
-}
-
-/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit
- immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit
- immediate field.
- ARCH64: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in a 13 bit immediate field. This is an acceptable DImode operand
- for most 3 address instructions. */
-
-int
-arith_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || (! TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)
- || (TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
-}
-
-/* Return true if OP is a constant 4096 for DImode on ARCH64 */
-
-int
-arith_double_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (TARGET_ARCH64 &&
- ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
- (GET_CODE (op) == CONST_DOUBLE &&
- CONST_DOUBLE_LOW (op) == 4096 &&
- CONST_DOUBLE_HIGH (op) == 0)));
-}
-
-/* Return true if OP is suitable as second operand for add/sub in DImode */
-
-int
-arith_double_add_operand (rtx op, enum machine_mode mode)
-{
- return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
-}
-
-/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in an 11 bit immediate field. This is an acceptable DImode
- operand for the movcc instructions. */
-/* ??? Replace with arith11_operand? */
-
-int
-arith11_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_DOUBLE
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x400) == 0)))
- || (GET_CODE (op) == CONST_INT
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));
-}
-
-/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in an 10 bit immediate field. This is an acceptable DImode
- operand for the movrcc instructions. */
-/* ??? Replace with arith10_operand? */
-
-int
-arith10_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_DOUBLE
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x200) == 0)))
- || (GET_CODE (op) == CONST_INT
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));
-}
-
-/* Return truth value of whether OP is an integer which fits the
- range constraining immediate operands in most three-address insns,
- which have a 13 bit immediate field. */
-
-int
-small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
-}
-
-int
-small_int_or_double (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));
-}
-
-/* Recognize operand values for the umul instruction. That instruction sign
- extends immediate values just like all other sparc instructions, but
- interprets the extended result as an unsigned number. */
-
-int
-uns_small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-#if HOST_BITS_PER_WIDE_INT > 32
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
- || (INTVAL (op) >= 0xFFFFF000
- && INTVAL (op) <= 0xFFFFFFFF)));
-#else
- return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
-#endif
-}
-
-int
-uns_arith_operand (rtx op, enum machine_mode mode)
-{
- return register_operand (op, mode) || uns_small_int (op, mode);
-}
-
-/* Return truth value of statement that OP is a call-clobbered register. */
-int
-clobbered_register (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
-}
-
-/* Return 1 if OP is a valid operand for the source of a move insn. */
-
-int
-input_operand (rtx op, enum machine_mode mode)
-{
- enum mode_class mclass;
-
- /* If both modes are non-void they must be the same. */
- if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- /* Allow any one instruction integer constant, and all CONST_INT
- variants when we are working in DImode and !arch64. */
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ((GET_CODE (op) == CONST_INT
- && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
- || SPARC_SIMM13_P (INTVAL (op))
- || (mode == DImode
- && ! TARGET_ARCH64)))
- || (TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && ((CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SETHI_P (CONST_DOUBLE_LOW (op)))
- ||
-#if HOST_BITS_PER_WIDE_INT == 64
- (CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))
-#else
- (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
- && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
- && CONST_DOUBLE_HIGH (op) == 0)
- || (CONST_DOUBLE_HIGH (op) == -1
- && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))
-#endif
- ))))
- return 1;
-
- /* If !arch64 and this is a DImode const, allow it so that
- the splits can be generated. */
- if (! TARGET_ARCH64
- && mode == DImode
- && GET_CODE (op) == CONST_DOUBLE)
- return 1;
-
- if (register_operand (op, mode))
- return 1;
-
- mclass = GET_MODE_CLASS (mode);
- if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
- || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR))
- return 1;
-
- /* If this is a SUBREG, look inside so that we handle
- paradoxical ones. */
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* Check for valid MEM forms. */
- if (GET_CODE (op) == MEM)
- return memory_address_p (mode, XEXP (op, 0));
-
- return 0;
-}
-
-/* Return 1 if OP is valid for the lhs of a compare insn. */
-
-int
-compare_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == ZERO_EXTRACT)
- return (register_operand (XEXP (op, 0), mode)
- && small_int_or_double (XEXP (op, 1), mode)
- && small_int_or_double (XEXP (op, 2), mode)
- /* This matches cmp_zero_extract. */
- && ((mode == SImode
- && ((GET_CODE (XEXP (op, 2)) == CONST_INT
- && INTVAL (XEXP (op, 2)) > 19)
- || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (XEXP (op, 2)) > 19)))
- /* This matches cmp_zero_extract_sp64. */
- || (mode == DImode
- && TARGET_ARCH64
- && ((GET_CODE (XEXP (op, 2)) == CONST_INT
- && INTVAL (XEXP (op, 2)) > 51)
- || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (XEXP (op, 2)) > 51)))));
- else
- return register_operand (op, mode);
-}
-
/* We know it can't be done in one insn when we get here,
the movsi expander guarantees this. */
@@ -1660,15 +900,6 @@ sparc_emit_set_const32 (rtx op0, rtx op1)
enum machine_mode mode = GET_MODE (op0);
rtx temp;
- if (GET_CODE (op1) == CONST_INT)
- {
- HOST_WIDE_INT value = INTVAL (op1);
-
- gcc_assert (! SPARC_SETHI_P (value & GET_MODE_MASK (mode))
- && ! SPARC_SIMM13_P (value));
- }
-
- /* Full 2-insn decomposition is needed. */
if (reload_in_progress || reload_completed)
temp = op0;
else
@@ -1676,20 +907,15 @@ sparc_emit_set_const32 (rtx op0, rtx op1)
if (GET_CODE (op1) == CONST_INT)
{
+ gcc_assert (!small_int_operand (op1, mode)
+ && !const_high_operand (op1, mode));
+
/* Emit them as real moves instead of a HIGH/LO_SUM,
this way CSE can see everything and reuse intermediate
values if it wants. */
- if (TARGET_ARCH64
- && HOST_BITS_PER_WIDE_INT != 64
- && (INTVAL (op1) & 0x80000000) != 0)
- emit_insn (gen_rtx_SET
- (VOIDmode, temp,
- immed_double_const (INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
- 0, DImode)));
- else
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- GEN_INT (INTVAL (op1)
- & ~(HOST_WIDE_INT)0x3ff)));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ GEN_INT (INTVAL (op1)
+ & ~(HOST_WIDE_INT)0x3ff)));
emit_insn (gen_rtx_SET (VOIDmode,
op0,
@@ -1703,7 +929,6 @@ sparc_emit_set_const32 (rtx op0, rtx op1)
gen_rtx_HIGH (mode, op1)));
emit_insn (gen_rtx_SET (VOIDmode,
op0, gen_rtx_LO_SUM (mode, temp, op1)));
-
}
}
@@ -1910,6 +1135,13 @@ sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
}
}
+#if HOST_BITS_PER_WIDE_INT == 32
+void
+sparc_emit_set_const64 (rtx op0 ATTRIBUTE_UNUSED, rtx op1 ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+#else
/* These avoid problems when cross compiling. If we do not
go through all this hair then the optimizer will see
invalid REG_EQUAL notes or in some cases none at all. */
@@ -1918,17 +1150,6 @@ static rtx gen_safe_SET64 (rtx, HOST_WIDE_INT);
static rtx gen_safe_OR64 (rtx, HOST_WIDE_INT);
static rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
-#if HOST_BITS_PER_WIDE_INT == 64
-#define GEN_HIGHINT64(__x) GEN_INT ((__x) & ~(HOST_WIDE_INT)0x3ff)
-#define GEN_INT64(__x) GEN_INT (__x)
-#else
-#define GEN_HIGHINT64(__x) \
- immed_double_const ((__x) & ~(HOST_WIDE_INT)0x3ff, 0, DImode)
-#define GEN_INT64(__x) \
- immed_double_const ((__x) & 0xffffffff, \
- ((__x) & 0x80000000 ? -1 : 0), DImode)
-#endif
-
/* The optimizer is not to assume anything about exactly
which bits are set for a HIGH, they are unspecified.
Unfortunately this leads to many missed optimizations
@@ -1937,25 +1158,25 @@ static rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
static void
sparc_emit_set_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
{
- emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val & ~(HOST_WIDE_INT)0x3ff)));
}
static rtx
gen_safe_SET64 (rtx dest, HOST_WIDE_INT val)
{
- return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));
+ return gen_rtx_SET (VOIDmode, dest, GEN_INT (val));
}
static rtx
gen_safe_OR64 (rtx src, HOST_WIDE_INT val)
{
- return gen_rtx_IOR (DImode, src, GEN_INT64 (val));
+ return gen_rtx_IOR (DImode, src, GEN_INT (val));
}
static rtx
gen_safe_XOR64 (rtx src, HOST_WIDE_INT val)
{
- return gen_rtx_XOR (DImode, src, GEN_INT64 (val));
+ return gen_rtx_XOR (DImode, src, GEN_INT (val));
}
/* Worker routines for 64-bit constant formation on arch64.
@@ -2293,8 +1514,7 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
if (reload_in_progress || reload_completed)
temp = op0;
- if (GET_CODE (op1) != CONST_DOUBLE
- && GET_CODE (op1) != CONST_INT)
+ if (GET_CODE (op1) != CONST_INT)
{
sparc_emit_set_symbolic_const64 (op0, op1, temp);
return;
@@ -2303,28 +1523,8 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
if (! temp)
temp = gen_reg_rtx (DImode);
- if (GET_CODE (op1) == CONST_DOUBLE)
- {
-#if HOST_BITS_PER_WIDE_INT == 64
- high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff;
- low_bits = CONST_DOUBLE_LOW (op1) & 0xffffffff;
-#else
- high_bits = CONST_DOUBLE_HIGH (op1);
- low_bits = CONST_DOUBLE_LOW (op1);
-#endif
- }
- else
- {
-#if HOST_BITS_PER_WIDE_INT == 64
- high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
- low_bits = (INTVAL (op1) & 0xffffffff);
-#else
- high_bits = ((INTVAL (op1) < 0) ?
- 0xffffffff :
- 0x00000000);
- low_bits = INTVAL (op1);
-#endif
- }
+ high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
+ low_bits = (INTVAL (op1) & 0xffffffff);
/* low_bits bits 0 --> 31
high_bits bits 32 --> 63 */
@@ -2452,26 +1652,20 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
|| (((~high_bits) & 0xffffffff) == 0xffffffff
&& ((~low_bits) & 0x80000000) != 0))
{
- int fast_int = (~low_bits & 0xffffffff);
+ unsigned HOST_WIDE_INT fast_int = (~low_bits & 0xffffffff);
if ((SPARC_SETHI_P (fast_int)
&& (~high_bits & 0xffffffff) == 0)
|| SPARC_SIMM13_P (fast_int))
emit_insn (gen_safe_SET64 (temp, fast_int));
else
- sparc_emit_set_const64 (temp, GEN_INT64 (fast_int));
+ sparc_emit_set_const64 (temp, GEN_INT (fast_int));
}
else
{
rtx negated_const;
-#if HOST_BITS_PER_WIDE_INT == 64
negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
(((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
-#else
- negated_const = immed_double_const ((~low_bits) & 0xfffffc00,
- (~high_bits) & 0xffffffff,
- DImode);
-#endif
sparc_emit_set_const64 (temp, negated_const);
}
@@ -2536,6 +1730,7 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
#endif
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
}
+#endif /* HOST_BITS_PER_WIDE_INT == 32 */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
@@ -3448,7 +2643,7 @@ legitimate_constant_p (rtx x)
&& (GET_MODE (x) == SFmode
|| GET_MODE (x) == DFmode
|| GET_MODE (x) == TFmode)
- && fp_zero_operand (x, GET_MODE (x)))
+ && const_zero_operand (x, GET_MODE (x)))
return true;
return false;
@@ -8643,7 +7838,7 @@ sparc_extra_constraint_check (rtx op, int c, int strict)
break;
case 'Y':
- return fp_zero_operand (op, GET_MODE (op));
+ return const_zero_operand (op, GET_MODE (op));
default:
return 0;